App的国际化和本地化(四) —— 国际化代码(一)

版本记录

版本号 时间
V1.0 2018.05.09

前言

很多APP都有国际化版本,常见于一些大公司的产品,比如Facebook、Wechat等,那么国际化需要我们APP做哪些更改呢,接下来这几篇就一起来看一下APP的国际化和本地化。感兴趣的可以看上面几篇。
1. App的国际化和本地化(一) —— 简单介绍(一)
2. App的国际化和本地化(二) —— 查看语言和区域设置(一)
3. App的国际化和本地化(三) —— 国际化用户界面(一)

回顾

上一篇主要介绍国际化用户界面,本篇主要介绍国际化代码。


Internationalizing Your Code - 国际化代码

除了国际化您的用户界面之外,编写处理多种语言文本的代码。 首先将国际文本存储在字符串文件中,类似于Internationalizing the User Interfacebase internationalization使用的字符串文件。 还可以使用语言和区域设置敏感的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”是从本地化字符串文件中检索的文本的key。 @“distance for a marathon”参数是一个关于存储在字符串文件中的键值对的注释,作为本地化器的一个提示。 如果您需要不同的行为,请使用Foundation Functions Reference中介绍的采用更多参数的其他NSLocalizedString宏之一。

提示:请勿覆盖key或从多个key组成短语。 一些语言具有性别文章,形容词结尾和完全不同的词序。 相反,将单独的键值对添加到字符串文件中所有唯一的短语。

例如,替换这些键值对:

/* 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以了解如何为具有不同复数规则的语言扩展此机制。


Using Unicode Strings - 使用Unicode字符串

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

有关字符串对象的全面文档,请阅读String Programming Guide

1. Accessing Characters in Strings - 获取字符串中的字符

NSString类通过允许您访问字符集群或ranges来处理字符编码的复杂性。 使用rangeOfComposedCharacterSequenceAtIndex:rangeOfComposedCharacterSequencesForRange:方法确保您不会拆分字符串中的用户字符并打算文本。 这些方法在表示用户字符的字符串内返回一个range。

例如,表3-1显示了UTF-16和UTF-32编码中用户字符的数字表示形式。 请注意,无论使用何种编码格式,用户字符的长度都不相同。

Table 3-1 Unicode Encoding of User Characters

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

2. Enumerating Strings - 枚举字符串

通过组合字符序列,单词,句子或段落来枚举字符串,而不是字符串中的单个字符。 要通过组合字符序列来枚举字符串,请使用enumerateSubstringsInRange:options:usingBlock:方法并传递NSStringEnumerationByComposedCharacterSequences作为选项参数。 要逐个枚举字符串(跳过标点符号),请传递NSStringEnumerationByWords作为options参数。

例如,如果将NSStringEnumerationByComposedCharacterSequences传递给enumerateSubstringsInRange:options:usingBlock:方法,它将返回用户字符,如同组合字符序列中一样:

如果字符串是:

你传递NSStringEnumerationByWords作为options参数,返回下面的词语:

注意空格和标点符号不包含在单词中。

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

3. Searching Strings - 搜索字符串

要使用区域设置敏感的比较算法搜索字符串的内容或验证字符串中是否存在字符串,请使用rangeOfString:options:range:locale:,将当前位置作为区域设置参数传递。 您可以组合并传递的常量作为选项参数:

例如,如果要在字符串中搜索用户文本,请将NSCaseInsensitiveSearchNSDiacriticInsensitiveSearch常量作为options参数传递给rangeOfString:options:range:locale:方法。 通常情况下,搜索文本是一种大小写和变音不敏感操作,但排序文本是大小写和变音符号敏感。

4. Sorting Strings - 排序字符串

对于向用户显示的文本,请使用区域敏感的API进行排序和比较字符串。 不同的语言和地区有不同的排序顺序标准。 例如,法语中的变音符号很重要,而英语中则不是。 在某些语言中,多个字母被组合并影响排序顺序。

要使用区域敏感的比较算法,请使用与Finder产生相同结果的localizedStandardCompare:方法。

如果您不想获得与Finder相同的结果,请使用compare:options:range:locale:方法,将当前地区作为本地参数或localizedCompare:方法传递。

不要使用localizedCaseInsensitiveCompare:方法进行排序。

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

5. Displaying Text - 展示文本

使用标准视图和控件来处理Unicode文本布局和显示的复杂性。字符串中的字符不直接对应于屏幕上呈现的文本。屏幕上显示的是一系列字形。字形是字体中最小的可显示单位。字形可能代表一个字符,多个字符或字符的一部分。字符到字形的映射并不简单 - 它可以是多对多的。另外,一行中字形的顺序和位置很复杂。标准视图和控件甚至可以为您正确地设计双向文本 - 例如,包含英文单词和希伯来单词的字符串中的字符顺序与用于在视图中放置文本的顺序不同处理双向文本,如Handling Bidirectional Text中所示。

如果您需要编写自定义显示代码,请使用适当的低版本文本API。要了解iOS的文本类,请阅读Text Programming Guide for iOS和Mac,阅读Text Layout Programming Guide

6. 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 Only) - 确定用户确认标记文本的时间(仅限iOS)

要确定用户是否确认了标记的文本,请将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 Class Reference


Getting the Current Language - 获取当前语言

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

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

后记

本篇主要讲述了国际化代码,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容