赶时间?直接在浏览器中把独立的 .strings 文件转换为目录:免费,无需注册,不上传任何内容。
迁移之前
两项预防措施,可以避免大多数意外:
- 干净的 Git 工作区,并在专门的分支上进行。迁移后值得检查的内容都在差异里,所以你需要一个只包含迁移的差异。
- 迁移前构建能通过。Xcode 在构建时扫描代码来填充目录。如果项目无法编译,目录就会不完整,而你却不知道原因。
迁移本身
在项目导航器中右键点击 Localizable.strings,然后选择 Migrate to String Catalog。Xcode 会列出涉及的文件和 target;具体措辞可能随 Xcode 版本变化,但思路不变。
fr.lproj/Localizable.strings、de.lproj/Localizable.strings 等文件会被一个包含所有语言的 Localizable.xcstrings 取代。.strings 文件中的注释会成为每个键的注释。
文件长什么样
String Catalog 是 JSON。一个简单的键:
{
"sourceLanguage" : "en",
"strings" : {
"welcome_user" : {
"comment" : "Home screen greeting",
"localizations" : {
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Bon retour, %@ !"
}
}
}
}
},
"version" : "1.0"
}
复数则存放在 variations 下:
"items_left" : {
"localizations" : {
"fr" : {
"variations" : {
"plural" : {
"one" : { "stringUnit" : { "state" : "translated", "value" : "%lld article restant" } },
"other" : { "stringUnit" : { "state" : "translated", "value" : "%lld articles restants" } }
}
}
}
}
}
注意格式:每个冒号前有一个空格,这是 Xcode 的写法。如果某个工具把文件重写成“标准” JSON,就会产生巨大的差异,却没有改动任何一条译文。
差异中要审阅什么
标记为 Stale 的键。构建后,Xcode 会标记在代码中再也找不到的键。它们不一定是废弃的:运行时动态生成的键(NSLocalizedString(variable, comment: "")、从配置文件读取的键)对扫描是不可见的。删除前请先确认。
从代码中提取的新键。构建可能会添加你从未放进 Localizable.strings 的字符串,典型的是 SwiftUI 的 Text("…") 字面量,它们默认就是可本地化的。这些字符串没有译文,所以 Xcode 显示的各语言完成百分比会下降,这属于正常现象。
状态。每个值都有一个状态:translated、needs_review,或者表示尚未有人翻译的 new。三个月后,你就是靠它来了解哪些内容真正审阅过。
格式说明符。像 Text("\(count) items left") 这样的 SwiftUI 字符串会生成键 %lld items left。如果旧的 .strings 对同一句话使用的是 %d,你现在就会有两个几乎重复的键;保留代码实际使用的那个。
旧版 iOS 怎么办?
不需要 iOS 17。目录是一种源格式:构建时,Xcode 会把它编译成应用包中的常规 .strings 文件。最低部署版本不会改变。
在 Xcode 之外编辑目录
处理少量字符串时,Xcode 的编辑器就够用了。若要审阅整种语言、批量翻译或检查占位符,专门的工具会更方便。LocalePilot 打开 .xcstrings 文件,并按 Xcode 的风格写回:未修改的目录逐字节相同,一次编辑只改动它自己的那几行,编辑过的值会变为 translated 状态。复数和设备变体可以编辑;使用替换(%#@count@)的键和标记为 shouldTranslate: false 的键会原样保留,留给你在 Xcode 中编辑。