1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-06 06:32:56 +01:00

Upgrade platform_get_locale_language()

This commit is contained in:
Gymnasiast
2022-01-08 12:19:24 +01:00
parent 77d607a4c0
commit 12034b2d36
11 changed files with 205 additions and 216 deletions

View File

@@ -164,7 +164,7 @@ namespace Config
model->rct1_path = reader->GetCString("rct1_path", nullptr);
model->rct2_path = reader->GetString("game_path", "");
model->landscape_smoothing = reader->GetBoolean("landscape_smoothing", true);
model->language = reader->GetEnum<int32_t>("language", platform_get_locale_language(), Enum_LanguageEnum);
model->language = reader->GetEnum<int32_t>("language", Platform::GetLocaleLanguage(), Enum_LanguageEnum);
model->measurement_format = reader->GetEnum<MeasurementFormat>(
"measurement_format", platform_get_locale_measurement_format(), Enum_MeasurementFormat);
model->play_intro = reader->GetBoolean("play_intro", false);

View File

@@ -26,11 +26,6 @@ bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
}
# endif
uint16_t platform_get_locale_language()
{
return LANGUAGE_ENGLISH_UK;
}
CurrencyType platform_get_locale_currency()
{
return platform_get_currency_value(NULL);

View File

@@ -34,79 +34,6 @@
# include <locale.h>
# include <pwd.h>
uint16_t platform_get_locale_language()
{
const char* langString = setlocale(LC_MESSAGES, "");
if (langString != nullptr)
{
// The locale has the following form:
// language[_territory[.codeset]][@modifier]
// (see https://www.gnu.org/software/libc/manual/html_node/Locale-Names.html)
// longest on my system is 29 with codeset and modifier, so 32 for the pattern should be more than enough
char pattern[32];
// strip the codeset and modifier part
int32_t length = strlen(langString);
{
for (int32_t i = 0; i < length; ++i)
{
if (langString[i] == '.' || langString[i] == '@')
{
length = i;
break;
}
}
} // end strip
std::memcpy(pattern, langString, length); // copy all until first '.' or '@'
pattern[length] = '\0';
// find _ if present
const char* strip = strchr(pattern, '_');
if (strip != nullptr)
{
// could also use '-', but '?' is more flexible. Maybe LanguagesDescriptors will change.
// pattern is now "language?territory"
pattern[strip - pattern] = '?';
}
// Iterate through all available languages
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
{
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
{
return i;
}
}
// special cases :(
if (!fnmatch(pattern, "en_CA", 0))
{
return LANGUAGE_ENGLISH_US;
}
if (!fnmatch(pattern, "zh_CN", 0))
{
return LANGUAGE_CHINESE_SIMPLIFIED;
}
if (!fnmatch(pattern, "zh_TW", 0))
{
return LANGUAGE_CHINESE_TRADITIONAL;
}
// no exact match found trying only language part
if (strip != nullptr)
{
pattern[strip - pattern] = '*';
pattern[strip - pattern + 1] = '\0'; // pattern is now "language*"
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
{
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
{
return i;
}
}
}
}
return LANGUAGE_ENGLISH_UK;
}
CurrencyType platform_get_locale_currency()
{
char* langstring = setlocale(LC_MONETARY, "");

View File

@@ -10,6 +10,7 @@
#ifdef __ANDROID__
# include "../core/Guard.hpp"
# include "../localisation/Language.h"
# include "Platform2.h"
namespace Platform
@@ -54,6 +55,11 @@ namespace Platform
{
return false;
}
uint16_t GetLocaleLanguage()
{
return LANGUAGE_ENGLISH_UK;
}
} // namespace Platform
#endif

View File

@@ -9,6 +9,8 @@
#if defined(__unix__) && !defined(__ANDROID__) && !defined(__APPLE__)
# include <cstring>
# include <fnmatch.h>
# include <limits.h>
# include <pwd.h>
# include <vector>
@@ -23,6 +25,7 @@
# endif // __linux__
# include "../OpenRCT2.h"
# include "../core/Path.hpp"
# include "../localisation/Language.h"
# include "Platform2.h"
# include "platform.h"
@@ -168,6 +171,71 @@ namespace Platform
{
return false;
}
uint16_t GetLocaleLanguage()
{
const char* langString = setlocale(LC_MESSAGES, "");
if (langString != nullptr)
{
// The locale has the following form:
// language[_territory[.codeset]][@modifier]
// (see https://www.gnu.org/software/libc/manual/html_node/Locale-Names.html)
// longest on my system is 29 with codeset and modifier, so 32 for the pattern should be more than enough
char pattern[32];
// strip the codeset and modifier part
int32_t length = strlen(langString);
{
for (int32_t i = 0; i < length; ++i)
{
if (langString[i] == '.' || langString[i] == '@')
{
length = i;
break;
}
}
} // end strip
std::memcpy(pattern, langString, length); // copy all until first '.' or '@'
pattern[length] = '\0';
// find _ if present
const char* strip = strchr(pattern, '_');
if (strip != nullptr)
{
// could also use '-', but '?' is more flexible. Maybe LanguagesDescriptors will change.
// pattern is now "language?territory"
pattern[strip - pattern] = '?';
}
// Iterate through all available languages
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
{
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
{
return i;
}
}
// special case
if (fnmatch(pattern, "en_CA", 0) == 0)
{
return LANGUAGE_ENGLISH_US;
}
// no exact match found trying only language part
if (strip != nullptr)
{
pattern[strip - pattern] = '*';
pattern[strip - pattern + 1] = '\0'; // pattern is now "language*"
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
{
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
{
return i;
}
}
}
}
return LANGUAGE_ENGLISH_UK;
}
} // namespace Platform
#endif

