Home | History | Annotate | Download | only in internal
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "languages/public/languages.h"
      6 
      7 #include "base/string_util.h"
      8 #include "encodings/compact_lang_det/win/cld_basictypes.h"
      9 
     10 
     11 Language default_language() {return ENGLISH;}
     12 
     13 
     14 // Language names and codes
     15 
     16 struct LanguageInfo {
     17   const char * language_name_;
     18   const char * language_code_639_1_;   // the ISO-639-1 code for the language
     19   const char * language_code_639_2_;   // the ISO-639-2 code for the language
     20   const char * language_code_other_;   // some nonstandard code for the language
     21 };
     22 
     23 static const LanguageInfo kLanguageInfoTable[] = {
     24   { "ENGLISH",             "en", "eng", NULL},
     25   { "DANISH",              "da", "dan", NULL},
     26   { "DUTCH",               "nl", "dut", NULL},
     27   { "FINNISH",             "fi", "fin", NULL},
     28   { "FRENCH",              "fr", "fre", NULL},
     29   { "GERMAN",              "de", "ger", NULL},
     30   { "HEBREW",              "he", "heb", NULL},
     31   { "ITALIAN",             "it", "ita", NULL},
     32   { "Japanese",            "ja", "jpn", NULL},
     33   { "Korean",              "ko", "kor", NULL},
     34   { "NORWEGIAN",           "nb", "nor", NULL},
     35   { "POLISH",              "pl", "pol", NULL},
     36   { "PORTUGUESE",          "pt", "por", NULL},
     37   { "RUSSIAN",             "ru", "rus", NULL},
     38   { "SPANISH",             "es", "spa", NULL},
     39   { "SWEDISH",             "sv", "swe", NULL},
     40   { "Chinese",             "zh", "chi", "zh-CN"},
     41   { "CZECH",               "cs", "cze", NULL},
     42   { "GREEK",               "el", "gre", NULL},
     43   { "ICELANDIC",           "is", "ice", NULL},
     44   { "LATVIAN",             "lv", "lav", NULL},
     45   { "LITHUANIAN",          "lt", "lit", NULL},
     46   { "ROMANIAN",            "ro", "rum", NULL},
     47   { "HUNGARIAN",           "hu", "hun", NULL},
     48   { "ESTONIAN",            "et", "est", NULL},
     49   // TODO: Although Teragram has two output names "TG_UNKNOWN_LANGUAGE"
     50   // and "Unknown", they are essentially the same. Need to unify them.
     51   // "un" and "ut" are invented by us, not from ISO-639.
     52   //
     53   { "TG_UNKNOWN_LANGUAGE", NULL, NULL, "ut"},
     54   { "Unknown",             NULL, NULL, "un"},
     55   { "BULGARIAN",           "bg", "bul", NULL},
     56   { "CROATIAN",            "hr", "scr", NULL},
     57   { "SERBIAN",             "sr", "scc", NULL},
     58   { "IRISH",               "ga", "gle", NULL},
     59   { "GALICIAN",            "gl", "glg", NULL},
     60   // Impossible to tell Tagalog from Filipino at the moment.
     61   // Use ISO 639-2 code for Filipino here.
     62   { "TAGALOG",             NULL, "fil", NULL},
     63   { "TURKISH",             "tr", "tur", NULL},
     64   { "UKRAINIAN",           "uk", "ukr", NULL},
     65   { "HINDI",               "hi", "hin", NULL},
     66   { "MACEDONIAN",          "mk", "mac", NULL},
     67   { "BENGALI",             "bn", "ben", NULL},
     68   { "INDONESIAN",          "id", "ind", NULL},
     69   { "LATIN",               "la", "lat", NULL},
     70   { "MALAY",               "ms", "may", NULL},
     71   { "MALAYALAM",           "ml", "mal", NULL},
     72   { "WELSH",               "cy", "wel", NULL},
     73   { "NEPALI",              "ne", "nep", NULL},
     74   { "TELUGU",              "te", "tel", NULL},
     75   { "ALBANIAN",            "sq", "alb", NULL},
     76   { "TAMIL",               "ta", "tam", NULL},
     77   { "BELARUSIAN",          "be", "bel", NULL},
     78   { "JAVANESE",            "jw", "jav", NULL},
     79   { "OCCITAN",             "oc", "oci", NULL},
     80   { "URDU",                "ur", "urd", NULL},
     81   { "BIHARI",              "bh", "bih", NULL},
     82   { "GUJARATI",            "gu", "guj", NULL},
     83   { "THAI",                "th", "tha", NULL},
     84   { "ARABIC",              "ar", "ara", NULL},
     85   { "CATALAN",             "ca", "cat", NULL},
     86   { "ESPERANTO",           "eo", "epo", NULL},
     87   { "BASQUE",              "eu", "baq", NULL},
     88   { "INTERLINGUA",         "ia", "ina", NULL},
     89   { "KANNADA",             "kn", "kan", NULL},
     90   { "PUNJABI",             "pa", "pan", NULL},
     91   { "SCOTS_GAELIC",        "gd", "gla", NULL},
     92   { "SWAHILI",             "sw", "swa", NULL},
     93   { "SLOVENIAN",           "sl", "slv", NULL},
     94   { "MARATHI",             "mr", "mar", NULL},
     95   { "MALTESE",             "mt", "mlt", NULL},
     96   { "VIETNAMESE",          "vi", "vie", NULL},
     97   { "FRISIAN",             "fy", "fry", NULL},
     98   { "SLOVAK",              "sk", "slo", NULL},
     99   { "ChineseT",
    100     NULL,  NULL,  // We intentionally set these 2 fields to NULL to avoid
    101                   // confusion between CHINESE_T and CHINESE.
    102     "zh-TW"},
    103   { "FAROESE",             "fo", "fao", NULL},
    104   { "SUNDANESE",           "su", "sun", NULL},
    105   { "UZBEK",               "uz", "uzb", NULL},
    106   { "AMHARIC",             "am", "amh", NULL},
    107   { "AZERBAIJANI",         "az", "aze", NULL},
    108   { "GEORGIAN",            "ka", "geo", NULL},
    109   { "TIGRINYA",            "ti", "tir", NULL},
    110   { "PERSIAN",             "fa", "per", NULL},
    111   { "BOSNIAN",             "bs", "bos", NULL},
    112   { "SINHALESE",           "si", "sin", NULL},
    113   { "NORWEGIAN_N",         "nn", "nno", NULL},
    114   { "PORTUGUESE_P",        NULL, NULL, "pt-PT"},
    115   { "PORTUGUESE_B",        NULL, NULL, "pt-BR"},
    116   { "XHOSA",               "xh", "xho", NULL},
    117   { "ZULU",                "zu", "zul", NULL},
    118   { "GUARANI",             "gn", "grn", NULL},
    119   { "SESOTHO",             "st", "sot", NULL},
    120   { "TURKMEN",             "tk", "tuk", NULL},
    121   { "KYRGYZ",              "ky", "kir", NULL},
    122   { "BRETON",              "br", "bre", NULL},
    123   { "TWI",                 "tw", "twi", NULL},
    124   { "YIDDISH",             "yi", "yid", NULL},
    125   { "SERBO_CROATIAN",      "sh", NULL, NULL},
    126   { "SOMALI",              "so", "som", NULL},
    127   { "UIGHUR",              "ug", "uig", NULL},
    128   { "KURDISH",             "ku", "kur", NULL},
    129   { "MONGOLIAN",           "mn", "mon", NULL},
    130   { "ARMENIAN",            "hy", "arm", NULL},
    131   { "LAOTHIAN",            "lo", "lao", NULL},
    132   { "SINDHI",              "sd", "snd", NULL},
    133   { "RHAETO_ROMANCE",      "rm", "roh", NULL},
    134   { "AFRIKAANS",           "af", "afr", NULL},
    135   { "LUXEMBOURGISH",       "lb", "ltz", NULL},
    136   { "BURMESE",             "my", "bur", NULL},
    137   // KHMER is known as Cambodian for Google user interfaces.
    138   { "KHMER",               "km", "khm", NULL},
    139   { "TIBETAN",             "bo", "tib", NULL},
    140   { "DHIVEHI",             "dv", "div", NULL},
    141   { "CHEROKEE",            NULL, "chr", NULL},
    142   { "SYRIAC",              NULL, "syr", NULL},
    143   { "LIMBU",               NULL, NULL, "sit-NP"},
    144   { "ORIYA",               "or", "ori", NULL},
    145   { "ASSAMESE",            "as", "asm", NULL},
    146   { "CORSICAN",            "co", "cos", NULL},
    147   { "INTERLINGUE",         "ie", "ine", NULL},
    148   { "KAZAKH",              "kk", "kaz", NULL},
    149   { "LINGALA",             "ln", "lin", NULL},
    150   { "MOLDAVIAN",           "mo", "mol", NULL},
    151   { "PASHTO",              "ps", "pus", NULL},
    152   { "QUECHUA",             "qu", "que", NULL},
    153   { "SHONA",               "sn", "sna", NULL},
    154   { "TAJIK",               "tg", "tgk", NULL},
    155   { "TATAR",               "tt", "tat", NULL},
    156   { "TONGA",               "to", "tog", NULL},
    157   { "YORUBA",              "yo", "yor", NULL},
    158   { "CREOLES_AND_PIDGINS_ENGLISH_BASED", NULL, "cpe", NULL},
    159   { "CREOLES_AND_PIDGINS_FRENCH_BASED",  NULL, "cpf", NULL},
    160   { "CREOLES_AND_PIDGINS_PORTUGUESE_BASED", NULL, "cpp", NULL},
    161   { "CREOLES_AND_PIDGINS_OTHER", NULL, "crp", NULL},
    162   { "MAORI",               "mi", "mao", NULL},
    163   { "WOLOF",               "wo", "wol", NULL},
    164   { "ABKHAZIAN",           "ab", "abk", NULL},
    165   { "AFAR",                "aa", "aar", NULL},
    166   { "AYMARA",              "ay", "aym", NULL},
    167   { "BASHKIR",             "ba", "bak", NULL},
    168   { "BISLAMA",             "bi", "bis", NULL},
    169   { "DZONGKHA",            "dz", "dzo", NULL},
    170   { "FIJIAN",              "fj", "fij", NULL},
    171   { "GREENLANDIC",         "kl", "kal", NULL},
    172   { "HAUSA",               "ha", "hau", NULL},
    173   { "HAITIAN_CREOLE",       "ht", NULL, NULL},
    174   { "INUPIAK",             "ik", "ipk", NULL},
    175   { "INUKTITUT",           "iu", "iku", NULL},
    176   { "KASHMIRI",            "ks", "kas", NULL},
    177   { "KINYARWANDA",         "rw", "kin", NULL},
    178   { "MALAGASY",            "mg", "mlg", NULL},
    179   { "NAURU",               "na", "nau", NULL},
    180   { "OROMO",               "om", "orm", NULL},
    181   { "RUNDI",               "rn", "run", NULL},
    182   { "SAMOAN",              "sm", "smo", NULL},
    183   { "SANGO",               "sg", "sag", NULL},
    184   { "SANSKRIT",            "sa", "san", NULL},
    185   { "SISWANT",             "ss", "ssw", NULL},
    186   { "TSONGA",              "ts", "tso", NULL},
    187   { "TSWANA",              "tn", "tsn", NULL},
    188   { "VOLAPUK",             "vo", "vol", NULL},
    189   { "ZHUANG",              "za", "zha", NULL},
    190   { "KHASI",               NULL, "kha", NULL},
    191   { "SCOTS",               NULL, "sco", NULL},
    192   { "GANDA",               "lg", "lug", NULL},
    193   { "MANX",                "gv", "glv", NULL},
    194   { "MONTENEGRIN",         NULL, NULL, "sr-ME"},
    195   { "XX",                  NULL, NULL, "XX"},
    196 };
    197 
    198 COMPILE_ASSERT(arraysize(kLanguageInfoTable) == NUM_LANGUAGES + 1,
    199                kLanguageInfoTable_has_incorrect_length);
    200 
    201 
    202 // LANGUAGE NAMES
    203 
    204 const char* default_language_name() {
    205   return kLanguageInfoTable[ENGLISH].language_name_;
    206 }
    207 
    208 static const char* const kInvalidLanguageName = "invalid_language";
    209 
    210 const char *invalid_language_name() {
    211   return kInvalidLanguageName;
    212 }
    213 
    214 const char* LanguageName(Language lang) {
    215   return IsValidLanguage(lang)
    216       ? kLanguageInfoTable[lang].language_name_
    217       : kInvalidLanguageName;
    218 }
    219 
    220 
    221 
    222 // LANGUAGE CODES
    223 
    224 
    225 // The space before invalid_language_code is intentional. It is used
    226 // to prevent it matching any two letter language code.
    227 //
    228 static const char* const kInvalidLanguageCode = " invalid_language_code";
    229 
    230 const char *invalid_language_code() {
    231   return kInvalidLanguageCode;
    232 }
    233 
    234 const char * LanguageCode(Language lang) {
    235   if (! IsValidLanguage(lang))
    236     return kInvalidLanguageCode;
    237   const LanguageInfo& info = kLanguageInfoTable[lang];
    238   if (info.language_code_639_1_) {
    239     return info.language_code_639_1_;
    240   } else if (info.language_code_639_2_) {
    241     return info.language_code_639_2_;
    242   } else if (info.language_code_other_) {
    243     return info.language_code_other_;
    244   } else {
    245     return kInvalidLanguageCode;
    246   }
    247 }
    248 
    249 const char* default_language_code() {
    250   return kLanguageInfoTable[ENGLISH].language_code_639_1_;
    251 }
    252 
    253 const char* LanguageCodeISO639_1(Language lang) {
    254   if (! IsValidLanguage(lang))
    255     return kInvalidLanguageCode;
    256   if (const char* code = kLanguageInfoTable[lang].language_code_639_1_)
    257     return code;
    258   return kInvalidLanguageCode;
    259 }
    260 
    261 const char* LanguageCodeISO639_2(Language lang) {
    262   if (! IsValidLanguage(lang))
    263     return kInvalidLanguageCode;
    264   if (const char* code = kLanguageInfoTable[lang].language_code_639_2_)
    265     return code;
    266   return kInvalidLanguageCode;
    267 }
    268 
    269 const char* LanguageCodeWithDialects(Language lang) {
    270   if (lang == CHINESE)
    271     return "zh-CN";
    272   return LanguageCode(lang);
    273 }
    274 
    275 
    276 
    277 bool LanguageFromCode(const char* lang_code, Language *language) {
    278   *language = UNKNOWN_LANGUAGE;
    279   if ( lang_code == NULL ) return false;
    280 
    281   for ( int i = 0 ; i < kNumLanguages ; i++ ) {
    282     const LanguageInfo& info = kLanguageInfoTable[i];
    283     if ((info.language_code_639_1_ &&
    284          !base::strcasecmp(lang_code, info.language_code_639_1_)) ||
    285         (info.language_code_639_2_ &&
    286          !base::strcasecmp(lang_code, info.language_code_639_2_)) ||
    287         (info.language_code_other_ &&
    288          !base::strcasecmp(lang_code, info.language_code_other_))) {
    289       *language = static_cast<Language>(i);
    290       return true;
    291     }
    292   }
    293 
    294   // For convenience, this function can also parse the non-standard
    295   // five-letter language codes "zh-cn" and "zh-tw" which are used by
    296   // front-ends such as GWS to distinguish Simplified from Traditional
    297   // Chinese.
    298   if (!base::strcasecmp(lang_code, "zh-cn") ||
    299       !base::strcasecmp(lang_code, "zh_cn")) {
    300     *language = CHINESE;
    301     return true;
    302   }
    303   if (!base::strcasecmp(lang_code, "zh-tw") ||
    304       !base::strcasecmp(lang_code, "zh_tw")) {
    305     *language = CHINESE_T;
    306     return true;
    307   }
    308   if (!base::strcasecmp(lang_code, "sr-me") ||
    309       !base::strcasecmp(lang_code, "sr_me")) {
    310     *language = MONTENEGRIN;
    311     return true;
    312   }
    313 
    314   // Process language-code synonyms.
    315   if (!base::strcasecmp(lang_code, "he")) {
    316     *language = HEBREW;  // Use "iw".
    317     return true;
    318   }
    319   if (!base::strcasecmp(lang_code, "in")) {
    320     *language = INDONESIAN;  // Use "id".
    321     return true;
    322   }
    323   if (!base::strcasecmp(lang_code, "ji")) {
    324     *language = YIDDISH;  // Use "yi".
    325     return true;
    326   }
    327 
    328   // Process language-detection synonyms.
    329   // These distinct languages cannot be differentiated by our current
    330   // language-detection algorithms.
    331   if (!base::strcasecmp(lang_code, "fil")) {
    332     *language = TAGALOG;
    333     return true;
    334   }
    335 
    336   return false;
    337 }
    338