12 | 功能组件:如何设置多语言支持,为全球化做准备_

[toc]

前言

本文来自拉勾网课程整理

作为iOS 开发者,不知道你有没有遇到过这样的情况:每次增加一种新语言,都需要重新改一遍,特别是在 App 进入其他国家的市场时,需要修改整个App的代码才能加入新语言。这样是不是很麻烦?

其实这种情况完全可以通过多语言设置来解决。下面我就以Moments App为例,看看怎样支持多语言。

安装 SwiftGen

Moments App使用了SwiftGen 来自动生成支持多语言常量字符串。为了保证整个团队所使用 SwiftGen 的版本都保持一致,我们使用CocoaPods来安装 SwiftGen。具体到Moments App 项目,我们在 Podfile 文件中添加 SwiftGen Pod 即可。

pod 'SwiftGen', '= 6.4.0', configurations: ['Debug']

为了在每次编译代码的时候,SwiftGen 都会启动代码生成任务,我们需要在主 App TargetMomentsBuild Phases 里面添加 Run SwiftGen步骤,然后配置它执行"${PODS_ROOT}/SwiftGen/bin/swiftgen"命令。

d6ce38812a4aec758ac678507687edf5

这里要注意,由于我们自己的源代码会使用到 SwiftGen 所生成的代码,因此必须把 Run SwiftGen 步骤放在 Compile Source 步骤之前。

增加多语言支持

Xcode 使用.strings文件来支持多语言。那什么是.strings呢?.strings文件是一个资源文件,用于存储各种语言的文本。该文件里面保存了一堆 Key-Value 信息,例子如下:

"userNameKey" = "User name";

其中userNameKeyKey,而User name是具体的值。在 Swift代码中,我们可以把Key传递给NSLocalizedString方法来取出.strings文件里配置的值。具体代码如下:

let use rName = NSLocalizedString("userNameKey", comment: "Label text for user name")

由于 Moments App 使用了纯代码的方式来呈现 UI,我们需要在Xcode里面建立一个名叫Localizable.strings的文件来存储Key-Value信息。该文件保存在 Moments/Resources/en.lproj 文件夹下面,其中en表示英文,因为 Moments App 的默认语言是英文,假如你的 App 的默认语言是简体中文,那么应该放在 zh-Hans.lproj文件夹下面。

b11b5181bd4f88b81451c3f00efd0844

那怎样支持新语言呢?我们可以在Project Info 配置里面的 Localizations下面点击加号按钮(+),然后选择需要添加的语言,如下图所示,我们添加了简体中文。

fb613dd8d39a5dcf983f7daae3227fd8

接着选择要增加简体中文支持的资源文件。在Moments App里面,我们使用了纯代码的方式来编写 UI,因此我们只选择刚才新建的Localizable.strings文件。

8052e50d1924b67e0ac842570680c6e5

然后你会看到在Localizable.strings下多了一个Localizable.strings(Chinese, Simplified) 文件用于保存简体中文的文本信息。

94695bcab167ecdf4d138ec3d756af6b

现在我们可以在Localizable.strings里面添加下面的Key-Value来让App 显示中文了。

"userNameKey" = "用户名";

当用户在iOSSettings App 里面把语言选择为简体中文以后,App里面的文本就会变成中文。我们也可以使用同样的办法来增加不同的语言支持。

32d5194f3ace26abd3a2614054a66d06

配置 swiftgen.yml 文件

不知道你发现没有,调用 NSLocalizedString 方法来取出文本并不方便,一不小心就会把 Key 写错了。那么,有没有什么好的办法方便我们使用.strings文件里面的文本呢?有,那就是使用 SwiftGen 来自动生成带类型信息的常量字符串。

为什么呢?因为 SwfitGen 在执行过程中会读取swiftgen.yml文件里面的信息,要知道,swiftgen.yml文件就是用来告诉 SwiftGen 读取那些文件,使用哪个模版以及在哪里存放生成的文件。那么,如何配置该文件,让 SeiftGen帮我们生成用于全球化和本地化的常量字符串呢?

做法非常简单,我们可以在swiftgen.yml文件添加以下一段代码。

strings:
inputs:
  - Moments/Resources/en.lproj
outputs:
  - templateName: structured-swift5
    output: Moments/Generated/Strings.swift

其中strings表示这是一个用户生成常量字符串的任务。inputs用于指定.strings文件所在的位置,在我们的项目中,该文件位于 Moments/Resources/en.lproj。要注意的是,我们只需要指定一个语言的文件夹就行,它通常是默认开发语言的文件夹。
outputs.templateName表示生成文件所使用的模版,我们使用structured-swift5模版表示所生成的代码支持点号(.)分割 Swift 5代码。outputs.output表示所生成文件存放的位置。以下是生成的 Moments/Generated/Strings.swift

internal enum L10n {
  internal enum InternalMenu {
    /// Area 51
    internal static let area51 = L10n.tr("Localizable", "internalMenu.area51")
    /// Avatars
    internal static let generalInfo = L10n.tr("Localizable", "internalMenu.generalInfo")
  }
}

因为我们在Localizable.strings 文件里定义 Key的时候使用了点号SwiftGen 会使用内嵌套枚举类型 (Nested enum) 来把各个常量字符串通过命名空间进行分组。下面是英文版本Localizable.strings文件的部分定义。

// Internal Menu
"internalMenu.area51" = "Area 51";
"internalMenu.generalInfo" = "General Info";
// Moments List
"momentsList.errorMessage" = "Something went wrong, please try again later";

我们可以对比一下中文版本Localizable.strings文件的部分定义。

// Internal Menu
"internalMenu.area51" = "51 区";
"internalMenu.generalInfo" = "通用信息";
// Moments List
"momentsList.errorMessage" = "出错啦,请稍后再试";

使用生成的字符串

SwiftGen 自动生成那些常量字符串以后,我们就可以很方便地使用它们,下面的代码演示了如何调用这些字符串。

let title = L10n.InternalMenu.area51
let infoSection = InternalMenuSection(
    title: L10n.InternalMenu.generalInfo,
    items: [InternalMenuDescriptionItemViewModel(title: appVersion)]
)

我们可以使用枚举类型L10n来取出相应的常量字符串。L10n的扩展方法 (Extension method)会根据当前用户的语言选择来读取相应的 Localizable.strings文件,并返回对应语言的字符串来显示给用户。
下面是Moments App 在英文语言和中文语言环境下的显示。

c3fa97b3b14cf54f97efd847fbbcc674

总结

这一章,介绍了如何使用.strings文件和 SwiftGen 来快速设置多语言支持。有了.strings文件,支持新的语言变得非常简单,甚至可以在没有程序员的情况下,由翻译人员来翻译并发布新的语言。另外,有了SwiftGen所生成的常量字符串,我们不会再把错误的 Key 传递给NSLocalizedString,从而提高了代码的质量。可以说,这个设置是一本万利,哪怕目前你的 App 还没有支持多个语言,我还是建议你花一丁点时来设置多语言支持。

0966d4c380f9026885299dda1e69dbcc

源码地址:
swiftgen.yml文件
https://github.com/lagoueduCol/iOS-linyongjian/blob/main/Moments/swiftgen.yml

你可能感兴趣的:(12 | 功能组件:如何设置多语言支持,为全球化做准备_)