88bifa必发唯一官网 12

iOS Programming Localization 本地化,ioslocalization

iOS Programming Localization 本地化

Internationalization is making sure your native cultural information is
not hard-coded into your application.


By cultural information, we mean language, currency, date formats,
number formats, and more.

说cultural information ,我们指的是language,currency,date formats ,number
formats 等等。

Localization, on the other hand, is the process of providing the
appropriate data in your application based on the user’s Language and
Region Format settings.

Localization 是提供恰当的数据在你的应用基于用户的语言,区域设置的过程。

You can find these settings in the Settings application. Select the
General row and then the International row.

你可以找到这些信息在你的setting application .选择general
行,然后是international 行。

88bifa必发唯一官网 1

Apple makes these processes relatively simple.

apple 尽量让这个进程更简单。

An application that takes advantage of the localization APIs does not
even need to be recompiled to be distributed in other languages or

APIs的应用甚至不需要重新编译来发布到另一个国家或地区 。

By the way, “internationalization” and “localization” are long words.
You will sometimes see people abbreviate them to i18n and l10n,

internationalization 和localization

1 Internationalization Using NSNumberFormat

88bifa必发唯一官网 2

NSDateFormatter has a locale property, which is set to the device’s
current locale.

NSDateFormatter有一个locale property,它会设置为设备现在的locale.

Whenever you use an NSDateFormatter to create a date, it checks its
locale property and sets the format accordingly. So the text of the date
label has been internationalized from the start.

无论什么时候你用NSDateFormatter 创建一个date,它会检查他的locale property
并系相应的设置格式。所以date label 的text在一开始就被设置为国际化了。

NSLocale knows how different regions display symbols, dates, and
decimals and whether they use the metric system.

NSLocale知道regions 之间显示symbols ,dates,decimals 和他们是否使用metric
system 的区别。

An instance of NSLocale represents one region’s settings for these
variables. In the Settings application, the user can choose a region,
like United States or United Kingdom.

When you send the message currentLocale to NSLocale, the instance of
NSLocale that represents the user’s region setting is returned. Once you
have that instance of NSLocale, you can ask it questions like, “What is
the currency symbol for this region?” or “Does this region use the
metric system?”

当你发送currentLocale 信息给NSLocale时,NSLocale的实例代表了用户的region
setting 。一旦你有了NSLocale的实例,你可以询问它问题例如”这个region
的currency symbol 是什么””这个region 是否使用metric system?”

To ask one of these questions, you send the NSLocale instance the
message objectForKey: with one of the NSLocale constants as an argument.


NSLocale *locale = [NSLocale currentLocale];

