Локализатор
Switch to English >>

Файлы

Текущая версия: 2.3.8

  • Загрузить
    Внутри собственно утилита (в подкаталоге exe), примеры, загрузчики, исходники. Никакой установки не требуется. Программа распространяется свободно. Проект является частично Open Source - в той мере, в какой здесь выложены исходники. Эти фрагменты вы можете использовать на свое усмотрение. Для компиляции необходима моя библиотека GreenWin, исходники которой на данный момент не распространяются.

Общие сведения

Программа позволяет выполнять автоматизированную локализацию для проектов.

Достоинства:

  • Внесение изменений в локализацию не вызывает изменений в общем заголовочном файле и не приводит к масштабной перекомпиляции проекта.
  • Локализованные строки представляют собой указатели типа const char *. Это делает работу со строками максимально эффективной. Во время исполнения не происходит поиска строк по ключу или идентификатору, не вызываются никакие функции.
  • Процесс локализации сильно автоматизирован. После первоначального освоения от пользователя требуются минимальные трудозатраты на поддержание проекта в "локализованном" состоянии.

Как обычно, никаких гарантий не дается. Однако программа используется почти ежедневно, и серьезных багов не замечено. Большинство изменений связаны с добавлением новых возможностей и опций. Версия 2.0 связана с добавлением поддержки Visual Studio 2010, Qt и Unicode.

Быстрый старт

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

У вас должен быть файл проекта Microsoft Visual Studio 2003, 2005, 2008, 2010. Либо должен быть просто список файлов в файле с расширением .lst. Либо вам придется перечислить ваши "исходники" вручную, можно с помощью масок.

Определите в программе специальный префикс:

#define LS
- такой или другой, лишь бы уникальный. Пометьте этим префиксом все строки, подлежащие локализации, например так: LS"this string" или так: LS("this string").

Вызовите программу-локализатор:

localizer -auto LS файл1 файл2...

Пример, пусть ваш проект называется "interval":

localizer -auto LS +interval.vcproj interval.eng.loc interval.rus.loc interval_loc.cpp interval.eng.bin interval.rus.bin
Или, если у вас нет проекта, а есть только список interval.lst, тогда:

localizer -auto LS +interval.lst interval.eng.loc interval.rus.loc interval_loc.cpp interval.eng.bin interval.rus.bin
Или, если у вас даже нет списка, но все .cpp/.h файлы находятся в текущем каталоге, тогда:

localizer -auto LS +*.cpp +*.h interval.eng.loc interval.rus.loc interval_loc.cpp interval.eng.bin interval.rus.bin

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

Среди параметров идет сначала префикс, потом список "исходников" со значком "+", потом файлы, связанные с локализацией.

Смысл файла определяется его расширением:

  • .vcproj или .vcxproj - проект Visual Studio версий 2003-2010. Нужен, чтобы взять оттуда список "исходников" вашего проекта.
  • .lst - альтернативный способ задать список исходников простым перечислением в текстовом файле.
  • .loc (первый) - файл эталонной (английской) локализации в формате:
    идентификатор_строки=содержимое
    идентификатор_строки=содержимое
    ...
    строки (в обычном формате C/C++ со всякими \n, \r только без обрамляющих кавычек).
  • .loc (последующие) - файлы локализации на других языках. Они будут синхронизированы с эталоном, все новые строки, нуждающиеся в переводе, будут помечены маркером /!TRANSLATE!/.
  • .cpp - этот файл надо будет добавить в свой проект, когда утилита его сгенерирует, в нем определены идентификаторы строк.
  • .bin (первый) - этот файл надо будет положить где-то рядом с готовой программой, или упаковать в ресурсы. В нем окажутся сгенерированы сами локализованные строки, которые будут подгружаться на runtime.
  • .bin (последующие) - если есть еще файлы с расширением .bin, то считается, что они соответствуют локализациям на других языках.

После того, как вы вызвали локализатор в первый раз, в исходном коде проекта произойдут изменения. Вместо литералов вида

LS"this string"
появятся указатели типа (const char *) вида
LS__this_string
и объявления вида
extern const char *LS__this_string;

Теперь добавьте в проект сгенерированный файл interval_loc.cpp, и еще файлы загрузчика (в архиве они в папке loaders). Всего в проект надо добавить три файла - два *.cpp и один *.h.

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

