diff --git a/include/language.h b/include/language.h index a8fc14b57..bec84f780 100644 --- a/include/language.h +++ b/include/language.h @@ -35,6 +35,14 @@ namespace Language */ extern void InitLanguages(); + /** Sets the locale to the specified language. + * @param lang The language to translate to. + */ + extern CoreExport void SetLocale(const char* lang); + + /** Sets the locale back to the default. */ + extern CoreExport void ResetLocale(); + /** Translates a string to the default language. * @param string A string to translate * @return The translated string if found, else the original string. diff --git a/language/anope.en_US.po b/language/anope.en_US.po index 279c9ed42..81a45468e 100644 --- a/language/anope.en_US.po +++ b/language/anope.en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Anope\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-29 12:59+0100\n" +"POT-Creation-Date: 2025-10-02 15:29+0100\n" "PO-Revision-Date: 2025-09-29 13:00+0100\n" "Last-Translator: Sadie Powell \n" "Language-Team: English\n" @@ -751,9 +751,6 @@ msgstr "" msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s" msgstr "" -msgid "%b %d %Y %H:%M:%S %Z" -msgstr "" - #, c-format msgid "%c is an unknown status mode." msgstr "" diff --git a/src/language.cpp b/src/language.cpp index 440461133..6e8f08b69 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -97,41 +97,41 @@ const char *Language::Translate(const NickCore *nc, int count, const char *singu extern "C" int _nl_msg_cat_cntr; #endif -namespace +void Language::SetLocale(const char* lang) { - void PreTranslate(const char* lang) - { + if (!lang || !*lang) + lang = Config->DefLanguage.c_str(); + #if defined(__GLIBC__) && defined(__USE_GNU_GETTEXT) - ++_nl_msg_cat_cntr; + ++_nl_msg_cat_cntr; #endif #ifdef _WIN32 - SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang), SUBLANG_DEFAULT), SORT_DEFAULT)); + SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang), SUBLANG_DEFAULT), SORT_DEFAULT)); #else - /* First, set LANG and LANGUAGE env variables. - * Some systems (Debian) don't care about this, so we must setlocale LC_ALL as well. - * BUT if this call fails because the LANGUAGE env variable is set, setlocale resets - * the locale to "C", which short circuits gettext and causes it to fail on systems that - * use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not - * C or POSIX) then. - */ - setenv("LANG", lang, 1); - setenv("LANGUAGE", lang, 1); - if (setlocale(LC_ALL, lang) == NULL) - setlocale(LC_ALL, "en_US"); + /* First, set LANG and LANGUAGE env variables. + * Some systems (Debian) don't care about this, so we must setlocale LC_ALL as well. + * BUT if this call fails because the LANGUAGE env variable is set, setlocale resets + * the locale to "C", which short circuits gettext and causes it to fail on systems that + * use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not + * C or POSIX) then. + */ + setenv("LANG", lang, 1); + setenv("LANGUAGE", lang, 1); + if (setlocale(LC_ALL, lang) == NULL) + setlocale(LC_ALL, "en_US"); #endif - } +} - void PostTranslate() - { +void Language::ResetLocale() +{ #ifdef _WIN32 - SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT)); + SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT)); #else - unsetenv("LANGUAGE"); - unsetenv("LANG"); - setlocale(LC_ALL, ""); + unsetenv("LANGUAGE"); + unsetenv("LANG"); + setlocale(LC_ALL, ""); #endif - } } const char *Language::Translate(const char *lang, const char *string) @@ -139,16 +139,13 @@ const char *Language::Translate(const char *lang, const char *string) if (!string || !*string) return ""; - if (!lang || !*lang) - lang = Config->DefLanguage.c_str(); - - PreTranslate(lang); + SetLocale(lang); const char *translated_string = dgettext("anope", string); for (unsigned i = 0; translated_string == string && i < Domains.size(); ++i) translated_string = dgettext(Domains[i].c_str(), string); - PostTranslate(); + ResetLocale(); return translated_string; } @@ -157,19 +154,24 @@ const char *Language::Translate(const char *lang, int count, const char *singula if (!singular || !*singular || !plural || !*plural) return ""; - if (!lang || !*lang) - lang = Config->DefLanguage.c_str(); - - PreTranslate(lang); + SetLocale(lang); const char *translated_string = dngettext("anope", singular, plural, count); for (unsigned i = 0; (translated_string == singular || translated_string == plural) && i < Domains.size(); ++i) translated_string = dngettext(Domains[i].c_str(), singular, plural, count); - PostTranslate(); + ResetLocale(); return translated_string; } #else +void Language::SetLocale(const char* lang) +{ +} + +void Language::ResetLocale() +{ +} + const char *Language::Translate(const char *lang, const char *string) { return string != NULL ? string : ""; diff --git a/src/misc.cpp b/src/misc.cpp index 14a037e6c..2f151fd77 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -619,12 +619,18 @@ Anope::string Anope::Duration(time_t t, const NickCore *nc, bool round) Anope::string Anope::strftime(time_t t, const NickCore *nc, bool short_output) { + if (nc) + Language::SetLocale(nc->language.c_str()); + char buf[BUFSIZE]; - strftime(buf, sizeof(buf), Language::Translate(nc, _("%b %d %Y %H:%M:%S %Z")), gmtime(&t)); + strftime(buf, sizeof(buf), "%b %d %Y %H:%M:%S %Z", gmtime(&t)); + + if (nc) + Language::ResetLocale(); + if (short_output) return buf; - - if (t < Anope::CurTime) + else if (t < Anope::CurTime) return Anope::Format(Language::Translate(nc, _("%s (%s ago)")), buf, Duration(Anope::CurTime - t, nc, true).c_str()); else if (t > Anope::CurTime) return Anope::Format(Language::Translate(nc, _("%s (%s from now)")), buf, Duration(t - Anope::CurTime, nc, true).c_str(), nc);