# Singlang - Lightweight Internationalization (i18n) Library for D ## Description `singlang` integrates GNU Gettext for translations. The module features a singleton `Singlang` class for configuration and a convenient `_()` function for translating messages. ## Installation To use `singlang` in your D project, add it as a dependency in your `dub.json` or `dub.sdl` file: ### dub.json ```json { "dependencies": { "singlang": "~>0.1.0" } } ``` ## Usage ### Initializing the Translation System Before translating messages, you must initialize the `Singlang` class with a domain name and a directory containing translation files (`.mo`): ```d import singlang; void main() { if (Singlang.set("myapp", "/usr/local/share/locale")) { writeln("Translation system ready!"); } else { writeln("Setup failed, check stderr for details!"); } } ``` - `domain`: The name of your application or translation domain. - `localeDir`: The path to the directory containing your `.mo` translation files. ### Translating Messages Use the `_()` function to translate messages: ```d writeln(_("Hello, world!")); // Outputs the translated version of "Hello, world!" if available writeln(_("Error: File not found")); // Outputs translated text or original if unavailable ``` If the system is not initialized or a translation is unavailable, the original message is returned. ## Localization and Build Mechanisms This project includes mechanisms to customize localization environments and automate translation workflows, located in the `preload` and `scripts` directories. Below is a detailed overview of their structure, purpose, and how to leverage them effectively in your project. ### `preload` Directory The `preload` directory provides tools to intercept and customize the `bindtextdomain` function from the GNU Gettext library, allowing you to redirect the path to localization files. #### Structure ``` preload ├── build.sh └── override_bindtextdomain.c ``` #### Files ##### `build.sh` - **Purpose**: Compiles a shared library, `liboverride_bindtextdomain.so`, which intercepts the `bindtextdomain` function to customize localization paths. - **Usage**: ```bash ./preload/build.sh ``` Replace `` with the name of your program (e.g., `myapp`). - **How It Works**: Compiles `override_bindtextdomain.c` into a shared library, `.preload/liboverride_bindtextdomain.so`, defining `PNAME` as a macro. - **Output**: Generates `.preload/liboverride_bindtextdomain.so`, which can be preloaded with `LD_PRELOAD` to override `bindtextdomain` behavior. ##### `override_bindtextdomain.c` - **Purpose**: A C source file that intercepts calls to `bindtextdomain` and redirects the localization path to `build/usr/share/locale` for a specified program name (`PNAME`). - **How It Works**: Checks if the `domainname` matches the predefined `PNAME` (set during compilation). If matched, redirects the localization path to `build/usr/share/locale`. - **Requirements**: The `PNAME` macro must be defined during compilation (via `build.sh`); if undefined, it exits with an error. - **Use Case**: Ideal for projects needing to override default localization paths without modifying the core application code. ### `scripts` Directory The `scripts` directory contains utilities to streamline translation file management, including compiling `.mo` files and generating/updating `.po` files. #### Structure ``` scripts ├── compile_mo.sh └── generate_translations.sh ``` #### Files ##### `generate_translations.sh` - **Purpose**: Automates the creation and updating of `.po` translation files based on D source code in the `source/` directory. - **Usage**: ```bash ./scripts/generate_translations.sh [language] ``` Replace `[language]` with an optional language code (e.g., `ru` or `en`). If omitted, processes `ru` and `en` by default. For help: ```bash ./scripts/generate_translations.sh --help ``` - **How It Works**: 1. Checks for `.d` files in `source/`. 2. Generates or updates `translations/messages.pot` using `xgettext` to extract translatable strings (marked with `_`). 3. For each language: - Creates a new `.po` file with `msginit` if it doesn’t exist. - Updates existing `.po` files with `msgmerge`, preserving prior translations. 4. Deletes the temporary `.pot` file upon completion. - **Example**: ```bash ./scripts/generate_translations.sh ru ``` Creates or updates `translations/ru.po`. - **Requirements**: GNU Gettext tools (`xgettext`, `msgmerge`, `msginit`). - **Output**: Fresh or updated `.po` files in `translations`, ready for translation and compilation into `.mo` files. ##### `compile_mo.sh` - **Purpose**: Compiles `.po` files from the `translations` directory into `.mo` files and generates a `run.sh` script for launching the program with a chosen language. - **Usage**: ```bash ./scripts/compile_mo.sh ``` Replace with the path to your program (e.g., `./build/usr/bin/myapp`). - **How It Works**: 1. Compiles each `.po` file into an `.mo` file, placing them in `build/usr/share/locale//LC_MESSAGES/.mo`. 2. Creates an executable `run.sh` script that: - Accepts a language code (e.g., `ru` or `en`) as an argument. - Validates the language against available `.po` files. - Sets `LANG` and `LD_PRELOAD` environment variables to run the program with the selected localization. - **Example Launch**: ```bash ./run.sh ru ``` Runs the program with Russian localization, preloading `.preload/liboverride_bindtextdomain.so`. - **Output**: Compiled `.mo` files and a `run.sh` script for easy, localized program execution. ### Applying These Mechanisms in Your Project The `preload` mechanism allows overriding localization paths without altering the program’s source code. #### Integration Example with `dub.json` For seamless automation, integrate these mechanisms into your build process using the `"postBuildCommands"` field in `dub.json`, the configuration file for the DUB build tool. Add the following to your `dub.json`: ```json { "postBuildCommands": [ "bash scripts/compile_mo.sh ", "bash preload/build.sh " ] } ``` Replace with the path to your program (e.g., `./build/usr/bin/myapp`). Replace `` with your program’s name (e.g., `myapp`). ##### How It Works: 1. **Build the Project**: Run `dub build` in your project’s root directory. 2. **Post-Build Steps**: - `bash scripts/compile_mo.sh ./build/usr/bin/myapp`: - Compiles `.po` files into `.mo` files, storing them in `build/usr/share/locale//LC_MESSAGES/myapp.mo`. - Generates a `run.sh` script for launching `myapp` with a specified language. - `bash preload/build.sh myapp`: - Compiles `.preload/liboverride_bindtextdomain.so` with `PNAME` set to `myapp`. 3. **Run the Program**: ```bash ./run.sh ru ``` Launches `myapp` with Russian localization, leveraging the preloaded library.