#include "localizer.h"
...
static Localizer localizer;
...
extern const char **LS_all[];
if (!localizer.load("interval_loc.bin", LS_all))
    (обработка ошибки)

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

После этого вы можете время от времени переводить строки в *.loc-файлах (в дополнительных, в эталонном переводить не надо) и запускать локализатор с теми же параметрами. Также вы можете добавлять в программу новые модули, помечать в них строки префиксом, и при очередном запуске локализатора эти строки будут извлечены и распределены по файлам локализации.

Рекомендуется такой порядок действий. Сначала программируете как обычно, в кавычках пишете текст на английском и помечаете префиксом то, что потребует перевода. Когда таких строк накопится много, вызываете локализатор. Потом смотрите в .loc файлы и переводите все, что помечено маркером /!TRANSLATE!/, убирая маркеры. Потом еще раз запускаете локализатор и компилируете проект.

Вот и весь "быстрый старт". Дальше идут детали и подробности.

Синтаксис командной строки

В общем случае вызов локализатора имеет вид:

  
путь\localizer.exe [опции] команда [префикс] [список исходников] [прочие файлы]

Все опции начинаются с символа "-", они немного изменяют порядок исполнения команды. Полный список опций здесь.

Команда начинается с символа "-", она обязательна и только одна. Ниже перечислены все команды с уточнением их синтаксиса.

О префиксе написано здесь.

[список исходников] - это список тех файлов вашей программы, которые подлежат локализации. Список исходников формируется серией операторов, начинающихся с символов "+", "-" и "=". Как только встречается аргумент без такого символа в начале, считается, что [список исходников] кончился и начались [прочие файлы].

Операторы

  • +... добавляют в список исходников новые файлы,
  • -... исключают из списка,
  • =... сохраняют список в файле на диске (если хочется проверить его правильность).

После значка + или - может стоять:

  • Обычный файл с путем или без, например: +my.cpp
  • Маска файлов с путем или без, например: +D:\ExtProject\Includes\*.h
  • Файл с расширением .lst, например: +D:\ExtProject\files.lst
    - в этом случае список путей берется из того файла. Предполагается, что это обычный текстовый файл, на каждой строке один путь. Если там пути не абсолютные, то они считаются от того места, где лежит .lst файл.
  • Файл с расширением .vcproj или .vcxproj, например: +D:\ExtProject\my.vcxproj
    - этот файл полагается файлом проекта Visual Studio. Он разбирается, и файлы оттуда добавляются в список. Если там пути не абсолютные, то они считаются от того места, где лежит файл проекта.

Между значком +/-/= и именем файла не должно быть пробела. А перед значком пробел должен быть. Комбинируя операторы, можно составлять очень сложные списки, объединяя много разных частей проекта.

Список команд

Смысл каждой команды подробно поясняется в последующих разделах.

    localizer.exe [опции] -auto префикс [список исходников] cpp_файл
      текстовый_файл_локализации текстовый_файл_локализации... bin_файл bin_файл...
    - основная команда. Комбинирует эффекты команд list, get, put, cpp, bin и merge.
    localizer.exe [опции] -list [список исходников]
    - проверяет список исходников.
    localizer.exe [опции] -mark префикс [список исходников]
    - выполняет автоматическую расстановку маркеров локализации в проекте, который ранее не локализовался.
    localizer.exe [опции] -get префикс [список исходников] текстовый_файл_локализации
    - сканирует исходники, собирает маркированные строки в текстовый файл.
    localizer.exe [опции] -put префикс [список исходников] текстовый_файл_локализации
    - плюс к тому модифицирует исходники, заменяя маркированные строки.
    localizer.exe [опции] -puttest префикс [список исходников] текстовый_файл_локализации
    - для очень осторожных: вместо модификации исходных файлов создает их варианты с расширением .rez.
    localizer.exe [опции] -cpp префикс текстовый_файл_локализации cpp_файл
    - создает cpp-файл для включения в проект.
    localizer.exe [опции] -bin текстовый_файл_локализации bin_файл
    - создает bin-файл для включения в дистрибутив или ресурсы.
    localizer.exe [опции] -test bin_файл
    - показывает содержимое bin-файла в читаемом виде.
    localizer.exe [опции] -merge текстовый_файл_локализации текстовый_файл_локализации...
    - обновляет файлы локализаций на других языках по первому файлу как эталону.

