Overview

Project Goals

gettext-header is a modern C++26 reimplementation of the GNU gettext runtime library (libintl). It provides:

  1. A C++ header-only library — just #include <gettext/gettext.hpp>, no linking required. All functions live in the intl namespace.

  2. A C-compatible shared library (libintl.so) — drop-in replacement for GNU gettext’s libintl.

  3. A C-compatible static library (libintl.a) — for static linking.

  4. A msgfmt replacement — compiles .po files to .mo binary format, replacing the need for GNU gettext tools.

Architecture

The library is structured as:

include/
  gettext/
    gettext.hpp           ← Public C++ API (intl:: namespace)
    detail/
      mo_parser.hpp       ← MO binary file reader
      po_parser.hpp       ← PO text file parser
      plural_eval.hpp     ← Plural-Forms expression evaluator
      catalog.hpp         ← In-memory translation catalog
      locale_resolver.hpp ← Locale/env var resolution
      charset.hpp         ← iconv charset conversion
      mo_writer.hpp       ← MO binary file writer
  libintl.h               ← C API header
src/
  libintl.cpp             ← C API implementation
  msgfmt.cpp              ← msgfmt tool

Data Flow

When intl::gettext("Hello") is called:

  1. The current domain and locale are resolved from global state and environment variables (LANGUAGE, LC_ALL, LC_MESSAGES, LANG).

  2. A .mo file path is constructed: <base_dir>/<locale>/LC_MESSAGES/<domain>.mo

  3. The MO file is loaded into memory and parsed.

  4. The msgid is looked up via hash table or binary search.

  5. For plural forms, the Plural-Forms expression is evaluated.

  6. The translated string is returned, or the original msgid if not found.

License

GNU Affero General Public License v3 (AGPL-3.0).