macOS 开发之本地化工具 bartycrouch 4 使用教程
前些日子写了三篇关于 macOS app 本地化的文章,在文章中用到了一个名为 bartycrouch 的工具,当时十里安装的 bartycrouch 版本是 v3.13.3,昨天升级了 bartycrouch 现在是 v4.0.0 ,发现使用方法变化还挺大,所以赶快在前面三篇文章中标注了一下版本使用问题,本文简单介绍一下 bartycrouch 4 的使用。
开发平台
- macOS 10.14.3
- swift 4.2.1
- xcode 10.1
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 可以依据 interfaces 文件( xib 文件) 和代码(swift 、m、h 文件)来增量更新 strings 文件。在这里 增量 是指 bartycrouch 会默认保留已经翻译的值及改变了的注释。另外您也可使用 bartycrouch 借助微软的服务从一种语言机器翻译成超过 60+ 种语言。在命令行调用几个简单的命令您就可以轻而易举的使用 bartycrouch,另外您也可以在 xcode 的工程配置中添加运行脚本自动化使用 bartycrouch 完成您期望的任务。
依赖
- Xcode 10.1+
- Swift 4.2+
- Xcode Command Line Tools (详见:点我)
安装方法
使用 [Homebrew](https://brew.sh/) 安装
通过下面的命令可以很容易安装 bartycrouch:
brew install bartycrouch
另外可以通过下面的命令更新 bartycrouch,保证一直使用最新保本:
brew upgrade bartycrouch
通过 [Mint](https://github.com/yonaskolb/Mint) 安装
通过以下命令就可以安装 bartycrouch(目前通过这种方式会出现缺少动态库的问题,估计很快就会修复了,所以建议使用 homebrew 安装的方式):
mint install Flinesoft/BartyCrouch
bartycrouch 使用
这里提醒一下,如果您直接用一个现有的工程尝试这个工具的话,以防万一请先用 git 提交 一下您的代码,尽量保证安全,另外这里强烈建议如果研究明白怎么用了后使用为 xcode 创建编译脚本 的方式使用 bartycrouch。
在命令行下,先执行一下 bartycrouch -h
:
$ bartycrouch -h
Usage: bartycrouch <command> [options]
Incrementally update & translate your Strings files from code or interface files.
Commands:
init Creates the default configuration file & creates a build script if Xcode project found
update Update your .strings file contents with the configured tasks (default: interfaces, code, normalize)
lint Lints your .strings file contents
help Prints help information
version Prints the current version of this app
help
: 打印帮助信息,也就是上面,bartycrouch -h
等同于bartycrouch help
version
: 打印当前 bartycrouch 的版本号
下面以 bartycrouch 正常的使用流程分别讲一下 init
update
和 lint
三个命令。
init 命令
这个命令用于生成针对 Xcode 工程的 bartycrouch 配置文件。进入到 xcode 的根目录,执行以下命令:
bartycrouch init
工程根目录下会出现名为 .bartycrouch.toml
的文件。
`.bartycrouch.toml` 默认内容
[update]
tasks = ["interfaces", "code", "transform", "normalize"]
[update.interfaces]
path = "."
defaultToBase = false
ignoreEmptyStrings = false
unstripped = false
[update.code]
codePath = "."
localizablePath = "."
defaultToKeys = false
additive = true
unstripped = false
[update.transform]
codePath = "."
localizablePath = "."
transformer = "foundation"
supportedLanguageEnumPath = "."
typeName = "BartyCrouch"
translateMethodName = "translate"
[update.normalize]
path = "."
sourceLocale = "en"
harmonizeWithSource = true
sortByKeys = true
[lint]
path = "."
duplicateKeys = true
emptyValues = true
在这个配置文件中包含了另外两个命令( update 和 lint )的相关配置,这是 bartycrouch 的默认配置,应该可以在绝大多数工程中使用,但是这里需要注意以下几点:
[update]
的值就代表了,执行bartycrouch update
时要完成的任务,不想执行某个任务可以直接删除,比如不执行code
任务,可以写成:
[update]
tasks = ["interfaces", "transform", "normalize"]
-
每个任务子项中都包含了对应的配置信息,可依据工程需要进行调整,具体含义可以参考后面任务的介绍
-
尽可能为包含关键字的
path
键提供具体的路径名称 (例如:codePath
设置为包含 swift 代码文件的目录) -
如果您的工程是纯 swift 实现并且使用了 update 命令的的
tranform
任务,可以删除code
任务 -
如果您正在使用支持
structured-swift4
模板的 SwiftGen ,您需要将[update.transform]
的transformer
从foundation
改为swiftgenStructured
-
如果您要使用
transform
任务,需要在工程中创建一个新文件,命名为BartyCrouch.swift
,内容如下:
`BartyCrouch.swift` 代码
//
// This file is required in order for the `transform` task of the translation helper tool BartyCrouch to work.
// See here for more details: https://github.com/Flinesoft/BartyCrouch
//
import Foundation
enum BartyCrouch {
enum SupportedLanguage: String {
// TODO: remove unsupported languages from the following cases list & add any missing languages
case arabic = "ar"
case chineseSimplified = "zh-Hans"
case chineseTraditional = "zh-Hant"
case english = "en"
case french = "fr"
case german = "de"
case hindi = "hi"
case italian = "it"
case japanese = "ja"
case korean = "ko"
case malay = "ms"
case portuguese = "pt-BR"
case russian = "ru"
case spanish = "es"
case turkish = "tr"
}
static func translate(key: String, translations: [SupportedLanguage: String], comment: String? = nil) -> String {
let typeName = String(describing: BartyCrouch.self)
let methodName = #function
print(
"Warning: [BartyCrouch]",
"Untransformed \(typeName).\(methodName) method call found with key '\(key)' and base translations '\(translations)'.",
"Please ensure that BartyCrouch is installed and configured correctly."
)
// fall back in case something goes wrong with BartyCrouch transformation
return "BC: TRANSFORMATION FAILED!"
}
}
-
如果您的第一语言不是英语, 您需要将
normalize
任务的sourceLocale
改为您的第一语言,值参考上面代码中的枚举SupportedLanguage
的元素 -
如果您想使用 bartycrouch 的翻译功能,需要将如下的配置添加到
.bartycrouch.toml
中,并且将translate
添加到任务列表中,其中您需要将secret
的值替换成您的 Microsoft Translator Text API Subscription Key:
[update.translate]
path = "."
secret = "<#Subscription Key#>"
sourceLocale = "en"
update 命令
update 命令可以执行以下几个任务:
interfaces
: 从 Storyboards & XIBs 更新.strings
文件code
: 根据代码中的NSLocalizedString
调用更新Localizable.strings
transform
: 仅支持 swift 文件,可以替换特定方法的调用替换为可以提供多种语言翻译的单行方式translate
: 从指定语言翻译成多种语言并替换结果到 strings 文件中normalize
: 格式化.strings
文件内容:排序或者清楚多余内容
上面已经提到过的,可以通过 .bartycrouch.toml
的 task
配置要执行的任务:
[update]
tasks = ["interfaces", "code", "transform", "normalize"]
任务配置项介绍
`interfaces` 配置项含义
path
: 查找 Storyboards & XIB 文件的路径defaultToBase
: 添加 Base translation 作为新键的值ignoreEmptyStrings
: 不添加 views 中是空值的项unstripped
: 保留 Strings 文件开始和结尾的空白字符串
`code` 配置项含义
codePath
: 查找 Swift 代码文件的路径localizablePath
: 包含Localizable.strings
文件的目录的父目录defaultsToKeys
: 为新键添加与新键名称一致的值additive
: 不清除未在代码中发现的键customFunction
: 替代NSLocalizedString
的函数名称customLocalizableName
: 替代Localizable.strings
的文件的名称unstripped
: 保留 Strings 文件开始和结尾的空白字符串
`transform` 配置项含义
codePath
: 查找 Swift 代码文件的路径localizablePath
: 包含Localizable.strings
文件的目录的父目录transformer
: 指定转换的模式: 若调用NSLocalizedString
接口,值就设成foundation
; 若调用L10n
形式的接口,值就设成swiftgenStructured
supportedLanguageEnumPath
: 包含SupportedLanguage
枚举定义的 swift 文件的路径typeName
: 包含SupportedLanguage
枚举和翻译方法的类型名称translateMethodName
: 翻译方法的名称customLocalizableName
: 替代Localizable.strings
的文件的名称
`translate` 配置项含义
path
: 查找.strings
文件的路径secret
: 您的 Microsoft Translator Text API Subscription Key.sourceLocale
: 指定从哪种语言翻译成其他语言
`normalize` 配置项含义
path
: 查找.strings
文件的路径sourceLocale
: 指定依照哪种语言对其他语言的 string 文件进行格式化harmonizeWithSource
: 同步键值对的源语言sortByKeys
: 按照字母顺序对键进行排序
transform 任务
如果配置文件中配置了 transform
任务(详见 init 命令)并且已经在 xcode 中创建编译脚本, 在开发中您可以使用下面简化的流程编写本地化代码:
- 您可以使用
BartyCrouch.translate
替代NSLocalizedString
指定键、翻译方法和注释,例如:
self.title = BartyCrouch.translate(key: "onboarding.first-page.header-title", translations: [.english: "Welcome!"])
-
编译应用的时候, BartyCrouch 会自动向所有的
Localizable.strings
文件中添加您指定的键,并且为指定语言的键添加指定语言翻译结果 -
同时 BartyCrouch 会自动依据配置中指定的
transformer
替换上面BartyCrouch.translate
的调用为对应的方法-
当
transformer
设置为foundation
, 上面BartyCrouch.translate
的调用会替换为如下的结果:self.title = NSLocalizedString("onboarding.first-page.header-title", comment: "")
-
当
transformer
设置为swiftgenStructured
, 上面BartyCrouch.translate
的调用会替换为如下的结果:self.title = L10n.Onboarding.FirstPage.headerTitle
-
使用 transform
的优点:
- 不用为了添加翻译的键值而不断的切换不同语言的 Strings 文件
- 一旦使用了 SwiftGen, 不需要手动替换
NSLocalizedString
为L10n
的调用了 - 与机器翻译配合使得只需在代码中使用一行代码就可以实现所有语言的翻译和值的替换
使用 transform
的缺点:
- 只支持 swift 代码而不支持 Objective-C
- 在下次编译之前,xcode 会有一些错误提示,但是一编译就会没有了错误提示
- 由于 SwiftSyntax 当前运行不是特别快所以看上去不如
code
任务快速. (但是这个会随着时间改善!)
lint 命令
lint 命令可以检查 .strings
文件,主要有下面两个检查项:
duplicateKeys
: 查找同一个文件中重复的键值对emptyValues
: 查找空值的键值对
创建编译脚本
为了让 xcode 可以使用 bartycrouch 来更新和检查您的 .strings
文件,您可以添加一个编译脚本实现。
按照下图所示步骤添加脚本:
脚本内容(点我查看)
if which bartycrouch > /dev/null; then
bartycrouch update -x
bartycrouch lint -x
else
echo "warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch"
fi
下一步确保这个运行脚本在 Compiling Sources
和 SwiftGen
(如果使用了的话) 之前运行,比如在 Target Dependencies
后面,像下图这样:
现在每次运行工程,都会自动的更新和检查 .strings
文件,而不用手动处理了。另外如果工程的成员如果没有安装 bartycrouch 的脚本会产生警告:
warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch
另外补充的是,lint 和 update 有以下三个参数可用:
-v
,--verbose
: 打印更多的执行信息-x
,--xcode-output
: 以 xcode 兼容的形式呈现错误和提醒,在 xcode 中的运行脚本中添加以后,一旦检查出错误或警告会在 xcode 的 issue 导航栏中呈现-w
,--fail-on-warnings
: 遇到警告的时候返回对应代码