<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>http://lorwiki.zhbert.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F</id>
	<title>Локализация - История изменений</title>
	<link rel="self" type="application/atom+xml" href="http://lorwiki.zhbert.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F"/>
	<link rel="alternate" type="text/html" href="http://lorwiki.zhbert.ru/index.php?title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;action=history"/>
	<updated>2026-10-12T23:42:28Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.39.0</generator>
	<entry>
		<id>http://lorwiki.zhbert.ru/index.php?title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=307&amp;oldid=prev</id>
		<title>Admin: 1 версия импортирована</title>
		<link rel="alternate" type="text/html" href="http://lorwiki.zhbert.ru/index.php?title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=307&amp;oldid=prev"/>
		<updated>2023-02-27T18:39:17Z</updated>

		<summary type="html">&lt;p&gt;1 версия импортирована&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 21:39, 27 февраля 2023&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://lorwiki.zhbert.ru/index.php?title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=306&amp;oldid=prev</id>
		<title>lor&gt;Cetjs2: Откат правок Abc123456 (обсуждение) к версии Mandala</title>
		<link rel="alternate" type="text/html" href="http://lorwiki.zhbert.ru/index.php?title=%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&amp;diff=306&amp;oldid=prev"/>
		<updated>2018-05-04T11:14:02Z</updated>

		<summary type="html">&lt;p&gt;Откат правок &lt;a href=&quot;/index.php/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Abc123456&quot; title=&quot;Служебная:Вклад/Abc123456&quot;&gt;Abc123456&lt;/a&gt; (&lt;a href=&quot;/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Abc123456&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Обсуждение участника:Abc123456 (страница не существует)&quot;&gt;обсуждение&lt;/a&gt;) к версии &lt;a href=&quot;/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Mandala&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Участник:Mandala (страница не существует)&quot;&gt;Mandala&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Существует множество способов локализации своих приложений. Наиболее распространенным является использование &amp;lt;code&amp;gt;gettext&amp;lt;/code&amp;gt;, но бывают случаи, когда необходим более простой способ локализации, когда перевод &amp;quot;вшит&amp;quot; в бинарник (и когда языков немного).&lt;br /&gt;
