1 // Copyright (c) 2012 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/files/file_path.h" 8 #include "base/logging.h" 9 #include "third_party/icu/source/common/unicode/uloc.h" 10 11 namespace chrome { 12 namespace spellcheck_common { 13 14 struct LanguageRegion { 15 const char* language; // The language. 16 const char* language_region; // language & region, used by dictionaries. 17 }; 18 19 struct LanguageVersion { 20 const char* language; // The language input. 21 const char* version; // The corresponding version. 22 }; 23 24 static const LanguageRegion g_supported_spellchecker_languages[] = { 25 // Several languages are not to be included in the spellchecker list: 26 // th-TH, vi-VI. 27 {"af", "af-ZA"}, 28 {"bg", "bg-BG"}, 29 {"ca", "ca-ES"}, 30 {"cs", "cs-CZ"}, 31 {"da", "da-DK"}, 32 {"de", "de-DE"}, 33 {"el", "el-GR"}, 34 {"en-AU", "en-AU"}, 35 {"en-CA", "en-CA"}, 36 {"en-GB", "en-GB"}, 37 {"en-US", "en-US"}, 38 {"es", "es-ES"}, 39 {"et", "et-EE"}, 40 {"fo", "fo-FO"}, 41 {"fr", "fr-FR"}, 42 {"he", "he-IL"}, 43 {"hi", "hi-IN"}, 44 {"hr", "hr-HR"}, 45 {"hu", "hu-HU"}, 46 {"id", "id-ID"}, 47 {"it", "it-IT"}, 48 {"ko", "ko"}, 49 {"lt", "lt-LT"}, 50 {"lv", "lv-LV"}, 51 {"nb", "nb-NO"}, 52 {"nl", "nl-NL"}, 53 {"pl", "pl-PL"}, 54 {"pt-BR", "pt-BR"}, 55 {"pt-PT", "pt-PT"}, 56 {"ro", "ro-RO"}, 57 {"ru", "ru-RU"}, 58 {"sh", "sh"}, 59 {"sk", "sk-SK"}, 60 {"sl", "sl-SI"}, 61 {"sq", "sq"}, 62 {"sr", "sr"}, 63 {"sv", "sv-SE"}, 64 {"ta", "ta-IN"}, 65 {"tg", "tg-TG"}, 66 {"tr", "tr-TR"}, 67 {"uk", "uk-UA"}, 68 {"vi", "vi-VN"}, 69 }; 70 71 bool IsValidRegion(const std::string& region) { 72 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); 73 ++i) { 74 if (g_supported_spellchecker_languages[i].language_region == region) 75 return true; 76 } 77 return false; 78 } 79 80 // This function returns the language-region version of language name. 81 // e.g. returns hi-IN for hi. 82 std::string GetSpellCheckLanguageRegion(const std::string& input_language) { 83 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); 84 ++i) { 85 if (g_supported_spellchecker_languages[i].language == input_language) { 86 return std::string( 87 g_supported_spellchecker_languages[i].language_region); 88 } 89 } 90 91 return input_language; 92 } 93 94 base::FilePath GetVersionedFileName(const std::string& input_language, 95 const base::FilePath& dict_dir) { 96 // The default dictionary version is 3-0. This version indicates that the bdic 97 // file contains a checksum. 98 static const char kDefaultVersionString[] = "-3-0"; 99 100 // Add non-default version strings here. Use the same version for all the 101 // dictionaries that you add at the same time. Increment the major version 102 // number if you're updating either dic or aff files. Increment the minor 103 // version number if you're updating only dic_delta files. 104 static LanguageVersion special_version_string[] = { 105 {"tr-TR", "-4-0"}, // Jan 9, 2013: Add "FLAG num" to aff to avoid heapcheck 106 // crash. 107 {"tg-TG", "-5-0"}, // Mar 4, 2014: Add Tajik dictionary. 108 }; 109 110 // Generate the bdict file name using default version string or special 111 // version string, depending on the language. 112 std::string language = GetSpellCheckLanguageRegion(input_language); 113 std::string versioned_bdict_file_name(language + kDefaultVersionString + 114 ".bdic"); 115 for (size_t i = 0; i < arraysize(special_version_string); ++i) { 116 if (language == special_version_string[i].language) { 117 versioned_bdict_file_name = 118 language + special_version_string[i].version + ".bdic"; 119 break; 120 } 121 } 122 123 return dict_dir.AppendASCII(versioned_bdict_file_name); 124 } 125 126 std::string GetCorrespondingSpellCheckLanguage(const std::string& language) { 127 // Look for exact match in the Spell Check language list. 128 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); 129 ++i) { 130 // First look for exact match in the language region of the list. 131 std::string spellcheck_language( 132 g_supported_spellchecker_languages[i].language); 133 if (spellcheck_language == language) 134 return language; 135 136 // Next, look for exact match in the language_region part of the list. 137 std::string spellcheck_language_region( 138 g_supported_spellchecker_languages[i].language_region); 139 if (spellcheck_language_region == language) 140 return g_supported_spellchecker_languages[i].language; 141 } 142 143 // No match found - return blank. 144 return std::string(); 145 } 146 147 void SpellCheckLanguages(std::vector<std::string>* languages) { 148 for (size_t i = 0; i < arraysize(g_supported_spellchecker_languages); 149 ++i) { 150 languages->push_back(g_supported_spellchecker_languages[i].language); 151 } 152 } 153 154 void GetISOLanguageCountryCodeFromLocale(const std::string& locale, 155 std::string* language_code, 156 std::string* country_code) { 157 DCHECK(language_code); 158 DCHECK(country_code); 159 char language[ULOC_LANG_CAPACITY] = ULOC_ENGLISH; 160 const char* country = "USA"; 161 if (!locale.empty()) { 162 UErrorCode error = U_ZERO_ERROR; 163 char id[ULOC_LANG_CAPACITY + ULOC_SCRIPT_CAPACITY + ULOC_COUNTRY_CAPACITY]; 164 uloc_addLikelySubtags(locale.c_str(), id, arraysize(id), &error); 165 error = U_ZERO_ERROR; 166 uloc_getLanguage(id, language, arraysize(language), &error); 167 country = uloc_getISO3Country(id); 168 } 169 *language_code = std::string(language); 170 *country_code = std::string(country); 171 } 172 173 } // namespace spellcheck_common 174 } // namespace chrome 175