2015-01-11 4 views
2

В проекте, над которым я работаю, я бы хотел загрузить различные ресурсы в зависимости от текущей локали. С помощью строк это довольно просто: просто создайте пакет ресурсов, добавив некоторые файлы, например Localization.properties и Localization_de.properties, а затем загрузите его через ResourceBundle.getBundle("domain.project.Localization").Загрузить локализованные ресурсы

Но как загрузить локализованные ресурсы, которые не являются простыми строками?

В частности, я хотел бы загрузить изображения и HTML-файлы на основе языка. Достаточно получить правильный URL-адрес этого ресурса. Например, я хотел бы иметь файл Welcome.html и Welcome_de.html и загрузить позже, когда текущий языковой стандарт - немецкий.

Просто используя getClass().getResource("Welcome.html") не работает, он всегда возвращает именно этот файл и не выполняет обработку локали. Я не нашел удобный способ решить эту проблему, кроме ручного возиться с именем файла на основе текущей локали.

Одним из решений, которое я придумал, является добавление ключа в мой файл Localization.properties, который содержит имя правильного локализованного HTML-файла. Но это кажется взломанным и неправильным.

Обратите внимание, что это не приложение для Android, а просто стандартное приложение для настольных компьютеров Java 8.

+0

Почему бы просто не помещать файлы + карты локализации в разные папки? Как «/LANGUAGE/img/image1.jpg», где язык может быть «DE» или «EN» или что-то еще? Таким образом, вам просто нужно hava язык, который хранится где-то [и, возможно, нужно обрабатывать отсутствующие файлы (резервное копирование на ressource, который определенно завершен?)] – Cyphrags

+0

@Cyphrags: На самом деле это хорошая идея. Я подумаю об этом. – DarkDust

ответ

2

Это на самом деле оказалось довольно легко получить такое же поведение, как ResourceBundle.getBundle. У меня есть looked at the code и нашел, что самая важная часть для обработки локалей и имен файлов - ResourceBundle.Control.

Так вот простой метод, который возвращает URL в локализованный ресурс (по той же схеме имени файла в качестве наборов ресурсов) без кэширования и поддержки только для текущей локали:

/** Load localized resource for current locale. 
* 
* @param baseName Basename of the resource. May include a path. 
* @param suffix File extension of the resource. 
* @return URL for the localized resource or null if none was found. 
*/ 
public static URL getLocalizedResource(String baseName, String suffix) { 
    Locale locale = Locale.getDefault(); 
    ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); 
    List<Locale> candidateLocales = control.getCandidateLocales(baseName, locale); 

    for (Locale specificLocale : candidateLocales) { 
     String bundleName = control.toBundleName(baseName, specificLocale); 
     String resourceName = control.toResourceName(bundleName, suffix); 

     // Replace "Utils" with the name of your class! 
     URL url = Utils.class.getResource(resourceName); 
     if (url != null) { 
      return url; 
     } 
    } 

    return null; 
} 

Если кто-то хочет продлить его поддерживать общие локали в качестве аргумента: важная часть в ResourceBundle.getBundleImpl реализации является:

for (Locale targetLocale = locale; 
    targetLocale != null; 
    targetLocale = control.getFallbackLocale(baseName, targetLocale)) { 
     List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale); 
     ... 
} 

последней записью в getCandidateLocales является пустым локали (Locale.ROOT). Его следует игнорировать, если локали, так как ресурс по умолчанию будет найден в первой итерации for, до того, как будет проверена резервная локаль.

+0

Хорошее решение :) – ToYonos

0

Наличие ресурса для хранения имени локализованного файла действительно является допустимым решением, но, как вы уже упоминали, является громоздким. Если вам нужно отобразить HTML-страницу в вашем приложении, почему бы не включить небольшой веб-сервер и не иметь ли он серверные JSP-страницы? Таким образом, весь HTML останется прежним, и сами страницы будут локализованы.

Другой вариант - использовать локальный механизм шаблонов (например, FreeMarker) и динамически генерировать HTML-файлы перед их обслуживанием.

+0

Интересная идея, но не очень подходит для моих нужд, я боюсь. Мне нравится предлагать страницы справки с длинными отформатированными текстами. Локализованные страницы JSP кажутся еще более полезными для этого. Кроме того, это похоже на использование кувалды, чтобы взломать орех. И последнее, но не менее важное: он не решает загружать локализованные изображения. – DarkDust

+0

Это именно то, что делает Eclipse - для помощи они открывают локальный экземпляр tomcat. Кроме того, для локализованных изображений вам необходимо сохранить имена изображений в качестве локализованного ресурса. Сколько страниц мы говорим? –

+0

Прямо сейчас есть только один. Я ожидаю, что вам понадобится дюжина или два. Слишком много, что заставляет меня нервничать. Кажется, что редактирование такой страницы более громоздко. Tomcat больше, чем мое приложение, и я думаю, что он имеет более высокий объем памяти. Очень много работы по настройке и обслуживанию, когда все, что я хочу, это отобразить HTML-файл в WebView. Я очень ценю эту идею, но есть слишком много вещей об этом, которые пахнут мне. – DarkDust

