Home | History | Annotate | Download | only in l10n
      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 base::string16& label) {
     57   const base::char16 kEllipsisUTF16 = 0x2026;
     58   base::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     base::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 base::string16& a) {
     91   return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id,
     92                                                              a));
     93 }
     94 
     95 NSString* GetNSStringF(int message_id,
     96                        const base::string16& a,
     97                        const base::string16& b) {
     98   return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id,
     99                                                              a, b));
    100 }
    101 
    102 NSString* GetNSStringF(int message_id,
    103                        const base::string16& a,
    104                        const base::string16& b,
    105                        const base::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 base::string16& a,
    112                        const base::string16& b,
    113                        const base::string16& c,
    114                        const base::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 base::string16& a,
    121                        const base::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 base::string16& a) {
    133   return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id,
    134                                                            a));
    135 }
    136 
    137 NSString* GetNSStringFWithFixup(int message_id,
    138                                 const base::string16& a,
    139                                 const base::string16& b) {
    140   return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id,
    141                                                            a, b));
    142 }
    143 
    144 NSString* GetNSStringFWithFixup(int message_id,
    145                                 const base::string16& a,
    146                                 const base::string16& b,
    147                                 const base::string16& c) {
    148   return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id,
    149                                                            a, b, c));
    150 }
    151 
    152 NSString* GetNSStringFWithFixup(int message_id,
    153                                 const base::string16& a,
    154                                 const base::string16& b,
    155                                 const base::string16& c,
    156                                 const base::string16& d) {
    157   return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id,
    158                                                            a, b, c, d));
    159 }
    160 
    161 
    162 }  // namespace l10n_util
    163