Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(904)

Side by Side Diff: app/l10n_util.cc

Issue 1073005: Move RTL related functions from app/l10n_util to base/i18n/rtl... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « app/l10n_util.h ('k') | app/l10n_util_dummy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "app/l10n_util.h" 5 #include "app/l10n_util.h"
6 6
7 #include <cstdlib> 7 #include <cstdlib>
8 8
9 #include "app/app_paths.h" 9 #include "app/app_paths.h"
10 #include "app/app_switches.h" 10 #include "app/app_switches.h"
11 #include "app/gfx/canvas.h" 11 #include "app/gfx/canvas.h"
12 #include "app/l10n_util_collator.h" 12 #include "app/l10n_util_collator.h"
13 #include "app/resource_bundle.h" 13 #include "app/resource_bundle.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/i18n/file_util_icu.h" 16 #include "base/i18n/file_util_icu.h"
17 #include "base/i18n/rtl.h"
17 #include "base/path_service.h" 18 #include "base/path_service.h"
18 #include "base/scoped_ptr.h" 19 #include "base/scoped_ptr.h"
19 #include "base/string16.h" 20 #include "base/string16.h"
20 #include "base/string_piece.h" 21 #include "base/string_piece.h"
21 #include "base/string_util.h" 22 #include "base/string_util.h"
22 #include "base/sys_string_conversions.h" 23 #include "base/sys_string_conversions.h"
23 #include "build/build_config.h" 24 #include "build/build_config.h"
24 #include "unicode/coll.h"
25 #include "unicode/locid.h"
26 #include "unicode/rbbi.h" 25 #include "unicode/rbbi.h"
27 #include "unicode/uchar.h"
28 #include "unicode/uscript.h"
29
30 #if defined(TOOLKIT_GTK)
31 #include <gtk/gtk.h>
32 #endif
33 26
34 #if defined(OS_MACOSX) 27 #if defined(OS_MACOSX)
35 #include "app/l10n_util_mac.h" 28 #include "app/l10n_util_mac.h"
36 #endif 29 #endif
37 30
38 // TODO(playmobil): remove this undef once SkPostConfig.h is fixed. 31 // TODO(playmobil): remove this undef once SkPostConfig.h is fixed.
39 // skia/include/corecg/SkPostConfig.h #defines strcasecmp() so we can't use 32 // skia/include/corecg/SkPostConfig.h #defines strcasecmp() so we can't use
40 // base::strcasecmp() without #undefing it here. 33 // base::strcasecmp() without #undefing it here.
41 #undef strcasecmp 34 #undef strcasecmp
42 35
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 "vi", // Vietnamese 174 "vi", // Vietnamese
182 "xh", // Xhosa 175 "xh", // Xhosa
183 "yi", // Yiddish 176 "yi", // Yiddish
184 "yo", // Yoruba 177 "yo", // Yoruba
185 "zh", // Chinese 178 "zh", // Chinese
186 "zh-CN", // Chinese (Simplified) 179 "zh-CN", // Chinese (Simplified)
187 "zh-TW", // Chinese (Traditional) 180 "zh-TW", // Chinese (Traditional)
188 "zu", // Zulu 181 "zu", // Zulu
189 }; 182 };
190 183
191
192 // Get language and region from the OS.
193 void GetLanguageAndRegionFromOS(std::string* lang, std::string* region) {
194 // Later we may have to change this to be OS-dependent so that
195 // it's not affected by ICU's default locale. It's all right
196 // to do this way because SetICUDefaultLocale is internal
197 // to this file and we know that it's not yet called when this function
198 // is called.
199 icu::Locale locale = icu::Locale::getDefault();
200 const char* language = locale.getLanguage();
201 const char* country = locale.getCountry();
202 DCHECK(language);
203 *lang = language;
204 *region = country;
205 }
206
207 // Convert Chrome locale name to ICU locale name
208 std::string ICULocaleName(const std::string& locale_string) {
209 // If not Spanish, just return it.
210 if (locale_string.substr(0, 2) != "es")
211 return locale_string;
212 // Expand es to es-ES.
213 if (LowerCaseEqualsASCII(locale_string, "es"))
214 return "es-ES";
215 // Map es-419 (Latin American Spanish) to es-FOO depending on the system
216 // locale. If it's es-RR other than es-ES, map to es-RR. Otherwise, map
217 // to es-MX (the most populous in Spanish-speaking Latin America).
218 if (LowerCaseEqualsASCII(locale_string, "es-419")) {
219 std::string lang, region;
220 GetLanguageAndRegionFromOS(&lang, &region);
221 if (LowerCaseEqualsASCII(lang, "es") &&
222 !LowerCaseEqualsASCII(region, "es")) {
223 lang.append("-");
224 lang.append(region);
225 return lang;
226 }
227 return "es-MX";
228 }
229 // Currently, Chrome has only "es" and "es-419", but later we may have
230 // more specific "es-RR".
231 return locale_string;
232 }
233
234 // Represents the locale-specific ICU text direction.
235 l10n_util::TextDirection g_icu_text_direction = l10n_util::UNKNOWN_DIRECTION;
236
237 // Sets the default locale of ICU.
238 // Once the application locale of Chrome in GetApplicationLocale is determined,
239 // the default locale of ICU need to be changed to match the application locale
240 // so that ICU functions work correctly in a locale-dependent manner.
241 // This is handy in that we don't have to call GetApplicationLocale()
242 // everytime we call locale-dependent ICU APIs as long as we make sure
243 // that this is called before any locale-dependent API is called.
244 void SetICUDefaultLocale(const std::string& locale_string) {
245 icu::Locale locale(ICULocaleName(locale_string).c_str());
246 UErrorCode error_code = U_ZERO_ERROR;
247 icu::Locale::setDefault(locale, error_code);
248 // This return value is actually bogus because Locale object is
249 // an ID and setDefault seems to always succeed (regardless of the
250 // presence of actual locale data). However,
251 // it does not hurt to have it as a sanity check.
252 DCHECK(U_SUCCESS(error_code));
253 g_icu_text_direction = l10n_util::UNKNOWN_DIRECTION;
254 }
255
256 // Returns true if |locale_name| has an alias in the ICU data file. 184 // Returns true if |locale_name| has an alias in the ICU data file.
257 bool IsDuplicateName(const std::string& locale_name) { 185 bool IsDuplicateName(const std::string& locale_name) {
258 static const char* const kDuplicateNames[] = { 186 static const char* const kDuplicateNames[] = {
259 "en", 187 "en",
260 "pt", 188 "pt",
261 "zh", 189 "zh",
262 "zh_hans_cn", 190 "zh_hans_cn",
263 "zh_hant_tw" 191 "zh_hant_tw"
264 }; 192 };
265 193
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 } 307 }
380 308
381 return false; 309 return false;
382 } 310 }
383 311
384 // Get the locale of the operating system. The return value is of the form 312 // Get the locale of the operating system. The return value is of the form
385 // language[-country] (e.g., en-US) where the language is the 2 letter code from 313 // language[-country] (e.g., en-US) where the language is the 2 letter code from
386 // ISO-639. 314 // ISO-639.
387 std::string GetSystemLocale() { 315 std::string GetSystemLocale() {
388 std::string language, region; 316 std::string language, region;
389 GetLanguageAndRegionFromOS(&language, &region); 317 base::i18n::GetLanguageAndRegionFromOS(&language, &region);
390 std::string ret; 318 std::string ret;
391 if (!language.empty()) 319 if (!language.empty())
392 ret.append(language); 320 ret.append(language);
393 if (!region.empty()) { 321 if (!region.empty()) {
394 ret.append("-"); 322 ret.append("-");
395 ret.append(region); 323 ret.append(region);
396 } 324 }
397 return ret; 325 return ret;
398 } 326 }
399 327
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // We emulate gettext's behavior here, which ignores LANG/LC_MESSAGES/LC_ALL 411 // We emulate gettext's behavior here, which ignores LANG/LC_MESSAGES/LC_ALL
484 // when LANGUAGE is specified. If no language specified in LANGUAGE is valid, 412 // when LANGUAGE is specified. If no language specified in LANGUAGE is valid,
485 // then just fallback to the locale based on LC_ALL/LANG. 413 // then just fallback to the locale based on LC_ALL/LANG.
486 if (candidates.empty()) 414 if (candidates.empty())
487 candidates.push_back(system_locale); 415 candidates.push_back(system_locale);
488 #endif 416 #endif
489 417
490 std::vector<std::string>::const_iterator i = candidates.begin(); 418 std::vector<std::string>::const_iterator i = candidates.begin();
491 for (; i != candidates.end(); ++i) { 419 for (; i != candidates.end(); ++i) {
492 if (CheckAndResolveLocale(*i, locale_path, &resolved_locale)) { 420 if (CheckAndResolveLocale(*i, locale_path, &resolved_locale)) {
493 SetICUDefaultLocale(resolved_locale); 421 base::i18n::SetICUDefaultLocale(resolved_locale);
494 return resolved_locale; 422 return resolved_locale;
495 } 423 }
496 } 424 }
497 425
498 // Fallback on en-US. 426 // Fallback on en-US.
499 const std::string fallback_locale("en-US"); 427 const std::string fallback_locale("en-US");
500 if (IsLocaleAvailable(fallback_locale, locale_path)) { 428 if (IsLocaleAvailable(fallback_locale, locale_path)) {
501 SetICUDefaultLocale(fallback_locale); 429 base::i18n::SetICUDefaultLocale(fallback_locale);
502 return fallback_locale; 430 return fallback_locale;
503 } 431 }
504 432
505 // No locale data file was found; we shouldn't get here. 433 // No locale data file was found; we shouldn't get here.
506 NOTREACHED(); 434 NOTREACHED();
507 435
508 return std::string(); 436 return std::string();
509 437
510 #else // !defined(OS_MACOSX) 438 #else // !defined(OS_MACOSX)
511 439
512 // Use any override (Cocoa for the browser), otherwise use the command line 440 // Use any override (Cocoa for the browser), otherwise use the command line
513 // argument. 441 // argument.
514 std::string app_locale = l10n_util::GetLocaleOverride(); 442 std::string app_locale = l10n_util::GetLocaleOverride();
515 if (app_locale.empty()) { 443 if (app_locale.empty()) {
516 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 444 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
517 app_locale = parsed_command_line.GetSwitchValueASCII(switches::kLang); 445 app_locale = parsed_command_line.GetSwitchValueASCII(switches::kLang);
518 } 446 }
519 447
520 // The above should handle all of the cases Chrome normally hits, but for some 448 // The above should handle all of the cases Chrome normally hits, but for some
521 // unit tests, we need something to fall back too. 449 // unit tests, we need something to fall back too.
522 if (app_locale.empty()) 450 if (app_locale.empty())
523 app_locale = "en-US"; 451 app_locale = "en-US";
524 452
525 // Windows/Linux call SetICUDefaultLocale after determining the actual locale 453 // Windows/Linux call SetICUDefaultLocale after determining the actual locale
526 // with CheckAndResolveLocal to make ICU APIs work in that locale. 454 // with CheckAndResolveLocal to make ICU APIs work in that locale.
527 // Mac doesn't use a locale directory tree of resources (it uses Mac style 455 // Mac doesn't use a locale directory tree of resources (it uses Mac style
528 // resources), so mirror the Windows/Linux behavior of calling 456 // resources), so mirror the Windows/Linux behavior of calling
529 // SetICUDefaultLocale. 457 // SetICUDefaultLocale.
530 SetICUDefaultLocale(app_locale); 458 base::i18n::SetICUDefaultLocale(app_locale);
531 return app_locale; 459 return app_locale;
532 #endif // !defined(OS_MACOSX) 460 #endif // !defined(OS_MACOSX)
533 } 461 }
534 462
535 string16 GetDisplayNameForLocale(const std::string& locale, 463 string16 GetDisplayNameForLocale(const std::string& locale,
536 const std::string& display_locale, 464 const std::string& display_locale,
537 bool is_for_ui) { 465 bool is_for_ui) {
538 std::string locale_code = locale; 466 std::string locale_code = locale;
539 // Internally, we use the language code of zh-CN and zh-TW, but we want the 467 // Internally, we use the language code of zh-CN and zh-TW, but we want the
540 // display names to be Chinese (Simplified) and Chinese (Traditional) instead 468 // display names to be Chinese (Simplified) and Chinese (Traditional) instead
(...skipping 19 matching lines...) Expand all
560 UErrorCode error = U_ZERO_ERROR; 488 UErrorCode error = U_ZERO_ERROR;
561 const int buffer_size = 1024; 489 const int buffer_size = 1024;
562 490
563 string16 display_name; 491 string16 display_name;
564 int actual_size = uloc_getDisplayName(locale_code.c_str(), 492 int actual_size = uloc_getDisplayName(locale_code.c_str(),
565 display_locale.c_str(), 493 display_locale.c_str(),
566 WriteInto(&display_name, buffer_size + 1), buffer_size, &error); 494 WriteInto(&display_name, buffer_size + 1), buffer_size, &error);
567 DCHECK(U_SUCCESS(error)); 495 DCHECK(U_SUCCESS(error));
568 display_name.resize(actual_size); 496 display_name.resize(actual_size);
569 // Add an RTL mark so parentheses are properly placed. 497 // Add an RTL mark so parentheses are properly placed.
570 if (is_for_ui && GetTextDirection() == RIGHT_TO_LEFT) { 498 if (is_for_ui && base::i18n::IsRTL())
571 display_name.push_back(static_cast<char16>(kRightToLeftMark)); 499 display_name.push_back(static_cast<char16>(base::i18n::kRightToLeftMark));
572 }
573 return display_name; 500 return display_name;
574 } 501 }
575 502
576 std::wstring GetString(int message_id) { 503 std::wstring GetString(int message_id) {
577 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 504 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
578 return UTF16ToWide(rb.GetLocalizedString(message_id)); 505 return UTF16ToWide(rb.GetLocalizedString(message_id));
579 } 506 }
580 507
581 std::string GetStringUTF8(int message_id) { 508 std::string GetStringUTF8(int message_id) {
582 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 509 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 737
811 string16 ToUpper(const string16& string) { 738 string16 ToUpper(const string16& string) {
812 icu::UnicodeString upper_u_str( 739 icu::UnicodeString upper_u_str(
813 icu::UnicodeString(string.c_str()).toUpper(icu::Locale::getDefault())); 740 icu::UnicodeString(string.c_str()).toUpper(icu::Locale::getDefault()));
814 string16 result; 741 string16 result;
815 upper_u_str.extract(0, upper_u_str.length(), 742 upper_u_str.extract(0, upper_u_str.length(),
816 WriteInto(&result, upper_u_str.length() + 1)); 743 WriteInto(&result, upper_u_str.length() + 1));
817 return result; 744 return result;
818 } 745 }
819 746
820 TextDirection GetICUTextDirection() {
821 if (g_icu_text_direction == UNKNOWN_DIRECTION) {
822 const icu::Locale& locale = icu::Locale::getDefault();
823 g_icu_text_direction = GetTextDirectionForLocale(locale.getName());
824 }
825 return g_icu_text_direction;
826 }
827
828 TextDirection GetTextDirection() {
829 #if defined(TOOLKIT_GTK)
830 GtkTextDirection gtk_dir = gtk_widget_get_default_direction();
831 return (gtk_dir == GTK_TEXT_DIR_LTR) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
832 #else
833 return GetICUTextDirection();
834 #endif
835 }
836
837 TextDirection GetTextDirectionForLocale(const char* locale_name) {
838 UErrorCode status = U_ZERO_ERROR;
839 ULayoutType layout_dir = uloc_getCharacterOrientation(locale_name, &status);
840 DCHECK(U_SUCCESS(status));
841 // Treat anything other than RTL as LTR.
842 return (layout_dir != ULOC_LAYOUT_RTL) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
843 }
844
845 TextDirection GetFirstStrongCharacterDirection(const std::wstring& text) {
846 #if defined(WCHAR_T_IS_UTF32)
847 string16 text_utf16 = WideToUTF16(text);
848 const UChar* string = text_utf16.c_str();
849 #else
850 const UChar* string = text.c_str();
851 #endif
852 size_t length = text.length();
853 size_t position = 0;
854 while (position < length) {
855 UChar32 character;
856 size_t next_position = position;
857 U16_NEXT(string, next_position, length, character);
858
859 // Now that we have the character, we use ICU in order to query for the
860 // appropriate Unicode BiDi character type.
861 int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
862 if ((property == U_RIGHT_TO_LEFT) ||
863 (property == U_RIGHT_TO_LEFT_ARABIC) ||
864 (property == U_RIGHT_TO_LEFT_EMBEDDING) ||
865 (property == U_RIGHT_TO_LEFT_OVERRIDE)) {
866 return RIGHT_TO_LEFT;
867 } else if ((property == U_LEFT_TO_RIGHT) ||
868 (property == U_LEFT_TO_RIGHT_EMBEDDING) ||
869 (property == U_LEFT_TO_RIGHT_OVERRIDE)) {
870 return LEFT_TO_RIGHT;
871 }
872
873 position = next_position;
874 }
875
876 return LEFT_TO_RIGHT;
877 }
878
879 bool AdjustStringForLocaleDirection(const std::wstring& text,
880 std::wstring* localized_text) {
881 if (GetTextDirection() == LEFT_TO_RIGHT || text.length() == 0)
882 return false;
883
884 // Marking the string as LTR if the locale is RTL and the string does not
885 // contain strong RTL characters. Otherwise, mark the string as RTL.
886 *localized_text = text;
887 bool has_rtl_chars = StringContainsStrongRTLChars(text);
888 if (!has_rtl_chars)
889 WrapStringWithLTRFormatting(localized_text);
890 else
891 WrapStringWithRTLFormatting(localized_text);
892
893 return true;
894 }
895
896 bool StringContainsStrongRTLChars(const std::wstring& text) {
897 #if defined(WCHAR_T_IS_UTF32)
898 string16 text_utf16 = WideToUTF16(text);
899 const UChar* string = text_utf16.c_str();
900 #else
901 const UChar* string = text.c_str();
902 #endif
903 size_t length = text.length();
904 size_t position = 0;
905 while (position < length) {
906 UChar32 character;
907 size_t next_position = position;
908 U16_NEXT(string, next_position, length, character);
909
910 // Now that we have the character, we use ICU in order to query for the
911 // appropriate Unicode BiDi character type.
912 int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
913 if ((property == U_RIGHT_TO_LEFT) || (property == U_RIGHT_TO_LEFT_ARABIC))
914 return true;
915
916 position = next_position;
917 }
918
919 return false;
920 }
921
922 void WrapStringWithLTRFormatting(std::wstring* text) {
923 // Inserting an LRE (Left-To-Right Embedding) mark as the first character.
924 text->insert(0, 1, static_cast<wchar_t>(kLeftToRightEmbeddingMark));
925
926 // Inserting a PDF (Pop Directional Formatting) mark as the last character.
927 text->push_back(static_cast<wchar_t>(kPopDirectionalFormatting));
928 }
929
930 void WrapStringWithRTLFormatting(std::wstring* text) {
931 // Inserting an RLE (Right-To-Left Embedding) mark as the first character.
932 text->insert(0, 1, static_cast<wchar_t>(kRightToLeftEmbeddingMark));
933
934 // Inserting a PDF (Pop Directional Formatting) mark as the last character.
935 text->push_back(static_cast<wchar_t>(kPopDirectionalFormatting));
936 }
937
938 void WrapPathWithLTRFormatting(const FilePath& path,
939 string16* rtl_safe_path) {
940 // Wrap the overall path with LRE-PDF pair which essentialy marks the
941 // string as a Left-To-Right string.
942 // Inserting an LRE (Left-To-Right Embedding) mark as the first character.
943 rtl_safe_path->push_back(kLeftToRightEmbeddingMark);
944 #if defined(OS_MACOSX)
945 rtl_safe_path->append(UTF8ToUTF16(path.value()));
946 #elif defined(OS_WIN)
947 rtl_safe_path->append(path.value());
948 #else // defined(OS_POSIX) && !defined(OS_MACOSX)
949 std::wstring wide_path = base::SysNativeMBToWide(path.value());
950 rtl_safe_path->append(WideToUTF16(wide_path));
951 #endif
952 // Inserting a PDF (Pop Directional Formatting) mark as the last character.
953 rtl_safe_path->push_back(kPopDirectionalFormatting);
954 }
955
956 std::wstring GetDisplayStringInLTRDirectionality(std::wstring* text) {
957 if (GetTextDirection() == RIGHT_TO_LEFT)
958 WrapStringWithLTRFormatting(text);
959 return *text;
960 }
961
962 int DefaultCanvasTextAlignment() {
963 if (GetTextDirection() == LEFT_TO_RIGHT) {
964 return gfx::Canvas::TEXT_ALIGN_LEFT;
965 } else {
966 return gfx::Canvas::TEXT_ALIGN_RIGHT;
967 }
968 }
969
970
971 // Compares the character data stored in two different strings by specified 747 // Compares the character data stored in two different strings by specified
972 // Collator instance. 748 // Collator instance.
973 UCollationResult CompareStringWithCollator(const icu::Collator* collator, 749 UCollationResult CompareStringWithCollator(const icu::Collator* collator,
974 const std::wstring& lhs, 750 const std::wstring& lhs,
975 const std::wstring& rhs) { 751 const std::wstring& rhs) {
976 DCHECK(collator); 752 DCHECK(collator);
977 UErrorCode error = U_ZERO_ERROR; 753 UErrorCode error = U_ZERO_ERROR;
978 #if defined(WCHAR_T_IS_UTF32) 754 #if defined(WCHAR_T_IS_UTF32)
979 // Need to convert to UTF-16 to be compatible with UnicodeString's 755 // Need to convert to UTF-16 to be compatible with UnicodeString's
980 // constructor. 756 // constructor.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 for (size_t i = 0; i < arraysize(kAcceptLanguageList); ++i) { 828 for (size_t i = 0; i < arraysize(kAcceptLanguageList); ++i) {
1053 if (!IsLocaleNameTranslated(kAcceptLanguageList[i], display_locale)) 829 if (!IsLocaleNameTranslated(kAcceptLanguageList[i], display_locale))
1054 // TODO(jungshik) : Put them at the of the list with language codes 830 // TODO(jungshik) : Put them at the of the list with language codes
1055 // enclosed by brackets instead of skipping. 831 // enclosed by brackets instead of skipping.
1056 continue; 832 continue;
1057 locale_codes->push_back(kAcceptLanguageList[i]); 833 locale_codes->push_back(kAcceptLanguageList[i]);
1058 } 834 }
1059 } 835 }
1060 836
1061 } // namespace l10n_util 837 } // namespace l10n_util
OLDNEW
« no previous file with comments | « app/l10n_util.h ('k') | app/l10n_util_dummy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698