0

Как насчет ListResourceBundle?

Определите ваши связки:

public class MyBundle_fr_FR extends ListResourceBundle 
{ 
    public Object[][] getContents() 
    { 
     return new Object[][] 
     { 
      { "welcome_file", getClass().getResource("Welcome_fr.html") }, 
      { "another_file", getClass().getResource("foo_fr.html") } 
     }; 
    } 
} 

public class MyBundle_de_DE extends ListResourceBundle 
{ 
    public Object[][] getContents() 
    { 
     return new Object[][] 
     { 
      { "welcome_file", getClass().getResource("Welcome_de.html") }, 
      { "another_file", getClass().getResource("foo_de.html") } 
     }; 
    } 
} 

И затем использовать его как это:

ResourceBundle bundle = ResourceBundle.getBundle("MyBundle", Locale.GERMANY); 
URL url = (URL) bundle.getObject("welcome_file"); 
+0

Это всего лишь вариант схемы имени файла в свойствах. То есть для каждого ресурса мне нужно добавить новые записи в ListResourceBundle. Я бы поместил имя файла в файл 'Localization.properties'; ваше предложение имеет то преимущество, что вместо URL-адреса вместо имени «имя файла» возвращается URL-адрес. – DarkDust

0

так, что вы делаете это немного странно для меня. Я разработал некоторые международные приложения и никогда не использовал этот подход. Стоимость обслуживания вашего подхода настолько высока. Представьте, что вы хотите изменить одну часть файла welcome.html, в которой вам нужно изменить все другие файлы приветствия, которые являются огромным усилием. Общее решение этой проблемы в java использует JSTL fmt taglib с получением помощи некоторых файлов свойств, содержащих пару ключей и ключей, которые являются фиксированными, а значения изменяются в соответствии с той локалью, в которой вы находитесь. Например, вы в своем Localization.properties файле, имеют ключевое значение (ы), как:

page.welcome.welcome=welcome 

и у вас есть еще один файл с именем Localization_de.properties, который имеет один и тот же ключ с другим значением

page.welcome.welcome=willkommen 

Теперь в вашем welcome.jsp вы можете использовать что-то вроде этого <fmt:message key="page.welcome.welcome"/>, чтобы обеспечить правильное значение на вашей странице. Для изображений вы можете получить тот же подход. просто импортируйте имя изображения в каждый файл свойства в качестве ключа и назовите его правильно как его значение и используйте ключ в jsp. Для i18n используйте плагины eclipse (например, Resource Bundel Editor), чтобы облегчить вам жизнь.

В других языках, которые я использовал как django, я видел тот же подход, что и выше.

+0

Вы действительно делаете это для длинных файлов справки? Если речь идет о локализации файла с, скажем, дюжиной строк, я бы сказал, что это раздражает, но вы можете это сделать. Но как насчет HTML-страницы с 30 _paragraphs_, плюс таблицы и списки? Это кажется очень громоздким, и я бы не делал этого на других платформах, таких как Mac, iOS или Android, где вы локализуете полные произвольные файлы, помещая их в нужные каталоги. Особенно, когда вы локализуете, скажем, 30 файлов справки: у вас будет файл свойств ресурса _monster_. Легко оставить мертвые записи тоже. Это просто так плохо для меня. – DarkDust

+0

Большинство приложений, над которыми я работал, были ориентированы на данные и обычно не содержали много статических файлов. Обычно мы используем и извлекаем локализованные данные из базы данных. Для данных, показанных пользователю, мы обычно помещаем их в файлы свойств. Для вашей конкретной проблемы я думаю, что apache имеет некоторые возможности для статической интернационализации файлов, но я не использовал его. – Reza

1

(Это дополнение к моему комментарию, чтобы иметь более подробное объяснение)

Вы можете поставить RESSOURCES в разных папках, основываясь на их языке.

файла дерево может выглядеть следующим образом:

  • pathToRessources

    • DE

      • Изображения
        • Image1.png
        • Image2.png
      • Локализация
        • MainPage // Больше на сайте здесь ....
        • Impressum
    • EN

      • .. .

И используя как "файл-локализация траектории-строитель-класс" (утверждая, что лучшее название когда-либо)

public static Locale currentLocale = Locale.GERMAN; 

public static String baseRessourcePath = "Path to your basic folder for ressources"; 

public static String getLocalizedPathToFile(String ressourcePath) 
{ 
    return Paths.get(currentLocale.getLanguage(), ressourcePath).toString(); 
} 

Везде, где вам необходимо загрузить Ressource просто позвоните своему загрузчик с

getLocalizedPath(PathToFile) 

где PathToFile, как /Images/Image1.png или что-то еще.

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

Надеется, что это помогает :)

+0

Спасибо, мне нравится ваша идея (upvoted), но тем временем я [нашел решение] (http://stackoverflow.com/a/27953622/400056), которого я действительно искал. – DarkDust

+0

Да, я это видел, и спасибо за верхнюю! :) – Cyphrags

Смежные вопросы