Префикс

Префикс - это короткий идентификатор, например, дальше для определенности используется префикс LS. По префиксу локализатор распознает локализованные строки и строки, подлежащие локализации.

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

Префикс должен быть объявлен где-нибудь в общем хэдере как пустой define:

#define LS

Файлы

Следующие файлы используются для локализатора.

[proj]. Файл проекта vcproj или vcxproj. Нужен для того, чтобы извлечь из него список исходников, подлежащих анализу. Локализатор понимает проекты Visual Studio версий 2003, 2005, 2008, 2010.

[lst]. Список файлов, подлежащих анализу (просто имена файлов, каждый на отдельной строке). Расширение .lst.

[src]. Исходные файлы проекта. Обычные исходники, в которых могут быть локализованные строки. Локализатор сканирует такие файлы, а их имена берет из [lst] или [proj].

[loc]. Главный файл локализации. Расширение .loc. Этот файл содержит идентификаторы локализованных строк и их содержимое. Допускается два вида таких файлов: в формате "raw" и в формате "escape". подробнее см. здесь.

[loc+]. Дополнительный файл локализации. Расширение .loc. Все аналогично [loc], но содержимое строк идет на другом языке (перевод). Идентификаторы переводить нельзя. Дополнительные файлы локализации получаются из [loc] и затем синхронизируются с ним.

[cpp]. cpp-файл локализации. Расширение .cpp. Этот файл содержит все локализованные строки - по отдельности и списком. Его надо включить в проект. Для всех языков применяется один и тот же cpp-файл локализации.

[bin]. Бинарный файл локализации. Расширение .bin. В нем находится содержимое строк. Для каждого языка - свой [bin]. Бинарый файл должен соответствовать [cpp], порядок строк и количество строк в нем те же самые. подробнее см. здесь.

Формат loc-файла

Формат "raw":

/комментарий
идентификатор
содержимое
/END/
/комментарий
идентификатор
содержимое
/END/
...

Формат "escape":

/комментарий
идентификатор=содержимое
/комментарий
идентификатор=содержимое
...

При желании в одном файле локализации можно смешивать строки в обоих форматах.

Идентификатор - это последовательность символов, среди которых могут быть латинские буквы, цифры и знак подчеркивания. Последовательность может начинаться с цифры. Внутри программы к этим идентификаторам добавляется префикс и два знака подчеркивания. Например, идентификатор 'OK' превращается в 'LS__OK'.

Содержимое - произвольная строка.

Для формата "raw" здесь допускаются любые символы, включая '\0', переводы строк и прочее. Строка "\r\n/END/\r\n" - признак конца содержимого, такая строка не может присутствовать в содержимом.

Для формата "escape" содержимое строки кодируется обычной C/C++ строкой с применением escape-символа "\". Обрамляющие кавычки не нужны, пробелы вокруг разделителя "=" оставлять не следует. Для многострочного содержимого можно использовать знак \ в конце строки (как в обычном исходнике на C/C++).

При загрузке в конец каждой строки будет добавлен еще один символ '\0', так что вручную этого делать не нужно.

Комментарий - необязательная строка комментария. Каждая строка может сопровождаться одним комметарием перед ней. Также программа может генерировать специальные комментарии вида:

/!текст!/

Главный файл локализации должен содержать содержимое локализованных строк для базового языка. Очень желательно, чтобы базовым языком был английский. Тогда локализатор сможет автоматически сгенерировать осмысленные идентификаторы, приемлемые с точки зрения синтаксиса C++. Также можно использовать русский язык в кодировке Windows-1251, в этом случае идентификаторы будут сгенерированы с применением транслита.

Формат bin-файла

Формат:

DWORD N - число строк 
DWORD SZ - длина блока строк 
DWORD OFFSET[N] - блок смещений 
 - смещение каждой из N строк в блоке строк относительно начала блока 
BYTE  DATA[SZ] - блок строк

Для всех чисел порядок байт x86 (старший байт-старший адрес).

Локализованная строка

Локализованная строка - это просто указатель const char *, с которым работают как обычно. При запуске программы локализованные строки загружаются из [bin], и каждый указатель настраиваются на нужную точку в памяти. Конкретнее из [bin] в память грузится 'блок строк', а j-й указатель настраивается на адрес: DATA + OFFSET[j]

