国际化你的代码(Internationalizing Your Code)

为了国际化你的用户界面,写以多种语言处理文本的代码。首先在字符串文件中存储国际化文本类似于国际化用户界面中的基础国际化中使用的字符串文件。一样在代码中使用语言和本地化敏感的API来枚举,搜索和排序文本。也使用编制文本视图展示并解析文本输入。让这些API为你处理不同编写和输入系统的复杂性。

从你的代码中分离出面向用户的文本(Separating User-Facing Text from Your Code)

应用程序编程提供的所有面向用户的文本都需要进行本地化-不包含在.storyboard或.xib文件中的面向用户的文本,比如错误消息,在展示给用户之前需要翻译成当前语言。iOS和OS X提供机制以在运行时从字符串文件中检索本地化的文本。在代码中,使用NSLocalizedString宏的返回值替换包含面向用户的文本的字符串。当你导出本地化时,Xcode在代码中搜索该宏,并在导出的用来翻译的本地化文件中包含字符串文件。当你导入本地化时,Xcode添加代码使用的字符串文件到你的Xcode工程中。
例如,而不是在代码中使用@“26.22 miles”字符串,使用:

NSLocalizedString(@"RunningDistance", @"distance for a marathon")

@"RunningDistance"是从本地化字符串文件中检索的文本的键值。@"distance for a marathon"参数是关于保持在字符串文件中的键值对的注释,作为对本地化者的提示。如果你想要不同的行为,使用基础函数参考中介绍的采用更多参数的其他NSLocalizedString宏之一。

提示:不要超载键或从多个键组成短语。一些语言具有性别文章,形容词结尾和完全不同的词序(Some languages have gender articles, adjective endings, and completely different word order.)。相反,为所有唯一的短语添加一个单独的键值对到字符串文件。
例如,替换这些键值对:

/* Go to next page/chapter */
"GoToNext" = "Go to next %@";
"chapter" = "chapter";
"page" = "page";

为每个语句用独立的键值对:

/* Go to next chapter */
"GoToNextChapter" = "Go to next chapter";

/* Go to next page */
"GoToNextPage" = "Go to next page";

不要在本地化字符串中放数字,因为不同的地区可以使用不同的数字。

你不需要存储所有键值对在通一个字符串文件中。你可以使用其他NSLocalizedString宏创建独立的字符串文件,并且可以选择存储它们在不同的包中。更多关于NSLocalizedString宏的信息,阅读资源编程指南(Resource Programming Guide)中的字符串资源(String Resources)。

从字符串文件中检索一个本地化字符串,而不是添加它到一个字符串文件,使用NSBundle类中的localizedStringForKey:value:table:方法。当指定表格相对应的字符串文件不在你的项目中时,NSLocalizedString宏和localizedStringForKey:value:table: 方法返回参数值作为本地化字符串。

后面,当你导入本地化时,像Importing Localizations中描述的一样,本地化字符串文件被添加到你的项目中。(或者,你可以从NSLocalizedString宏直接生成开发语言字符串文件,像Creating Strings Files for User-Facing Text in Your Code描述的一样。)

如果你的字符串包含复数名词或测量单位,请阅读Handling Noun Plurals and Units of Measurement以了解如何为具有不同复数规则的语言扩展此机制。

使用Unicode字符串(Using Unicode Strings)

对于所有面向用户的文本,使用支持Unicode的字符串对象--NSString,NSAtrributedString和它们的子类。Unicode是从全世界的写入系统编码字符的标准。字符串对象封装了一个以UTF-16格式编码的Unicode字符串。用户看到的字符可以表示并编码为Unicode字符串中的多个字符。因此,使用处理组合字符序列的字符串方法,而不是字符串中的单个字符。使用合适的字符串API进行迭代,搜索和排序。使用正确展示Unicode字符串对象的标准视图和控件。

关于字符串对象的全面性的文档,参阅String Programming Guide

访问字符中的字符(Accessing Characters in Strings)

NSString类通过允许你访问字符串或范围来为你处理字符串编码的复杂性。使用rangeOfComposedCharacterSequenceAtIndex:和rangeOfComposedCharacterSequencesForRange:方法确保你不会将字符串中的用户字符分割并打破文本。

例如,表格3-1展示了用户字符在UTF-16和UTF-32编码中的数字展示。注意,不管你使用什么编码格式,用户字符的长度都不同。

表格3-1 用户字符的Unicode编码

User Character UTF-16 UTF-32
D85E DFFD 27BFD
1100 1161 11A8 01100 01161 011A8

视频:WWDC 2013 Making Your App World-Ready: International Text > Composed Character Sequences

遍历字符串(Enumerating Strings)

遍历字符串通过组成字符序列,单词,句子或段落,而不是字符串中的单个字符。通过组成字符序列遍历字符串,使用enumerateSubstringsInRange:options:usingBlock:方法并传递NSStringEnumerationByComposedCharacterSequences作为选项参数。通过单词(跳过标点符号)遍历字符串,传递pass NSStringEnumerationByWords作为选项参数。 例如,如果你传递NSStringEnumerationByComposedCharacterSequencesenumerateSubstringsInRange:options:usingBlock:方法,它返回用户字符,就像在组成字符序列:
  
   如果字符串是    并且你传递NSStringEnumerationByWords作为选项参数,返回下面的单词:   Say          注意空格和标点符号不包含在单词中。

