29 #if !defined(_MSC_VER) && !defined(__MINGW32__)
30 extern "C" int _putenv(
const char*);
39 #include <SDL3/SDL_system.h>
43 #define DBG_G LOG_STREAM(debug, lg::general())
44 #define LOG_G LOG_STREAM(info, lg::general())
45 #define WRN_G LOG_STREAM(warn, lg::general())
46 #define ERR_G LOG_STREAM(err, lg::general())
50 std::vector<config> languages;
51 std::vector<language_def> known_languages;
53 int min_translation_percent = 80;
56 std::map<std::string, std::string> translation_names;
79 static bool result =
true;
85 const utils::string_map::const_iterator
i = strings_.find(key);
86 if(
i != strings_.end()) {
94 empty_string =
"UNTLB " + key;
101 return (*
this)[std::string(key)];
106 return strings_.find(key);
111 return strings_.end();
115 : language(
t_string(
N_(
"System default language"),
"wesnoth"))
121 : localename(
cfg[
"locale"])
123 , windows_locale(
cfg[
"windows_locale"].str(
"C"))
124 , windows_alternates(
utils::
split(
cfg[
"windows_alternates"]))
125 , language(
cfg[
"name"].t_str())
126 , sort_name(
cfg[
"sort_name"].str(language))
127 , rtl(
cfg[
"dir"] ==
"rtl")
128 , percent(
cfg[
"percent"].to_int())
134 translation_names.emplace(alternate,
language);
143 known_languages.clear();
144 known_languages.emplace_back();
147 known_languages.emplace_back(lang);
152 }
catch(
const utils::bad_optional_access&) {
163 std::sort(known_languages.begin(), known_languages.end());
165 if(all || min_translation_percent == 0) {
166 LOG_G <<
"Found " << known_languages.size() <<
" known languages";
167 return known_languages;
170 std::vector<language_def> result;
171 std::copy_if(known_languages.begin(), known_languages.end(), std::back_inserter(result),
172 [](
const language_def& lang) { return lang.percent >= min_translation_percent; });
174 LOG_G <<
"Found " << result.size() <<
" sufficiently translated languages";
180 auto itor = translation_names.find(locale_id);
181 return itor != translation_names.end() ? itor->second :
"";
186 return min_translation_percent;
190 min_translation_percent = percent;
195 std::vector<std::string>
const *alternates)
197 std::string locale = slocale;
208 std::vector<std::string>::const_iterator
i;
209 if (alternates)
i = alternates->begin();
213 std::string lang = locale, extra;
214 std::string::size_type pos = locale.find(
'@');
215 if (pos != std::string::npos) {
217 extra = locale.substr(pos);
224 char const *encoding[] {
".utf-8",
".UTF-8",
"" };
225 for (
int j = 0; j != 3; ++j)
227 locale = lang + encoding[j] + extra;
228 res = std::setlocale(category, locale.c_str());
230 LOG_G <<
"Set locale to '" << locale <<
"' result: '" << res <<
"'.";
235 if (!alternates ||
i == alternates->end())
break;
240 WRN_G <<
"setlocale() failed for '" << slocale <<
"'.";
242 if (category == LC_TIME) {
255 DBG_G <<
"Numeric locale: " << std::setlocale(LC_NUMERIC,
nullptr);
256 DBG_G <<
"Full locale: " << std::setlocale(LC_ALL,
nullptr);
263 current_language = locale;
270 JNIEnv* env =
reinterpret_cast<JNIEnv*
>(SDL_GetAndroidJNIEnv());
271 jobject wesnoth_instance =
reinterpret_cast<jobject
>(SDL_GetAndroidActivity());
272 jclass wesnoth_activity(env->GetObjectClass(wesnoth_instance));
273 jmethodID locale = env->GetMethodID(wesnoth_activity,
"getLocaleCode",
"()Ljava/lang/String;");
274 jstring lcode =
reinterpret_cast<jstring
>(env->CallObjectMethod(wesnoth_instance, locale));
275 localename = env->GetStringUTFChars(lcode,
nullptr);
277 if(env->ExceptionCheck() == JNI_TRUE) {
278 env->ExceptionDescribe();
279 env->ExceptionClear();
282 env->DeleteLocalRef(wesnoth_instance);
283 env->DeleteLocalRef(wesnoth_activity);
304 if(complain && languages.empty()) {
305 PLAIN_LOG <<
"No [language] block found";
308 for(
const config& lang : languages) {
309 for(
const auto& [key,
value] : lang.attribute_range()) {
310 strings_[key] =
value.t_str();
321 assert(!known_languages.empty());
323 const std::string& prefs_locale =
prefs::get().locale();
324 if(prefs_locale.empty() ==
false) {
327 if(prefs_locale == def.localename) {
331 LOG_G <<
"'" << prefs_locale <<
"' locale not found in known array; defaulting to system locale";
332 return known_languages[0];
335 LOG_G <<
"locale could not be determined; defaulting to system locale";
336 return known_languages[0];
343 const std::string &name =
t[
"name"];
344 const std::string &
path =
t[
"path"];
352 WRN_G <<
"no location found for '" <<
path <<
"', skipping textdomain";
361 languages.push_back(l);
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(std::string_view key)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
static void add_textdomain(const std::string &name, const std::string &path)
Declarations for File-IO.
const language_def & get_locale()
std::vector< language_def > get_languages(bool all)
Return a list of available translations.
static void wesnoth_setlocale(int category, const std::string &slocale, std::vector< std::string > const *alternates)
void init_textdomains(const game_config_view &cfg)
Initializes the list of textdomains from a configuration object.
bool load_strings(bool complain)
bool & time_locale_correct()
int get_min_translation_percent()
const language_def & get_language()
bool load_language_list()
std::string get_translation_name(const std::string &locale_id)
bool init_strings(const game_config_view &cfg)
Initializes certain English strings.
void set_language(const language_def &locale)
void set_min_translation_percent(int percent)
Standard logging facilities (interface).
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > ¤t_dir)
Returns a translated path to the actual file or directory, if it exists.
utils::optional< std::string > get_binary_dir_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual directory of a given type, if it exists.
std::string get_intl_dir()
config read(std::istream &in, abstract_validator *validator)
void set_language(const std::string &language, const std::vector< std::string > *)
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map &defines)
Function to use the WML preprocessor on a file.
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
std::vector< std::string > windows_alternates
bool operator==(const language_def &) const
std::string windows_locale
Windows has no knowledge of most POSIX locale IDs, so on that platform the OS-level setlocale() call ...
std::string short_localename() const
std::vector< std::string > alternates
language_def()
Creates the 'System Default Language' definition.
utils::string_map::const_iterator end() const
const t_string & operator[](const std::string &key) const
Look up the string mappings given in [language] tags.
utils::string_map::const_iterator find(const std::string &key) const
Look up the string mappings given in [language] tags.