У нас есть проект Java, который содержит большое количество строк на английском языке для пользовательских подсказок, сообщений об ошибках и так далее. Мы хотим извлечь все переводимые строки в файл свойств, чтобы их можно было перевести позже.

Например, мы хотели бы заменить:

Foo.java

String msg = "Hello, " + name + "! Today is " + dayOfWeek;

С участием:

Foo.java

String msg = Language.getString("foo.hello", name, dayOfWeek);

language.properties

foo.hello = Hello, {0}! Today is {1}

Я понимаю, что сделать это полностью автоматизированным способом практически невозможно, так как не каждую строку нужно переводить. Однако нам было интересно, существует ли полуавтоматический способ, который устраняет часть трудоемкости.

13
Simon Nickerson 18 Июн 2009 в 12:17

8 ответов

Лучший ответ

Вам нужен инструмент, который заменяет каждое выражение, включающее конкатенацию строк, вызовом библиотеки, с очевидным особым случаем выражений, включающих только одну буквальную строку.

Это может сделать система преобразования программ, в которой вы можете выразить желаемые шаблоны. Такая система принимает правила в форме:

         lhs_pattern -> rhs_pattern  if condition ;

Где шаблоны - это фрагменты кода с ограничениями категории синтаксиса для переменных шаблона. Это заставляет инструмент искать синтаксис, соответствующий lhs_pattern, и, если он найден, заменять на rhs_pattern, где сопоставление с образцом выполняется по языковым структурам, а не по тексту. Таким образом, он работает независимо от форматирования кода, отступов, комментариев и т. Д.

Набросок нескольких правил (и чрезмерное упрощение, чтобы оно оставалось кратким), следуя стилю вашего примера:

  domain Java;

  nationalize_literal(s1:literal_string):
    " \s1 " -> "Language.getString1(\s1 )";

  nationalize_single_concatenation(s1:literal_string,s2:term):
    " \s1 + \s2 " -> "Language.getString1(\s1) + \s2"; 

  nationalize_double_concatenation(s1:literal_string,s2:term,s3:literal_string): 
      " \s1 + \s2 + \s3 " -> 
      "Language.getString3(\generate_template1\(\s1 + "{1}" +\s3\, s2);"
   if IsNotLiteral(s2);

Сами шаблоны заключены в "..."; это не строковые литералы Java, а скорее способ сказать мультикомпьютерно-языковому механизму сопоставления шаблонов, что суффикс внутри "..." является (доменом) Java-кодом. Мета-материал помечен символом \, например, метапеременные \ s1, \ s2, \ s3, а встроенный вызов шаблона \ сгенерировать с помощью (и) для обозначения его списка мета-параметров: -}

Обратите внимание на использование ограничений категории синтаксиса для метапеременных s1 и s3, чтобы гарантировать соответствие только строковых литералов. То, что мета-переменные совпадают с шаблоном слева, подставляется справа.

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

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

На самом деле, я предполагаю, что вам нужно закодировать ~~ 100 подобных правил, чтобы охватить комбинаторику и особые случаи интересов. Вознаграждение состоит в том, что ваш код автоматически улучшается. Если все сделано правильно, вы можете многократно применять это преобразование к своему коду, поскольку ваш код проходит через несколько выпусков; он оставит в покое ранее национализированные выражения и просто изменит новые, вставленные беспечными программистами.

Система, которая может это сделать, - это DMS Software Reengineering Toolkit. DMS может анализировать / сопоставлять с образцом / преобразовывать / печатать на многих языках, включая Java и C #.

4
Ira Baxter 26 Авг 2009 в 11:15

Eclipse будет экстернализировать каждую отдельную строку и не будет автоматически строить замену, как вы ищете. Если у вас есть очень последовательное соглашение о том, как вы строите свои строки, вы можете написать сценарий Perl, чтобы сделать некоторую интеллектуальную замену в файлах .java. Но этот сценарий будет довольно сложным, если вы захотите обработать

  • String msg = new String («Привет»);
  • Строка msg2 = "Hello2";
  • Строка msg3 = новый StringBuffer (). Append ("Hello3"). ToString ();
  • Строка msg4 = "Привет" + 4;
  • и т.п.

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

РЕДАКТИРОВАТЬ: Это инструмент Globalyzer от Lingport. На веб-сайте говорится, что он поддерживает экстернализацию строк, но не конкретно, как это сделать. Не уверен, поддерживает ли он замену переменных. Существует бесплатная пробная версия, так что вы можете попробовать и убедиться.

2
Brad C 19 Июн 2009 в 21:58

Globalyzer обладает обширными возможностями по обнаружению, управлению и экстернализации строк, а также значительно ускоряет работу по сравнению с просмотром строк и их экстернализацией по одной. Вы можете фильтровать строки, а также видеть их в контексте, а затем выводить их на экстернали по одной или партиями. Он работает с широким спектром языков программирования и типов ресурсов, включая, конечно, Java. К тому же Globalyzer найдет для ваших проектов интернационализации гораздо больше, чем просто встроенные строки. Вы можете узнать больше на http://lingoport.com/globalyzer и там есть ссылки для подписки на демонстрацию. учетная запись. Globalyzer сначала создавался для выполнения крупных сервисных проектов по интернационализации, а затем с годами превратился в полномасштабный корпоративный инструмент, обеспечивающий интернационализацию разработки и ее сохранение.

1
Adam 9 Дек 2009 в 23:16

А также Экстернализатор строк Eclipse, который генерирует файлы свойств, Eclipse имеет предупреждение для неинтерактивных строк, которое полезно для поиска файлов, которые вы не интернационализировали.

String msg = "Hello " + name;

Выдает предупреждение «Невнешний строковый литерал; за ним должен следовать // $ NON-NLS- $». Для строк, которые действительно входят в код, вы можете добавить аннотацию (@SuppressWarnings("nls")) или добавить комментарий:

String msg = "Hello " + name; //$NON-NLS-1$

Это очень полезно для преобразования проекта в правильную интернационализацию.

1
Campa 29 Май 2019 в 14:00

Я думаю, что у eclipse есть возможность перенести все строки в файл свойств.

0
Noam Gal 18 Июн 2009 в 08:19

Вы можете использовать метод «Externalize String» из eclipse. Откройте файл Java в редакторе, а затем щелкните «Внешняя строка» в главном меню «Источник». ИТ-служба создает для вас файл свойств со всеми отмеченными в выбранном вами строчками.

Надеюсь это поможет.

0
Lars 26 Авг 2009 в 09:54

Так как все взвешивают в IDE, думаю, мне лучше встать на защиту Netbeans :)

Инструменты -> Интернационализация -> Мастер интернационализации

Очень кстати..

0
Nico 28 Авг 2009 в 09:16

Идея InteliJ - еще один инструмент, обладающий этой функцией.

alt text

Вот ссылка на демонстрацию

0
Glorfindel 16 Апр 2019 в 22:48