Skip to content

Commit

Permalink
Implement language detection by POSIX locale
Browse files Browse the repository at this point in the history
  • Loading branch information
albel727 committed Sep 24, 2014
1 parent dc79a43 commit 109cb41
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
84 changes: 83 additions & 1 deletion ui_i18n.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdint.h>
#include <string.h>

#include "sized_string.h"
#include "ui_i18n_decls.h"
Expand All @@ -12,12 +13,23 @@
#ifdef msgstr
#error "msgstr is already defined"
#endif
#ifdef LANG_POSIX_LOCALE
#error "LANG_POSIX_LOCALE is already defined"
#endif
#ifdef LANG_PRIORITY
#error "LANG_PRIORITY is already defined"
#endif

#define STR(x) { .str = (uint8_t*)x, .length = sizeof(x) - 1 }

/***** Parsing localized strings *****/

#define msgid(x) curr_id = (STR_##x);
#define msgstr(x) \
localized_strings[_LANG_ID][curr_id].str = (uint8_t*)(x); \
localized_strings[_LANG_ID][curr_id].length = sizeof(x) - 1;
#define LANG_POSIX_LOCALE(x)
#define LANG_PRIORITY(x)

static STRING canary = STR("BUG. PLEASE REPORT.");

Expand All @@ -36,9 +48,10 @@ static void init_strings(STRING (*localized_strings)[STRS_MAX+1]) {

}

#undef LANG_PRIORITY
#undef LANG_POSIX_LOCALE
#undef msgstr
#undef msgid
#undef STR

