From 75a775e59d70c48e007996421a4e6065eafe93a3 Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 4 May 2025 19:04:15 +0200 Subject: [PATCH] Codechange: Make GetCurrentLocale return a std::string instead of a reference to a static buffer. For win32 this is even a fix, because the static buffer was only updated once. Later calls discarded the determined locale. --- src/os/macosx/macos.mm | 10 ++++++---- src/os/unix/unix.cpp | 7 ++++--- src/os/windows/win32.cpp | 5 ++--- src/strings.cpp | 23 +++++++++++++---------- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/os/macosx/macos.mm b/src/os/macosx/macos.mm index 3ad91412e7..d644d1232b 100644 --- a/src/os/macosx/macos.mm +++ b/src/os/macosx/macos.mm @@ -151,16 +151,18 @@ void OSOpenBrowser(const std::string &url) /** * Determine and return the current user's locale. */ -std::optional GetCurrentLocale(const char *) +std::optional GetCurrentLocale(const char *) { - static char retbuf[32] = { '\0' }; NSUserDefaults *defs = [ NSUserDefaults standardUserDefaults ]; NSArray *languages = [ defs objectForKey:@"AppleLanguages" ]; NSString *preferredLang = [ languages objectAtIndex:0 ]; /* preferredLang is either 2 or 5 characters long ("xx" or "xx_YY"). */ - [ preferredLang getCString:retbuf maxLength:32 encoding:NSASCIIStringEncoding ]; - + std::string retbuf{32, '\0'}; + [ preferredLang getCString:retbuf.data() maxLength:retbuf.size() encoding:NSASCIIStringEncoding ]; + auto end = retbuf.find('\0'); + if (end == 0) return std::nullopt; + if (end != std::string::npos) retbuf.erase(end); return retbuf; } diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 5c51267bf0..52bf064816 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -89,7 +89,7 @@ bool FiosIsHiddenFile(const std::filesystem::path &path) #include "../../debug.h" #include "../../string_func.h" -std::optional GetCurrentLocale(const char *param); +std::optional GetCurrentLocale(const char *param); #define INTERNALCODE "UTF-8" @@ -98,7 +98,7 @@ std::optional GetCurrentLocale(const char *param); * variables. MacOSX is hardcoded, other OS's are dynamic. If no suitable * locale can be found, don't do any conversion "" */ -static std::string_view GetLocalCode() +static std::string GetLocalCode() { #if defined(__APPLE__) return "UTF-8-MAC"; @@ -108,7 +108,8 @@ static std::string_view GetLocalCode() if (!locale.has_value()) return ""; auto pos = locale->find('.'); if (pos == std::string_view::npos) return ""; - return locale->substr(pos + 1); + locale.erase(0, pos + 1); + return locale; #endif } diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 49cb4a5847..c7405a3707 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -395,7 +395,7 @@ wchar_t *convert_to_fs(std::string_view src, std::span dst_buf) } /** Determine the current user's locale. */ -std::optional GetCurrentLocale(const char *) +std::optional GetCurrentLocale(const char *) { const LANGID userUiLang = GetUserDefaultUILanguage(); const LCID userUiLocale = MAKELCID(userUiLang, SORT_DEFAULT); @@ -407,8 +407,7 @@ std::optional GetCurrentLocale(const char *) return nullptr; } /* Format it as 'en_us'. */ - static char retbuf[6] = {lang[0], lang[1], '_', country[0], country[1], 0}; - return retbuf; + return fmt::format("{}_{}", std::string_view{lang, 2}, std::string_view{country, 2}); } diff --git a/src/strings.cpp b/src/strings.cpp index 0c7f4228c9..8b803246bd 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2083,23 +2083,26 @@ bool ReadLanguagePack(const LanguageMetadata *lang) * set. Pass nullptr if you don't want additional checks. * @return return string containing current charset, or nullptr if not-determinable */ -std::optional GetCurrentLocale(const char *param) +std::optional GetCurrentLocale(const char *param) { auto env = GetEnv("LANGUAGE"); - if (env.has_value()) return env; + if (env.has_value()) return std::string{*env}; env = GetEnv("LC_ALL"); - if (env.has_value()) return env; + if (env.has_value()) return std::string{*env}; if (param != nullptr) { env = GetEnv(param); - if (env.has_value()) return env; + if (env.has_value()) return std::string{*env}; } - return GetEnv("LANG"); + env = GetEnv("LANG"); + if (env.has_value()) return std::string{*env}; + + return std::nullopt; } #else -std::optional GetCurrentLocale(const char *param); +std::optional GetCurrentLocale(const char *param); #endif /* !(defined(_WIN32) || defined(__APPLE__)) */ /** @@ -2180,8 +2183,8 @@ void InitializeLanguagePacks() if (_languages.empty()) UserError("No available language packs (invalid versions?)"); /* Acquire the locale of the current system */ - auto lang = GetCurrentLocale("LC_MESSAGES"); - if (!lang.has_value()) lang = "en_GB"; + auto str_lang = GetCurrentLocale("LC_MESSAGES"); + std::string_view lang = str_lang.has_value() ? std::string_view{*str_lang} : "en_GB"; const LanguageMetadata *chosen_language = nullptr; ///< Matching the language in the configuration file or the current locale const LanguageMetadata *language_fallback = nullptr; ///< Using pt_PT for pt_BR locale when pt_BR is not available @@ -2203,8 +2206,8 @@ void InitializeLanguagePacks() /* Only auto-pick finished translations */ if (!lng.IsReasonablyFinished()) continue; - if (iso_code.starts_with(lang->substr(0, 5))) chosen_language = &lng; - if (iso_code.starts_with(lang->substr(0, 2))) language_fallback = &lng; + if (iso_code.starts_with(lang.substr(0, 5))) chosen_language = &lng; + if (iso_code.starts_with(lang.substr(0, 2))) language_fallback = &lng; } /* We haven't found the language in the config nor the one in the locale.