Use findlocale by Adam D. Moss (http://icculus.org/~aspirin/findlocale/)
authorWolfgang Becker <uafr@gmx.de>
Mon, 26 Jun 2006 16:38:47 +0000 (16:38 +0000)
committerWolfgang Becker <uafr@gmx.de>
Mon, 26 Jun 2006 16:38:47 +0000 (16:38 +0000)
to determine language on all plattforms.

SVN-Revision: 3770

src/tinygettext/findlocale.cpp [new file with mode: 0644]
src/tinygettext/findlocale.hpp [new file with mode: 0644]
src/tinygettext/tinygettext.cpp

diff --git a/src/tinygettext/findlocale.cpp b/src/tinygettext/findlocale.cpp
new file mode 100644 (file)
index 0000000..da3fa1c
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ findlocale-0.46.tar.gz from http://icculus.org/~aspirin/findlocale/
+Copyright (C) 2004 Adam D. Moss (the "Author").  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the Author of the
+Software shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written authorization
+from the Author.
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <winnt.h>
+#endif
+
+#include "findlocale.hpp"
+
+static int
+is_lcchar(const int c) {
+  return isalnum(c);
+}
+
+static void
+lang_country_variant_from_envstring(const char *str,
+                                    char **lang,
+                                    char **country,
+                                    char **variant) {
+  int end = 0;
+  int start;
+
+  /* get lang, if any */
+  start = end;
+  while (is_lcchar(str[end])) {
+    ++end;
+  }
+  if (start != end) {
+    int i;
+    int len = end - start;
+    char *s = (char*) malloc(len + 1);
+    for (i=0; i<len; ++i) {
+      s[i] = tolower(str[start + i]);
+    }
+    s[i] = '\0';
+    *lang = s;
+  } else {
+    *lang = NULL;
+  }
+
+  if (str[end] && str[end]!=':') { /* not at end of str */
+    ++end;
+  }
+
+  /* get country, if any */
+  start = end;
+  while (is_lcchar(str[end])) {
+    ++end;
+  }
+  if (start != end) {
+    int i;
+    int len = end - start;
+    char *s = (char*) malloc(len + 1);
+    for (i=0; i<len; ++i) {
+      s[i] = toupper(str[start + i]);
+    }
+    s[i] = '\0';
+    *country = s;
+  } else {
+    *country = NULL;
+  }
+
+  if (str[end] && str[end]!=':') { /* not at end of str */
+    ++end;
+  }
+
+  /* get variant, if any */
+  start = end;
+  while (str[end] && str[end]!=':') {
+    ++end;
+  }
+  if (start != end) {
+    int i;
+    int len = end - start;
+    char *s = (char*) malloc(len + 1);
+    for (i=0; i<len; ++i) {
+      s[i] = str[start + i];
+    }
+    s[i] = '\0';
+    *variant = s;
+  } else {
+    *variant = NULL;
+  }
+}
+
+
+static int
+accumulate_locstring(const char *str, FL_Locale *l) {
+  char *lang = NULL;
+  char *country = NULL;
+  char *variant = NULL;
+  if (str) {
+    lang_country_variant_from_envstring(str, &lang, &country, &variant);
+    if (lang) {
+      l->lang = lang;
+      l->country = country;
+      l->variant = variant;
+      return 1;
+    }
+  }
+  free(lang); free(country); free(variant);
+  return 0;
+}
+
+
+static int
+accumulate_env(const char *name, FL_Locale *l) {
+  char *env;
+  char *lang = NULL;
+  char *country = NULL;
+  char *variant = NULL;
+  env = getenv(name);
+  if (env) {
+    return accumulate_locstring(env, l);
+  }
+  free(lang); free(country); free(variant);
+  return 0;
+}
+
+
+static void
+canonise_fl(FL_Locale *l) {
+  /* this function fixes some common locale-specifying mistakes */
+  /* en_UK -> en_GB */
+  if (l->lang && 0 == strcmp(l->lang, "en")) {
+    if (l->country && 0 == strcmp(l->country, "UK")) {
+      free((void*)l->country);
+      l->country = strdup("GB");
+    }
+  }
+  /* ja_JA -> ja_JP */
+  if (l->lang && 0 == strcmp(l->lang, "ja")) {
+    if (l->country && 0 == strcmp(l->country, "JA")) {
+      free((void*)l->country);
+      l->country = strdup("JP");
+    }
+  }
+}
+
+
+#ifdef WIN32
+#include <stdio.h>
+#define ML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##pn##_##sn)
+#define MLN(pn) MAKELANGID(LANG_##pn, SUBLANG_DEFAULT)
+#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
+typedef struct {
+  LANGID id;
+  char*  code;
+} IDToCode;
+static const IDToCode both_to_code[] = {
+  {ML(ENGLISH,US),           "en_US.ISO_8859-1"},
+  {ML(ENGLISH,CAN),          "en_CA"}, /* english / canadian */
+  {ML(ENGLISH,UK),           "en_GB"},
+  {ML(ENGLISH,EIRE),         "en_IE"},
+  {ML(ENGLISH,AUS),          "en_AU"},
+  {MLN(GERMAN),              "de_DE"},
+  {MLN(SPANISH),             "es_ES"},
+  {ML(SPANISH,MEXICAN),      "es_MX"},
+  {MLN(FRENCH),              "fr_FR"},
+  {ML(FRENCH,CANADIAN),      "fr_CA"},
+  {ML(FRENCH,BELGIAN),       "fr_BE"}, /* ? */
+  {ML(DUTCH,BELGIAN),        "nl_BE"}, /* ? */
+  {ML(PORTUGUESE,BRAZILIAN), "pt_BR"},
+  {MLN(PORTUGUESE),          "pt_PT"},
+  {MLN(SWEDISH),             "sv_SE"},
+  {ML(CHINESE,HONGKONG),     "zh_HK"},
+  /* these are machine-generated and not yet verified */
+  {RML(AFRIKAANS,DEFAULT), "af_ZA"},
+  {RML(ALBANIAN,DEFAULT), "sq_AL"},
+  {RML(ARABIC,ARABIC_ALGERIA), "ar_DZ"},
+  {RML(ARABIC,ARABIC_BAHRAIN), "ar_BH"},
+  {RML(ARABIC,ARABIC_EGYPT), "ar_EG"},
+  {RML(ARABIC,ARABIC_IRAQ), "ar_IQ"},
+  {RML(ARABIC,ARABIC_JORDAN), "ar_JO"},
+  {RML(ARABIC,ARABIC_KUWAIT), "ar_KW"},
+  {RML(ARABIC,ARABIC_LEBANON), "ar_LB"},
+  {RML(ARABIC,ARABIC_LIBYA), "ar_LY"},
+  {RML(ARABIC,ARABIC_MOROCCO), "ar_MA"},
+  {RML(ARABIC,ARABIC_OMAN), "ar_OM"},
+  {RML(ARABIC,ARABIC_QATAR), "ar_QA"},
+  {RML(ARABIC,ARABIC_SAUDI_ARABIA), "ar_SA"},
+  {RML(ARABIC,ARABIC_SYRIA), "ar_SY"},
+  {RML(ARABIC,ARABIC_TUNISIA), "ar_TN"},
+  {RML(ARABIC,ARABIC_UAE), "ar_AE"},
+  {RML(ARABIC,ARABIC_YEMEN), "ar_YE"},
+  {RML(ARMENIAN,DEFAULT), "hy_AM"},
+  {RML(AZERI,AZERI_CYRILLIC), "az_AZ"},
+  {RML(AZERI,AZERI_LATIN), "az_AZ"},
+  {RML(BASQUE,DEFAULT), "eu_ES"},
+  {RML(BELARUSIAN,DEFAULT), "be_BY"},
+/*{RML(BRETON,DEFAULT), "br_FR"},*/
+  {RML(BULGARIAN,DEFAULT), "bg_BG"},
+  {RML(CATALAN,DEFAULT), "ca_ES"},
+  {RML(CHINESE,CHINESE_HONGKONG), "zh_HK"},
+  {RML(CHINESE,CHINESE_MACAU), "zh_MO"},
+  {RML(CHINESE,CHINESE_SIMPLIFIED), "zh_CN"},
+  {RML(CHINESE,CHINESE_SINGAPORE), "zh_SG"},
+  {RML(CHINESE,CHINESE_TRADITIONAL), "zh_TW"},
+/*{RML(CORNISH,DEFAULT), "kw_GB"},*/
+  {RML(CZECH,DEFAULT), "cs_CZ"},
+  {RML(DANISH,DEFAULT), "da_DK"},
+  {RML(DUTCH,DUTCH), "nl_NL"},
+  {RML(DUTCH,DUTCH_BELGIAN), "nl_BE"},
+/*{RML(DUTCH,DUTCH_SURINAM), "nl_SR"},*/
+  {RML(ENGLISH,ENGLISH_AUS), "en_AU"},
+  {RML(ENGLISH,ENGLISH_BELIZE), "en_BZ"},
+  {RML(ENGLISH,ENGLISH_CAN), "en_CA"},
+  {RML(ENGLISH,ENGLISH_CARIBBEAN), "en_CB"},
+  {RML(ENGLISH,ENGLISH_EIRE), "en_IE"},
+  {RML(ENGLISH,ENGLISH_JAMAICA), "en_JM"},
+  {RML(ENGLISH,ENGLISH_NZ), "en_NZ"},
+  {RML(ENGLISH,ENGLISH_PHILIPPINES), "en_PH"},
+  {RML(ENGLISH,ENGLISH_SOUTH_AFRICA), "en_ZA"},
+  {RML(ENGLISH,ENGLISH_TRINIDAD), "en_TT"},
+  {RML(ENGLISH,ENGLISH_UK), "en_GB"},
+  {RML(ENGLISH,ENGLISH_US), "en_US"},
+  {RML(ENGLISH,ENGLISH_ZIMBABWE), "en_ZW"},
+/*{RML(ESPERANTO,DEFAULT), "eo_"},*/
+  {RML(ESTONIAN,DEFAULT), "et_EE"},
+  {RML(FAEROESE,DEFAULT), "fo_FO"},
+  {RML(FARSI,DEFAULT), "fa_IR"},
+  {RML(FINNISH,DEFAULT), "fi_FI"},
+  {RML(FRENCH,FRENCH), "fr_FR"},
+  {RML(FRENCH,FRENCH_BELGIAN), "fr_BE"},
+  {RML(FRENCH,FRENCH_CANADIAN), "fr_CA"},
+  {RML(FRENCH,FRENCH_LUXEMBOURG), "fr_LU"},
+  {RML(FRENCH,FRENCH_MONACO), "fr_MC"},
+  {RML(FRENCH,FRENCH_SWISS), "fr_CH"},
+/*{RML(GAELIC,GAELIC), "ga_IE"},*/
+/*{RML(GAELIC,GAELIC_MANX), "gv_GB"},*/
+/*{RML(GAELIC,GAELIC_SCOTTISH), "gd_GB"},*/
+/*{RML(GALICIAN,DEFAULT), "gl_ES"},*/
+  {RML(GEORGIAN,DEFAULT), "ka_GE"},
+  {RML(GERMAN,GERMAN), "de_DE"},
+  {RML(GERMAN,GERMAN_AUSTRIAN), "de_AT"},
+  {RML(GERMAN,GERMAN_LIECHTENSTEIN), "de_LI"},
+  {RML(GERMAN,GERMAN_LUXEMBOURG), "de_LU"},
+  {RML(GERMAN,GERMAN_SWISS), "de_CH"},
+  {RML(GREEK,DEFAULT), "el_GR"},
+  {RML(GUJARATI,DEFAULT), "gu_IN"},
+  {RML(HEBREW,DEFAULT), "he_IL"},
+  {RML(HINDI,DEFAULT), "hi_IN"},
+  {RML(HUNGARIAN,DEFAULT), "hu_HU"},
+  {RML(ICELANDIC,DEFAULT), "is_IS"},
+  {RML(INDONESIAN,DEFAULT), "id_ID"},
+  {RML(ITALIAN,ITALIAN), "it_IT"},
+  {RML(ITALIAN,ITALIAN_SWISS), "it_CH"},
+  {RML(JAPANESE,DEFAULT), "ja_JP"},
+  {RML(KANNADA,DEFAULT), "kn_IN"},
+  {RML(KAZAK,DEFAULT), "kk_KZ"},
+  {RML(KONKANI,DEFAULT), "kok_IN"},
+  {RML(KOREAN,KOREAN), "ko_KR"},
+/*{RML(KYRGYZ,DEFAULT), "ky_KG"},*/
+  {RML(LATVIAN,DEFAULT), "lv_LV"},
+  {RML(LITHUANIAN,LITHUANIAN), "lt_LT"},
+  {RML(MACEDONIAN,DEFAULT), "mk_MK"},
+  {RML(MALAY,MALAY_BRUNEI_DARUSSALAM), "ms_BN"},
+  {RML(MALAY,MALAY_MALAYSIA), "ms_MY"},
+  {RML(MARATHI,DEFAULT), "mr_IN"},
+/*{RML(MONGOLIAN,DEFAULT), "mn_MN"},*/
+  {RML(NORWEGIAN,NORWEGIAN_BOKMAL), "nb_NO"},
+  {RML(NORWEGIAN,NORWEGIAN_NYNORSK), "nn_NO"},
+  {RML(POLISH,DEFAULT), "pl_PL"},
+  {RML(PORTUGUESE,PORTUGUESE), "pt_PT"},
+  {RML(PORTUGUESE,PORTUGUESE_BRAZILIAN), "pt_BR"},
+  {RML(PUNJABI,DEFAULT), "pa_IN"},
+  {RML(ROMANIAN,DEFAULT), "ro_RO"},
+  {RML(RUSSIAN,DEFAULT), "ru_RU"},
+  {RML(SANSKRIT,DEFAULT), "sa_IN"},
+  {RML(SERBIAN,DEFAULT), "hr_HR"},
+  {RML(SERBIAN,SERBIAN_CYRILLIC), "sr_SP"},
+  {RML(SERBIAN,SERBIAN_LATIN), "sr_SP"},
+  {RML(SLOVAK,DEFAULT), "sk_SK"},
+  {RML(SLOVENIAN,DEFAULT), "sl_SI"},
+  {RML(SPANISH,SPANISH), "es_ES"},
+  {RML(SPANISH,SPANISH_ARGENTINA), "es_AR"},
+  {RML(SPANISH,SPANISH_BOLIVIA), "es_BO"},
+  {RML(SPANISH,SPANISH_CHILE), "es_CL"},
+  {RML(SPANISH,SPANISH_COLOMBIA), "es_CO"},
+  {RML(SPANISH,SPANISH_COSTA_RICA), "es_CR"},
+  {RML(SPANISH,SPANISH_DOMINICAN_REPUBLIC), "es_DO"},
+  {RML(SPANISH,SPANISH_ECUADOR), "es_EC"},
+  {RML(SPANISH,SPANISH_EL_SALVADOR), "es_SV"},
+  {RML(SPANISH,SPANISH_GUATEMALA), "es_GT"},
+  {RML(SPANISH,SPANISH_HONDURAS), "es_HN"},
+  {RML(SPANISH,SPANISH_MEXICAN), "es_MX"},
+  {RML(SPANISH,SPANISH_MODERN), "es_ES"},
+  {RML(SPANISH,SPANISH_NICARAGUA), "es_NI"},
+  {RML(SPANISH,SPANISH_PANAMA), "es_PA"},
+  {RML(SPANISH,SPANISH_PARAGUAY), "es_PY"},
+  {RML(SPANISH,SPANISH_PERU), "es_PE"},
+  {RML(SPANISH,SPANISH_PUERTO_RICO), "es_PR"},
+  {RML(SPANISH,SPANISH_URUGUAY), "es_UY"},
+  {RML(SPANISH,SPANISH_VENEZUELA), "es_VE"},
+  {RML(SWAHILI,DEFAULT), "sw_KE"},
+  {RML(SWEDISH,SWEDISH), "sv_SE"},
+  {RML(SWEDISH,SWEDISH_FINLAND), "sv_FI"},
+/*{RML(SYRIAC,DEFAULT), "syr_SY"},*/
+  {RML(TAMIL,DEFAULT), "ta_IN"},
+  {RML(TATAR,DEFAULT), "tt_TA"},
+  {RML(TELUGU,DEFAULT), "te_IN"},
+  {RML(THAI,DEFAULT), "th_TH"},
+  {RML(TURKISH,DEFAULT), "tr_TR"},
+  {RML(UKRAINIAN,DEFAULT), "uk_UA"},
+  {RML(URDU,URDU_PAKISTAN), "ur_PK"},
+  {RML(UZBEK,UZBEK_CYRILLIC), "uz_UZ"},
+  {RML(UZBEK,UZBEK_LATIN), "uz_UZ"},
+  {RML(VIETNAMESE,DEFAULT), "vi_VN"},
+/*{RML(WALON,DEFAULT), "wa_BE"},*/
+/*{RML(WELSH,DEFAULT), "cy_GB"},*/
+};
+static const IDToCode primary_to_code[] = {
+  {LANG_AFRIKAANS,  "af"},
+  {LANG_ARABIC,     "ar"},
+  {LANG_AZERI,      "az"},
+  {LANG_BULGARIAN,  "bg"},
+/*{LANG_BRETON,     "br"},*/
+  {LANG_BELARUSIAN, "by"},
+  {LANG_CATALAN,    "ca"},
+  {LANG_CZECH,      "cs"},
+/*{LANG_WELSH,      "cy"},*/
+  {LANG_DANISH,     "da"},
+  {LANG_GERMAN,     "de"},
+  {LANG_GREEK,      "el"},
+  {LANG_ENGLISH,    "en"},
+/*{LANG_ESPERANTO,  "eo"},*/
+  {LANG_SPANISH,    "es"},
+  {LANG_ESTONIAN,   "et"},
+  {LANG_BASQUE,     "eu"},
+  {LANG_FARSI,      "fa"},
+  {LANG_FINNISH,    "fi"},
+  {LANG_FAEROESE,   "fo"},
+  {LANG_FRENCH,     "fr"},
+/*{LANG_GAELIC,     "ga"},*/
+/*{LANG_GALICIAN,   "gl"},*/
+  {LANG_GUJARATI,   "gu"},
+  {LANG_HEBREW,     "he"},
+  {LANG_HINDI,      "hi"},
+  {LANG_SERBIAN,    "hr"},
+  {LANG_HUNGARIAN,  "hu"},
+  {LANG_ARMENIAN,   "hy"},
+  {LANG_INDONESIAN, "id"},
+  {LANG_ITALIAN,    "it"},
+  {LANG_JAPANESE,   "ja"},
+  {LANG_GEORGIAN,   "ka"},
+  {LANG_KAZAK,      "kk"},
+  {LANG_KANNADA,    "kn"},
+  {LANG_KOREAN,     "ko"},
+/*{LANG_KYRGYZ,     "ky"},*/
+  {LANG_LITHUANIAN, "lt"},
+  {LANG_LATVIAN,    "lv"},
+  {LANG_MACEDONIAN, "mk"},
+/*{LANG_MONGOLIAN,  "mn"},*/
+  {LANG_MARATHI,    "mr"},
+  {LANG_MALAY,      "ms"},
+  {LANG_NORWEGIAN,  "nb"},
+  {LANG_DUTCH,      "nl"},
+  {LANG_NORWEGIAN,  "nn"},
+  {LANG_NORWEGIAN,  "no"},/* unofficial? */
+  {LANG_PUNJABI,    "pa"},
+  {LANG_POLISH,     "pl"},
+  {LANG_PORTUGUESE, "pt"},
+  {LANG_ROMANIAN,   "ro"},
+  {LANG_RUSSIAN,    "ru"},
+  {LANG_SLOVAK,     "sk"},
+  {LANG_SLOVENIAN,  "sl"},
+  {LANG_ALBANIAN,   "sq"},
+  {LANG_SERBIAN,    "sr"},
+  {LANG_SWEDISH,    "sv"},
+  {LANG_SWAHILI,    "sw"},
+  {LANG_TAMIL,      "ta"},
+  {LANG_THAI,       "th"},
+  {LANG_TURKISH,    "tr"},
+  {LANG_TATAR,      "tt"},
+  {LANG_UKRAINIAN,  "uk"},
+  {LANG_URDU,       "ur"},
+  {LANG_UZBEK,      "uz"},
+  {LANG_VIETNAMESE, "vi"},
+/*{LANG_WALON,      "wa"},*/
+  {LANG_CHINESE,    "zh"},
+};
+static int num_primary_to_code =
+  sizeof(primary_to_code) / sizeof(*primary_to_code);
+static int num_both_to_code =
+  sizeof(both_to_code) / sizeof(*both_to_code);
+
+static const int
+lcid_to_fl(LCID lcid,
+           FL_Locale *rtn) {
+  LANGID langid       = LANGIDFROMLCID(lcid);
+  LANGID primary_lang = PRIMARYLANGID(langid);
+  LANGID sub_lang     = SUBLANGID(langid);
+  int i;
+  /* try to find an exact primary/sublanguage combo that we know about */
+  for (i=0; i<num_both_to_code; ++i) {
+    if (both_to_code[i].id == langid) {
+      accumulate_locstring(both_to_code[i].code, rtn);
+      return 1;
+    }
+  }
+  /* fallback to just checking the primary language id */
+  for (i=0; i<num_primary_to_code; ++i) {
+    if (primary_to_code[i].id == primary_lang) {
+      accumulate_locstring(primary_to_code[i].code, rtn);
+      return 1;
+    }
+  }
+  return 0;
+}
+#endif
+
+
+FL_Success
+FL_FindLocale(FL_Locale **locale, FL_Domain /*domain*/) {
+  FL_Success success = FL_FAILED;
+  FL_Locale *rtn = (FL_Locale*) malloc(sizeof(FL_Locale));
+  rtn->lang = NULL;
+  rtn->country = NULL;
+  rtn->variant = NULL;
+
+#ifdef WIN32
+  /* win32 >= mswindows95 */
+  {
+    LCID lcid = GetThreadLocale();
+    if (lcid_to_fl(lcid, rtn)) {
+      success = FL_CONFIDENT;
+    }
+    if (success == FL_FAILED) {
+      /* assume US English on mswindows systems unless we know otherwise */
+      if (accumulate_locstring("en_US.ISO_8859-1", rtn)) {
+        success = FL_DEFAULT_GUESS;
+      }
+    }
+  }
+#else
+  /* assume unixoid */
+  {
+    /* examples: */
+    /* sv_SE.ISO_8859-1 */
+    /* fr_FR.ISO8859-1 */
+    /* no_NO_NB */
+    /* no_NO_NY */
+    /* no_NO */
+    /* de_DE */
+    /* try the various vars in decreasing order of authority */
+    if (accumulate_env("LC_ALL", rtn) ||
+        accumulate_env("LC_MESSAGES", rtn) ||
+        accumulate_env("LANG", rtn) ||
+        accumulate_env("LANGUAGE", rtn)) {
+      success = FL_CONFIDENT;
+    }
+    if (success == FL_FAILED) {
+      /* assume US English on unixoid systems unless we know otherwise */
+      if (accumulate_locstring("en_US.ISO_8859-1", rtn)) {
+        success = FL_DEFAULT_GUESS;
+      }
+    }
+  }
+#endif
+
+  if (success != FL_FAILED) {
+    canonise_fl(rtn);
+  }
+
+  *locale = rtn;
+  return success;
+}
+
+
+void
+FL_FreeLocale(FL_Locale **locale) {
+  if (locale) {
+    FL_Locale *l = *locale;
+    if (l) {
+      if (l->lang) {
+        free((void*)l->lang);
+      }
+      if (l->country) {
+        free((void*)l->country);
+      }
+      if (l->variant) {
+        free((void*)l->variant);
+      }
+      free(l);
+      *locale = NULL;
+    }
+  }
+}
diff --git a/src/tinygettext/findlocale.hpp b/src/tinygettext/findlocale.hpp
new file mode 100644 (file)
index 0000000..ab4d847
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ findlocale-0.46.tar.gz from http://icculus.org/~aspirin/findlocale/
+
+Copyright (C) 2004 Adam D. Moss (the "Author").  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the Author of the
+Software shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in this Software without prior written authorization
+from the Author.
+
+*/
+
+#ifndef __findlocale_h_
+#define __findlocale_h_
+
+typedef const char* FL_Lang;
+typedef const char* FL_Country;
+typedef const char* FL_Variant;
+
+typedef struct {
+  FL_Lang    lang;
+  FL_Country country;
+  FL_Variant variant;
+} FL_Locale;
+
+typedef enum {
+  /* for some reason we failed to even guess: this should never happen */
+  FL_FAILED        = 0,
+  /* couldn't query locale -- returning a guess (almost always English) */
+  FL_DEFAULT_GUESS = 1,
+  /* the returned locale type was found by successfully asking the system */
+  FL_CONFIDENT     = 2
+} FL_Success;
+
+typedef enum {
+  FL_MESSAGES = 0
+} FL_Domain;
+
+/* This allocates/fills in a FL_Locale structure with pointers to
+   strings (which should be treated as static), or NULL for inappropriate /
+   undetected fields. */
+FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
+/* This should be used to free the struct written by FL_FindLocale */
+void FL_FreeLocale(FL_Locale **locale);
+
+#endif /*__findlocale_h_*/
index e248801..d51f627 100644 (file)
@@ -30,6 +30,7 @@
 #include "log.hpp"
 #include "physfs/physfs_stream.hpp"
 #include "log.hpp"
+#include "findlocale.hpp"
 
 //#define TRANSLATION_DEBUG
 
@@ -180,15 +181,18 @@ DictionaryManager::DictionaryManager()
   : current_dict(&empty_dict)
 {
   parseLocaleAliases();
-  // setup language from environment vars
-  const char* lang = getenv("LC_ALL");
-  if(!lang)
-    lang = getenv("LC_MESSAGES");
-  if(!lang)
-    lang = getenv("LANG");
-  
-  if(lang)
-    set_language(lang);
+  // Environment variable SUPERTUX_LANG overrides language settings.
+  const char* lang = getenv( "SUPERTUX_LANG" );
+  if( lang ){
+    set_language( lang );
+    return;
+  }  
+  // use findlocale to setup language
+  FL_Locale *locale;
+  FL_FindLocale( &locale, FL_MESSAGES );
+      if( locale->lang)
+        set_language( locale->lang );
+  FL_FreeLocale( &locale );
 }
 
 void