mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-10 09:32:29 +01:00
Fix #4318: Use user locale on macOS
This commit is contained in:
@@ -22,7 +22,10 @@
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fnmatch.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "../config.h"
|
||||
#include "../localisation/language.h"
|
||||
#include "../localisation/string_ids.h"
|
||||
#include "../util/util.h"
|
||||
@@ -148,6 +151,94 @@ 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, "");
|
||||
|
||||
if (langstring == NULL) {
|
||||
return platform_get_currency_value(NULL);
|
||||
}
|
||||
|
||||
struct lconv *lc = localeconv();
|
||||
|
||||
return platform_get_currency_value(lc->int_curr_symbol);
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_measurement_format(){
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
const char *langstring = setlocale(LC_MEASUREMENT, "");
|
||||
#else
|
||||
const char *langstring = setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
if(langstring != NULL){
|
||||
//using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if(!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0)){
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}
|
||||
}
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
static void execute_cmd(char *command, int *exit_value, char *buf, size_t *buf_size) {
|
||||
FILE *f;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <mach-o/dyld.h>
|
||||
#include "platform.h"
|
||||
#include "../util/util.h"
|
||||
#include "../localisation/language.h"
|
||||
#include "../config.h"
|
||||
|
||||
bool platform_check_steam_overlay_attached() {
|
||||
STUB();
|
||||
@@ -191,4 +193,86 @@ 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<NSString*> *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
|
||||
{
|
||||
NSString *currencyCode = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencyCode];
|
||||
return platform_get_currency_value(currencyCode.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_measurement_format()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSNumber *metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
|
||||
|
||||
if (metricSystem.boolValue) {
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#include "../util/util.h"
|
||||
#include "platform.h"
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
#include <locale.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <fts.h>
|
||||
@@ -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) {
|
||||
@@ -863,35 +801,6 @@ time_t platform_file_get_modified_time(const utf8* path){
|
||||
return 100;
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_currency(){
|
||||
char *langstring = setlocale(LC_MONETARY, "");
|
||||
|
||||
if (langstring == NULL) {
|
||||
return platform_get_currency_value(NULL);
|
||||
}
|
||||
|
||||
struct lconv *lc = localeconv();
|
||||
|
||||
return platform_get_currency_value(lc->int_curr_symbol);
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_measurement_format(){
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
const char *langstring = setlocale(LC_MEASUREMENT, "");
|
||||
#else
|
||||
const char *langstring = setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
if(langstring != NULL){
|
||||
//using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if(!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0)){
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}
|
||||
}
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_temperature_format(){
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
|
||||
Reference in New Issue
Block a user