| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/extensions/extension_l10n_util.h" | 5 #include "extensions/common/extension_l10n_util.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
| 13 #include "base/files/file_enumerator.h" | 13 #include "base/files/file_enumerator.h" |
| 14 #include "base/json/json_file_value_serializer.h" | 14 #include "base/json/json_file_value_serializer.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/memory/linked_ptr.h" | 16 #include "base/memory/linked_ptr.h" |
| 17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/values.h" | 19 #include "base/values.h" |
| 20 #include "chrome/common/extensions/extension_file_util.h" | |
| 21 #include "chrome/common/extensions/message_bundle.h" | |
| 22 #include "chrome/common/url_constants.h" | |
| 23 #include "extensions/common/constants.h" | 20 #include "extensions/common/constants.h" |
| 24 #include "extensions/common/error_utils.h" | 21 #include "extensions/common/error_utils.h" |
| 22 #include "extensions/common/file_util.h" |
| 25 #include "extensions/common/manifest_constants.h" | 23 #include "extensions/common/manifest_constants.h" |
| 24 #include "extensions/common/message_bundle.h" |
| 26 #include "third_party/icu/source/common/unicode/uloc.h" | 25 #include "third_party/icu/source/common/unicode/uloc.h" |
| 27 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
| 28 | 27 |
| 29 namespace errors = extensions::manifest_errors; | 28 namespace errors = extensions::manifest_errors; |
| 30 namespace keys = extensions::manifest_keys; | 29 namespace keys = extensions::manifest_keys; |
| 31 | 30 |
| 32 namespace { | 31 namespace { |
| 33 | 32 |
| 34 // Loads contents of the messages file for given locale. If file is not found, | 33 // Loads contents of the messages file for given locale. If file is not found, |
| 35 // or there was parsing error we return NULL and set |error|. | 34 // or there was parsing error we return NULL and set |error|. |
| 36 // Caller owns the returned object. | 35 // Caller owns the returned object. |
| 37 base::DictionaryValue* LoadMessageFile(const base::FilePath& locale_path, | 36 base::DictionaryValue* LoadMessageFile(const base::FilePath& locale_path, |
| 38 const std::string& locale, | 37 const std::string& locale, |
| 39 std::string* error) { | 38 std::string* error) { |
| 40 base::FilePath file = locale_path.AppendASCII(locale) | 39 base::FilePath file = |
| 41 .Append(extensions::kMessagesFilename); | 40 locale_path.AppendASCII(locale).Append(extensions::kMessagesFilename); |
| 42 JSONFileValueSerializer messages_serializer(file); | 41 JSONFileValueSerializer messages_serializer(file); |
| 43 base::Value* dictionary = messages_serializer.Deserialize(NULL, error); | 42 base::Value* dictionary = messages_serializer.Deserialize(NULL, error); |
| 44 if (!dictionary) { | 43 if (!dictionary) { |
| 45 if (error->empty()) { | 44 if (error->empty()) { |
| 46 // JSONFileValueSerializer just returns NULL if file cannot be found. It | 45 // JSONFileValueSerializer just returns NULL if file cannot be found. It |
| 47 // doesn't set the error, so we have to do it. | 46 // doesn't set the error, so we have to do it. |
| 48 *error = base::StringPrintf("Catalog file is missing for locale %s.", | 47 *error = base::StringPrintf("Catalog file is missing for locale %s.", |
| 49 locale.c_str()); | 48 locale.c_str()); |
| 50 } else { | 49 } else { |
| 51 *error = extensions::ErrorUtils::FormatErrorMessage( | 50 *error = extensions::ErrorUtils::FormatErrorMessage( |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 171 |
| 173 base::ListValue* file_handlers = NULL; | 172 base::ListValue* file_handlers = NULL; |
| 174 if (manifest->GetList(keys::kFileBrowserHandlers, &file_handlers)) { | 173 if (manifest->GetList(keys::kFileBrowserHandlers, &file_handlers)) { |
| 175 key.assign(keys::kFileBrowserHandlers); | 174 key.assign(keys::kFileBrowserHandlers); |
| 176 for (size_t i = 0; i < file_handlers->GetSize(); i++) { | 175 for (size_t i = 0; i < file_handlers->GetSize(); i++) { |
| 177 base::DictionaryValue* handler = NULL; | 176 base::DictionaryValue* handler = NULL; |
| 178 if (!file_handlers->GetDictionary(i, &handler)) { | 177 if (!file_handlers->GetDictionary(i, &handler)) { |
| 179 *error = errors::kInvalidFileBrowserHandler; | 178 *error = errors::kInvalidFileBrowserHandler; |
| 180 return false; | 179 return false; |
| 181 } | 180 } |
| 182 if (!LocalizeManifestValue(keys::kPageActionDefaultTitle, messages, | 181 if (!LocalizeManifestValue( |
| 183 handler, error)) | 182 keys::kPageActionDefaultTitle, messages, handler, error)) |
| 184 return false; | 183 return false; |
| 185 } | 184 } |
| 186 } | 185 } |
| 187 | 186 |
| 188 base::ListValue* media_galleries_handlers = NULL; | 187 base::ListValue* media_galleries_handlers = NULL; |
| 189 if (manifest->GetList(keys::kMediaGalleriesHandlers, | 188 if (manifest->GetList(keys::kMediaGalleriesHandlers, |
| 190 &media_galleries_handlers)) { | 189 &media_galleries_handlers)) { |
| 191 key.assign(keys::kMediaGalleriesHandlers); | 190 key.assign(keys::kMediaGalleriesHandlers); |
| 192 for (size_t i = 0; i < media_galleries_handlers->GetSize(); i++) { | 191 for (size_t i = 0; i < media_galleries_handlers->GetSize(); i++) { |
| 193 base::DictionaryValue* handler = NULL; | 192 base::DictionaryValue* handler = NULL; |
| 194 if (!media_galleries_handlers->GetDictionary(i, &handler)) { | 193 if (!media_galleries_handlers->GetDictionary(i, &handler)) { |
| 195 *error = errors::kInvalidMediaGalleriesHandler; | 194 *error = errors::kInvalidMediaGalleriesHandler; |
| 196 return false; | 195 return false; |
| 197 } | 196 } |
| 198 if (!LocalizeManifestValue(keys::kPageActionDefaultTitle, messages, | 197 if (!LocalizeManifestValue( |
| 199 handler, error)) | 198 keys::kPageActionDefaultTitle, messages, handler, error)) |
| 200 return false; | 199 return false; |
| 201 } | 200 } |
| 202 } | 201 } |
| 203 | 202 |
| 204 // Initialize all input_components | 203 // Initialize all input_components |
| 205 base::ListValue* input_components = NULL; | 204 base::ListValue* input_components = NULL; |
| 206 if (manifest->GetList(keys::kInputComponents, &input_components)) { | 205 if (manifest->GetList(keys::kInputComponents, &input_components)) { |
| 207 for (size_t i = 0; i < input_components->GetSize(); ++i) { | 206 for (size_t i = 0; i < input_components->GetSize(); ++i) { |
| 208 base::DictionaryValue* module = NULL; | 207 base::DictionaryValue* module = NULL; |
| 209 if (!input_components->GetDictionary(i, &module)) { | 208 if (!input_components->GetDictionary(i, &module)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 224 // Initialize app.launch.web_url. | 223 // Initialize app.launch.web_url. |
| 225 if (!LocalizeManifestValue(keys::kLaunchWebURL, messages, manifest, error)) | 224 if (!LocalizeManifestValue(keys::kLaunchWebURL, messages, manifest, error)) |
| 226 return false; | 225 return false; |
| 227 | 226 |
| 228 // Initialize description of commmands. | 227 // Initialize description of commmands. |
| 229 base::DictionaryValue* commands_handler = NULL; | 228 base::DictionaryValue* commands_handler = NULL; |
| 230 if (manifest->GetDictionary(keys::kCommands, &commands_handler)) { | 229 if (manifest->GetDictionary(keys::kCommands, &commands_handler)) { |
| 231 for (base::DictionaryValue::Iterator iter(*commands_handler); | 230 for (base::DictionaryValue::Iterator iter(*commands_handler); |
| 232 !iter.IsAtEnd(); | 231 !iter.IsAtEnd(); |
| 233 iter.Advance()) { | 232 iter.Advance()) { |
| 234 key.assign(base::StringPrintf("commands.%s.description", | 233 key.assign( |
| 235 iter.key().c_str())); | 234 base::StringPrintf("commands.%s.description", iter.key().c_str())); |
| 236 if (!LocalizeManifestValue(key, messages, manifest, error)) | 235 if (!LocalizeManifestValue(key, messages, manifest, error)) |
| 237 return false; | 236 return false; |
| 238 } | 237 } |
| 239 } | 238 } |
| 240 | 239 |
| 241 // Initialize search_provider fields. | 240 // Initialize search_provider fields. |
| 242 base::DictionaryValue* search_provider = NULL; | 241 base::DictionaryValue* search_provider = NULL; |
| 243 if (manifest->GetDictionary(keys::kOverrideSearchProvider, | 242 if (manifest->GetDictionary(keys::kOverrideSearchProvider, |
| 244 &search_provider)) { | 243 &search_provider)) { |
| 245 for (base::DictionaryValue::Iterator iter(*search_provider); | 244 for (base::DictionaryValue::Iterator iter(*search_provider); |
| 246 !iter.IsAtEnd(); | 245 !iter.IsAtEnd(); |
| 247 iter.Advance()) { | 246 iter.Advance()) { |
| 248 key.assign(base::StringPrintf( | 247 key.assign(base::StringPrintf( |
| 249 "%s.%s", keys::kOverrideSearchProvider, iter.key().c_str())); | 248 "%s.%s", keys::kOverrideSearchProvider, iter.key().c_str())); |
| 250 bool success = (key == keys::kSettingsOverrideAlternateUrls) ? | 249 bool success = |
| 251 LocalizeManifestListValue(key, messages, manifest, error) : | 250 (key == keys::kSettingsOverrideAlternateUrls) |
| 252 LocalizeManifestValue(key, messages, manifest, error); | 251 ? LocalizeManifestListValue(key, messages, manifest, error) |
| 252 : LocalizeManifestValue(key, messages, manifest, error); |
| 253 if (!success) | 253 if (!success) |
| 254 return false; | 254 return false; |
| 255 } | 255 } |
| 256 } | 256 } |
| 257 | 257 |
| 258 // Initialize chrome_settings_overrides.homepage. | 258 // Initialize chrome_settings_overrides.homepage. |
| 259 if (!LocalizeManifestValue( | 259 if (!LocalizeManifestValue( |
| 260 keys::kOverrideHomepage, messages, manifest, error)) | 260 keys::kOverrideHomepage, messages, manifest, error)) |
| 261 return false; | 261 return false; |
| 262 | 262 |
| 263 // Initialize chrome_settings_overrides.startup_pages. | 263 // Initialize chrome_settings_overrides.startup_pages. |
| 264 if (!LocalizeManifestListValue( | 264 if (!LocalizeManifestListValue( |
| 265 keys::kOverrideStartupPage, messages, manifest, error)) | 265 keys::kOverrideStartupPage, messages, manifest, error)) |
| 266 return false; | 266 return false; |
| 267 | 267 |
| 268 // Add current locale key to the manifest, so we can overwrite prefs | 268 // Add current locale key to the manifest, so we can overwrite prefs |
| 269 // with new manifest when chrome locale changes. | 269 // with new manifest when chrome locale changes. |
| 270 manifest->SetString(keys::kCurrentLocale, CurrentLocaleOrDefault()); | 270 manifest->SetString(keys::kCurrentLocale, CurrentLocaleOrDefault()); |
| 271 return true; | 271 return true; |
| 272 } | 272 } |
| 273 | 273 |
| 274 bool LocalizeExtension(const base::FilePath& extension_path, | 274 bool LocalizeExtension(const base::FilePath& extension_path, |
| 275 base::DictionaryValue* manifest, | 275 base::DictionaryValue* manifest, |
| 276 std::string* error) { | 276 std::string* error) { |
| 277 DCHECK(manifest); | 277 DCHECK(manifest); |
| 278 | 278 |
| 279 std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); | 279 std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); |
| 280 | 280 |
| 281 scoped_ptr<extensions::MessageBundle> message_bundle( | 281 scoped_ptr<extensions::MessageBundle> message_bundle( |
| 282 extension_file_util::LoadMessageBundle( | 282 extensions::file_util::LoadMessageBundle( |
| 283 extension_path, default_locale, error)); | 283 extension_path, default_locale, error)); |
| 284 | 284 |
| 285 if (!message_bundle.get() && !error->empty()) | 285 if (!message_bundle.get() && !error->empty()) |
| 286 return false; | 286 return false; |
| 287 | 287 |
| 288 if (message_bundle.get() && | 288 if (message_bundle.get() && |
| 289 !LocalizeManifest(*message_bundle, manifest, error)) | 289 !LocalizeManifest(*message_bundle, manifest, error)) |
| 290 return false; | 290 return false; |
| 291 | 291 |
| 292 return true; | 292 return true; |
| 293 } | 293 } |
| 294 | 294 |
| 295 bool AddLocale(const std::set<std::string>& chrome_locales, | 295 bool AddLocale(const std::set<std::string>& chrome_locales, |
| 296 const base::FilePath& locale_folder, | 296 const base::FilePath& locale_folder, |
| 297 const std::string& locale_name, | 297 const std::string& locale_name, |
| 298 std::set<std::string>* valid_locales, | 298 std::set<std::string>* valid_locales, |
| 299 std::string* error) { | 299 std::string* error) { |
| 300 // Accept name that starts with a . but don't add it to the list of supported | 300 // Accept name that starts with a . but don't add it to the list of supported |
| 301 // locales. | 301 // locales. |
| 302 if (locale_name.find(".") == 0) | 302 if (locale_name.find(".") == 0) |
| 303 return true; | 303 return true; |
| 304 if (chrome_locales.find(locale_name) == chrome_locales.end()) { | 304 if (chrome_locales.find(locale_name) == chrome_locales.end()) { |
| 305 // Warn if there is an extension locale that's not in the Chrome list, | 305 // Warn if there is an extension locale that's not in the Chrome list, |
| 306 // but don't fail. | 306 // but don't fail. |
| 307 DLOG(WARNING) << base::StringPrintf("Supplied locale %s is not supported.", | 307 DLOG(WARNING) << base::StringPrintf("Supplied locale %s is not supported.", |
| 308 locale_name.c_str()); | 308 locale_name.c_str()); |
| 309 return true; | 309 return true; |
| 310 } | 310 } |
| 311 // Check if messages file is actually present (but don't check content). | 311 // Check if messages file is actually present (but don't check content). |
| 312 if (base::PathExists( | 312 if (base::PathExists(locale_folder.Append(extensions::kMessagesFilename))) { |
| 313 locale_folder.Append(extensions::kMessagesFilename))) { | |
| 314 valid_locales->insert(locale_name); | 313 valid_locales->insert(locale_name); |
| 315 } else { | 314 } else { |
| 316 *error = base::StringPrintf("Catalog file is missing for locale %s.", | 315 *error = base::StringPrintf("Catalog file is missing for locale %s.", |
| 317 locale_name.c_str()); | 316 locale_name.c_str()); |
| 318 return false; | 317 return false; |
| 319 } | 318 } |
| 320 | 319 |
| 321 return true; | 320 return true; |
| 322 } | 321 } |
| 323 | 322 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 350 all_fallback_locales->push_back(default_locale); | 349 all_fallback_locales->push_back(default_locale); |
| 351 } | 350 } |
| 352 | 351 |
| 353 bool GetValidLocales(const base::FilePath& locale_path, | 352 bool GetValidLocales(const base::FilePath& locale_path, |
| 354 std::set<std::string>* valid_locales, | 353 std::set<std::string>* valid_locales, |
| 355 std::string* error) { | 354 std::string* error) { |
| 356 std::set<std::string> chrome_locales; | 355 std::set<std::string> chrome_locales; |
| 357 GetAllLocales(&chrome_locales); | 356 GetAllLocales(&chrome_locales); |
| 358 | 357 |
| 359 // Enumerate all supplied locales in the extension. | 358 // Enumerate all supplied locales in the extension. |
| 360 base::FileEnumerator locales(locale_path, | 359 base::FileEnumerator locales( |
| 361 false, | 360 locale_path, false, base::FileEnumerator::DIRECTORIES); |
| 362 base::FileEnumerator::DIRECTORIES); | |
| 363 base::FilePath locale_folder; | 361 base::FilePath locale_folder; |
| 364 while (!(locale_folder = locales.Next()).empty()) { | 362 while (!(locale_folder = locales.Next()).empty()) { |
| 365 std::string locale_name = locale_folder.BaseName().MaybeAsASCII(); | 363 std::string locale_name = locale_folder.BaseName().MaybeAsASCII(); |
| 366 if (locale_name.empty()) { | 364 if (locale_name.empty()) { |
| 367 NOTREACHED(); | 365 NOTREACHED(); |
| 368 continue; // Not ASCII. | 366 continue; // Not ASCII. |
| 369 } | 367 } |
| 370 if (!AddLocale(chrome_locales, | 368 if (!AddLocale( |
| 371 locale_folder, | 369 chrome_locales, locale_folder, locale_name, valid_locales, error)) { |
| 372 locale_name, | |
| 373 valid_locales, | |
| 374 error)) { | |
| 375 return false; | 370 return false; |
| 376 } | 371 } |
| 377 } | 372 } |
| 378 | 373 |
| 379 if (valid_locales->empty()) { | 374 if (valid_locales->empty()) { |
| 380 *error = errors::kLocalesNoValidLocaleNamesListed; | 375 *error = errors::kLocalesNoValidLocaleNamesListed; |
| 381 return false; | 376 return false; |
| 382 } | 377 } |
| 383 | 378 |
| 384 return true; | 379 return true; |
| 385 } | 380 } |
| 386 | 381 |
| 387 extensions::MessageBundle* LoadMessageCatalogs( | 382 extensions::MessageBundle* LoadMessageCatalogs( |
| 388 const base::FilePath& locale_path, | 383 const base::FilePath& locale_path, |
| 389 const std::string& default_locale, | 384 const std::string& default_locale, |
| 390 const std::string& application_locale, | 385 const std::string& application_locale, |
| 391 const std::set<std::string>& valid_locales, | 386 const std::set<std::string>& valid_locales, |
| 392 std::string* error) { | 387 std::string* error) { |
| 393 std::vector<std::string> all_fallback_locales; | 388 std::vector<std::string> all_fallback_locales; |
| 394 GetAllFallbackLocales(application_locale, default_locale, | 389 GetAllFallbackLocales( |
| 395 &all_fallback_locales); | 390 application_locale, default_locale, &all_fallback_locales); |
| 396 | 391 |
| 397 std::vector<linked_ptr<base::DictionaryValue> > catalogs; | 392 std::vector<linked_ptr<base::DictionaryValue> > catalogs; |
| 398 for (size_t i = 0; i < all_fallback_locales.size(); ++i) { | 393 for (size_t i = 0; i < all_fallback_locales.size(); ++i) { |
| 399 // Skip all parent locales that are not supplied. | 394 // Skip all parent locales that are not supplied. |
| 400 if (valid_locales.find(all_fallback_locales[i]) == valid_locales.end()) | 395 if (valid_locales.find(all_fallback_locales[i]) == valid_locales.end()) |
| 401 continue; | 396 continue; |
| 402 linked_ptr<base::DictionaryValue> catalog( | 397 linked_ptr<base::DictionaryValue> catalog( |
| 403 LoadMessageFile(locale_path, all_fallback_locales[i], error)); | 398 LoadMessageFile(locale_path, all_fallback_locales[i], error)); |
| 404 if (!catalog.get()) { | 399 if (!catalog.get()) { |
| 405 // If locale is valid, but messages.json is corrupted or missing, return | 400 // If locale is valid, but messages.json is corrupted or missing, return |
| 406 // an error. | 401 // an error. |
| 407 return NULL; | 402 return NULL; |
| 408 } else { | 403 } else { |
| 409 catalogs.push_back(catalog); | 404 catalogs.push_back(catalog); |
| 410 } | 405 } |
| 411 } | 406 } |
| 412 | 407 |
| 413 return extensions::MessageBundle::Create(catalogs, error); | 408 return extensions::MessageBundle::Create(catalogs, error); |
| 414 } | 409 } |
| 415 | 410 |
| 416 bool ValidateExtensionLocales(const base::FilePath& extension_path, | 411 bool ValidateExtensionLocales(const base::FilePath& extension_path, |
| 417 const base::DictionaryValue* manifest, | 412 const base::DictionaryValue* manifest, |
| 418 std::string* error) { | 413 std::string* error) { |
| 419 std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); | 414 std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); |
| 420 | 415 |
| 421 if (default_locale.empty()) | 416 if (default_locale.empty()) |
| 422 return true; | 417 return true; |
| 423 | 418 |
| 424 base::FilePath locale_path = | 419 base::FilePath locale_path = extension_path.Append(extensions::kLocaleFolder); |
| 425 extension_path.Append(extensions::kLocaleFolder); | |
| 426 | 420 |
| 427 std::set<std::string> valid_locales; | 421 std::set<std::string> valid_locales; |
| 428 if (!GetValidLocales(locale_path, &valid_locales, error)) | 422 if (!GetValidLocales(locale_path, &valid_locales, error)) |
| 429 return false; | 423 return false; |
| 430 | 424 |
| 431 for (std::set<std::string>::const_iterator locale = valid_locales.begin(); | 425 for (std::set<std::string>::const_iterator locale = valid_locales.begin(); |
| 432 locale != valid_locales.end(); ++locale) { | 426 locale != valid_locales.end(); |
| 427 ++locale) { |
| 433 std::string locale_error; | 428 std::string locale_error; |
| 434 scoped_ptr<base::DictionaryValue> catalog( | 429 scoped_ptr<base::DictionaryValue> catalog( |
| 435 LoadMessageFile(locale_path, *locale, &locale_error)); | 430 LoadMessageFile(locale_path, *locale, &locale_error)); |
| 436 | 431 |
| 437 if (!locale_error.empty()) { | 432 if (!locale_error.empty()) { |
| 438 if (!error->empty()) | 433 if (!error->empty()) |
| 439 error->append(" "); | 434 error->append(" "); |
| 440 error->append(locale_error); | 435 error->append(locale_error); |
| 441 } | 436 } |
| 442 } | 437 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 ScopedLocaleForTest::ScopedLocaleForTest(const std::string& locale) | 469 ScopedLocaleForTest::ScopedLocaleForTest(const std::string& locale) |
| 475 : locale_(extension_l10n_util::CurrentLocaleOrDefault()) { | 470 : locale_(extension_l10n_util::CurrentLocaleOrDefault()) { |
| 476 extension_l10n_util::SetProcessLocale(locale); | 471 extension_l10n_util::SetProcessLocale(locale); |
| 477 } | 472 } |
| 478 | 473 |
| 479 ScopedLocaleForTest::~ScopedLocaleForTest() { | 474 ScopedLocaleForTest::~ScopedLocaleForTest() { |
| 480 extension_l10n_util::SetProcessLocale(locale_); | 475 extension_l10n_util::SetProcessLocale(locale_); |
| 481 } | 476 } |
| 482 | 477 |
| 483 } // namespace extension_l10n_util | 478 } // namespace extension_l10n_util |
| OLD | NEW |