Имена локализованных строк имеют вид: <префикс>__<идентификатор> Например: LS__OK, LS__It_is_a__0.

Массив локализованных строк

Это статический массив указателей на указатели на локализованные строки. Он имеет тип const char **[] и используется только один раз - при загрузке локализации на старте программы.

Его имя имеет вид: <префикс>_all.

Например: LS_all.

Определен в [cpp].

Определение локализованных строк

Все локализованные строки данной локализации определены в [cpp]. Этот файл надо включить в проект. В том же файле определен и массив локализованных строк.

Объявление (декларация) локализованных строк

Было решено отказаться от какого-либо хэдера, где перечислены имена локализованных строк. Такой хэдер пришлось бы включать во многие файлы и малейшие изменения в нем приводили бы к перекомпилированию значительной части проекта. Вместо этого используются объявления 'extern' в каждом файле, но их не надо добавлять вручную, это делает локализатор. Единственное (и однократное) исключение - объявление массива локализованных строк перед вызовом Localizer::load (см. ниже).

Строки, подлежащие локализации

Имеют вид: <префикс><литерал>

Например: LS"OK"

Таким методом надо отметить те строки, которые подлежат локализации. Если у вас есть старый проект, где много таких строк, то расстановку префисков можно выполнить автоматизированно командой localizer -mark.

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

Если в проекте есть несколько частей, для каждой из которых свой модуль локализации, то надо сделать разные префиксы для них.

Загрузка локализации приложения

Локализация собственной программы загружается через объект Localizer, функцию load. В папке loaders есть несколько вариантов загрузчиков:

  • Localizer для ANSI проекта,
  • WLocalizer для Unicode,
  • QLocalizer для Qt (опция -qt),
  • Q8Localizer для Qt (опция -qt8),
  • RLocalizer для загрузки из ресурсов.

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

1-й параметр функции - имя бинарного файла локализации (для RLocalizer - целочисленный идентификатор ресурса).

2-й параметр функции - массив локализованных строк (упоминается выше и см. пример ниже).

Возвращаемое значение - true при успехе, false при ошибке. Вызов load надо поместить в начало программы.

Пример:

#include "localizer.h"
...
static Localizer localizer;
...
extern const char **LS_all[];
if (!localizer.load("interval_loc.bin", LS_all))
{
	printf("Error of localization.\n")
    return -1;
}

В этом примере программа использует локализацию с префиксом LS и загружает ее из файла interval_loc.bin.

Автоматизация процесса локализации по шагам

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

Шаг 0. Добавить localizer.cpp и localizer.h в проект.

Шаг 1. Придумать уникальный префикс, который будет идентифицировать локализацию. Выберите короткий префикс, т.к. его придется писать много раз. Но это должен быть уникальный идентификатор, который не используется в программе.

Шаг 2. Определить префикс. Например:

#define LS

Эту директиву надо вставить в какой-то хэдер, желательно 'precompiled'.

Составление списка файлов, подлежащих локализации

Шаг 3. Теперь надо составить список файлов, подлежащих локализации. В список должны войти все файлы проекта, где встречается или может встретиться в будущем метка LS. Список можно составить вручную или автоматически.

Можно использовать стандартную команду dir, чтобы создать файл со списком, например:

dir /B *.cpp >my.lst
dir /B *.h >>my.lst
dir /B *.hpp >>my.lst

Но лучше использовать файл проекта .vcproj или .vcxproj. Тогда в список не попадут случайные файлы, которые находятся в папке, но не относятся к проекту, либо в проекте, но исключены из сборки.

Пример вызова локализатора для составления списка:

localizer.exe -list +greenwin.vcproj =greenwin.lst

Файл greenwin.lst здесь - необязательный параметр, просто если хотите посмотреть, какие файлы попадут в обработку.

Шаг 4. Указать строки, подлежащие локализации. Надо выполнить поиск литералов по всем файлам проекта (например, по символу кавычки) и отметить префиксом все литералы, которые надо локализовать. Конечно, можно отметить так вообще все строки, но это излишне. Следует отмечать только те строки, которые могут выглядеть по-разному на разных языках.

Процесс можно ускорить, применив локализатор:

localizer.exe -mark LS +greenwin.vcproj