== Статическая локализация ==&lt;br /&gt;
Для локализации простого двуязычного приложения (например, CGI) можно использовать статическую локализацию.&lt;br /&gt;
Суть такой локализации в том, что заранее отдельно создаются строковые массивы, содержащие фразу на обоих языках. В зависимости от языка пользователя из массива выбирается фраза с нужным индексом.&lt;br /&gt;
&lt;br /&gt;
Определим макросы &amp;lt;tt&amp;gt;_LANG&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;_L&amp;lt;/tt&amp;gt;, которые позволяют выбрать нужный текст в зависимости от текущего языка. Язык определяется переменной &amp;lt;tt&amp;gt;Lang&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
#define		_LANG(_var, _ru, _en)	char _var##ru[] = _ru;\&lt;br /&gt;
					char _var##en[] = _en;\&lt;br /&gt;
					char *_var[2] = {_var##ru,  _var##en};&lt;br /&gt;
#define		_L(x)	(x[Lang])&lt;br /&gt;
unsigned char Lang = 1; // по умолчанию - английский&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Макрос &amp;lt;tt&amp;gt;_LANG&amp;lt;/tt&amp;gt; инициализирует очередной массив с именем &amp;lt;tt&amp;gt;_var&amp;lt;/tt&amp;gt; двумя строками - следующими аргументами. Чтобы вывести нужный текст, используется макрос &amp;lt;tt&amp;gt;_L&amp;lt;/tt&amp;gt;, который просто выводит нужную строку из массива, в зависимости от языка.&lt;br /&gt;
Вот пример использования этого метода:&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
char *ptr = getenv(&amp;quot;HTTP_ACCEPT_LANGUAGE&amp;quot;);&lt;br /&gt;
if(ptr &amp;amp;&amp;amp; strncmp(ptr, &amp;quot;ru&amp;quot;, 2) == 0) Lang = 0;&lt;br /&gt;
...&lt;br /&gt;
printf(&amp;quot;%s:&amp;lt;input ... &amp;gt;\n&amp;quot;, _L(_s_Name_));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Отдельно необходимо будет заполнить массив с фразами на русском и английском языке:&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
_LANG(_s_Name_, &amp;quot;Ваше имя&amp;quot;, &amp;quot;Your name&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Достоинства этого метода: в одном бинарнике содержится все, т.е. меньше шансов при переносе CGI из одного хранилища в другое &amp;quot;потерять&amp;quot; локализацию. Минусы тоже очевидны: приходится отдельно подготавливать строковые массивы, а в месте использования правильно указать название массива. Еще один минус: для добавления еще одного языка придется править исходники и перекомпилировать приложение.&lt;br /&gt;
&lt;br /&gt;
== Динамическая локализация ==&lt;br /&gt;
Gettext - стандартный способ локализации. В отличие от статической локализации он требует наличия еще как минимум одного дополнительного файла (mo-файл), в котором содержится база данных локализации для функции &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;. Т.к. локализация лежит отдельно, ее всегда можно подправить, не влезая в нутро исходников программы.&lt;br /&gt;
Однако, при работе с &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;'ом выбор нужной фразы производится в реальном времени: для отображения фразы в соответствии с настройками локали, в базе данных для текущей локали ищется английская фраза (запакованная в макрос &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;). Если есть фраза на нужном языке, она выводится &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;'ом, иначе - отображается фраза на английском.&lt;br /&gt;
&lt;br /&gt;
Средства работы с &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt; автоматизированы: утилита &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt; выбирает из исходников нужные фразы (оформленные определенным макросом) и помещает их в po-файл, а утилита &amp;lt;code&amp;gt;poedit&amp;lt;/code&amp;gt; позволяет редактировать po-файлы (кроме того, их можно редактировать вручную).&lt;br /&gt;
&lt;br /&gt;
База данных (mo-файл) для каждой локали формируется при помощи утилиты msgfmt из текстового po-файла (который, кстати, тоже отдельный для каждой локали). Так как в процессе разработки зачастую приходится к уже имеющемуся po-файлу с переводом добавлять новые фразы, есть удобная утилита msgmerge, добавляющая лишь новые, не переведенные, фразы. Естественно, в &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt; есть макросы для работы с &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;, так что разработчкику все сделать достаточно просто.&lt;br /&gt;
&lt;br /&gt;
Чтобы было удобно работать с &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt;, необходимо определить какие-то простые макросы для &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;, например:&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
#define _(String)				gettext(String)&lt;br /&gt;
#define gettext_noop(String)	String&lt;br /&gt;
#define N_(String)				gettext_noop(String)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В этом случае, например, фраза &amp;lt;code&amp;gt;printf(_(&amp;quot;Capture frame %d\n&amp;quot;), j);&amp;lt;/code&amp;gt; при запуске &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt; с обозначением разделителей как &amp;lt;code&amp;gt;-k_ -kN_&amp;lt;/code&amp;gt; создаст po-файл, в котором будут строки&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
msgid   &amp;quot;Capture frame %d\n&amp;quot;&lt;br /&gt;
msgstr  &amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;msgid&amp;lt;/tt&amp;gt; - идентификатор нашего сообщения (т.е. само сообщение на английском), а &amp;lt;tt&amp;gt;msgstr&amp;lt;/tt&amp;gt; - это же сообщение на другом языке.&lt;br /&gt;
&lt;br /&gt;
Подготовив такой файл, переведя его и сформировав из него при помощи &amp;lt;code&amp;gt;msgfmt&amp;lt;/code&amp;gt; базу данных для нашей локали, мы сможем видеть перевод. Но для этого еще необходимо будет указать &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt;'у, где искать mo-файл. Это делается при помощи функций&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);&lt;br /&gt;
textdomain(GETTEXT_PACKAGE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Макросы &amp;lt;tt&amp;gt;GETTEXT_PACKAGE&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;LOCALEDIR&amp;lt;/tt&amp;gt; определяются обычно при подготовке компиляции (например, тем же &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;). &amp;lt;tt&amp;gt;LOCALEDIR&amp;lt;/tt&amp;gt; - путь к директории, в которой лежат файлы локализации (если мы хотим русифицировать приложение, в директории &amp;lt;tt&amp;gt;LOCALEDIR&amp;lt;/tt&amp;gt; должна быть вложена директория &amp;lt;tt&amp;gt;ru/LC_MESSAGES&amp;lt;/tt&amp;gt;, где &amp;lt;tt&amp;gt;ru&amp;lt;/tt&amp;gt; - нужный нам язык, &amp;lt;tt&amp;gt;LC_MESSAGES&amp;lt;/tt&amp;gt; - сами сообщения (по значению этой переменной и определяется язык, кстати).&lt;br /&gt;
&lt;br /&gt;
Чтобы оформить все это в &amp;lt;tt&amp;gt;CMakeLists.txt&amp;lt;/tt&amp;gt;, достаточно указать, что нам необходимо подключить нужные библиотеки для работы &amp;lt;tt&amp;gt;gettext&amp;lt;/tt&amp;gt; и найти &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt; (если po-файл еще не сформирован):&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
find_package(Gettext REQUIRED)&lt;br /&gt;
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Введем макросы:&lt;br /&gt;
* &amp;lt;tt&amp;gt;PO_FILE&amp;lt;/tt&amp;gt; - po-файл, формируемый &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;tt&amp;gt;RU_FILE&amp;lt;/tt&amp;gt; - переведенный po-файл (в который будут добавляться новые данные при помощи msgmerge);&lt;br /&gt;
* &amp;lt;tt&amp;gt;MO_FILE&amp;lt;/tt&amp;gt; - mo-файл (т.е. сама база данных - только он и нужен в конечном итоге).&lt;br /&gt;
&lt;br /&gt;
Тогда для генерирования po- и mo-файлов &amp;quot;на лету&amp;quot; нам нужно дописать в &amp;lt;tt&amp;gt;CMakeLists.txt&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;code lang=&amp;quot;C&amp;quot;&amp;gt;&amp;lt;pre style=&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;&lt;br /&gt;
add_custom_command(&lt;br /&gt;
	OUTPUT ${PO_FILE}&lt;br /&gt;
	COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=koi8-r ${SOURCES} -c -k_ -kN_ -o ${PO_FILE}&lt;br /&gt;
	COMMAND sed 's/charset=UTF-8/charset=koi8-r/' ${PO_FILE} | enconv &amp;gt; tmp &amp;amp;&amp;amp; mv -f tmp ${PO_FILE}&lt;br /&gt;
	COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE}&lt;br /&gt;
	DEPENDS ${SOURCES})&lt;br /&gt;
add_custom_command(&lt;br /&gt;
	OUTPUT ${MO_FILE}&lt;br /&gt;
	COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE}&lt;br /&gt;
	DEPENDS ${RU_FILE})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
(локаль у меня - КОИ8, поэтому необходимо указать входную локаль для &amp;lt;code&amp;gt;xgettext&amp;lt;/code&amp;gt;'а, а также подкорректировать неправильное отображение локали в формируемом po-файле.&lt;br /&gt;
&lt;br /&gt;
;Облегчение работы переводчика&lt;br /&gt;
:Ключ &amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt; позволяет в po-файл добавлять строку с комментариями, расположенными до строки, где встречается макрос, указанный в аргументе ключа &amp;lt;tt&amp;gt;-k&amp;lt;/tt&amp;gt;. Таким образом, если в комментариях сразу писать перевод на русский язык, можно даже будет автоматизировать создание готового po-файла с переводом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если все выполнить правильно и не забыть скопировать mo-файл по указанному пути, то после запуска приложение должно &amp;quot;заговорить&amp;quot; на родном для вашей локали языке.&lt;/div&gt;</summary>
		<author><name>lor&gt;Cetjs2</name></author>
	</entry>
</feed>