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