Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Локализация


Автор: Zamuta 17.3.2007, 04:01
Всем здрасьте...

Как доставать  ресурсы из bundle.key я уже понял, а если нужно в java коде указать какое значение выводить, то как это записать?

Например String text="#{var.key}" не проходит......

Автор: tux 17.3.2007, 11:47
Цитата(Zamuta @  17.3.2007,  04:01 Найти цитируемый пост)
Как доставать  ресурсы из bundle.key я уже понял, а если нужно в java коде указать какое значение выводить, то как это записать?

Тогда придется дергать значения из properties-файла самому:
Код

Properties props = new Properties();
InputStream is = new FileInputStream("путь_к_твоему_файлу");
props.load(is);
String value = props.getProperty("var.key");

Или примерно также из ресурса используя
Код

InputStream is = this.getClass().getResourceAsStream();

Веб-фреймворки могу располагать своими средствами для чтения пропертей, в любом случае они делают это точно также.

Автор: Maksym 17.3.2007, 15:51
Цитата(tux @  17.3.2007,  11:47 Найти цитируемый пост)
Веб-фреймворки могу располагать своими средствами для чтения пропертей, в любом случае они делают это точно также. 

Например, для jsf это можно сделать с помощью такого утилитного метода:
Код

public static String getResourceString(String key) {
    FacesContext context = FacesContext.getCurrentInstance();
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle(
         context.getApplication().getMessageBundle(), 
         context.getViewRoot().getLocale()
    );
    String result = "";
    try {
        result = bundle.getString(key);
    } catch (MissingResourceException exc) {
        // MissingResourceException logging
    }
    return result;
}


Автор: Zamuta 17.3.2007, 19:18
А вообще, если сервер получает от браузера, например локаль "ru", то страница автоматически переключиться на эту локаль? Я имею в виду у java существуют такие встроенные механизмы или их нужно писать самому, например определение по сообщению о локали от браузера или по ip адресу....

Автор: y3u 17.3.2007, 21:55
есть специальные документированые способы именования файлов *.properties, чтобы доставать по локали автоматически нужный бандл. А саму локаль можно всегда достать из реквеста, если надо. Если надо каким либо еще способом ее сетапить, незавсимо от браузера, скажем, по выбору пользователя в его профайле, можно использовать ThreadLocal... Вообще, имеет смысл полчитать в инете на тему локализации приложений статейки, их сейчас много развелось. В официальном тьюториле тоже на эту тему пишут

Автор: Zamuta 19.3.2007, 19:18
Хочется небольшого уточнения. В чём разница между context.getViewRoot().getLocale()  и request.getLocale() ?

Автор: y3u 20.3.2007, 01:00
Цитата(Zamuta @  19.3.2007,  19:18 Найти цитируемый пост)
request.getLocale() 

достается системная локаль из браузера. Это которая, к примеру, в винде ставится на панели управления в региональных настройках. Ну или которая в браузере настроена, к примеру в мозиле можно руками локальнастроить...

Цитата(Zamuta @  19.3.2007,  19:18 Найти цитируемый пост)
context.getViewRoot().getLocale()  

лично я не в курсе, посмотри джавадоки

Автор: Zamuta 20.3.2007, 15:34
Во всех примерах которые я нахожу в интернете и в литературе с request и response работают только внутри метода с параметрами RequestServlet request, ServletResponse response, например так:

Код

public void servise(RequestServlet request, ServletResponse response){
Locale locale = request.getLocale();
}


Теперь небольшое отступление. Локализация. Также в литературе или интернете можно найти примерно вот такой пример работы с локалями (часть кода):
Код

  public static String getDisplayString(String bundleName, String id, Object params[], Locale locale) {
        String text = null;
        ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale, getCurrentClassLoader(params));
        try {
            text = bundle.getString(id);
        } catch (MissingResourceException e) {
            text = "!! key " + id + " not found !!";
        }
        if (params != null) {
            MessageFormat mf = new MessageFormat(text, locale);
            text = mf.format(params, new StringBuffer(), null).toString();
        }
        return text;
    }


А затем вызываем этот метод и получаем нужный текст. И у меня вопрос, почему нельзя сделать просто так:
Код

RequestServlet request;
String text = getDisplayString(bundleName, "text", null, request.getLocale());   <-NullPointerException


Автор: y3u 20.3.2007, 16:17
 где именно падает эксцепшен-то? Если getCurrentClassLoader(params), ты туда null передаешь, то приводи код метода, но, судя по твоему коду, он падает по request.getLocale(), т.к. ты написал 
Цитата(Zamuta @  20.3.2007,  15:34 Найти цитируемый пост)
RequestServlet request;
String text = getDisplayString(bundleName, "text", null, request.getLocale());