При этом префиксы будут автоматически расставлены перед всеми строками, содержащими латинские буквы, и останется только удалить лишнее.

Создание главного файла локализации

Шаг 5. Создание главного файла локализации:

localizer.exe -get LS +greenwin.vcproj greenwin.eng.loc

На этом этапе происходит анализ исходников и сбор строк, подлежащих локализации в главный файл локализации (в данном случае greenwin.eng.loc). Весь процесс полностью автоматический.

Возможны следующие ситуации:

- Главный файл локализации еще не создан. Тогда он считается пустым и создается заново.

- Главный файл локализации уже есть. Тогда его содержимое загружается и сравнивается с результатами сканирования.

- При сканировании обнаружена уже локализованная строка, которой нет в файле локализации. Например, встречается идентификатор LS__OK. Локализатор выдаст предупреждение об этом. Причиной может быть то, что была взята устаревшая версия исходника, где такая строка еще использовалась. Желательно избавиться от таких идентификаторов.

- При сканировании обнаружена уже локализованная строка, которая есть в файле локализации. Это нормальная ситуация. Значит, файл уже локализовывался раньше, и содержимое строки хранится в greenwin.eng.loc.

- При сканировании обнаружена строка, подлежащая локализации. Ее содержимое эквивалентно одной из строк в greenwin.eng.loc. Это нормальная ситуация. Для всех одинаковых строк используется одно хранилище, так что эта строка просто будет ссылаться на существующую строку, и для нее будет использован тот же идентификатор.

- При сканировании обнаружена строка, подлежащая локализации. Ее содержимое не похоже ни на одну из строк в greenwin.eng.loc. Это нормальная ситуация. Для такой строки будет автоматически сгенерирован уникальный идентификатор (по буквам и цифрам из начала строки) и ее содержимое будет сохранено в greenwin.eng.loc.

- В greenwin.eng.loc есть строка, которая не упоминается в проекте, и ни одна из строк, подлежащих локализации, не содержит такого текста. Причина может быть связана с тем, что эта строка была найдена раньше, но с тех пор файл, из которого она была взята, был удален. Или был удален фрагмент текста, откуда она взята. Такие строки должны быть удалены из greenwin.eng.loc, чтобы не занимать лишнее место. Будет выдано предупреждение о том, что строка удалена. В файле greenwin.eng.loc перед этой строкой появится комментарий /!REMOVE!/. Удалите ее оттуда вручную или запустите localizer с опцией -remove. По-умолчанию такие строки не удаляются из greenwin.eng.loc - на тот случай, а вдруг вы отредактируете файл обратно, и в нем снова появится этот идентификатор. Такие строки не будут загружаться в память во время исполнения.

Шаг 6. Корректировка главного файла локализации.

Теперь вы можете внести в greenwin.eng.loc ручные исправления, если они нужны. В основном это имеет смысл для автоматически сгенерированных идентификаторов - если они недостаточно "красивы". Если данный идентификатор уже используется в программе, его надо исправить и в исходниках. При исправлении соблюдайте уникальность идентификаторов, иначе программа выдаст ошибку. А вот сортировку можно не делать, она будет восстановлена при очередном вызове локализатора.

Локализация строк

Шаг 7. Локализация строк

localizer.exe -put LS +greenwin.vcproj greenwin.eng.loc

На этом этапе происходит модификация исходников программы. Все строки, подлежащие локализации, вида LS"..." заменяются на указатели вида LS__... Кроме того, в каждый файл, где есть такие строки, добавляется их объявление вида:

/*--LOCALIZER DECLARATIONS--  Localizer: LS --BEGIN-- */
extern const char 
	*LS__..., *LS__...;
/*--LOCALIZER DECLARATIONS--  Localizer: LS --END-- */

