Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2011 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 "chrome/common/spellcheck_common.h"
      6 
      7 #include "base/file_path.h"
      8 
      9 namespace SpellCheckCommon {
     10 
     11 static const struct {
     12   // The language.
     13   const char* language;
     14 
     15   // The corresponding language and region, used by the dictionaries.
     16   const char* language_region;
     17 } g_supported_spellchecker_languages[] = {
     18   // Several languages are not to be included in the spellchecker list:
     19   // th-TH, uk-UA
     20   {"bg", "bg-BG"},
     21   {"ca", "ca-ES"},
     22   {"cs", "cs-CZ"},
     23   {"da", "da-DK"},
     24   {"de", "de-DE"},
     25   {"el", "el-GR"},
     26   {"en-AU", "en-AU"},
     27   {"en-CA", "en-CA"},
     28   {"en-GB", "en-GB"},
     29   {"en-US", "en-US"},
     30   {"es", "es-ES"},
     31   {"et", "et-EE"},
     32   {"fr", "fr-FR"},
     33   {"he", "he-IL"},
     34   {"hi", "hi-IN"},
     35   {"hr", "hr-HR"},
     36   {"hu", "hu-HU"},
     37   {"id", "id-ID"},
     38   {"it", "it-IT"},
     39   {"lt", "lt-LT"},
     40   {"lv", "lv-LV"},
     41   {"nb", "nb-NO"},
     42   {"nl", "nl-NL"},
     43   {"pl", "pl-PL"},
     44   {"pt-BR", "pt-BR"},
     45   {"pt-PT", "pt-PT"},
     46   {"ro", "ro-RO"},
     47   {"ru", "ru-RU"},
     48   {"sk", "sk-SK"},
     49   {"sl", "sl-SI"},
     50   {"sh", "sh"},
     51   {"sr", "sr"},
     52   {"sv", "sv-SE"},
     53   {"tr", "tr-TR"},
     54   {"uk", "uk-UA"},
     55   {"vi", "vi-VN"},
     56 };
     57 
     58 // This function returns the language-region version of language name.
     59 // e.g. returns hi-IN for hi.
     60 std::string GetSpellCheckLanguageRegion(const std::string& input_language) {
     61   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
     62        ++i) {
     63     if (g_supported_spellchecker_languages[i].language == input_language) {
     64       return std::string(
     65           g_supported_spellchecker_languages[i].language_region);
     66     }
     67   }
     68 
     69   return input_language;
     70 }
     71 
     72 FilePath GetVersionedFileName(const std::string& input_language,
     73                               const FilePath& dict_dir) {
     74   // The default dictionary version is 1-2. These versions have been augmented
     75   // with additional words found by the translation team.
     76   static const char kDefaultVersionString[] = "-1-2";
     77 
     78   static const struct {
     79     // The language input.
     80     const char* language;
     81 
     82     // The corresponding version.
     83     const char* version;
     84   } special_version_string[] = {
     85     {"es-ES", "-1-1"},  // 1-1: Have not been augmented with addtional words.
     86     {"nl-NL", "-1-1"},
     87     {"sv-SE", "-1-1"},
     88     {"he-IL", "-1-1"},
     89     {"el-GR", "-1-1"},
     90     {"hi-IN", "-1-1"},
     91     {"tr-TR", "-1-1"},
     92     {"et-EE", "-1-1"},
     93     {"lt-LT", "-1-3"},  // 1-3 (Feb 2009): new words, as well as an upgraded
     94                         // dictionary.
     95     {"pl-PL", "-1-3"},
     96     {"fr-FR", "-2-0"},  // 2-0 (2010): upgraded dictionaries.
     97     {"hu-HU", "-2-0"},
     98     {"ro-RO", "-2-0"},
     99     {"ru-RU", "-2-0"},
    100     {"bg-BG", "-2-0"},
    101     {"sr",    "-2-0"},
    102     {"uk-UA", "-2-0"},
    103     {"en-US", "-2-1"},  // 2-1 (Mar 2011): upgraded dictionaries.
    104     {"en-CA", "-2-1"},
    105     {"pt-BR", "-2-2"},  // 2-2 (Mar 2011): upgraded a dictionary.
    106     {"sh",    "-2-2"},  // 2-2 (Mar 2011): added a dictionary.
    107   };
    108 
    109   // Generate the bdict file name using default version string or special
    110   // version string, depending on the language.
    111   std::string language = GetSpellCheckLanguageRegion(input_language);
    112   std::string versioned_bdict_file_name(language + kDefaultVersionString +
    113                                         ".bdic");
    114   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(special_version_string); ++i) {
    115     if (language == special_version_string[i].language) {
    116       versioned_bdict_file_name =
    117           language + special_version_string[i].version + ".bdic";
    118       break;
    119     }
    120   }
    121 
    122   return dict_dir.AppendASCII(versioned_bdict_file_name);
    123 }
    124 
    125 std::string GetCorrespondingSpellCheckLanguage(const std::string& language) {
    126   // Look for exact match in the Spell Check language list.
    127   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
    128        ++i) {
    129     // First look for exact match in the language region of the list.
    130     std::string spellcheck_language(
    131         g_supported_spellchecker_languages[i].language);
    132     if (spellcheck_language == language)
    133       return language;
    134 
    135     // Next, look for exact match in the language_region part of the list.
    136     std::string spellcheck_language_region(
    137         g_supported_spellchecker_languages[i].language_region);
    138     if (spellcheck_language_region == language)
    139       return g_supported_spellchecker_languages[i].language;
    140   }
    141 
    142   // Look for a match by comparing only language parts. All the 'en-RR'
    143   // except for 'en-GB' exactly matched in the above loop, will match
    144   // 'en-US'. This is not ideal because 'en-ZA', 'en-NZ' had
    145   // better be matched with 'en-GB'. This does not handle cases like
    146   // 'az-Latn-AZ' vs 'az-Arab-AZ', either, but we don't use 3-part
    147   // locale ids with a script code in the middle, yet.
    148   // TODO(jungshik): Add a better fallback.
    149   std::string language_part(language, 0, language.find('-'));
    150   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
    151        ++i) {
    152     std::string spellcheck_language(
    153         g_supported_spellchecker_languages[i].language_region);
    154     if (spellcheck_language.substr(0, spellcheck_language.find('-')) ==
    155         language_part) {
    156       return spellcheck_language;
    157     }
    158   }
    159 
    160   // No match found - return blank.
    161   return std::string();
    162 }
    163 
    164 
    165 void SpellCheckLanguages(std::vector<std::string>* languages) {
    166   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(g_supported_spellchecker_languages);
    167        ++i) {
    168     languages->push_back(g_supported_spellchecker_languages[i].language);
    169   }
    170 }
    171 
    172 }  // namespace SpellCheckCommon
    173