视频:WWDC 2013 Making Your App World-Ready: International Text > String APIs: Iteration

搜索字符串(Searching Strings)

搜索字符串的内容或使用区域设置敏感的比较算法验证字符串中是否存在字符串,使用rangeOfString:options:range:locale:方法,传递当前地点作为地点参数。你可以组合并作为选项参数传递的常量是: NSCaseInsensitiveSearch  不区分大小写搜索。例如,‘B’跟‘b’一样。 NSDiacriticInsensitiveSearch  忽略变音符。例如‘ö’等于‘o’。 NSBackwardsSearch  向后搜索。(默认是向前的。) NSAnchoredSearch  在起点搜索。 例如,如果在字符串中搜索用户文本,传递NSCaseInsensitiveSearchNSDiacriticInsensitiveSearch常量作为选项参数给rangeOfString:options:range:locale:方法。通常,搜索文本是不区分大小写和变音字符字符的操作,但是排序文本是大小写和变音字符敏感的。

排序字符串(Sorting Strings)

对于展示给用户的文本,使用语言环境敏感的API排序和比较字符串。不同的语言和地区有不同的排序顺序标准。例如,法语中变音字符是重要的,但在英语中不重要。在一些语言中多个字符合并在一起影响排序顺序。 要使用语言环境敏感的比较算法,使用跟Finder产生同样结果的localizedStandardCompare:方法。 如果不想要Finder一样的结果,使用compare:options:range:locale:方法,传递当前语言环境作为语言环境参数,或localizedCompare:方法。 不要使用localizedCaseInsensitiveCompare:方法排序。

视频:WWDC 2013 Making Your App World-Ready: International Text > String APIs: Sorting

展示文本(Displaying Text)

使用标准视图和控件为你处理Unicode文本布局的复杂性并展示。字符串中的字符不直接相当于屏幕上渲染的文本。屏幕上显示的是一系列字形。字形是一个字体中最小的可展示单元。一个字形可能代表一个字符,多个字符,或者字符的一部分。字符对字形的映射不简单--它可以是多对多的。此外,一行中字形的顺序和位置是复杂的。标准视图和控件甚至可以正确设置双向文本--例如,包含英文单词和希伯来单词的字符串中的字符顺序与用于在视图中排列文本的顺序不同,像Handling Bidirectional Text中描述的一样。 如果你需要编写自定义展示代码,使用合适的底层文本API。学习iOS关于文本的类,阅读Text Programming Guide for iOS,Mac阅读Text Layout Programming Guide

解析文本输入(Parsing Text Input)

用户可能以任何语言和格式输入文本。iOS和OS X可以辨认出用户键入的语言并提供合适的键盘选择。如果你在用户输入文本时解析它,记住从键盘字符到语言字符有一个多对多的映射。

解析语言字符(Parsing Language Characters)

对于某些语言,用户一次不会输入一个字符的文本。 也就是说,用户在键盘上按下的键不一定对应于该语言中的字符。 在法语中,用户通过从弹出式菜单中选择插入点来添加口音。 在日语和汉语中,用户输入语音表示并从候选列表中选择一个候选以确认标记的文本。 在这两种情况下,首先插入初步文本,然后在用户确认后将其转换为最终文本。

视频:WWDC 2013 Making Your App World-Ready: International Text > Text Input

确定用户何时确认了标记文本(Determining When the User Confirms Marked Text )(仅iOS(iOS Only))

要确定用户是否确认了标记的文本,请将markedTextRange发送到文本视图。 如果此方法返回空字符串,则用户确认了一些输入的文本。

确定打字语言(Determining the Typed Language (iOS Only (仅iOS)))

获取用户当前打字的语言,使用UIResponder类的textInputMode属性,就像:

NSString *languageID = [[[UIApplication sharedApplication] textInputMode] primaryLanguage];

返回字符串是一个语言ID,如Language and Locale IDs中所描述的,用于标识书面语言或方言。 获取用户启用的语言集合:

NSArray *languages = [[[UIApplication sharedApplication] textInputMode] activeInputModes];

返回数组包含UITextInputMode类的实例。

检测人名,邮件地址和电话号码(Detecting Personal Names, Mailing Addresses, and Phone Numbers)

在全球范围内,个人姓名,邮寄地址和电话号码的格式差别很大。 个人名称有很多不同的格式,包括组件的不同排序。 例如,在亚洲国家,姓氏后面跟着名字,两者之间没有空格。 邮寄地址的格式取决于国家。 电话号码在它们之间有不同的数字和标点符号。 要在文本视图中处理不同的输入格式,请使用Interface Builder将数据检测器添加到文本视图。 数据检测器以许多不同的国际格式识别地址和电话号码,并可选择将其转换为链接。 要以编程方式在字符串中检测此类数据,请阅读NSDataDetector类参考。

获得当前语言(Getting the Current Language)

要从主应用程序包获取应用程序使用的语言,请使用NSBundle类中的preferredLocalizations方法:

NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;

results matching ""

    No results matching ""