Эти объявления генерируются автоматически и автоматически поддерживаются в правильном состоянии при каждом вызове localizer.exe -put... Место для таких деклараций также подбирается автоматически - перед первой функцией или объявлением, но после первоначальных комментариев, пустых строк и директив (вроде #include). Если вас не удовлетворяет автоматически выбранное место, этот кусок кода можно переместить ниже или выше, и последующие вызовы localizer.exe -put... станут писать декларации именно туда.

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

Вместо -put можно использовать команду -puttest, тогда исходные файлы не будут изменены, а вместо них будут сгенерированы файлы с расширением .rez. Это может пригодиться, если вы не хотите пока локализовать проект, но хотите посмотреть, что получится в результате генерации.

Шаг 8. Компиляция программы

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

static char mystring[]= LS"mystring";
- превращается в:
static char mystring[]= LS__mystring; 
- и это compile error.

Для исправления эта строка просто убирается, и везде вместо mystring пишется LS__mystring.

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

Учтите, что локализация загружается в момент исполнения Localizer::load из функции main/WinMain/DllMain (или где вы там вставите вызов). Не следует использовать локализованные строки в статических объектах, которые создаются до вызова Localizer::load, поскольку в момент создания статических объектов все локализованные строки указывают на "". Однако можно инициализировать статические объекты указателями на указатели локализованных строк, которые не изменятся.

Например, пусть дана локализованная строка с идентификатором OK и содержимым "&OK". Это значит, что:

- В исходнике определен указатель:

extern const char *LS__OK;

- В файле локализации есть фрагмент:

OK=&OK

Сначала указатель LS__OK указывает на "", но после загрузки локализации будет указывать на строку "&OK". В статическом объекте можно сохранить &LS__OK, а потом сделать разыменование указателя, когда локализация уже загружена.

Другой случай:

struct SomeClass
{
   char *text;
   int id;
};
static SomeClass bups = {LS"blin", 12 };
- превращается в:
static SomeClass bups = {LS__blin, 12 };
- и это неприятно, поскольку указатель LS__blin инициализируется слишком поздно.

Это исправляется так:

struct SomeClass
{
   char **text;
   int id;
};
static SomeClass bups = {&LS__blin, 12 };

Генерация cpp-модуля

Шаг 9. Генерация cpp-модуля.

Для успешной линковки не хватает сгенерированного [cpp] файла. Сгенерируйте его:

localizer.exe -cpp LS greenwin.eng.loc greenwin_loc.cpp

Добавьте этот файл в проект. Теперь линковка должна пройти нормально.

Генерация bin-модуля

Шаг 10. Генерация бинарного файла.

localizer.exe -bin greenwin.eng.loc greenwin.eng.bin

Этот [bin]-файл надо добавить в дистрибутив. В установленной программе он должен находиться где-то рядом с исполняемым файлом, чтобы программа могла его найти и загрузить вызовом Localizer::load.

Шаг 11. Загрузка локализации

Теперь нужно добавить в программу код загрузки локализованных строк. Пример уже приводился выше:

#include "localizer.h"
...
static Localizer localizer;
...
extern const char **LS_all[];
if (!localizer.load("greenwin.eng.bin", LS_all))
    throw GInitException();

В общем, надо где-то определить объект Localizer и вызвать у него функцию load. На вход дается имя [bin]-файла и массив вида префикс_all, который определен в сгенерированном [cpp]-файле.

Шаг 12. Отладка

После этого локализованная программа готова к запуску. Убедитесь, что все работает.

Обновления

Шаг 13. Обновление локализации.

Все упомянутые команды можно объединить в одну:

localizer.exe -auto LS +greenwin.vcproj greenwin.eng.loc greenwin_loc.cpp greenwin.eng.bin

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

Перевод

Шаг 14. Перевод на другие языки.

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

Шаг 15. Изменение языка программы.

Допустим, вы создали вариант greenwin.rus.loc, где все строки переведены на русский. Для него понадобится соответствующий бинарный файл, допустим, greenwin.rus.bin. Добавьте эти файлы в обычный вызов локализатора:

localizer.exe -auto LS +greenwin.vcproj greenwin_loc.cpp 
   greenwin.eng.loc greenwin.rus.loc greenwin.eng.bin greenwin.rus.bin

Потом надо либо заменить этим greenwin.rus.bin прежний файл greenwin.eng.bin, либо модифицировать загрузку локализации так, чтобы загружался один из bin-модулей в зависимости от нужного языка.

Синхронизация обновлений

Шаг 16. Синхронизация обновлений

Если программа изменилась и, как следствие, изменился главный файл локализации [loc], тогда и переводы тоже должны измениться соответственно. Тот же самый вызов произведет и синхронизацию переводов. При желании это можно делать отдельной командой -merge:

localizer.exe -merge greenwin.eng.loc greenwin.rus.loc

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

Все идентификаторы, которые есть в главном файле, но которых нет в переведенном, будут добавлены в переведенный, и их надо будет перевести. Для облегчения поиска таких мест, перед идентификатором будет добавлен комментарий /!TRANSLATE!/

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

После этого надо перегенерировать bin-модуль для этого языка (все тем же универсальным вызовом localizer -auto или специальной командой localizer -bin).

Программа без двоичного файла

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

Но может возникнуть желание игнорировать отсутствие файла локализации и работать нормально. В этом случае надо добавить опцию "-default" перед командой "-auto" или "-cpp". В результате в файл cpp будут записаны все строки из [loc]. Всем переменным будут присвоены строки "по умолчанию" из главного [loc]. Тогда ошибку загрузки файла локализации можно просто игнорировать и продолжать исполнение программы с этими строками.

Дополнительные опции

Дополнительные опции можно указывать перед командой в любом порядке:

  • "-backup". Каждый раз, когда программа меняет файл локализации ([loc], [loc+]), она будет создавать его страховочную копию с расширением .bak.
  • "-verbose". Опция включает более подробные сообщения.
  • "-remove". Опция удаляет из файла локализации все строки, которые больше не используются в исходниках. Если не выставить эту опцию, тогда все подобные строки будут помечены комментарием /!REMOVE!/, и вам надо будет удалить их вручную. По-умолчанию эта опция отключена, чтобы избежать случайного удаления строк.
  • "-rawout". Записывает все строки в "raw"-формате. По-умолчанию строки записываются в том формате, в котором были изначально.
  • "-escout". Записывает все строки в "escape"-формате. По-умолчанию строки записываются в том формате, в котором были изначально.
  • "-raw". Создает новые строки в "raw"-формате. По-умолчанию новые строки создаются в "escape"-формате.
  • "-default". Записывает в [cpp] не только идентификаторы строк, но и их содержимое для главного файла локализации. Это позволяет запускать программу без ошибок даже при отсутствии файла локализации. Размер исполняемого файла программы при этом немного увеличивается (приблизительно на размер строк).
  • "-regenid". Работает только с командой -auto. Запускает процесс генерации идентификаторов строк заново. Эта опция может быть полезна для тех, кто любит содержать код в идеальном порядке. Если какие-то строки были удалены или изменены, то первоначально сгенерированные идентификаторы могут не совсем соответствовать содержимому строк, также в нумерации похожих строк могут возникнуть пропуски.
        При запуске локализатор постарается оптимизировать идентификаторы и корректно исправить их в файлах локализации и в исходниках. Поскольку эта опция может затронуть сразу множество файлов, рекомендуется сделать страховочную копию проекта перед ее запуском. Настоятельно рекомендуется указывать в командной строке все файлы локализации, чтобы не произошло их рассинхронизации.
  • "-nosplit". По-умолчанию в "escape"-формате тексты, содержащие символ \n, разбиваются на несколько строк для удобочитаемости файлов локализации ([loc], [loc+]). Если разбиение нежелательно и надо, чтобы все сливалось в одну длинную строку, надо указать эту опцию.
  • "-config конфигурация". Если в вашем проекте Visual Studio имеется несколько конфигураций (Debug, Release) и для каждой конфигурации используются разные наборы файлов (с помощью опции Exclude From Build), то эта опция позволит вам по-разному обрабатывать разные конфигурации.
  • "-unicode". Используется для unicode-проектов (16-битный Unicode). Файлы локализации [loc+] должны быть в кодировке UTF-8, а загруженные строки будут иметь тип extern const wchar_t*.
  • "-qt". Используется для QT-проектов. Файлы локализации [loc+] должны быть в кодировке UTF-8, а загруженные строки будут иметь тип extern QString. Создает [bin] в 16-битном Unicode.
  • "-qt8". Используется для QT-проектов. Подобен предыдущему, но создает [bin] в кодировке UTF-8. Загрузка может быть чуть дольше, зато совместимо с UNIX-системами, где Unicode не 16-битный.
  • "-remdups". Если в файлах локализации обнаруживаются одинаковые идентификаторы, они корректно объединяются, и "лишние" помечаюся на удаление.
  • "-()". Действует для команды -mark. Генерирует строки вида LCL("строка") вместо LCL"строка".
  • "-prepend". Добавляет в начало [cpp]-файла строку. Обычно это имеет смысл для включения PCH-хэдера, например:
    -prepend #include""my_pch.h""
  • "-append". Аналогично добавляет строку в конце.

Загрузка локализации из ресурсов

Локализованные строки можно хранить и непосредственно в exe-файле, а при запуске программы загружать их оттуда. Вот порядок действий для такого проекта.

1. В ресурсном хэдере (это обычно файл с расширением .rh) добавьте идентификаторы для ресурсов. Что-нибудь вроде:

#define IDLOC_ENGLISH      4000
#define IDLOC_RUSSIAN      4001

2. В ресурсном файле (это обычно файл с расширением .rc) добавьте ресурсы с указанием [bin]-файлов локализации. Что-нибудь вроде:

IDLOC_ENGLISH     BINARY  "interval_loc.bin"
IDLOC_RUSSIAN     BINARY  "interval_loc.rus.bin"

3. Для загрузки/выгрузки нужной локализации используйте загрузчик RLocalizer и примерно такой код:

#include "rlocalizer.h"
#include "resource.rh"
...
static RLocalizer localizer;
...
extern const char **LS_all[];
if (!localizer.load(IDLOC_RUSSIAN, LS_all))
  (обработка ошибки)

Локализация Unicode

При локализации Unicode проектов имеются следующие отличия:

  1. При вызове локализатора надо использовать опцию -unicode.
  2. Файлы локализации [loc+] должны быть в кодировке UTF-8.
  3. Загруженные строки будут иметь тип const wchar_t*.
  4. Надо использовать загрузчик WLocalizer.
  5. Исходные файлы должны быть в кодировке ANSI или UTF-8.
  6. Локализуемые строки в исходниках надо набирать в ANSI или UTF-8, помечать префиксом и сразу запускать локализатор. Либо помечать префиксом L и позднее заменять префикс L на префикс локализатора. Не используйте для таких строк специфический для unicode синтаксис.

Локализация Qt

При локализации Qt проектов имеются следующие отличия:

  1. При вызове локализатора надо использовать опцию -qt8 или -qt.
  2. Файлы локализации [loc+] должны быть в кодировке UTF-8.
  3. Загруженные строки будут иметь тип QString.
  4. Надо использовать загрузчик QLocalizer.
  5. Исходные файлы должны быть в кодировке ANSI или UTF-8.
  6. Локализуемые строки в исходниках надо набирать в ANSI или UTF-8, помечать префиксом и сразу запускать локализатор. Не используйте для таких строк специфический для unicode синтаксис.

Замена префикса

Если есть желание заменить префикс, можно использовать соответствующую команду:

localizer -prefix LS LSN +interval.vcproj

Здесь LS - старый префикс, LSN - новый, далее идет список файлов, которые надо просканировать.

Объединение и разделение проектов

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

  1. Проведите обычное разделение без учета локализации.
  2. Исправьте скрипты или .bat-файлы локализации с учетом того, что могли измениться каталоги, названия проектов, список исходников.
  3. Если хочется для второго проекта использовать другой префикс, используйте команду "localizer -prefix...", чтобы не изменять префиксы в исходниках вручную.
  4. Все .loc файлы просто продублируйте в двух экземплярах под оба проекта.
  5. Теперь запустите локализацию для каждого проекта. Поскольку все строки в них продублированы, то окажется, что первый проект теперь не использует некоторые строки второго проекта, а второй - некоторые строки из первого. Все "лишние" строки будут помечены комментарием "/!REMOVE!/". Их можно удалить, запустив локализацию с опцией "-remove" или вручную.

Допустим теперь, что у вас есть два проекта, которые вы хотите объединить, в том числе объединить и локализации. Для этого:

  1. Проведите обычное объединение без учета локализации.
  2. Исправьте скрипты или .bat-файлы локализации с учетом того, что могли измениться каталоги, названия проектов, список исходников.
  3. Если проекты использовали разные префиксы, используйте команду "localizer -prefix...", чтобы автоматически заменить перфиксы в исходниках на один общий префикс.
  4. Все .loc файлы просто объедините копированием (например, с помощью команды "copy" со значком "+").
  5. Теперь запустите локализацию для каждого проекта. Может обнаружиться, что некоторые идентификаторы строки повторяются. Запустите локализатор с опцией "-remdups", чтобы выполнить объединение таких идентификаторов.