This commit is contained in:
Alexander Zhirov 2025-06-26 22:12:31 +03:00
commit 97f78f7728
Signed by: alexander
GPG key ID: C8D8BE544A27C511
8 changed files with 218 additions and 0 deletions

16
.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
.dub
docs.json
__dummy.html
docs/
/gettext-syslocale
gettext-syslocale.so
gettext-syslocale.dylib
gettext-syslocale.dll
gettext-syslocale.a
gettext-syslocale.lib
gettext-syslocale-test-*
*.exe
*.pdb
*.o
*.obj
*.lst

16
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
// Используйте IntelliSense, чтобы узнать о возможных атрибутах.
// Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.
// Для получения дополнительной информации посетите: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "code-d",
"request": "launch",
"dubBuild": true,
"name": "Build & Debug DUB project",
"cwd": "${command:dubWorkingDirectory}",
"program": "bin/${command:dubTarget}"
}
]
}

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"editor.insertSpaces": false,
"editor.tabSize": 4,
"editor.detectIndentation": false
}

23
LICENSE Normal file
View file

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

44
README.md Normal file
View file

@ -0,0 +1,44 @@
# gettext_syslocale
A D module that extends the `gettext` library to support system locale detection and standard GNU/Linux translation paths.
## Overview
The `gettext_syslocale` module enhances the `gettext` library by automatically selecting the system locale from environment variables (`LC_ALL`, `LC_MESSAGES`, `LANG`) and loading translation `.mo` files from standard GNU/Linux paths (`/usr/share/locale/<language>/LC_MESSAGES/<programName>.mo`). It prioritizes full language codes (e.g., `ru_RU`) before falling back to short codes (e.g., `ru`).
## Features
- Automatically detects the system locale.
- Searches for `.mo` files in `/usr/share/locale/<language>/LC_MESSAGES/<programName>.mo`.
- Checks full language codes (e.g., `ru_RU`) before short codes (e.g., `ru`).
## Usage
```d
import gettext;
import gettext_syslocale;
void main(string[] args) {
mixin(gettext.main);
initializeSystemLocale(args[0].baseName);
writeln(tr!"Hello, world!");
}
```
1. Include `mixin(gettext.main)` in your `main` function.
2. Call `initializeSystemLocale` with the program name (e.g., `args[0].baseName`).
3. Use `tr` for translatable strings, as provided by the `gettext` library.
## Requirements
- D compiler (e.g., DMD, LDC).
- The `gettext` library for D, including the `mofile` module.
- `.mo` translation files in `/usr/share/locale/<language>/LC_MESSAGES/`.
## Installation
Add `gettext_syslocale.d` to your project and ensure the `gettext` library is available. Compile with a D compiler supporting the `gettext` library.
## License
Boost License 1.0, consistent with the `gettext` library.

13
dub.json Normal file
View file

@ -0,0 +1,13 @@
{
"authors": [
"Alexander Zhirov"
],
"copyright": "Copyright © 2025, Alexander Zhirov",
"dependencies": {
"gettext": "~>1"
},
"description": "Support system locale detection and standard GNU/Linux translation paths for gettext",
"license": "BSL-1.0",
"name": "gettext-syslocale",
"targetType": "library"
}

7
dub.selections.json Normal file
View file

@ -0,0 +1,7 @@
{
"fileVersion": 1,
"versions": {
"gettext": "1.0.8",
"mofile": "0.2.1"
}
}

View file

@ -0,0 +1,94 @@
module gettext_syslocale;
import gettext;
import std.file : exists, isFile;
import std.path : buildPath, baseName;
import std.process : environment;
import std.string : split, empty;
/**
* Extends the gettext library with support for system locale and standard GNU/Linux paths.
*
* This module automatically selects the language from system environment variables
* (LC_ALL, LC_MESSAGES, LANG) and searches for .mo files in the standard path
* /usr/share/locale/<language>/LC_MESSAGES/<programName>.mo.
* It first checks the full language code (e.g., "ru_RU"), then the short code (e.g., "ru").
*
* Params:
* programName = The name of the program (required parameter).
*/
bool initializeSystemLocale(string programName) @safe
{
if (programName.empty)
{
throw new Exception("Program name must not be empty");
}
// Get the language from the system locale
string fullLang = getSystemLanguage();
if (fullLang.empty)
{
selectLanguage(""); // Empty MoFile if no locale is defined
return false;
}
// Check full and short language codes
string shortLang = fullLang.split("_")[0];
foreach (lang; [fullLang, shortLang])
{
if (tryLoadMoFile(programName, lang))
{
return true; // Successfully loaded .mo file
}
}
// If no file is found, use an empty MoFile
selectLanguage("");
return false;
}
/**
* Attempts to load an .mo file for the specified program name and language code.
*
* Params:
* programName = The name of the program.
* lang = The language code (e.g., "ru_RU" or "ru").
*
* Returns:
* true if the .mo file is found and loaded, false otherwise.
*/
private bool tryLoadMoFile(string programName, string lang) @safe
{
string moPath = buildPath("/usr/share/locale", lang, "LC_MESSAGES", programName ~ ".mo");
if (moPath.exists && moPath.isFile)
{
selectLanguage(moPath);
return true;
}
return false;
}
/**
* Retrieves the language from the system locale.
*
* Checks environment variables LC_ALL, LC_MESSAGES, LANG in that order.
* Returns the full language code (e.g., "ru_RU" from "ru_RU.UTF-8").
* If the locale contains only a short code (e.g., "ru"), returns it as is.
*
* Returns:
* The full language code (e.g., "ru_RU", "zh_CN") or an empty string if no locale is defined.
*/
private string getSystemLanguage() @safe
{
foreach (var; ["LC_ALL", "LC_MESSAGES", "LANG"])
{
string value = environment.get(var);
if (!value.empty)
{
// Split on dot to ignore encoding (e.g., .UTF-8)
auto parts = value.split(".");
return parts[0]; // Return the full language code (e.g., ru_RU or ru)
}
}
return "";
}