Лучший способ дизайна для локализации строк - PullRequest
20 голосов
/ 09 октября 2008

Это общий вопрос, открытый для мнений. Я пытался придумать хороший способ разработки для локализации строковых ресурсов для приложения Windows MFC и связанных утилит. Мой список пожеланий:

  • Необходимо сохранить строковые литералы в коде (вместо замены на макрос #define идентификаторы ресурса), чтобы сообщения по-прежнему читались в строке
  • Необходимо разрешить локализованные строковые ресурсы (duh)
  • Не должно накладывать дополнительных ограничений среды выполнения (например, зависимость от .NET и т. Д.)
  • Должен иметь минимальное вмешательство в существующий код (чем меньше модификаций, тем лучше)
  • Должен быть отлаживаемым
  • Должен генерировать файлы ресурсов, которые можно редактировать с помощью общих инструментов (например, общий формат)
  • Не следует использовать блоки комментариев копирования / вставки для сохранения литеральных строк в коде или чего-либо еще, что создает потенциал для десинхронизации
  • Было бы неплохо разрешить статическую (во время компиляции) проверку того, что каждая «нотационная» строка находится в файле (ах) ресурса
  • Было бы неплохо разрешить пул строк межязыкового ресурса (для компонентов на разных языках, например: родной C ++ и .NET)

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

Edit: Решение, которое у меня сейчас есть, выглядит так:

ShowMessage( RESTRING( _T("Some string") ) );
ShowMessage( RESTRING( _T("Some string with variable %1"), sNonTranslatedStringVariable ) );

Затем у меня есть специальная утилита для анализа строк из блоков 'RESTRING' и помещения их в файл .resx для локализации, а также отдельный объект C # COM для загрузки их из локализованных файлов ресурсов с резервным восстановлением. Если объект C # недоступен (или не может загрузить), я возвращаюсь к строке в коде. Макрос расширяется до шаблонного класса, который вызывает COM-объект и выполняет форматирование и т. Д.

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

Ответы [ 7 ]

3 голосов
/ 09 октября 2008

Мы используем английскую строку в качестве идентификатора.

Если не удается найти объект международного ресурса (загруженный из установленной библиотеки I18N), то по умолчанию используется строка идентификатора.

Код выглядит так:

doAction(I18N.get("Press OK to continue"));

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

Мы можем иметь несколько DLL для каждого местного. Название dll основано на RFC 3066
язык [_territory] [. Codeset] [@ модификатор]

Мы пытаемся извлечь языковой стандарт из машины и быть максимально точными при загрузке dll I18N, но отступаем к менее конкретным локальным вариациям, если более конкретная версия отсутствует.

Пример:

В Великобритании: если местный был en_GB.UTF-8
(Я использую термин dll свободно, но не в определенном смысле Windows).

Сначала найдите I18N.en_GB.UTF-8 dll. Если эта dll не существует, вернитесь к I18N.en_GB . Если эта dll не существует, вернитесь к I18N.en Если эта dll не существует, вернитесь к I18N.default

Единственное исключение из этого правила: Упрощенный китайский (zh_CN), где запасной вариант - американский английский (en_US). Если машина не поддерживает упрощенный китайский, маловероятно, что она полностью поддерживает китайский.

1 голос
/ 24 октября 2008

Простой способ - использовать только строковые идентификаторы в вашем коде - без буквенных строк. Затем вы можете создавать разные версии файла .rc для каждого языка и создавать только библиотеки ресурсов только для ресурсов или просто разные языковые сборки.

Существует несколько условно-бесплатных утилит, помогающих локализовать rc-файл, которые обрабатывают изменение размеров диалоговых элементов для языков с более длинными словами и предупреждают об отсутствующих переводах.

Более сложной проблемой является порядок слов, если у вас есть несколько чисел в printf, которые должны быть в другом порядке для грамматики другого языка. В codeproject есть несколько расширенных классов printf, которые позволяют вам указывать такие вещи, как printf («слово% 1s и% 2s», var1, var2), так что вы можете переключать% 1s и% 2s при необходимости.

1 голос
/ 10 октября 2008

Ваше решение очень похоже на решение * gettext для Unix / Linux. На самом деле вам не нужно писать процедуры извлечения.

Я не уверен, почему вы хотите, чтобы макрос _RESTRING обрабатывал несколько аргументов. Мой код (использующий поддержку gettext для wxWidgets) выглядит так: MyString.Format(_("Some string with variable %ls"), _("variable"));. То есть String :: Format (...) получает два индивидуально переведенных аргумента. В ретроспективе, Boost :: Format был бы лучше, но это также позволило бы boost::format(_("Some string with variable %1")) % _("variable");

(для краткости мы используем макрос _())

1 голос
/ 09 октября 2008

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

В вашем коде вы увидите строки на своем родном языке, а не непрозрачные идентификаторы.

0 голосов
/ 09 октября 2008

Вам нужна продвинутая утилита, которую я всегда хотел написать, но у меня никогда не было времени. Если вы не найдете такого инструмента, вы можете использовать мои классы-оболочки CMsg () и CFMsg (), которые позволяют очень легко извлекать строки из таблицы ресурсов. (CFMsg даже предоставляет однострочную оболочку FormatMessage. И да, в отсутствие нужного вам инструмента, сохранение копии строки в комментарии является хорошим решением. Что касается десинхронизации комментария, помните, что строковые литералы очень редко меняются.

http://www.codeproject.com/KB/string/stringtable.aspx

Кстати, нативные программы Win32 и .NET имеют совершенно другое управление хранением ресурсов. Вам будет трудно найти общее решение для обоих.

0 голосов
/ 09 октября 2008

Так как это открыто для мнений, вот как я это делаю.

Мой локализованный текстовый файл - это простой текстовый файл с разделителями табуляции, который можно загрузить в Excel и отредактировать. Первый столбец предназначен для определения, а каждый столбец справа является последующим языком, например:

ID              ENGLISH      FRENCH    GERMAN
STRING_YES      YES          OUI       YA
STRING_NO       NO           NON       NEIN

Тогда в моем make-файле есть шаг сборки cusom, который генерирует файл strings.h и strings.dat. В моем случае он создает список перечисления для строковых идентификаторов, а затем двоичный файл со смещениями для текста. Так как в моем приложении пользователь может изменить язык в любое время, у меня все они есть в памяти, но вы могли бы легко сделать так, чтобы ваш препроцессор генерировал разные выходные файлы для каждого языка, если это необходимо.

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

0 голосов
/ 09 октября 2008

В одном проекте, который я локализовал на 10+ языков, я поместил все, что должно было быть локализовано, в одну dll только для ресурсов. Во время установки пользователь выбирает, какая dll установлена ​​с его приложением.

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

Я знаю, что это не идеально, но это сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...