macOS system language detection.
It appears the system language detection doesn't work on [some versions of?] macOS. Fixed. Strangely, querying the Cocoa API for the system locale on a system in US with the preferred language set to Korean produces the invalid locale "ko-US" instead of the expected "ko-KR". This behavior of returning the language with a invalid region qualifier for the language appears to happen only with languages where macOS does not have regional variants (this issue does not seem to occur with Canadian English, en-CA, for example.) A fuzzy matching locale function has been added to handle this issue.
This commit is contained in:
parent
c2ab6d461c
commit
c9e195549f
6 changed files with 96 additions and 4 deletions
|
|
@ -113,6 +113,9 @@ http://www.tuxpaint.org/
|
|||
* Tux Paint for macOS can now localize the macOS menubar.
|
||||
Mark Kim <markuskimius@gmail.com>
|
||||
|
||||
* Tux Paint for macOS can now detect the system language.
|
||||
Mark Kim <markuskimius@gmail.com>
|
||||
|
||||
* Updated `src/po/check_translations.sh` sanity-checking script
|
||||
so it properly finds the updated docs & other changes.
|
||||
Bill Kendrick <bill@newbreedsoftware.com>
|
||||
|
|
|
|||
57
src/i18n.c
57
src/i18n.c
|
|
@ -47,6 +47,12 @@
|
|||
#include <wctype.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "macos.h"
|
||||
#elif defined(__IOS__)
|
||||
#include "ios.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Globals: */
|
||||
|
||||
|
|
@ -790,7 +796,7 @@ static void ctype_utf8(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* For a given language, return its local, or exit with a usage error.
|
||||
* For a given language, return its locale, or exit with a usage error.
|
||||
*
|
||||
* @param langstr Name of language (e.g., "german")
|
||||
* @return Locale (e.g., "de_DE.UTF-8")
|
||||
|
|
@ -811,6 +817,47 @@ static const char *language_to_locale(const char *langstr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given locale, return the known locale that matches it closest, or exit
|
||||
* with a usage error.
|
||||
*
|
||||
* @param inlocale Name of some locale (e.g., "ko_US")
|
||||
* @return Known locale. (e.g., "ko_KR.UTF-8")
|
||||
*/
|
||||
static const char *locale_to_closest_locale(const char *inlocale)
|
||||
{
|
||||
const int numlocale = sizeof(language_to_locale_array) / sizeof(language_to_locale_array[0]);
|
||||
const char* outlocale = NULL;
|
||||
int outlocale_score = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
/* find the locale with the longest string match */
|
||||
for (i=0; i<numlocale; i++)
|
||||
{
|
||||
const char* candidate = language_to_locale_array[i].locale;
|
||||
|
||||
for (j=0; j<strlen(inlocale) && j<strlen(candidate); j++)
|
||||
{
|
||||
if(inlocale[j] != candidate[j]) break;
|
||||
}
|
||||
|
||||
if (j > outlocale_score)
|
||||
{
|
||||
outlocale = candidate;
|
||||
outlocale_score = j;
|
||||
}
|
||||
}
|
||||
|
||||
/* locale must match at least three characters */
|
||||
if (outlocale_score < 3)
|
||||
{
|
||||
outlocale = NULL;
|
||||
}
|
||||
|
||||
return outlocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set language ("langint" global) based on a given locale;
|
||||
* will try a few ways of checking, is case-insensitive, etc.
|
||||
|
|
@ -1225,7 +1272,13 @@ int setup_i18n(const char *restrict lang, const char *restrict locale, int * num
|
|||
}
|
||||
}
|
||||
else
|
||||
locale = "";
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
locale = locale_to_closest_locale(apple_locale());
|
||||
#else
|
||||
locale = "";
|
||||
#endif
|
||||
}
|
||||
|
||||
if (lang)
|
||||
locale = language_to_locale(lang);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
|
||||
void apple_init(void);
|
||||
const char *apple_locale(void);
|
||||
const char *apple_fontsPath(void);
|
||||
const char *apple_preferencesPath(void);
|
||||
const char *apple_globalPreferencesPath(void);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ void apple_init(void)
|
|||
}
|
||||
|
||||
|
||||
const char *apple_locale(void)
|
||||
{
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
const char *apple_fontsPath(void)
|
||||
{
|
||||
return IOS_FONTS_PATH;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
|
||||
void apple_init(void);
|
||||
const char *apple_locale(void);
|
||||
const char *apple_fontsPath(void);
|
||||
const char *apple_preferencesPath(void);
|
||||
const char *apple_globalPreferencesPath(void);
|
||||
|
|
|
|||
32
src/macos.m
32
src/macos.m
|
|
@ -34,6 +34,9 @@
|
|||
#define MACOS_PICTURES_PATH "%s/Pictures"
|
||||
|
||||
|
||||
static char *APPLE_LOCALE = NULL;
|
||||
|
||||
|
||||
static void setupApplicationMenu(void)
|
||||
{
|
||||
/*
|
||||
|
|
@ -130,10 +133,35 @@ static void removeSdlMenu(void)
|
|||
void apple_init(void)
|
||||
{
|
||||
/* Override SDL's default menu with our gettext-translatable menu. We do
|
||||
* this by adding our menus, then removing the menus installed by SDL. */
|
||||
* this by removing the menus added by SDL, then adding ours. */
|
||||
removeSdlMenu();
|
||||
setupApplicationMenu();
|
||||
setupWindowMenu();
|
||||
removeSdlMenu();
|
||||
}
|
||||
|
||||
|
||||
const char *apple_locale(void)
|
||||
{
|
||||
if(!APPLE_LOCALE) {
|
||||
const char *locale = [[[NSLocale preferredLanguages] firstObject] UTF8String];
|
||||
|
||||
/* Copy to writable memory */
|
||||
APPLE_LOCALE = strdup(locale);
|
||||
|
||||
if(!APPLE_LOCALE) {
|
||||
perror("apple_locale");
|
||||
return "C"; /* Default to C */
|
||||
}
|
||||
|
||||
/* Change the locale hyphen separator to underscore (e.g., en-US to en_US) */
|
||||
if(APPLE_LOCALE[2] == '-') {
|
||||
APPLE_LOCALE[2] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("locale=%s\n", APPLE_LOCALE);
|
||||
|
||||
return APPLE_LOCALE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue