WWDC Quick Look 💓 By SwiftGGTeam
Discover String Catalogs

Discover String Catalogs

观看原视频

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") { }
            }
        }
    }
}

关键点:

  • LabelButtonText 等控件的字符串参数类型是 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 可以在运行时转换为 StringAttributedString
  • 支持富文本本地化
  • 需要在 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
  • 英语有 oneother,乌克兰语有 onefewmanyother
  • 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",
    // ...
)

核心启发

  1. 一键多语言支持

    • 做什么:为现有 App 添加 5-10 种语言支持
    • 为什么值得做:String Catalogs 自动提取字符串,翻译进度可视化,大幅降低本地化门槛
    • 怎么开始:在项目中添加 Localizable.xcstrings,构建一次,Xcode 自动提取所有字符串,然后导出 XLIFF 给翻译
  2. 智能复数处理

    • 做什么:在显示数量相关的 UI 中使用复数变体
    • 为什么值得做:避免 “1 items” 这种语法错误,自动适配不同语言的复数规则
    • 怎么开始:在 String Catalog Editor 中右键字符串选择 “Vary by Plural”,为每个 case 填入正确的翻译
  3. 多平台文本适配

    • 做什么:为 iOS/iPadOS/macOS 统一代码库,但显示平台特定的文本
    • 为什么值得做:一套代码跑在所有平台,但用户体验自然(tap vs click)
    • 怎么开始:在 Catalog 中为关键字符串添加 “Vary by Device”,为 Mac 和 Apple Watch 提供适配文本
  4. 实时翻译进度仪表盘

    • 做什么:在 CI 中集成翻译完整性检查
    • 为什么值得做:防止未完全本地化的版本发布到 App Store
    • 怎么开始:利用 String Catalog 的状态标记(New/Needs Review/Translated),在构建脚本中检查是否有未翻译的字符串
  5. Swift Package 本地化

    • 做什么:为开源 Swift Package 添加本地化支持
    • 为什么值得做:让全球开发者都能用你的库
    • 怎么开始:在 Package.swift 中设置 defaultLocalization,添加 .xcstrings 文件到 target 的 resources 中

关联 Session

评论

GitHub Issues · utterances