// SPDX-License-Identifier: GPL-3.0-or-later // Copyright (C) 2026 steredbits and Pelagia contributors #include "util/i18n.h" #include #include #include namespace util { namespace { const char* const kEnglish[] = { #define STR(id, text) text, #include "util/i18n/strings_en.def" #undef STR }; const char* const kFrench[] = { #define STR(id, text) text, #include "util/i18n/strings_fr.def" #undef STR }; constexpr size_t kCount = static_cast(Str::Count); static_assert(std::size(kEnglish) == kCount, "strings_en.def and the Str enum differ"); static_assert(std::size(kFrench) == kCount, "strings_fr.def lacks (or adds) strings"); std::atomic g_language{static_cast(Lang::En)}; std::string lowercase_base(const std::string& locale) { std::string out; for (char c : locale) { if (c == '_' || c == '-' || c == '.' || c == '@') break; out.push_back(c >= 'A' && c <= 'Z' ? static_cast(c + 32) : c); } return out; } } // namespace Lang current_language() { return static_cast(g_language.load()); } void set_current_language(Lang lang) { g_language.store(static_cast(lang)); } const char* language_code(Lang lang) { return lang == Lang::Fr ? "fr" : "en"; } const char* tr(Str id, Lang lang) { const size_t i = static_cast(id); if (i >= kCount) return ""; return lang == Lang::Fr ? kFrench[i] : kEnglish[i]; } const char* tr(Str id) { return tr(id, current_language()); } std::string trf(Str id, ...) { const char* format = tr(id); va_list args; va_start(args, id); va_list copy; va_copy(copy, args); const int n = std::vsnprintf(nullptr, 0, format, copy); va_end(copy); std::string out; if (n > 0) { out.resize(static_cast(n) + 1); std::vsnprintf(&out[0], out.size(), format, args); out.resize(static_cast(n)); } va_end(args); return out; } Lang language_from_locales(const std::vector& locales, Lang fallback) { for (const std::string& locale : locales) { const std::string base = lowercase_base(locale); if (base == "fr" || base == "fra" || base == "fre") return Lang::Fr; if (base == "en" || base == "eng") return Lang::En; } return fallback; } const char* language_setting_code(LanguageSetting setting) { switch (setting) { case LanguageSetting::English: return "en"; case LanguageSetting::French: return "fr"; case LanguageSetting::Auto: break; } return "auto"; } bool parse_language_setting(const std::string& code, LanguageSetting* out) { if (code == "auto") *out = LanguageSetting::Auto; else if (code == "en") *out = LanguageSetting::English; else if (code == "fr") *out = LanguageSetting::French; else return false; return true; } Lang resolve_language(LanguageSetting setting, const std::vector& system_locales) { switch (setting) { case LanguageSetting::English: return Lang::En; case LanguageSetting::French: return Lang::Fr; case LanguageSetting::Auto: break; } return language_from_locales(system_locales, Lang::En); } } // namespace util