iOS国际化及本地化(一)不一样语言的差别处理及测试

国际化及本地化概念

将标题取名为国际化及本地化(internationalization and localization),是由于这两个概念是有差别的,而这个差别经常被咱们忽略,如下是维基百科的解释:html

国际化是指在设计软件,将软件与特定语言及地区脱钩的过程。当软件被移植到不一样的语言及地区时,软件自己不用作内部工程上的改变或修正。本地化则是指当移植软件时,加上与特定区域设置有关的信息和翻译文件的过程。json

国际化和本地化之间的区别虽然微妙,但却很重要。国际化意味着产品有适用于任何地方的“潜力”;本地化则是为了更适合于“特定”地方的使用,而另外增添的特点。用一项产品来讲,国际化只需作一次,但本地化则要针对不一样的区域各作一次。这二者之间是互补的,而且二者合起来才能让一个系统适用于各地。xcode

有些时候咱们也会用国际化或者全球化代替这二者含义。安全

做为一款优秀的产品咱们作多语言版本时不该仅仅考虑到翻译这一层面,还有更多本地化相关内容须要咱们注意,这篇文章主要涉及的也是本地化这一块。app

国际化工做流程

本篇文章主要介绍Internationalize和Test这两步。dom

本文目录为:ide

1.增长多语言布局

2.UI元素的本地化post

3.资源文件本地化测试

4.字符串相关的本地化

5.使用NSLocal进行本地化

6.从右到左语言的处理

7.本地化测试

增长多语言

一、在项目导航栏选择项目(不是target)

二、在Localizations一栏,点击“+”号,添加语言

每一个条目都是由语言名称和语言id构成,例如 Chinese(Simplified)(zh-Hans), Japanese(ja) 至此咱们的项目就开启了对应语言的本地化支持。

三、在对话框中选中你想本地化的文件。

语言和区域的影响

经过观察系统日历,咱们能够看到即便语言同样,国家区域的不一致也会有一些约定上的区别,关于日期和时间的本地化会在下面介绍。

一、语言设置:Setting -> General -> Language & Region

一样的,关于Region和Calendar的设置也在该页面。

资源文件的本地化

storyboard, xib文件

对于sotryboardxib文件的本地化是Xcode直接支持的。 在添加语言时会提示咱们自动选择建立本地化文件,若是是在添加语言以后建立的IB文件,能够经过xcode右侧属性栏中点击Localize...生成本地化文件。

图片文件

一、方法一 对于图片内容咱们能够经过同IB文件的方式进行本地化,可是有一个限制就是图片要是放到项目文件层级的,而不能放到Assets文件夹中。 好消息是Xcode 11将放开这种限制,对于Assets引入的图片也能够作本地化处理。

二、方法二 除了Xcode自己支持的方式,咱们还能够经过命名来区分图片内容,把图片名当作须要本地化的字符串,各个语言对应不一样版本的图片名,这样也能够实现图片文件的本地化。

音视频及其余资源文件

若是是内置的像是音视频,json或者其余类型的配置文件这类内容,可使用图片文件的方法二进行引入。

更多详细的设置能够参考这个文章:iOS语言国际化/本地化-实践总结

UI元素的本地化

使用Auto layout

Auto layout是相对布局,它有能力在语言和区域变化时进行自适应。如下有几点使用auto layout的技巧:

一、移除宽度的约束 相同含义下不一样语言宽度每每不同,应该让控件可以自适应。

二、使用内容内部大小 fields和label默认是自动调整大小的,若是一个显示本地化内容的视图须要这个功能,选择该view,选择Editor > Size To Fit Content

三、使用leadingtrailing属性 正常leadingtrailing对应leftright,他们含义相同。可是有些国家,像是希伯来和阿拉伯的人使用习惯是从右往左。若是你是使用leadingtrailing,在该环境下将自动对应rightleft

四、将视图固定到相邻视图 就是定义相邻约束,避免某一视图变化致使重叠。

使用伪本地化发现问题

这个功能只支持使用storyboardxib进行布局的UI。 一、选中须要测试的.storyboard或者.xib文件 二、选择菜单栏 View > Assistant Editor > Show Assistant Editor

字符串相关的本地化

使用Unicode字符串

对于全部面向用户的字符串都要使用NSString, NSAttributedString,对于Swift就是String, AttributedString,由于他们支持Unicode,Unicode是世界上全部书写系统的字符编码标准。

对于一些特殊的字符串需求: 一、访问字符串中的字符 使用NSString中的rangeOfComposedCharacterSequenceAtIndex:rangeOfComposedCharacterSequencesForRange:方法,他们会确保你在取字符串时不会破坏原文本。看一个例子你可能会明白:

这两个文字不管是在UTF-16仍是UTF-32编码的状况下都是不一样的长度,因此咱们不能经过长度而要经过以上的两种方式取目标字符串。

二、遍历字符串

若是咱们要遍历展现下面的字符串:

