0
点赞
收藏
分享

微信扫一扫

详解NSLocale.preferredLanguages的含义


NSLocale.preferredLanguages的应用

在我们开发​​iOS​​程序时,经常有“使用当前应用设置的语言进行差异化操作”的需求。

比如当你开发一个浏览器,需要根据用户设置的语言,给用户推送不同语言的网页文章时。这时候就需要用到​​NSLocale.preferredLanguages​​。

一般情况下,应用开发者只需要区分中英文就可以完成基本需求了,比如如下代码:

if NSLocale.preferredLanguages[0].hasPrefix("en") {
// 分支逻辑
}

而如果你试着去打印​​NSLocale.preferredLanguages​​,用如下代码

print("\(NSLocale.preferredLanguages)")

你将会得到一个数组,示例结果如下:

["en-HK", "zh-Hans-HK", "zh-Hant-HK", "zh-Hant-TW", "yue-Hant-HK"]

数组的含义

为什么​​NSLocale.preferredLanguages​​​返回结果是一个数组,不是只要返回一个​​en-HK​​就够了吗?

该函数的作用是提供本地设备语言偏好,提供数组的意义在于系统会根据用户本机信息以及用户的系统设置,返回多个按优先级排序的​语言-地区​设置。这样一来当最高级优先级语言应用程序无法支持时,可以依据列表选择可能支持的语言。

en-HK是什么?

在​​preferredLanguages​​​中,我们可以看到类似这样一个字符串​​en-HK​​​,凭借直觉,我们可以猜测,​​en​​​指的是英文,​​HK​​指的是香港。

这个猜测自然是没错的,但是具体这些编码是遵循什么严格的标准,如果我们要支持多语言,应该怎么写代码来进行判断。

首先说​​en​​​,​​en​​​是用来表示一门语言,比如英语用​​en​​​,中文用​​zh​​,这种编码叫​全球语言标准码​ - ​​ISO-639​​。

​ISO-639​​​的语言编码又有细分,后续细分通过数字代号来表示,苹果选用的编码为​​ISO-639-1​​​和​​ISO-639-2​​​。其中​​ISO-639-1​​​通过两个英文字母来标记一门语言,​​ISO-639-2​​是通过三个字母来标记一门语言。

语言对应的​​ISO-639-1​​​和​​ISO-639-2​​代码示例如下:

语言

ISO-639-1

ISO-639-2

英语

en

eng

法语

fr

fre

德语

de

ger

日语

ja

jpn

​preferredLanguages​​​返回结果的单元中,​​en​​​即是​​ISO-639-1​​中的英语代号。

但是,因为​​ISO-639-1​​​表示法不能穷尽所有语言,比如对于夏威夷语,在​​ISO-639-1​​​中就无法找到对应的代号,而在​​ISO-639-2​​​中可以找到,其代号为​​haw​​。

所以苹果的语言代号的返回规则是:​优先返回​​ISO-639-1​​中找到的对应代号,如果没有,则返回​​ISO-639-2​​的代号​。

同理,符号​​HK​​​属于地区编码,该编码采用的是​​ISO 3166-1​​,是国家和地区建立国际认可的编码。

​ISO 3166-1​​编码示例如下:

地区

ISO 3166-1

中国大陆

CN

美国

US

英国

GB

法国

FR

文字编码

前面已经讲清楚了​​en-hk​​​的含义,但是我们有时候会看到返回的结果不只两个代码,也有类似​​zh-Hant-HK​​这样的,有两个分隔符分隔三个代码的,这又是怎么回事?

这就要说到文字编码了,比如我们中文来说,即使一样是普通话写出来的文字,也分简体中文和繁体中文。

所以在返回的编码结果中,如果文字系统没有区分和疑义的,比如英文,那么就不需要在中间追加文字编码,而如果有细分的,则会追加文字编码。文字编码也是由​​ISO​​标准化组织规定。

简体中文和繁体中文的文字编码示例如下:

文字

编码

简体中文

Hans

繁体中文

Hant

所以,在例子​​zh-Hant-HK​​中,我们可以得出该返回的结果表示​中文-繁体-香港​ 。

其他注意事项

可能有些人看到这里,在写代码的时候会默认​​preferredLanguages​​​返回的元素编码一定带有​​-​​​,事实绝非如此,返回结果有时候可能只是一个​​en​​,并没有地区编码。

也就是说,当我们获取​​NSLocale.preferredLanguages​​时,返回的数组元素值有三种可能,具体可以用以下三个值表示:

en
en-hk
zh-Hant-HK

当返回结果只有语言,没有地区时,开发者可以优先选用该语言的代表地区作为默认选项,具体而言,英文可以默认美国,中文简体默认中国大陆等。

写一个简易的封装语言地区代码的类

下面我们用一个用来接收​​preferredLanguages​​数组元素的类来结束这篇文章。

class LanguageRegionCode {
private var _languageCode: String?
private var _scriptCode: String?
private var _regionCode: String?

var languageCode: String? {
_languageCode
}

var scriptCode: String? {
_scriptCode
}

var regionCode: String? {
_regionCode
}

init(code: String) {
let splits = code.split(separator: "-")
if let lCode = splits.first {
_languageCode = String(lCode)
}
if splits.count == 3 {
_scriptCode = String(splits[1])
_regionCode = String(splits[2])
} else if splits.count == 2 {
_regionCode = String(splits[1])
}
}
}

该类的使用代码如下:

let code = NSLocale.preferredLanguages[0]
let languageRegionCode = LanguageRegionCode(code: code)

if let languageCode = languageRegionCode.languageCode {
print("language code = \(languageCode)")
}

if let scriptCode = languageRegionCode.scriptCode {
print("script code = \(scriptCode)")
}

if let regionCode = languageRegionCode.regionCode {
print("region code = \(regionCode)")
}

对于​​zh-Hant-HK​​,打印结果如下:

language code = zh
script code = Hant
region code = HK

参考资料:



苹果 NSLocale.preferredLanguages 官方文档:https://developer.apple.com/documentation/foundation/nslocale/1415614-preferredlanguages



苹果技术文档:https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html#//apple_ref/doc/uid/10000171i-CH15

想要一起讨论的朋友可以在我的公众号​风海铜锣​的加群菜单栏中​申请加群​完成加群申请,一起共同进步。



举报

相关推荐

0 条评论