Реквест и респонз в сервлет передает вебконтейнер, а ты тут объявляешь переменную, но не инициализируешь ее никак, поэтому она у тебя null, а если у null дергать какие-либо методы, то будет падать NullPointerException...

Автор: Zamuta 20.3.2007, 16:44
Падает на request.getLocale(). С сервлетами никогда не работал, поэтому и спотыкаюсь. Как можно в моём случае просто получить локаль request.getLocale(). 

Автор: y3u 20.3.2007, 17:09
без кода сказать сложно, я не экстрасенс  smile 

ну, во-первых, посмотри, может в твоем классике, если ты наследуешься от чего-нить, присутствует соответствующий метод getRequest() или getServletRequest() или getHttpServletRequest() - что-то в этом роде.
Во-вторых, есил не найдешь, либо приведи, таки полный код, либо псмотри во всякого рода контекстах и пр., если используются, может из них как-то можно подцепить реквест... Обычно все дело заканчивается сервлетом и каким нибудь методом doGet(...) или doPost(...), где и реквест и респоз папрметрами приходят

Автор: Zamuta 20.3.2007, 17:20
В том то и дело что я работаю с jsf и как такового сервлетного кода в моих классах нет. А сейчас встал вопрос локализации. Чтобы отобразить страницу на текущем языке юзера нужно получить его локаль. 

Привожу пример кода класса отвечающего работу с локалями:
класслоадер:
Код

 protected static ClassLoader getCurrentClassLoader(Object defaultObject) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            loader = defaultObject.getClass().getClassLoader();
        }
        return loader;
    }


Получатель строки из bundl'a:
Код

 public static String getDisplayString(String bundleName, String id, Object params[], Locale locale) {
        String text = null;
        ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale, getCurrentClassLoader(params));
        try {
            text = bundle.getString(id);
        } catch (MissingResourceException e) {
            text = "!! key " + id + " not found !!";
        }
        if (params != null) {
            MessageFormat mf = new MessageFormat(text, locale);
            text = mf.format(params, new StringBuffer(), null).toString();
        }
        return text;
    }


Ещё раз повторюсь, реквестов у меня в коде нет, а как с ними работать пока не понял. Пробую так, не бейте сильно   smile :
Код

public class Getlocale {
    
    /** Creates a new instance of Getlocale */
    public Getlocale() {
    }
    FilterConfig config = null;
    ServletContext servletContext = null;
    public static Locale locale;
    
    public void init(FilterConfig filterConfig) throws ServletException {
        config = filterConfig;
        servletContext = config.getServletContext();
    }
    
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
               
        HttpServletRequest httpRequest = (HttpServletRequest)request;
        HttpServletResponse httpResponse = (HttpServletResponse)response;
            
        locale = request.getLocale();
    }
    
    public void destroy() {
    }
}


А потом из этого класса тяну Getlocale.locale, возвращает null....

Автор: Maksym 20.3.2007, 17:38
Цитата(Zamuta @  19.3.2007,  19:18 Найти цитируемый пост)
Хочется небольшого уточнения. В чём разница между context.getViewRoot().getLocale()  и request.getLocale() ? 

Это я привел пример для jsf. Taм есть context.getViewRoot().getLocale(). Oтсюда ее берет и jsf resourceBudle механизм.

Автор: Zamuta 20.3.2007, 17:46
Maksym, но из context.getViewRoot().getLocale() мы же не сможем получить локаль установленную в браузере юзера?

Автор: Maksym 20.3.2007, 19:15
Zamuta
Думаю что сможем. Вот, что говорит документация:
Цитата

javax.faces.component
Class UIViewRoot
public java.util.Locale getLocale()

    Return the Locale to be used in localizing the response being created for this view.

    Algorithm:

    If we have a locale ivar, return it. If we have a value binding for "locale", get its value. If the value is null, return the result of calling ViewHandler.calculateLocale(javax.faces.context.FacesContext). If the value is an instance of java.util.Locale return it. If the value is a String, convert it to a java.util.Locale and return it. If there is no value binding for "locale", return the result of calling ViewHandler.calculateLocale(javax.faces.context.FacesContext).

    Returns:
        The current Locale obtained by executing the above algorithm.

Цитата

javax.faces.application
Class ViewHandler

public abstract java.util.Locale calculateLocale(javax.faces.context.FacesContext context)

    Returns an appropriate Locale to use for this and subsequent requests for the current client.

    Parameters:
        context - FacesContext for the current request 
    Throws:
        java.lang.NullPointerException - if context is null

то есть исходная локаль во UIViewRoot устанавливается исходя из request'а пользователя (что логично). В дальнейшем она может быть переключена програмно (по кнопочке сменить язык интерфейса, например)

Автор: Zamuta 20.3.2007, 19:25
Maksym, я сейчас читаю книжку JavaServer Faces in Action автор Kito D.Mann . Так  вот там есть такой пример:
Код

