From 3243e89cf9d1b1fda8be4e18d9166ba57300b392 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 21 Aug 2016 16:28:24 +0200 Subject: [PATCH] Honor preferred user language on macOS --- src/platform/linux.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ src/platform/macos.m | 62 ++++++++++++++++++++++++++++++++++++++++++- src/platform/posix.c | 62 ------------------------------------------- 3 files changed, 124 insertions(+), 63 deletions(-) diff --git a/src/platform/linux.c b/src/platform/linux.c index 07a2a702bf..783da34f4a 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -22,7 +22,10 @@ #include #include #include +#include +#include +#include "../config.h" #include "../localisation/language.h" #include "../localisation/string_ids.h" #include "../util/util.h" @@ -148,6 +151,66 @@ void platform_posix_sub_resolve_openrct_data_path(utf8 *out) { } } +uint16 platform_get_locale_language(){ + const char *langString = setlocale(LC_MESSAGES, ""); + if(langString != NULL){ + // 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 + int length = strlen(langString); + { + for(int i = 0; i < length; ++i){ + if(langString[i] == '.' || langString[i] == '@'){ + length = i; + break; + } + } + } //end strip + strncpy(pattern,langString, length); //copy all until first '.' or '@' + pattern[length] = '\0'; + //find _ if present + const char *strip = strchr(pattern, '_'); + if(strip != NULL){ + // 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(int 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; + } + else if (!fnmatch(pattern, "zh_CN", 0)){ + return LANGUAGE_CHINESE_SIMPLIFIED; + } + else if (!fnmatch(pattern, "zh_TW", 0)){ + return LANGUAGE_CHINESE_TRADITIONAL; + } + + //no exact match found trying only language part + if(strip != NULL){ + pattern[strip - pattern] = '*'; + pattern[strip - pattern +1] = '\0'; // pattern is now "language*" + for(int i = 1; i < LANGUAGE_COUNT; ++i){ + if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){ + return i; + } + } + } + } + return LANGUAGE_ENGLISH_UK; +} + uint8 platform_get_locale_currency(){ char *langstring = setlocale(LC_MONETARY, ""); diff --git a/src/platform/macos.m b/src/platform/macos.m index 88b065a863..0220344f9e 100644 --- a/src/platform/macos.m +++ b/src/platform/macos.m @@ -21,7 +21,8 @@ #include #include "platform.h" #include "../util/util.h" -#include "config.h" +#include "../localisation/language.h" +#include "../config.h" bool platform_check_steam_overlay_attached() { STUB(); @@ -192,6 +193,65 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) } } +bool platform_has_matching_language(NSString *preferredLocale, uint16* 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 platform_get_locale_language() +{ + @autoreleasepool + { + NSArray *preferredLanguages = [NSLocale preferredLanguages]; + for (NSString *preferredLanguage in preferredLanguages) { + uint16 languageIdentifier; + if (platform_has_matching_language(preferredLanguage, &languageIdentifier)) { + return languageIdentifier; + } + } + + // Fallback + return LANGUAGE_ENGLISH_UK; + } +} + uint8 platform_get_locale_currency() { @autoreleasepool diff --git a/src/platform/posix.c b/src/platform/posix.c index 3de0e18013..1847495e28 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -33,8 +33,6 @@ #include "../util/util.h" #include "platform.h" #include -#include -#include #include #include #include @@ -795,66 +793,6 @@ void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) log_verbose("outPath + subDirectory = '%s'", buffer); } -uint16 platform_get_locale_language(){ - const char *langString = setlocale(LC_MESSAGES, ""); - if(langString != NULL){ - // 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 - int length = strlen(langString); - { - for(int i = 0; i < length; ++i){ - if(langString[i] == '.' || langString[i] == '@'){ - length = i; - break; - } - } - } //end strip - strncpy(pattern,langString, length); //copy all until first '.' or '@' - pattern[length] = '\0'; - //find _ if present - const char *strip = strchr(pattern, '_'); - if(strip != NULL){ - // 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(int 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; - } - else if (!fnmatch(pattern, "zh_CN", 0)){ - return LANGUAGE_CHINESE_SIMPLIFIED; - } - else if (!fnmatch(pattern, "zh_TW", 0)){ - return LANGUAGE_CHINESE_TRADITIONAL; - } - - //no exact match found trying only language part - if(strip != NULL){ - pattern[strip - pattern] = '*'; - pattern[strip - pattern +1] = '\0'; // pattern is now "language*" - for(int i = 1; i < LANGUAGE_COUNT; ++i){ - if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){ - return i; - } - } - } - } - return LANGUAGE_ENGLISH_UK; -} - time_t platform_file_get_modified_time(const utf8* path){ struct stat buf; if (stat(path, &buf) == 0) {