macOS 开发之 storyboard 或 xib 本地化

开发了一款好用的 macOS app 后,为了让更多人的尝到自己 “真香” 的作品,app 的国际化和本地化是有必要的,app 的本地化分三部曲讲解,本文是第二部:storyboard 或 xib 本地化。

第一部传送门:macOS 开发之 APP 名称本地化

第三部传送门:macOS 开发之代码字符串的本地化

实现平台

  • macOS 10.14.3
  • swift 4.2.1
  • xcode 10.1

准备工程

本文直接使用上一篇文章macOS 开发之 APP 名称本地化的工程,点我下载!

打开工程后,会看到 Main.storyboard 左侧有个小三角,点开可以看到,包含了简体中文和日文的两个 Strings 文件,这两个文件是在添加语言支持 的时候添加上的,点击 Main.storyboard 可以在 Inspector 的 Localization 分组看到 English 没有勾选,勾选 English ,会看到新增了一个 English 的 Strings 文件。

上面提到的 String 文件包含了 storyboard 中所有可见控件中字符串对应的内容定义,App 运行的时候会根据系统语言读取对应语言的字符串内容,以达到 storyboard 界面元素本地化显示的效果!

如果要添加自己定义的 xib 文件,也会像 storyboard 文件一样,在 File Inspector 中会有一个 Localization 的分组,如果有 localize… 按钮,点击它就可以添加 xib 的新的语言支持!

修改 Strings 文件

打开上面提到的三个 Strigns 文件:

  • Main.Strings (English)
  • Main.Strings (Chinese(Simplified))
  • Main.Strings (Japanese)

可以看到文件中都包含了相同的字符串项,例如其中的窗口标题项:

/* Class = "NSWindow"; title = "Window"; ObjectID = "IQv-IB-iLA"; */
"IQv-IB-iLA.title" = "Window";
  1. 左侧的代表了字符串标识,右侧是相对应的字符串值,我们要对应语言修改的就是每一项的右侧值。

  2. 每一项后面必须有半角的分号

  3. 左侧标识使用了控件的 ObjectID,使用点语法表示属性的方式构成字符串标识,其中 ObjectID 可以在控件的 Identity Inspector 中查看,比如选中 Main.storyboard 中的 Window 将 Inspector 切换到 Identity 标签页可以在 Document 分组中看到 Object ID 是 IQv-IB-iLA"

下面的工作就是自行翻译并修改每一项右侧的值了,可以使用谷歌翻译协助翻译。

将 Main.Strings (Chinese(Simplified)) 和 Main.Strings (Japanese) 中的项修改完成后就可以验证效果了。

更新 Strings 文件

设计的 storyboard 并不是一成不变的,所以 Strings 文件也要随时更新。这里用到一个辅助工具叫做 bartycrouch:

BartyCrouch incrementally updates your Strings files from your Code and from Interface Builder files. “Incrementally” means that BartyCrouch will by default keep both your already translated values and even your altered comments. Additionally you can also use BartyCrouch for machine translating from one language to 60+ other languages. Using BartyCrouch is as easy as running a few simple commands from the command line what can even be automated using a build script within your project.

BartyCrouch

这个工具也能调用微软的 API 协助翻译。

安装 bartycrouch

可以使用 homebrew 安装这个工具:

$ brew install bartycrouch

⚠️:

bartycrouch 已经发布了 4.0.0,使用方法不同,这里展示的方法只适用于 bartycrouch v3.x.x 版本,后续十里会出一篇关于 bartycrouch v4.0.0 的使用教程,请持续关注博客 和 知乎专栏 macOS 开发

使用

为了验证使用,这里在 view controller 中添加了一个按钮和一个 label。

更新 interfaces

这里我们主要是用其从 storyboard 或者 xib 文件更新 Strings 文件的功能,只需要调用如下命令就可以工作:

$ bartycrouch interfaces -p InternationalDemo/
ℹ️ BartyCrouch: Successfully updated strings file(s) of Storyboard or XIB file.

其中需要使用 -p 指明包含工程文件的目录,因为此时工作目录是在工程根目录下,所以要指定的目录是存放文件的 InternationalDemo/

执行了上面的命令以后,查看三个 Strings 文件中确实新添了按钮和 label 的相关字符串!

/* Class = "NSButtonCell"; title = "Button"; ObjectID = "0A1-8b-fid"; */
"0A1-8b-fid.title" = "";

/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "by2-mL-GsU"; */
"by2-mL-GsU.title" = "";

检查 Strings 文件

bartycrouch 的子命令 lint 可以帮助检查:

  • Strings 文件中重复的键值,需要指定命令参数 -d
  • 文件中值为空字符串的键值,需要指定命令参数 -e

比如我们检查一下有没有空值的键

$ bartycrouch lint -e -p InternationalDemo

ℹ️ Found empty value for key '0A1-8b-fid.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/zh-Hans.lproj/Main.strings.
ℹ️ Found empty value for key 'by2-mL-GsU.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/zh-Hans.lproj/Main.strings.
ℹ️ Found empty value for key '0A1-8b-fid.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/ja.lproj/Main.strings.
ℹ️ Found empty value for key 'by2-mL-GsU.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/ja.lproj/Main.strings.
ℹ️ Found empty value for key '0A1-8b-fid.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/en.lproj/Main.strings.
ℹ️ Found empty value for key 'by2-mL-GsU.title' in file /Users/5km/Documents/workspace/macOS/InternationalDemo/InternationalDemo/en.lproj/Main.strings.
❌ Error! 6 issue(s) found in 3 file(s). Executed 1 checks in 6 Strings file(s) in total.

这就检查出刚刚新加的按钮和 label 的相对应的字符串配置了。

自动更新和检查

为了更方便快捷的更新和检查 Strings 文件,这里可以为工程新建一个 Build Phase,按照下图流程添加:

添加的 shell 脚本内容如下:

# Type a script or drag a script file from your workspace to insert its path.
if which bartycrouch > /dev/null; then
    bartycrouch interfaces -p .
    bartycrouch lint -e -d -p .
else
    echo "warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch"
fi

运行一下工程,build 失败,原因是 bartycrouch lint 命令检查出了有空值字符串,以后就是每次编译都会更新 Strings 文件。

再把按钮删除运行工程,检查出 String 文件中只有 label 相关的字符串了,给三个文件分别更改 label 标签的内容。

  • Main.strings (English)
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "by2-mL-GsU"; */
"by2-mL-GsU.title" = "Hello, world!";

  • Main.strings (Chinese(Simplified))
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "by2-mL-GsU"; */
"by2-mL-GsU.title" = "世界,你好!";

  • Main.strings (Japanese)
/* Class = "NSTextFieldCell"; title = "Label"; ObjectID = "by2-mL-GsU"; */
"by2-mL-GsU.title" = "こんにちは世界!";

至此,这一部分就讲完了,希望对您有所帮助!

此部分完成后的工程下载:InternationalDemo2