Internationalization (i18n) in C++: A Complete Guide with gettext and ICU

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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:



  1. Extracting strings: xgettext --keyword=_ main.cpp -o messages.po
  2. Editing the .po file — adding translations manually or via Poedit.
  3. 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

Recommendations