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 #import <Foundation/Foundation.h> 6 7 #include "base/lazy_instance.h" 8 #include "base/logging.h" 9 #include "base/mac/bundle_locations.h" 10 #include "base/strings/sys_string_conversions.h" 11 #include "ui/base/l10n/l10n_util.h" 12 #include "ui/base/l10n/l10n_util_mac.h" 13 14 namespace { 15 16 base::LazyInstance<std::string> g_overridden_locale = LAZY_INSTANCE_INITIALIZER; 17 18 } // namespace 19 20 namespace l10n_util { 21 22 const std::string& GetLocaleOverride() { 23 return g_overridden_locale.Get(); 24 } 25 26 void OverrideLocaleWithCocoaLocale() { 27 // NSBundle really should only be called on the main thread. 28 DCHECK([NSThread isMainThread]); 29 30 // Chrome really only has one concept of locale, but Mac OS X has locale and 31 // language that can be set independently. After talking with Chrome UX folks 32 // (Cole), the best path from an experience point of view is to map the Mac OS 33 // X language into the Chrome locale. This way strings like "Yesterday" and 34 // "Today" are in the same language as raw dates like "March 20, 1999" (Chrome 35 // strings resources vs ICU generated strings). This also makes the Mac acts 36 // like other Chrome platforms. 37 NSArray* languageList = [base::mac::OuterBundle() preferredLocalizations]; 38 NSString* firstLocale = [languageList objectAtIndex:0]; 39 // Mac OS X uses "_" instead of "-", so swap to get a real locale value. 40 std::string locale_value = 41 [[firstLocale stringByReplacingOccurrencesOfString:@"_" 42 withString:@"-"] UTF8String]; 43 44 // On disk the "en-US" resources are just "en" (http://crbug.com/25578), so 45 // the reverse mapping is done here to continue to feed Chrome the same values 46 // in all cases on all platforms. (l10n_util maps en to en-US if it gets 47 // passed this on the command line) 48 if (locale_value == "en") 49 locale_value = "en-US"; 50 51 g_overridden_locale.Get() = locale_value; 52 } 53 54 // Remove the Windows-style accelerator marker and change "..." into an 55 // ellipsis. Returns the result in an autoreleased NSString. 56 NSString* FixUpWindowsStyleLabel(const string16& label) { 57 const char16 kEllipsisUTF16 = 0x2026; 58 string16 ret; 59 size_t label_len = label.length(); 60 ret.reserve(label_len); 61 for (size_t i = 0; i < label_len; ++i) { 62 char16 c = label[i]; 63 if (c == '(' && i + 3 < label_len && label[i + 1] == '&' 64 && label[i + 3] == ')') { 65 // Strip '(&?)' patterns which means Windows-style accelerator in some 66 // non-English locales such as Japanese. 67 i += 3; 68 } else if (c == '&') { 69 if (i + 1 < label_len && label[i + 1] == '&') { 70 ret.push_back(c); 71 ++i; 72 } 73 } else if (c == '.' && i + 2 < label_len && label[i + 1] == '.' 74 && label[i + 2] == '.') { 75 ret.push_back(kEllipsisUTF16); 76 i += 2; 77 } else { 78 ret.push_back(c); 79 } 80 } 81 82 return base::SysUTF16ToNSString(ret); 83 } 84 85 NSString* GetNSString(int message_id) { 86 return base::SysUTF16ToNSString(l10n_util::GetStringUTF16(message_id)); 87 } 88 89 NSString* GetNSStringF(int message_id, 90 const string16& a) { 91 return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, 92 a)); 93 } 94 95 NSString* GetNSStringF(int message_id, 96 const string16& a, 97 const string16& b) { 98 return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, 99 a, b)); 100 } 101 102 NSString* GetNSStringF(int message_id, 103 const string16& a, 104 const string16& b, 105 const string16& c) { 106 return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, 107 a, b, c)); 108 } 109 110 NSString* GetNSStringF(int message_id, 111 const string16& a, 112 const string16& b, 113 const string16& c, 114 const string16& d) { 115 return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, 116 a, b, c, d)); 117 } 118 119 NSString* GetNSStringF(int message_id, 120 const string16& a, 121 const string16& b, 122 std::vector<size_t>* offsets) { 123 return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, 124 a, b, offsets)); 125 } 126 127 NSString* GetNSStringWithFixup(int message_id) { 128 return FixUpWindowsStyleLabel(l10n_util::GetStringUTF16(message_id)); 129 } 130 131 NSString* GetNSStringFWithFixup(int message_id, 132 const string16& a) { 133 return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, 134 a)); 135 } 136 137 NSString* GetNSStringFWithFixup(int message_id, 138 const string16& a, 139 const string16& b) { 140 return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, 141 a, b)); 142 } 143 144 NSString* GetNSStringFWithFixup(int message_id, 145 const string16& a, 146 const string16& b, 147 const string16& c) { 148 return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, 149 a, b, c)); 150 } 151 152 NSString* GetNSStringFWithFixup(int message_id, 153 const string16& a, 154 const string16& b, 155 const string16& c, 156 const string16& d) { 157 return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, 158 a, b, c, d)); 159 } 160 161 162 } // namespace l10n_util 163