BOOL isMetric = [[locale objectForKey:NSLocaleUsesMetricSystem]

NSString *currencySymbol = [locale



While NSLocale is extremely powerful and useful, always using it
directly would make the process of localizing apps very tedious. That’s
why you used NSDateFormatter earlier. There is another class,
NSNumberFormatter that does for numbers what NSDateFormatter does for

尽管NSLocale 极其强大和有用,总是用她,将使得localizing
apps的处理变得非常枯燥。NSNumberFormatter就像NSDateFormmater 对dates.


Depending on the locale, the numberAsString may be 123,456.789 or 123
456,789 or some other value.

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc]

NSString *numberAsString = [numberFormatter


What makes NSNumberFormatter even more useful is its capability to
format currency amounts. If the number formatter’s numberStyle property
is set to NSNumberFormatterCurrencyStyle, it will start producing the
numbers formatted not only with the appropriate group and decimal
separators, but also with the currency symbol.


NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc]

currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;

NSString *numberAsString = [currencyFormatter

In BNRItemsViewController.m, locate the method
tableView:cellForRowAtIndexPath:. Add the static variable
currencyFormatter and set its numberStyle to

// Create a number formatter for currency

static NSNumberFormatter *currencyFormatter = nil;

if (currencyFormatter == nil) {

currencyFormatter = [[NSNumberFormatter alloc] init];

currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;


When the text of the cell’s valueLabel is set in this method, the string
“$%d” is used, which makes the currency symbol always a dollar sign. Use
the currencyFormatter to format the amount correctly.

cell.valueLabel.text =
[currencyFormatter stringFromNumber:@(item.valueInDollars)];

These changes will display the value formatted appropriately for the
user’s region, with both the number format and currency symbol.


To make Homepwner update when the region settings change, you need to
use NSNotificationCenter. In BNRItemsViewController’s init

 method, register for locale change notifications:

为了让Homepwner更新当region settings
init方法里,注册locale change notifications .


// Register for locale change notifications

[nc addObserver:self




Add the method localeChanged.

– (void)localeChanged:(NSNotification *)note

[self.tableView reloadData];



2 Localizing Resources 本地化资源

When internationalizing, you ask the instance of NSLocale questions. But
the NSLocale only has a few region-specific variables. This is where
localization comes into play: Localization is the process by which
application-specific substitutions are created for different region and
language settings.

当internationalizing,你询问NSLocale 实例的问题。但是NSLocale

Localization usually means one of two things:

(1)generating multiple copies of resources like images, sounds, and
NIB files for different regions and languages

产生资源的倍数复制:像images,sounds,NIB files在不同的区域和语言。

(2)creating and accessing strings tables to translate text into
different languages

创建和获取string 表来翻译text 为不同的语言。

Any resource, whether it is an image or a XIB file, can be localized.


Localizing a resource puts another copy of the resource in the
application bundle.

Localizing a resource 把资源的一个拷贝放在了application bundle.

These resources are organized into language- specific directories, known
as lproj directories.

这些资源被组织放进language specific directories,称为lproj directories.

Each one of these directories is the name of the localization suffixed
with lproj.


For example, the American English localization is en_US: where en is
the English language code and US is the United States of America region
code. (The region can be omitted if you do not need to make regional
distinctions in your resource files.) These language and region codes
are standard on all platforms, not just iOS.

例如,American English localization 是en_US.en 是English language
code,US 是United Stated 区域code .

When a bundle is asked for the path of a resource file, it first looks
at the root level of the bundle for a file of that name. If it does not
find one, it looks at the locale and language settings of the device,
finds the appropriate lproj directory, and looks for the file there.
Thus, just by localizing resource files, your application will
automatically load the correct file.

当一个bundle 被询问资源文件的path,它首先查看bundle
的根层级找到那个名字的文件。如果没有找到,它会查看locale 和language
settings ,找到恰当的lproj 目录,寻找这个文件。因此,仅仅本地化resource
files ,你的应用将自动的加载正确的文件。

One option is to create separate XIB files and to manually edit each
string in this XIB file in Xcode. However, this approach does not scale
well if you are planning multiple localizations. What happens when you
add a new label or button to your localized XIB? You have to add this
view to the XIB for every language. This is not fun.


To simplify the process of localizing XIB files, Xcode has a feature
called Base internationalization. When it is enabled for the project,
Base internationalization creates the Base.lproj directory which
contains the main XIB files. Localizing individual XIB files can then be
done by creating just the Localizable.strings files. It is still
possible to create the full XIB files, in case localization cannot be
done by changing strings alone. However, with the help of Auto Layout,
strings replacement may be sufficient for most localization needs.

为了简化localizing XIB files的处理,Xcode有一个特性叫做Base
internationalization.当它被这个project使用时,Base internationalization
创建了Base.lproj 目录,它包含了main XIB files .本地化独特的XIB
文件能够同故宫创建仅有的Localizable.strings files.这仍然是可能的创建full
XIB files ,以防止localization 不能仅仅通过改变strings完成。然而,有Auto
layout 的帮助,strings replacement 可能对大多数的localization neees

In this section, you are going to localize one of Homepwner’s
interfaces: the BNRDetailViewController.xib file. You will create
English and Spanish localizations, which will create two lproj
directories, in addition to the base one.


BNRDetailViewController.xib文件。你将创建Englsih 和spanish localizations
,这将创建两个lproj 目录,除了基础的那个外。

Normally, you would first enable Base Internationalization in the
project Info settings. However, as of this writing, there is a bug in
Xcode that will not let you enable that option until at least one XIB
file is localized.

一般的,你应该打开Base Internationalization 在project info settings
.然而,在Xcode 中有一个bug,不让你选择直到一个XIB 文件已经localized .

So, start by localizing a XIB file. Select BNRDetailViewController.xib
in the project navigator. Then, show the utility area.

the 88bifa必发唯一官网 3tab
in the inspector selector to open the file inspector. Find the section
in this inspector named Localization and click the Localize… button

88bifa必发唯一官网 4

Select English. This signifies to Xcode that this file can be localized,
automatically creates en.lproj, and moves the
BNRDetailViewController.xib file to it.


Now you need to enable Base Internationalization.Make sure you select
the project Homepwner, and not the target Homepwner.


In the bottom section of the Info tab of the project, locate the Use
Base Internationalization checkbox in the Localizations section and
check it. You will see the prompt to select which files will be used to
create the Base localization; the table will consist of just
BNRDetailViewController.xib and English will be listed as the reference
language. Click Finish.

88bifa必发唯一官网 5

88bifa必发唯一官网 6

88bifa必发唯一官网 7

Click the + button under the list of languages and select Spanish. In
the dialog, you can uncheck the InfoPlist.strings files and only keep
the BNRDetailViewController.xib file checked. Make sure that the
reference language is Base and the file type is Localizable Strings.
Click Finish. This creates an es.lproj folder and generates the
BNRDetailViewController.strings in it that contains all the strings from
the base XIB file.

88bifa必发唯一官网 8

88bifa必发唯一官网 9

In the project navigator, click the Spanish version of
BNRDetailViewController.strings. When this file opens, the text is not
in Spanish. You have to translate localized files yourself; Xcode is not
that smart.

Edit this file according to the following text. The numbers and order
may be different in your file, but you can use the text field in the
comment to match up the translations.

files 你自己。Xcode 并不是那么聪明。


3 NSLocalizedString() and Strings Tables    NSLocalizedString和Strings

In many places in your applications, you create NSString instances
dynamically or display string literals to the user. To display
translated versions of these strings, you must create a strings table.

在许多地方,你动态的创建NSString实例或者展现string literals
给用户。为了展现这些strings 的翻译版本,你需要常见一个string table.

A strings table is a file containing a list of key-value pairs for all
of the strings that your application uses and their associated
translations. It is a resource file that you add to your application,
but you do not need to do a lot of work to get data from it.

string table 是一个包含了一列key-value对的所有的strings


You might use a string in your code like this:

NSString *greeting = @”Hello!”

To internationalize the string in your code, you replace literal strings
with the function NSLocalizedString.

NSString *greeting = NSLocalizedString(@”Hello!”, @”The greeting for
the user”);

This function takes two arguments: a key and a comment that describes
the string’s use. The key is the lookup value in a strings table. At
runtime, NSLocalizedString() will look through the strings tables
bundled with your application for a table that matches the user’s
language settings. Then, in that table, the function gets the translated
string that matches the key.

这个函数有两个参数:key和表述这个string 用途的comment.key 是在strings
table 的查找值。在运行是,NSLocalizedString()将查找string tables bundled

Now you are going to internationalize the string “Homepwner” that is
displayed in the navigation bar. In BNRItemsViewController.m, locate the
init method and change the line of code that sets the title of the

navItem.title = NSLocalizedString(@”Homepwner”, @”Name of application”);


Two more view controllers contain hard-coded strings that can be
internationalized. The toolbar in the BNRDetailViewController shows the
asset type. The title of the BNRAssetTypeViewController needs to be
updated just like the title of the BNRItemsViewController.

NSString *typeLabel = [self.item.assetType valueForKey:@”label”]; if
(!typeLabel) {

typeLabel = @”None”;

typeLabel = NSLocalizedString(@”None”, @”Type label None”); }


self.assetTypeButton.title = [NSString stringWithFormat:
NSLocalizedString(@”Type: %@”, @”Asset type button”), typeLabel];


In BNRAssetTypeViewController.m, update the init method:

if (self) {
self.navigationItem.title = @”Asset Type”; self.navigationItem.title =

NSLocalizedString(@”Asset Type”, @”BNRAssetTypeViewController title”);


return self; }

Once you have files that have been internationalized with the
NSLocalizedString function, you can generate strings tables with a
command-line application.

一旦你的文件被internationalized 用NSLocalizedString
函数,你能用command-line 应用产生string tables .

Open the Terminal app.

In Terminal, type the following:


followed by a space. 

Next, open Finder and locate BNRItemsViewController.m and the folder
that contains it. Drag the icon

of that folder onto the Terminal window. Terminal will fill out the path
for you. Press Enter.


88bifa必发唯一官网 10

To generate the strings table, enter the following into Terminal and
press Enter:

为了产生string table,输入如下:

genstrings BNRItemsViewController.m

This creates a file named Localizable.strings in the same directory as
BNRItemsViewController.m. Now you need to generate strings from the
other two view controllers. Since the file Localizable.strings already
exists, you will want to append to it, rather than create it from

controller.因为Localizable.strings已经存在,你需要append to it

To do so, enter the following commands in the Terminal (do not forget
the -a command line option) and press Enter after each line:

genstrings -a BNRDetailViewController.m

genstrings -a BNRAssetTypeViewController.m

The resulting file Localizable.strings now contains the strings from all
three view controllers. Drag from the Finder into the project navigator
(or use the Add Files to “Homepwner”… menu item). When the

application is compiled, this resource will be copied into the main

现在把他们拖动到project navigator中。

/* Name of application */

“Homepwner” = “Homepwner”;


/* Type Label None */

“None” = “None”;


/* Assert type button */

“Type:%@” = “Type:%@”;


Oddly enough, Xcode sometimes has a problem with strings tables. Open
the Localizable.strings file in the editor area. If you see a bunch of
upside-down question marks, you need to reinterpret this file as Unicode
(UTF-16). Show the utility area and select the file inspector. Locate
the area named Text Settings and change the pop-up menu next to Text
Encoding to Unicode (UTF-16) (Figure 25.10). It will ask if you want to
reinterpret or convert. Choose Reinterpret.

88bifa必发唯一官网 11

Notice that the comment above your string is the second argument you
supplied to the NSLocalizedString function. Even though the function
does not require the comment argument, including it will make your
localizing life easier.

argument,包含它将使你localizing life 更容易。

Now that you have created Localizable.strings, localize it in Xcode the
same way you did the XIB file. Select the file in the project navigator
and click the Localize… button in the utility area. Add the Spanish
localization and then open the Spanish version of Localizable.strings.
The string on the lefthand side is the key that is passed to the
NSLocalizedString function, and the string on the righthand side is what
is returned. Change the text on the righthand side to the Spanish
translation shown below.

它在Xcode中。选择Localize…button。添加Spanish localization
并打开Spanish 版本的LOcalizable.strings.左侧是key,右侧是你想返回的值。

/* Name of application */

“Homepwner” = “Dueño de casa”;


/* Type Label None */

“None” = “Nada”;


/* Assert type button */

“Type:%@” = “Tipo:%@”;





Programming Localization
本地化,ioslocalization iOS Programming Localization 本地化
Internationalization is making sure your native cultural information is
not hard-cod…


Internationalization and Localization


iOS 来说就是,使App能够适用于不同的语言,地区,文化的过程。

iOS 来说就是,将App的内容翻译为多种语言的过程。



在 iOS


使用Base Internationalization国际化界面文本

从Xcode5之后,工程默认支持Base Internationalization。


  1. 在项目的.xcodeproj文件中打开project.pbxproj
  2. 搜索developmentRegion,并将该key的值改为所要设置的开发语言对应的语言ID,比如en、zh等
  3. 保存,效果如下图所示
使用Auto Layout辅助国际化界面文本


  1. 显示文字的组件不使用固定宽度的约束,否则在某些语言下文字可能显示不完全,text
  2. 添加水平间距约束时,使用leading和trailing,这样针对左右顺序不同的语言可互换左右间距值。
  3. 因为语言不同视图组件所占空间不同,所以约束应于相邻视图组件建立,这样当语言改变时,其他视图组件也会自动适配。


"key1" = "value1";
"key2" = "value2";


NSLocalizedString("key1", "comment");
NSLocalizedStringFromTable("key1", "tableName", "comment");



格式化时用到NSLocale类,NSLocale类封装了某一个地区的相应的格式化信息,如果要获得用户当前设置地区的NSLocale实例可以使用[NSLocale currentLocale]或者[NSLocale autoupdatingCurrentLocale],两者的区别是,后一个类方法返回的值会根据用户设置的改变而改变,而前者不会。可以通过NSLocal查看很多这一地区的数据格式化信息,例如(其他key值请查阅相关文档):

NSNumber *metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
NSString *currencySymbol = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];
// 用当前地区的语言显示语言ID
NSLocale *zhHansLocal = [NSLocale localeWithLocaleIdentifier:@"zh-Hans"];
NSString *currentLocalZH = [zhHansLocal displayNameForKey:NSLocaleIdentifier value:@"zh-Hant-TW"];
NSString *currentLocalEN = [zhHansLocal displayNameForKey:NSLocaleIdentifier value:@"en-US"];
// 获取该地区所使用的引号
NSString *bQuote = [locale objectForKey:NSLocaleQuotationBeginDelimiterKey];
NSString *eQuote = [locale objectForKey:NSLocaleQuotationEndDelimiterKey];
// 国际化大小写转换
NSString *localizedUppercaseString = [string uppercaseStringWithLocale:[NSLocale currentLocale]];
NSString *localizedlowercaseString = [string lowercaseStringWithLocale:[NSLocale currentLocale]];
NSString *localizedCapitalizedString = [string capitalizedStringWithLocale:[NSLocale currentLocale]];

当使用[NSString stringWithFormat]去拼装字符串时,如果传入的参数带有数值,日期等需要格式化的内容,最好使用以下方式(更好的方式是使用formatter进行转换):

// 使[NSLocale systemLocale]
NSString *localizedString = [NSString localizedStringWithFormat:@"%3.2f", myNumber];
NSString *localizedString = [[NSString alloc] initWithFormat:@"%@" locale:[NSLocale localeWithLocaleIdentifier:@"zh"], [NSDate date]];


// 使用预设的格式
NSString *localizedDateTime = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterShortStyle];
// 使用自定义的格式
NSDateFormatter *dateFormatter = [NSDateFormatter new];
NSString *localeFormatString = [NSDateFormatter dateFormatFromTemplate:@"dMMM" options:0 locale:dateFormatter.locale];
dateFormatter.dateFormat = localeFormatString;
NSString *localizedString = [dateFormatter stringFromDate:[NSDate date]];


NSString *localizedString = [NSNumberFormatter localizedStringFromNumber:myNumber numberStyle:NSNumberFormatterDecimalStyle];



Base Internationalization和Auto

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {


Xcode 将开发语言的文本资源导出为 XLIFF (XML Localisation Interchange
文件,翻译人员在完成该文件内的相应翻译内容后,再通过 Xcode

  1. 在 Xcode 中选中工程或 target。
  2. 选择 Editor > Export For Localization。

之后 Xcode 会将 .xliff 文件导出到你指定的目录中。如果你在工程的
Localizations 设置项中还没有添加过其他的语言,而只有开发语言(如
English)一种,那么导出的文件为 en.xliff。这时的 en.xliff
Chinese)添加到 Localizations 中,这样导出的文件就为


xcodebuild -exportLocalizations -localizationPath <dirpath> -project <projectname> [[-exportLanguage <targetlanguage>]]

Xcode 的一项特性 Locking Views。可以只针对某一 view 修改,在该 view 的
Identity inspector 中修改 Lock 项。也可设置整个 nib
文件的该属性,选中对应 nib 文件后,修改 Editor > Localization Locking

  1. 在 Xcode 中选中工程或 target。
  2. 选择 Editor > Import Localizations。

Xcode 会从 XLIFF 文件中解析出翻译内容的 .strings
文件,然后放到对应语言的 .lproj 目录中,而在工程中,nib 文件和 .strings


xcodebuild -importLocalizations -localizationPath <filepath> -project <projectname>


88bifa必发唯一官网 12

在国际化资源文件后,就可以将本地化版本的文件加到对应的 .lproj 目录中。



developmentRegion 为
en.xliff 文件交由翻译人员翻译,并最终导入。最后一步,是要确认 Info.plist
文件中的 CFBundleDevelopmentRegion 字段设置为


You can choose from more than 100 different languages and dialects
designated by regions to localize your app. However, the more general
you make your localized resources, the more regions you can support
with a single set of resources. This can save a lot of space in your
app bundle and help reduce localization costs. For example, if you
don’t need to distinguish between different regions that use the
English language, you can add English to support users in the United
States, United Kingdom, and Australia. Even if you provide
region-specific resources always provide a complete set of
language-specific resources for all the languages you support.



在 Xcode
.storyboard 或 .xib 文件,打开辅助编辑器,在相关文件中选择
Preview,通过右下角语言选项,可以在国际化后选择 Double-Length
Pseudolocalizations 进行检测,本地化后选择对应语言进行检测。

Scheme,选择 Run -> Options,在 Application Language
一项中,可以选择对应语言资源,Double-Length Pseudolocalizations 以及
Right to Left Pseudolocalizations。勾选 Show non-localized strings