能够经过enumerateSubstringsInRange:options:usingBlock:方法,其中options参数若是传递NSStringEnumerationByComposedCharacterSequences将会按照最小字符进行遍历,若是选用NSStringEnumerationByWords将会按照词语进行遍历。 以上例子使用该值遍历的结果是:

更多关于字符串相关的本地化问题能够参照该条视频: WWDC 2013 Making Your App World-Ready

三、关于人名,邮寄地址,电话号码的检测 由于不一样国家对于人名和电话号码的规则差异较大,咱们能够针对不一样国家写正则进行检测,也可使用苹果提供的一个特殊含义字符的检测类:NSDataDetector

支持检测的类型包括日期,地址,连接,手机号,交通讯息。

获取当前语言

将语言设置为English(United Kingdom),区域设置成United States,经过如下API获取到:

//en
NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;
复制代码

通常获取语言所用的方式是经过Bundle也就是第一种方式。

使用NSLocal进行本地化

NSLocale对象封装关于特定区域格式化标准的信息,包括日期,时间,测量,数字,货币等一系列内容。

将语言设置为English(United Kingdom),区域设置成United States,经过如下API获取到:

//en-GB_US
[NSLocale currentLocale].localeIdentifier;
//en
[NSLocale currentLocale].languageCode;
复制代码

其中languageCode跟经过Bundle获取到的是同样的。

其中localIdentifier表示为en-GB_US,对应为:语言id-国家id_区域码,这几个内容均可以经过NSLocal对象取到。

获取特定语言的引号

由于每种语言对于引号的使用是不同的,咱们能够经过NSLocal获取到引号

//1.Get the language that the app is using.
NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;
//2.Get the associated locale object.
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:languageID];
//3.Get the beginning and ending symbols for quotes from the locale object.
bQuote = [locale objectForKey:NSLocaleQuotationBeginDelimiterKey];
eQuote = [locale objectForKey:NSLocaleQuotationEndDelimiterKey];
//4.Format a string using the locale-sensitive quotes.
quotedString = [NSString stringWithFormat:@"%@%@%@", bQuote, myText, eQuote];
复制代码

如下展现了不一样区域对于myText@"iPhone"时的字符串效果。

字符串的本地化

一、建立格式化字符串 应该使用localizedStringWithFormat:而不是stringWithFormat:

NSString *localizedString = [NSString localizedStringWithFormat:@"%3.2f", myNumber];
复制代码

此方法会根据系统Local进行显示。

日期时间本地化

二、日期和时间转字符串 使用NSDateFormatter表示NSDate对象。推荐使用这个方法:localizedStringFromDate:dateStyle:timeStyle:

//14 Aug 2019 at 11:19
NSString *localizedDateTime = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterShortStyle];
复制代码

下表展现了语言为英语,区域是美国时的日期和时间格式:

下表展现了 dateStyleNSDateFormatterMediumStyletimeStyleNSDateFormatterShortStyle在不一样语言和地区时的表现形式:
三、使用自定义日期和时间格式

//1.Create an NSDateFormatter object.
NSDateFormatter *dateFormatter = [NSDateFormatter new];
//2.get a localized format string from a template that you provide.
NSString *localeFormatString = [NSDateFormatter dateFormatFromTemplate:@"MMM d" options:0 locale:dateFormatter.locale];
//3.Set the format of the NSDateFormatter instance to the locale-sensitive format string.
dateFormatter.dateFormat = localeFormatString;
//4.Use the stringFromDate: method to get a localized string representation of the date.
NSString *localizedString = [dateFormatter stringFromDate:[NSDate date]];
复制代码

在不一样语言和区域下localizedString对应的内容为:

三、解析日期字符串

//1.Create a date formatter object.
NSDateFormatter *dateFormatter = [NSDateFormatter new];
//2.Set the formatter’s style to a preset style.
dateFormatter.dateStyle = NSDateFormatterMediumStyle;
//3.If the input string is not expected to contain a time, set the time style to none.
dateFormatter.timeStyle = NSDateFormatterNoStyle;
//4.Set the leniency to YES (enables the heuristics).
dateFormatter.lenient = YES;
//5.Convert the string to a date object.
NSDate *date = [dateFormatter dateFromString:inputString];
复制代码

咱们输入的字符串是9/3/14,dateStyle设为NSDateFormatterShortStyle,若是区域为美国,咱们获得的NSDate信息为:2014-09-03 07:00:00 +0000,若是区域为德国,咱们将获得2014-03-09 08:00:00 +0000

数字本地化

本地化设置会影响小数点符号,千分符,货币符等内容,好比数字1,234.56在乎大利应该表示为1.234,56,因此对于数字的格式化咱们应该用NSNumberFormatter处理。 注意:NSNumberFormatter不是现成安全的 一、将Number转成本地化的字符串 可使用NSNumberFormatterlocalizedStringFromNumber:numberStyle:方式

