From c3fa50327ce2a34fcffbb7c830d7a5bcc6da053d Mon Sep 17 00:00:00 2001 From: MarcZX10 <67475268+MarcZX10@users.noreply.github.com> Date: Thu, 29 Oct 2026 07:08:34 +0000 Subject: [PATCH] feat(libSceSystemService): read the host locales of a POSIX system PosixHostLocales takes an injectable environment reader and returns the locales in order of preference: LC_ALL, then LC_MESSAGES, then LANG, the first one that is set and not empty, as the C library chooses the locale of the messages category. When that locale is a real one (not C, POSIX or unset) the entries of LANGUAGE, the GNU preference list, come before it, as gettext ignores LANGUAGE under the C locale. --- .../libSceSystemService/LanguageLocale.hpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/libs/prx/libSceSystemService/LanguageLocale.hpp b/core/libs/prx/libSceSystemService/LanguageLocale.hpp index db27c10b3c..bc2263658d 100644 --- a/core/libs/prx/libSceSystemService/LanguageLocale.hpp +++ b/core/libs/prx/libSceSystemService/LanguageLocale.hpp @@ -2,10 +2,13 @@ #define CORE_LIBS_PRX_LIBSCESYSTEMSERVICE_LANGUAGELOCALE_HPP #include +#include +#include #include #include #include #include +#include namespace SystemServiceLocale { @@ -278,6 +281,32 @@ inline Match MatchLocale(std::string_view locale) { return {id, true}; } +using Environment = std::function; + +inline std::vector PosixHostLocales(const Environment& environment) { + const auto read = [&environment](const char* name) { + const char* value = environment(name); + return std::string_view(value != nullptr ? value : ""); + }; + std::string_view effective; + for (const char* name : {"LC_ALL", "LC_MESSAGES", "LANG"}) { + effective = read(name); + if (!effective.empty()) break; + } + std::vector locales; + if (!NormalizePosixLocale(effective).empty()) { + std::string_view preferred = read("LANGUAGE"); + while (!preferred.empty()) { + const std::size_t colon = preferred.find(':'); + const std::string_view entry = preferred.substr(0, colon); + if (!entry.empty()) locales.emplace_back(entry); + preferred = colon == std::string_view::npos ? std::string_view{} : preferred.substr(colon + 1); + } + } + if (!effective.empty()) locales.emplace_back(effective); + return locales; +} + } #endif