STRING* ui_gettext(UI_LANG_ID lang, UI_STRING_ID string_id) {
static STRING localized_strings[LANGS_MAX+1][STRS_MAX+1];
Expand All @@ -55,3 +68,72 @@ STRING* ui_gettext(UI_LANG_ID lang, UI_STRING_ID string_id) {

return &localized_strings[lang][string_id];
}

/***** Parsing detection by POSIX locale *****/

#define msgid(x)
#define msgstr(x)
#define LANG_POSIX_LOCALE(x) posix_locales[_LANG_ID] = (x);
#define LANG_PRIORITY(x) priorities[_LANG_ID] = (x);

static void init_posix_locales(const char* posix_locales[], int8_t priorities[]) {

#include "ui_i18n.h"

}

#undef LANG_PRIORITY
#undef LANG_POSIX_LOCALE
#undef msgstr
#undef msgid

UI_LANG_ID ui_guess_lang_by_posix_locale(const char* locale, UI_LANG_ID deflt) {
static const char* posix_locales[LANGS_MAX+1];
static int8_t priorities[LANGS_MAX+1];
static int ready = 0;

if(!ready) {
init_posix_locales(posix_locales, priorities);
ready = 1;
}

UI_LANG_ID i, found_lang;
int8_t found_prio = INT8_MAX;

// Try detecting by full prefix match first.
for(i = 0; i <= LANGS_MAX; i++) {
const char* l = posix_locales[i];
if(!l) continue;

if(strstr(locale, l)) {
if(found_prio > priorities[i]) {
found_lang = i;
found_prio = priorities[i];
}
}
}

if(found_prio < INT8_MAX) {
return found_lang;
}

// It appears we haven't found exact language_territory
// match (e.g. zh_TW) for given locale. ,
// Try stripping territory off and search only by language part.
for(i = 0; i <= LANGS_MAX; i++) {
const char* l = posix_locales[i];
if(!l) continue;

char* sep = strchr(l, '_');
if(!sep) continue;

if(!strncmp(locale, l, sep-l)) {
if(found_prio > priorities[i]) {
found_lang = i;
found_prio = priorities[i];
}
}
}

return found_prio < INT8_MAX ? found_lang : deflt;
}
24 changes: 24 additions & 0 deletions ui_i18n.h
Original file line number Diff line number Diff line change
@@ -1,113 +1,137 @@

//"CZECH" "Čeština"
#define _LANG_ID LANG_CS
LANG_POSIX_LOCALE("cs_CZ")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/cs.h"
#undef _LANG_ID

//"BULGARIAN" "Български"
#define _LANG_ID LANG_BG
LANG_POSIX_LOCALE("bg_BG")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/bg.h"
#undef _LANG_ID

//"GERMAN" "Deutsch"
#define _LANG_ID LANG_DE
LANG_POSIX_LOCALE("de_DE")
LANG_PRIORITY(-1) // Ensure this lang gets chosen for unknown de locales.
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/de.h"
#undef _LANG_ID

//"ENGLISH" "English"
#define _LANG_ID LANG_EN
LANG_POSIX_LOCALE("en_US")
LANG_PRIORITY(-1) // Ensure this lang gets chosen for unknown en locales.
#include "langs/en.h"
#undef _LANG_ID

//"SPANISH" "Spanish"
#define _LANG_ID LANG_ES
LANG_POSIX_LOCALE("es_ES")
LANG_PRIORITY(-1) // Ensure this lang gets chosen for unknown es locales.
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/es.h"
#undef _LANG_ID

//"FRENCH" "Français"
#define _LANG_ID LANG_FR
LANG_POSIX_LOCALE("fr_FR")
LANG_PRIORITY(-1) // Ensure this lang gets chosen for unknown fr locales.
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/fr.h"
#undef _LANG_ID

//"HINDI" "Hindi"
#define _LANG_ID LANG_HI
LANG_POSIX_LOCALE("hi_IN")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/hi.h"
#undef _LANG_ID

//"JAPANESE" "日本語"
#define _LANG_ID LANG_JA
LANG_POSIX_LOCALE("ja_JP")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/ja.h"
#undef _LANG_ID

//"ITALIAN" "Italiano"
#define _LANG_ID LANG_IT
LANG_POSIX_LOCALE("it_IT")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/it.h"
#undef _LANG_ID

//"LATVIAN" "Latviešu"
#define _LANG_ID LANG_LV
LANG_POSIX_LOCALE("lv_LV")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/lv.h"
#undef _LANG_ID

//"DUTCH" "Nederlands"
#define _LANG_ID LANG_NL
LANG_POSIX_LOCALE("nl_NL")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/nl.h"
#undef _LANG_ID

//"NORWEGIAN" "Norsk"
#define _LANG_ID LANG_NO
LANG_POSIX_LOCALE("no_NO")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/no.h"
#undef _LANG_ID

//"POLISH" "Polski"
#define _LANG_ID LANG_PL
LANG_POSIX_LOCALE("pl_PL")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/pl.h"
#undef _LANG_ID

//"ROMANIAN" "Română"
#define _LANG_ID LANG_RO
LANG_POSIX_LOCALE("ro_RO")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/ro.h"
#undef _LANG_ID

//"RUSSIAN" "Русский"
#define _LANG_ID LANG_RU
LANG_POSIX_LOCALE("ru_RU")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/ru.h"
#undef _LANG_ID

//"TURKISH" "Türk"
#define _LANG_ID LANG_TR
LANG_POSIX_LOCALE("tr_TR")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/tr.h"
#undef _LANG_ID

//"UKRAINIAN" "Українська"
#define _LANG_ID LANG_UA
LANG_POSIX_LOCALE("uk_UA")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/ua.h"
#undef _LANG_ID

//"SIMPLIFIED CHINESE" "简体中文"
#define _LANG_ID LANG_CN
LANG_POSIX_LOCALE("zh_CN")
LANG_PRIORITY(-1) // Ensure this lang gets chosen for unknown zh locales.
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/cn.h"
#undef _LANG_ID

//"TRADITIONAL CHINESE" "繁體中文"
#define _LANG_ID LANG_TW
LANG_POSIX_LOCALE("zh_TW")
#include "langs/en.h" //fallback to English for untranslated things
#include "langs/tw.h"
#undef _LANG_ID
Expand Down
2 changes: 2 additions & 0 deletions ui_i18n_decls.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,5 @@ typedef uint8_t UI_LANG_ID;
typedef uint16_t UI_STRING_ID;

STRING* ui_gettext(UI_LANG_ID lang, UI_STRING_ID string_id);

UI_LANG_ID ui_guess_lang_by_posix_locale(const char* locale, UI_LANG_ID deflt);

0 comments on commit 109cb41

Please sign in to comment.