singlang/README.md

185 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 <program_name>
```
Replace `<program_name>` 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 doesnt 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 <program_path>
```
Replace <program_path> 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/<lang>/LC_MESSAGES/<program_name>.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 programs 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 <program_path>",
"bash preload/build.sh <program_name>"
]
}
```
Replace <program_path> with the path to your program (e.g., `./build/usr/bin/myapp`).
Replace `<program_name>` with your programs name (e.g., `myapp`).
##### How It Works:
1. **Build the Project**: Run `dub build` in your projects 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/<lang>/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.