Подтвердить что ты не робот

Лучший способ разработки для локализации строк

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

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

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

Изменить: Решение, которое я сейчас просматриваю, выглядит следующим образом:

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Пример:

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

Поскольку он открыт для мнений, вот как я это делаю.

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

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

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

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

Ответ 7

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

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

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