public void doFilter(ServletRequest request, 
                     ServletResponse response,
                     FilterChain chain) 
             throws IOException, ServletException
{
  ...
  HttpServletRequest httpRequest = (HttpServletRequest)request;
  HttpServletResponse httpResponse = (HttpServletResponse)response;
  HttpSession session = httpRequest.getSession();
  String requestPath = httpRequest.getPathInfo();
  ...
     if ((role.equals(RoleType.UPPER_MANAGER) && requestPath.indexOf(Constants.PROTECTED_DIR) > 0) ||
          (!role.equals(RoleType.PROJECT_MANAGER) && requestPath.indexOf(Constants.EDIT_DIR) > 0))    
     {
        String text = 
          Utils.getDisplayString(Constants.BUNDLE_BASENAME, "PathNotFound", new Object[] { requestPath }, request.getLocale());
        httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND, text);            
     }
  ...
}


И дальше идёт описание
Цитата

First, note that the Constants class declares the name of the resource bundle, avoid-
ing the possibility of mistyping the name. Also, we pass in the current 
Locale directly from the HttpRequest object since there is no FacesContext yet (filters are 
executed before JSF begins processing the request)
. Since the string in the bundle 
has a parameter in it, we also need to send the 
getDisplayString method request- as a single parameter (it will replace “{0}” with the value of the requestPath).
Path

стр. 555.
Даже не знаю кому верить.... smile 

Автор: Maksym 20.3.2007, 19:48
Zamuta
То что в фильтр вывается над jsf lifecycle это понятно в этом же и смысл фильтра-то. Мне показалось, что мы говорим о работе с локалью в jsf контексте.

Автор: Zamuta 20.3.2007, 19:54
Да, мы говорим о работе с локалью в jsf контексте. Значит это я не правильно перевёл, перевёл что request вызывается раньше чем jsf. 
Тогда буду сейчас пробовать с context.getViewRoot().getLocale().

Автор: Maksym 20.3.2007, 20:41
Zamuta
То, что касается чистого jsf то, вкратце, все что нужно это:
1. Создать bundles с ресурсами, например, в виде .properties файлов с именами типа MessagesBundle_de_DE.properties, MessagesBundle_en_EN.properties и т.д.
2. Можно определить в faces-config.xml (но это, кажется, не обязательно)
Код

<faces-config>
    <application>
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>en</supported-locale>                
            <supported-locale>de</supported-locale>
        </locale-config>
        <message-bundle>
            mypackage.MessagesBundle
        </message-bundle>        
    </application>
</faces-config>

3. Определить переменную для MessagesBundle в странице, например
Код

<f:loadBundle var="bundle" basename="imypackage.MessagesBundle" /> 

и использовать в коде страниц:
Код

<h:outputText value="#{bundle.login_key}" />

4.  Переключать локали, например в action:
Код

  FacesContext context = FacesContext.getCurrentInstance();
  context.getViewRoot().setLocale(new Locale("de", "DE"));

Автор: Zamuta 20.3.2007, 20:51
Maksym, эти пункты есс-но сделаны, без них никак. Просто меня этот пример из книжки с толку сбил, там как раз удобнее доставать локаль из реквеста, а в jsf конечно же из контекста и какого меня понесло из реквеста её доставать. А сейчас говорит "ru". Максиму +1.

Автор: Samotnik 2.11.2007, 17:53
Цитата(Maksym @ 20.3.2007,  20:41)
Zamuta
То, что касается чистого jsf то, вкратце, все что нужно это:
1. Создать bundles с ресурсами, например, в виде .properties файлов с именами типа MessagesBundle_de_DE.properties, MessagesBundle_en_EN.properties и т.д.
2. Можно определить в faces-config.xml (но это, кажется, не обязательно)
Код

<faces-config>
    <application>
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>en</supported-locale>                
            <supported-locale>de</supported-locale>
        </locale-config>
        <message-bundle>
            mypackage.MessagesBundle
        </message-bundle>        
    </application>
</faces-config>

3. Определить переменную для MessagesBundle в странице, например
Код

<f:loadBundle var="bundle" basename="imypackage.MessagesBundle" /> 

и использовать в коде страниц:
Код

<h:outputText value="#{bundle.login_key}" />

4.  Переключать локали, например в action:
Код

  FacesContext context = FacesContext.getCurrentInstance();
  context.getViewRoot().setLocale(new Locale("de", "DE"));


А можно еще раз, только по-подробнее. Вот к примеру, я что-то знаю о интернационализации, и мне нужно реализовать ее на  jstl  ПАЖАЛСТА, по шагам,  еще раз, что где создать, и где потом вызывать !!

Автор: Maksym 2.11.2007, 19:20
Samotnik
Ты поднял тему о jsf, к jstl все вышесказанное не относится.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)