Internationalization (i18n) in C++: From Basics to Advanced Techniques
Internationalization (abbreviated as i18n — from "internationalization", where 18 is the number of letters between the first and last) is the process of designing software so that it can be easily adapted for different languages and regions without making changes to the source code. For the C++ language, which is traditionally used in high-performance and cross-platform applications, proper implementation of i18n is critically important. In this article, we will look at the main approaches, libraries, and practical examples for localizing C++ applications.
Basic Concepts of i18n
Before moving on to the tools, it is important to understand the key concepts:
- Localization (l10n) — adaptation of translated text, date, number, and currency formats for a specific region.
- Locale — a set of rules (language, region, encoding) that defines data formatting.
- Unicode and UTF-8 — a character encoding standard, mandatory for modern internationalization.
- Pluralization — correct display of plural forms (e.g., "1 file", "2 files", "10 files").
The GNU gettext Library for C++
GNU gettext is the most popular tool for internationalization in the Unix/Linux world, which also works excellently with C++. It provides a minimalistic API and powerful utilities for extracting and managing translations.
Installation and Setup
To use gettext in a C++ project, you need to install the libintl package and include the header file:
#include <libintl.h>#include <locale.h>
#define _(STRING) gettext(STRING)Basic Usage Example
#include <iostream>#include <libintl.h>#include <locale.h>
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;}Creating Translation Files
The process involves three steps:
- Extracting strings:
xgettext --keyword=_ main.cpp -o messages.po - Editing the .po file — adding translations manually or via Poedit.
- Compiling into .mo:
msgfmt messages.po -o locale/ru/LC_MESSAGES/myapp.mo
Pluralization Support
Gettext supports plural forms via the ngettext function:
int count = 5;printf(ngettext("%d file deleted", "%d files deleted", count), count);The ICU Library (International Components for Unicode)
ICU is a powerful library from IBM that provides a complete set of tools for internationalization: Unicode support, locale-aware sorting, formatting of numbers, dates, currencies, time zone handling, and much more. For C++, the C++ API from the icu4c package is used.
Installing ICU
On Ubuntu/Debian: sudo apt install libicu-dev
On macOS: brew install icu4c
Formatting Numbers and Dates
#include <unicode/numfmt.h>#include <unicode/datefmt.h>#include <iostream>
int main() { // Formatting a number for the ru_RU locale icu::UnicodeString pattern; icu::NumberFormat* fmt = icu::NumberFormat::createInstance( icu::Locale("ru", "RU"), status); icu::UnicodeString result; fmt->format(1234567.89, result); std::string utf8; result.toUTF8String(utf8); std::cout << "Number: " << utf8 << std::endl; // 1