View File

@@ -34,6 +34,7 @@
# include "../common.h"
# include "../core/Path.hpp"
# include "../core/String.hpp"
# include "../localisation/Language.h"
# include "Platform2.h"
# include "platform.h"
@@ -626,6 +627,75 @@ namespace Platform
}
return result;
}
uint16_t GetLocaleLanguage()
{
CHAR langCode[4];
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, reinterpret_cast<LPSTR>(&langCode), sizeof(langCode))
== 0)
{
return LANGUAGE_UNDEFINED;
}
if (strcmp(langCode, "ENG") == 0)
{
return LANGUAGE_ENGLISH_UK;
}
if (strcmp(langCode, "ENU") == 0)
{
return LANGUAGE_ENGLISH_US;
}
if (strcmp(langCode, "DEU") == 0)
{
return LANGUAGE_GERMAN;
}
if (strcmp(langCode, "NLD") == 0)
{
return LANGUAGE_DUTCH;
}
if (strcmp(langCode, "FRA") == 0)
{
return LANGUAGE_FRENCH;
}
if (strcmp(langCode, "HUN") == 0)
{
return LANGUAGE_HUNGARIAN;
}
if (strcmp(langCode, "PLK") == 0)
{
return LANGUAGE_POLISH;
}
if (strcmp(langCode, "ESP") == 0)
{
return LANGUAGE_SPANISH;
}
if (strcmp(langCode, "SVE") == 0)
{
return LANGUAGE_SWEDISH;
}
if (strcmp(langCode, "ITA") == 0)
{
return LANGUAGE_ITALIAN;
}
if (strcmp(langCode, "POR") == 0)
{
return LANGUAGE_PORTUGUESE_BR;
}
if (strcmp(langCode, "FIN") == 0)
{
return LANGUAGE_FINNISH;
}
if (strcmp(langCode, "NOR") == 0)
{
return LANGUAGE_NORWEGIAN;
}
if (strcmp(langCode, "DAN") == 0)
{
return LANGUAGE_DANISH;
}
return LANGUAGE_UNDEFINED;
}
} // namespace Platform
#endif

View File

@@ -12,6 +12,7 @@
# include "../OpenRCT2.h"
# include "../core/Path.hpp"
# include "../core/String.hpp"
# include "../localisation/Language.h"
# include "Platform2.h"
// undefine `interface` and `abstract`, because it's causing conflicts with Objective-C's keywords
@@ -150,6 +151,62 @@ namespace Platform
}
return false;
}
bool HasMatchingLanguage(NSString* preferredLocale, uint16_t* languageIdentifier)
{
@autoreleasepool
{
if ([preferredLocale isEqualToString:@"en"] || [preferredLocale isEqualToString:@"en-CA"])
{
*languageIdentifier = LANGUAGE_ENGLISH_US;
return YES;
}
// Find an exact match (language and region)
for (int i = 1; i < LANGUAGE_COUNT; i++)
{
if ([preferredLocale isEqualToString:[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]])
{
*languageIdentifier = i;
return YES;
}
}
// Only check for a matching language
NSString* languageCode = [[preferredLocale componentsSeparatedByString:@"-"] firstObject];
for (int i = 1; i < LANGUAGE_COUNT; i++)
{
NSString* optionLanguageCode = [[[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]
componentsSeparatedByString:@"-"] firstObject];
if ([languageCode isEqualToString:optionLanguageCode])
{
*languageIdentifier = i;
return YES;
}
}
return NO;
}
}
uint16_t GetLocaleLanguage()
{
@autoreleasepool
{
NSArray<NSString*>* preferredLanguages = [NSLocale preferredLanguages];
for (NSString* preferredLanguage in preferredLanguages)
{
uint16_t languageIdentifier;
if (HasMatchingLanguage(preferredLanguage, &languageIdentifier))
{
return languageIdentifier;
}
}
// Fallback
return LANGUAGE_ENGLISH_UK;
}
}
}
#endif

View File

