Интернационализация (i18n) в C++: от основ до продвинутых техник
Интернационализация (сокращённо i18n — от английского "internationalization", где 18 означает количество букв между первой 'i' и последней 'n') — это процесс проектирования программного обеспечения таким образом, чтобы оно могло быть адаптировано к различным языкам и региональным особенностям без изменения кода. В C++ эта задача имеет свою специфику: язык не предоставляет встроенных средств для работы с переводами, но существует несколько мощных библиотек, которые решают эту проблему.
Почему i18n важна для C++ проектов?
Современные C++ приложения редко ограничиваются одним языком. Десктопные программы, игры, серверные решения — все они требуют поддержки нескольких локалей. Основные проблемы, которые решает i18n:
- Работа с кодировками — переход от ASCII к UTF-8, UTF-16 и другим многобайтовым кодировкам;
- Форматирование чисел, дат и валют — в разных странах используются разные разделители и форматы;
- Порядок слов в предложениях — русский язык требует склонений, а английский — артиклей;
- Плюрализация — правила образования множественного числа различаются (в русском их 3 формы, в английском — 2).
Основные библиотеки для i18n в C++
1. GNU gettext — классика жанра
GNU gettext — самая популярная библиотека для интернационализации в C и C++. Она использует отдельные файлы переводов (.po/.mo) и позволяет изолировать строки от кода.
Базовый пример использования:
#include <iostream>
#include <libintl.h>
#include <locale.h>
#define _(str) gettext(str)
int main() {
setlocale(LC_ALL, "");
bindtextdomain("myapp", "./locale");
textdomain("myapp");
std::cout << _("Hello, world!") << std::endl;
std::cout << _("File not found") << std::endl;
return 0;
}
Для извлечения строк используется утилита xgettext, которая сканирует исходный код и создаёт .pot файл. Затем переводчики работают с .po файлами.
Преимущества:
- Простота интеграции;
- Огромное сообщество и множество инструментов (Poedit, Lokalize);
- Поддержка плюрализации через
ngettext(); - Работает на любой платформе.
Недостатки:
- Не поддерживает контекстные переводы без дополнительных ухищрений;
- Требует отдельного этапа сборки для генерации .mo файлов.
2. Boost.Locale — современный C++ подход
Библиотека Boost.Locale предоставляет более современный и типобезопасный интерфейс. Она построена поверх ICU (International Components for Unicode) или системных локалей.
Пример работы с переводами:
#include <boost/locale.hpp>
#include <iostream>
int main() {
using namespace boost::locale;
generator gen;
std::locale loc = gen("ru_RU.UTF-8");
std::locale::global(loc);
// Создаём переводчик
translator tr;
std::cout << tr("Hello, world!") << std::endl;
std::cout << tr("Today is {1}", "Monday") << std::endl;
// Плюрализация
std::cout << tr("You have {1} message", "You have {1} messages", 5) << std::endl;
return 0;
}
Преимущества:
- Нативная поддержка UTF-8;
- Форматирование дат, чисел и валют;
- Поддержка контекстных переводов;
- Работает с std::string и std::wstring.
Недостатки:
- Зависимость от Boost (тяжеловесная библиотека);
- Меньше инструментов для переводчиков.
3. ICU — промышленный стандарт
ICU (International Components for Unicode) — это мощная библиотека от IBM, которая предоставляет полный набор инструментов для работы с Unicode и локализацией. Она используется в таких проектах, как Chromium, LibreOffice и Android.
Пример работы с сообщениями:
#include <unicode/msgfmt.h>
#include <unicode/locid.h>
#include <iostream