NSString *localizedString = [NSNumberFormatter localizedStringFromNumber:myNumber numberStyle:NSNumberFormatterDecimalStyle];
复制代码

如下是不一样语言和区域关于数字的显示效果,左侧的style及numberStyle

二、将字符串转成NSNumber对象 这个相似日期的转换

//1.Create a number formatter object.
NSNumberFormatter *numberFormatter = [NSNumberFormatter new];
//2.Set the formatter’s style to a preset style.
numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
//3.Set the leniency to YES (enables the heuristics).
numberFormatter.lenient = YES;
//4.Convert the string to a number object.
NSNumber *number = [numberFormatter numberFromString:inputString];
复制代码

三、经过NSCalendar计算日期 NSCalendar类封装了日历的全部区域差别和复杂性。说他具备复杂性是由于在不一样国家,一年之中的月份多是12或者13,一月中的天数多是5到31的任意值,每周第一天多是周六,周日或者周一。能够看下表

所以使用NSCalendar取这些值将会很方便。 获取Calendar unit的方式为

//1.Create an NSDateComponents object.
NSDateComponents *components = [[NSCalendar currentCalendar]
    components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSEraCalendarUnit
    fromDate:[NSDate date]];
//2.Access the values for day, month, year, and era.
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
NSInteger era = [components era];
复制代码

四、监听本地化信息或者时区修改 能够经过NSCurrentLocaleDidChangeNotification监听区域的改变

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil];
复制代码

一样的监听时区变化能够经过NSSystemTimeZoneDidChangeNotification

从右到左语言的处理

建立从右到左语言的交互界面

支持从右到左向的语言,在约束层面应该使用Auto layout中的leadingtrailing属性,而不是rightright。能够经过如下对比看到区别

总体像是作了水平的翻转,有不少控件像是segmented控件, 进度指示器系统会自动作翻转。可是有些状况是不须要翻转的:

  • 视频控制和时间线指示器
  • 图片,除非他们传达方向感,如箭头
  • 时钟
  • 曲谱
  • 图表(x轴和y轴老是在一致的方向)

获取布局的方向性

若是咱们想获取当前语言是否应该是从右到左项的语言能够经过如下方法:

//right-to-left language
if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
    …
}
复制代码

设置文本的对齐方式

在iOS中默认的文本对齐方式是“natural”,在OS X中默认方式是“left”。natural的含义就是会感受语言的方向自动调整为left或者right。 若是你想NSMutableParagraphStyle对象的对齐方式为天然的方向,能够:

[[(NSMutableParagraphStyle *)paraStyle setAlignment:NSNaturalTextAlignment];
复制代码

对双向文本的处理

双向文本就是一段文本中及含有从右往左的文本还含有从左往右的文本。是否是感受很诧异?由于即便像阿拉伯和希伯来国家这些书写习惯为从右往左,可是对于数字和拉丁文是从左往右写的。若是你使用的是标准控件,像Label,TextView,Textfiled他们会自动处理双向文本内容。若是你是使用自定义控件,那这些问题就须要你手动处理。

向双向文本添加Unicode标记

在某些特殊的时候,系统默认的行为可能会致使一些不正确的结果,这时咱们能够经过添加Unicode标记进行纠正。

例如,手机号在全部语言中都是从左往右读的,若是一个须要本地化的字符串变量表示一个手机号,若是咱们须要保证他是从左往右的顺序展现,须要再字符串首部增长一个从左往右的嵌入字符(LRE):U+202A,在字符尾部增长定向格式字符(PDF):U+202C

// Wrap the plus (+) prefix and phone number in left-to-right directional markers
NSString *phoneNumber = @"408-555-1212";
NSString *localizedPhoneNumber = [NSString stringWithFormat:@"\u202A%@\u202C", phoneNumber];
复制代码

翻转Cocoa Touch视图

有些视图是不该该翻转的,在iOS9以后能够经过UIView的semanticContentAttribute属性手动指定视图应该是从左到后仍是从右往左的方式展现。

若是是想翻转图片能够经过UIImageimageFlippedForRightToLeftLayoutDirection方法。

本地化测试

经过IB预览测试本地化

这个功能只能在.storyboard和.xib文件实现。

选中preview以后咱们能够经过其右下角的语言选项切换不一样语言,而后咱们能够实时观察调换语言以后的效果。

经过伪语言功能测试

经过Edit Schema > Run > Options 而后点开语言选项,除了各类系统支持语言外,翻到最下面能够看到这几个选项。

1.Double-Length Pseudolanguage 能够将文本内容变成两倍长度。

2.Right-to-Left Pseudolanguage 将语言方向改为从右往左,也能够将语言改为阿拉伯文或者希伯来文。

3.Accented Pseudolanguage 带重音符号。

4.Bounded String Pseudolanguage 带边界的字符串。

5.Right-to-Left Pseudolanguage With Right-to-Left Strings 同从右往左语言。

引用

苹果文档:Internationzlization and Localization Guide

相关文章
相关标签/搜索