gettext-syslocale/source/gettext_syslocale.d
2025-06-26 22:12:31 +03:00

94 lines
2.5 KiB
D

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 "";
}