@@ -41,8 +41,11 @@ namespace Platform
uint64_t GetLastModified(const std::string& path);
uint64_t GetFileSize(std::string_view path);
std::string ResolveCasing(const std::string& path, bool fileExists);
uint16_t GetLocaleLanguage();
rct2_time GetTimeLocal();
rct2_date GetDateLocal();
bool FindApp(const std::string& app, std::string* output);
int32_t Execute(const std::string& command, std::string* output = nullptr);

View File

@@ -185,74 +185,6 @@ std::string platform_get_rct2_steam_dir()
return "Rollercoaster Tycoon 2";
}
uint16_t platform_get_locale_language()
{
CHAR langCode[4];
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, reinterpret_cast<LPSTR>(&langCode), sizeof(langCode)) == 0)
{
return LANGUAGE_UNDEFINED;
}
if (strcmp(langCode, "ENG") == 0)
{
return LANGUAGE_ENGLISH_UK;
}
if (strcmp(langCode, "ENU") == 0)
{
return LANGUAGE_ENGLISH_US;
}
if (strcmp(langCode, "DEU") == 0)
{
return LANGUAGE_GERMAN;
}
if (strcmp(langCode, "NLD") == 0)
{
return LANGUAGE_DUTCH;
}
if (strcmp(langCode, "FRA") == 0)
{
return LANGUAGE_FRENCH;
}
if (strcmp(langCode, "HUN") == 0)
{
return LANGUAGE_HUNGARIAN;
}
if (strcmp(langCode, "PLK") == 0)
{
return LANGUAGE_POLISH;
}
if (strcmp(langCode, "ESP") == 0)
{
return LANGUAGE_SPANISH;
}
if (strcmp(langCode, "SVE") == 0)
{
return LANGUAGE_SWEDISH;
}
if (strcmp(langCode, "ITA") == 0)
{
return LANGUAGE_ITALIAN;
}
if (strcmp(langCode, "POR") == 0)
{
return LANGUAGE_PORTUGUESE_BR;
}
if (strcmp(langCode, "FIN") == 0)
{
return LANGUAGE_FINNISH;
}
if (strcmp(langCode, "NOR") == 0)
{
return LANGUAGE_NORWEGIAN;
}
if (strcmp(langCode, "DAN") == 0)
{
return LANGUAGE_DANISH;
}
return LANGUAGE_UNDEFINED;
}
time_t platform_file_get_modified_time(const utf8* path)
{
WIN32_FILE_ATTRIBUTE_DATA data{};

View File

@@ -45,74 +45,6 @@ bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
}
# endif // NO_TTF
bool platform_has_matching_language(NSString* preferredLocale, uint16_t* languageIdentifier)
{
@autoreleasepool
{
if ([preferredLocale isEqualToString:@"en"] || [preferredLocale isEqualToString:@"en-CA"])
{
*languageIdentifier = LANGUAGE_ENGLISH_US;
return YES;
}
if ([preferredLocale isEqualToString:@"zh-CN"])
{
*languageIdentifier = LANGUAGE_CHINESE_SIMPLIFIED;
return YES;
}
if ([preferredLocale isEqualToString:@"zh-TW"])
{
*languageIdentifier = LANGUAGE_CHINESE_TRADITIONAL;
return YES;
}
// Find an exact match (language and region)
for (int i = 1; i < LANGUAGE_COUNT; i++)
{
if ([preferredLocale isEqualToString:[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]])
{
*languageIdentifier = i;
return YES;
}
}
// Only check for a matching language
NSString* languageCode = [[preferredLocale componentsSeparatedByString:@"-"] firstObject];
for (int i = 1; i < LANGUAGE_COUNT; i++)
{
NSString* optionLanguageCode = [[[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]
componentsSeparatedByString:@"-"] firstObject];
if ([languageCode isEqualToString:optionLanguageCode])
{
*languageIdentifier = i;
return YES;
}
}
return NO;
}
}
uint16_t platform_get_locale_language()
{
@autoreleasepool
{
NSArray<NSString*>* preferredLanguages = [NSLocale preferredLanguages];
for (NSString* preferredLanguage in preferredLanguages)
{
uint16_t languageIdentifier;
if (platform_has_matching_language(preferredLanguage, &languageIdentifier))
{
return languageIdentifier;
}
}
// Fallback
return LANGUAGE_ENGLISH_UK;
}
}
CurrencyType platform_get_locale_currency()
{
@autoreleasepool

View File

@@ -107,7 +107,6 @@ bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc,
utf8* platform_open_directory_browser(const utf8* title);
CurrencyType platform_get_locale_currency();
CurrencyType platform_get_currency_value(const char* currencyCode);
uint16_t platform_get_locale_language();
MeasurementFormat platform_get_locale_measurement_format();
TemperatureUnit platform_get_locale_temperature_format();
uint8_t platform_get_locale_date_format();