Highlight
Xcode 15 推出 String Catalogs,将 .strings 和 .stringsdict 文件合并为单一的 JSON 格式文件,支持自动从 SwiftUI、Swift、Objective-C、C 和 Interface Builder 中提取字符串,并提供可视化编辑器管理翻译进度和复数变体。
核心内容
本地化管理的旧痛点
以前做本地化,开发者需要维护两套文件:.strings 存普通字符串,.stringsdict 存复数规则。每次改代码都要手动同步这些文件,漏掉一个字符串就会导致用户看到未本地化的英文内容。更麻烦的是,复数规则在不同语言中差异很大,比如英语只有单复数两种,乌克兰语却有三种复数形式,手动维护 .stringsdict 的 plist 格式容易出错。
String Catalogs 的解决方案
Xcode 15 引入了 String Catalogs(.xcstrings 文件),把字符串和复数规则统一管理在一个可视化编辑器中。编译时,.xcstrings 会自动转换成 .strings 和 .stringsdict,不需要提高最低部署版本。Xcode 会在每次构建时自动扫描代码中的可本地化字符串,自动添加到 Catalog 中,翻译进度实时显示在侧边栏。
自动提取字符串的来源
(01:40)Xcode 15 可以从多个来源自动提取字符串:
- SwiftUI 中接受
LocalizedStringKey的控件(Label、Button、Text 等) - Swift 中使用
String(localized:)和LocalizedStringResource的代码 - Objective-C 中使用
NSLocalizedString宏的代码 - C 代码中使用
CFCopyLocalizedString的代码 - Interface Builder 文件(Storyboard 和 xib)
- Info.plist 文件
翻译状态管理
(13:30)String Catalog Editor 为每个字符串显示四种状态:
- New(黄色):新添加、尚未翻译
- Needs Review(橙色):源字符串已变更,需要检查翻译
- Translated(绿色):已翻译完成
- Stale(灰色):代码中已删除,但翻译还在
状态实时反映在侧边栏的进度百分比中,开发者可以确信提交到 App Store 前所有内容都已本地化。
详细内容
SwiftUI 中的本地化字符串
(07:36)SwiftUI 让本地化变得无缝。任何在视图中使用的字符串字面量都会被自动视为可本地化:
struct ContentView: View {
var body: some View {
VStack {
Label("Thanks for shopping with us!", systemImage: "bag")
.font(.title)
HStack {
Button("Clear Cart") { }
Button("Checkout") { }
}
}
}
}
关键点:
Label、Button、Text等控件的字符串参数类型是LocalizedStringKey,SwiftUI 会自动提取- 这些字符串会被放入名为
Localizable.xcstrings的 String Catalog 中 - 使用
Text的初始化器可以添加注释,帮助翻译者理解上下文
如果需要更精细的控制,可以用 LocalizedStringResource:
struct CardView: View {
let title: LocalizedStringResource
let subtitle: LocalizedStringResource
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10.0)
VStack {
Text(title)
Text(subtitle)
}
.padding()
}
}
}
CardView(title: "Recent Purchases", subtitle: "Items you've ordered in the past week.")
关键点:
LocalizedStringResource是推荐的类型,用于传递可本地化字符串- Xcode 看到用字符串字面量初始化
LocalizedStringResource时,就知道这个字符串需要本地化 - 支持指定注释、表名和默认值
Swift 代码中的本地化
(09:03)在模型层或需要延迟加载字符串的场景中,使用 Foundation 的 localized: 初始化器:
import Foundation
func stringsToPresent() -> (String, AttributedString) {
let deferredString = LocalizedStringResource("Title")
return (
String(localized: deferredString),
AttributedString(localized: "**Attributed** _Subtitle_")
)
}
关键点:
LocalizedStringResource可以在运行时转换为String或AttributedString- 支持富文本本地化
- 需要在 Build Settings 中启用 “Use Compiler to Extract Swift Strings”
复数变体
(15:25)String Catalog Editor 内置了复数变体支持。右键点击字符串,选择 “Vary by Plural”,Xcode 会根据默认语言自动创建相应的复数 case。
对于包含多个参数的复杂字符串,使用 substitutions:
Text("\(birds.count) birds in \(backyards.count) backyards")
在编辑器中,可以为每个参数分别设置复数变体,创建如 @birds 和 @yards 两个 substitution,运行时根据参数值自动选择正确的复数形式。
关键点:
- 不同语言的复数 case 数量不同,Xcode 会自动生成适合该语言的 case
- 英语有
one和other,乌克兰语有one、few、many和other - Substitution 名称可以自定义,提高可读性
设备变体
(02:47)多平台应用可能需要根据设备类型显示不同的文本。例如 “tap to learn more” 在 Mac 上应该显示 “click to learn more”:
右键点击字符串 -> “Vary by Device” -> 选择 Mac,即可为不同设备提供不同的翻译。
导出和导入翻译
(23:02)通过 Product > Export Localizations 导出 XLIFF 文件,发送给翻译人员。翻译完成后通过 Product > Import Localizations 导入,翻译会自动合并到对应的 String Catalog 中。
XLIFF 中的变体字符串使用新的格式标识:
<trans-unit id="%lld Recent Visitors|==|plural.one">
<source>%lld Recent Visitor</source>
<target>%lld Visitante Recente</target>
</trans-unit>
关键点:
- 格式为
key|==|variation.specifier - 支持 plural、device 等多种变体类型
- 可以在 Build Settings 中设置 “Localization Prefers String Catalogs” 为 Yes
迁移现有项目
(28:51)现有项目可以逐步迁移。右键点击 .strings 或 .stringsdict 文件,选择 “Migrate to String Catalog”,Xcode 会自动转换所有翻译内容。String Catalogs 可以与旧格式共存,开发者可以按需逐个表迁移。
对于 Swift Package,在 Package.swift 中设置默认本地化并添加 .xcstrings 文件即可:
// swift-tools-version:5.9
let package = Package(
defaultLocalization: "en",
// ...
)
核心启发
-
一键多语言支持
- 做什么:为现有 App 添加 5-10 种语言支持
- 为什么值得做:String Catalogs 自动提取字符串,翻译进度可视化,大幅降低本地化门槛
- 怎么开始:在项目中添加
Localizable.xcstrings,构建一次,Xcode 自动提取所有字符串,然后导出 XLIFF 给翻译
-
智能复数处理
- 做什么:在显示数量相关的 UI 中使用复数变体
- 为什么值得做:避免 “1 items” 这种语法错误,自动适配不同语言的复数规则
- 怎么开始:在 String Catalog Editor 中右键字符串选择 “Vary by Plural”,为每个 case 填入正确的翻译
-
多平台文本适配
- 做什么:为 iOS/iPadOS/macOS 统一代码库,但显示平台特定的文本
- 为什么值得做:一套代码跑在所有平台,但用户体验自然(tap vs click)
- 怎么开始:在 Catalog 中为关键字符串添加 “Vary by Device”,为 Mac 和 Apple Watch 提供适配文本
-
实时翻译进度仪表盘
- 做什么:在 CI 中集成翻译完整性检查
- 为什么值得做:防止未完全本地化的版本发布到 App Store
- 怎么开始:利用 String Catalog 的状态标记(New/Needs Review/Translated),在构建脚本中检查是否有未翻译的字符串
-
Swift Package 本地化
- 做什么:为开源 Swift Package 添加本地化支持
- 为什么值得做:让全球开发者都能用你的库
- 怎么开始:在 Package.swift 中设置
defaultLocalization,添加 .xcstrings 文件到 target 的 resources 中
关联 Session
- Spotlight your app with App Shortcuts — App Shortcut 短语的本地化改进
- SwiftUI essentials — SwiftUI 基础与本地化集成
- Build accessible apps for visionOS — 无障碍与本地化实践
- Meet SwiftUI for spatial computing — SwiftUI 多平台本地化
评论
GitHub Issues · utterances