在 Xcode 26 及更高版本中,字符串目录可以生成 Swift 访问器,替代手动输入的本地化键。本指南将一个小型 Mac 应用的选择摘要迁移为类型化属性和函数,然后检查编译器实际能保护哪些内容。

本任务刻意限定在较小范围:显示一个窗口标题,以及一个包含两个整数计数的摘要。所有标签和值都是示例内容。你将创建目录约定、将其连接到 SwiftUI,并验证编译器诊断和实际显示结果。

什么样的本地化访问器经过编译时检查?

Apple 在 Xcode 26 中引入了原生字符串目录符号生成。不含占位符的条目会生成静态属性;含占位符的条目会生成带类型化参数的函数。两者都会返回 LocalizedStringResource。新的 Xcode 26 项目默认启用符号生成;现有项目可能需要启用相应构建设置。跟着示例探索 Xcode 本地化

实用的变化发生在调用处。字符串字面量可以直接写出查找键,而不必引用 Swift 声明。生成的访问器则引用一个必须存在的成员,而生成的函数要求传入与其签名匹配的参数。根据这些已记录的机制,实际效果是:拼错成员名称或传入不兼容的参数会变成编译器错误。

这种保护有明确的范围。Swift 可以检查访问器是否存在,以及参数是否匹配。它无法判断措辞是否描述了预期界面,也无法判断两个有效的整数参数是否代表正确的计数。应将访问器视为消息的、经过检查的编程接口。

设置一个小型 Mac 应用及其消息约定

使用 Xcode 26 或更高版本,并创建一个 macOS SwiftUI 应用目标。本示例将部署目标设为 macOS 15 或更高版本。底层的 LocalizedStringResource 类型从 macOS 13 起即可使用;本例选择较高目标版本是前置条件的选择,并非该类型的最低版本要求。资源表示可本地化文本,其查找可以延迟到需要时进行。LocalizedStringResource

通过 File > New > File from Template 添加目录。在 Resource 下选择 String Catalog,将其命名为 Workbench,并将其加入应用目标。Apple 文档说明,每个目录代表一个表;此处使用单独的表,将本例中的两条消息放在一起。使用字符串目录本地化文本和变体

在项目编辑器中打开 Build Settings,筛选 Generate String,并将目标有效配置中的 Generate String Catalog Symbols 设为 Yes。这是 Apple 为较早项目记录的开关。在代码中使用生成的本地化符号

在 Workbench.xcstrings 中选择英语源本地化。使用目录编辑器工具栏中的 + 按钮添加以下两个条目。注释会定义消息的含义,包括参数各自的作用。

键 英语源值 注释
TITLE Selection overview Selection summary 上方的标题。
SUBTITLE %1$(selectedCount)lld selected; %2$(availableCount)lld available Selection summary。selectedCount 是已选数量;availableCount 是可选项目总数,包括已选项目。

对于 SUBTITLE,你可以通过 Xcode 的补全菜单逐个输入占位符:输入 %,选择整数占位符,然后将其命名为 selectedCount 或 availableCount。Apple 文档介绍了这些格式说明符对应的命名变量和生成参数。选择每个条目,并在 Attributes 检查器中查看 Generate Swift Symbol 和 Example Usages。在代码中使用生成的本地化符号

预期约定是一个标题属性,以及一个接受两个 Int 值的副标题函数。继续之前,请检查检查器中实际生成的拼写:Apple 表示,符号名称会同时使用键和值。以下示例使用 .Workbench.title 和 .Workbench.subtitle(selectedCount:availableCount:),遵循 Apple 文档中的大写键模式。跟着示例探索 Xcode 本地化

这个约定明确了一项重要区别:availableCount 包含已选项目。如果没有这条注释,调用方可能会合理地将其理解为剩余项目数。这两种理解都能通过类型检查,因此记录含义也是让访问器发挥作用的一部分。

在完整窗口中使用生成的访问器

创建目录后,选择 Product > Build。将模板应用声明和内容视图替换为以下程序,并确保目标中恰好只有一个 @main 声明。此程序需要目录资源;将 Swift 代码粘贴到独立文件中不会生成访问器。

import Foundation
import SwiftUI

@main
struct SelectionOverviewApp: App {
    var body: some Scene {
        WindowGroup {
            SelectionOverviewView(
                selectedCount: 3,
                availableCount: 12
            )
        }
    }
}

struct SelectionOverviewView: View {
    let selectedCount: Int
    let availableCount: Int

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(.Workbench.title)
                .font(.title2)

            Text(
                .Workbench.subtitle(
                    selectedCount: selectedCount,
                    availableCount: availableCount
                )
            )
        }
        .padding(24)
        .frame(minWidth: 360, minHeight: 140)
    }
}

启用英语源本地化后,示例输入应显示 Selection overview,接着显示 3 selected; 12 available。计数是固定的,便于检查参数位置,而无需引入选择管理代码。

Apple 文档说明,生成的资源可用于 SwiftUI,包括 Text,也可通过 Foundation 的 String(localized:) 初始化器使用。如果现有 Mac 界面需要已解析的 String,可在该边界处将生成的资源转换为字符串。跟着示例探索 Xcode 本地化

例如,目录创建后,可以将以下完整辅助函数添加到同一应用目标中:

import Foundation

func selectionSummary(
    selectedCount: Int,
    availableCount: Int
) -> String {
    String(
        localized: .Workbench.subtitle(
            selectedCount: selectedCount,
            availableCount: availableCount
        )
    )
}

从你自己的接口返回 LocalizedStringResource,可保留资源以便稍后查找;返回 String 则会在初始化器运行时解析它。根据接收方界面的需求选择。Apple 在 Foundation 文档中介绍了延迟查找与立即查找的区别。LocalizedStringResource

这些示例是依据检索到的文档检查过的。由于当前环境没有 Swift 可执行文件或 Xcode,因此未在此处编译。

为什么前导点和参数标签很重要

前导点是 Swift 的隐式成员语法。当周围上下文允许 Swift 推断类型时,它会简写对类型成员的访问。这是普通的 Swift 语法,而不是特殊的字符串键运算符。表达式 — 隐式成员表达式

对于生成的本地化符号,默认的 Localizable 表会直接公开成员,而具名表会引入表命名空间。因此,本例在成员名称前加上 .Workbench。Apple 对这两种形式都有说明。在代码中使用生成的本地化符号

selectedCount: 和 availableCount: 这些标签属于函数调用。Swift 区分调用处显示的参数标签与函数内部使用的参数名称。参数需要标签时,调用方必须提供该标签。函数 — 函数参数标签和参数名称

可读的标签有助于防止出错,但这里的两个参数类型相同。交换两个整数值仍然是有效的 Swift 代码。因此,消息约定和可见输出检查可以补充编译器检查。

迁移现有键,同时保留其含义

对于现有的可本地化字符串,Apple 提供了重构工作流。在字符串目录中选择条目,按住 Control 单击,然后选择 Refactor > Convert Strings to Symbols。检查预览,必要时调整建议的符号名称或参数名称,然后选择 Convert。在代码中使用生成的本地化符号

先迁移一组连贯的内容,例如此窗口的标题和摘要。在接受预览之前,比较旧消息和新约定:它们是否使用同一张表、描述同一个界面元素,并且为每个占位符赋予相同含义?检查键更改影响到的现有本地化值,不要假定重构能证明它们正确。

对于重构未更新的调用处,请使用目录检查器中生成的用法,并显式替换该引用。然后构建应用并检查生成的文本。在确认旧条目没有遗留调用方之前,不要删除它。

如果你安装的 Xcode 不支持原生生成,则此工作流需要更新的工具链。Apple 也支持从可本地化 API 提取字符串到目录,并建议将提取作为起步工作流。这仍然是受支持的本地化管理方式,但它本身不会提供此处介绍的生成访问器约定。跟着示例探索 Xcode 本地化

通过一组简单的诊断步骤验证迁移

在示例窗口上执行以下检查。这些步骤可以区分编译器保护、消息正确性和资源集成。

  1. 构建未经修改的示例,确认基线正常运行。
  2. 临时拼错标题成员名称并构建。不存在的成员应产生编译器诊断。然后恢复原名称。
  3. 临时在副标题需要 Int 的位置传入 String 值。构建以检查类型不匹配,然后恢复整数值。
  4. 将 selectedCount 设为 3,并将 availableCount 设为 12 后运行。确认数字位于预期位置。
  5. 仅将目录标题值改为 Current selection,重新构建,并确认显示的标题。检查生成的签名仍与代码所用的签名一致。

如果意外找不到某个成员,先检查目录条目生成的用法。然后检查生成设置、目录的目标成员资格和表名称。编译器诊断会指出引用失败;这些检查有助于区分拼写错误和生成声明不可用的情况。

最后,测试实际界面。Apple 文档中的操作路径是 Product > Scheme > Edit Scheme,然后选择 Run > Options,在其中选择 App Language 后运行。对项目支持的本地化语言重复此操作。运行应用时测试本地化

若要提前检查布局,Xcode 还提供 Double-Length Pseudolanguage,可扩展可本地化文本以暴露尺寸问题。在较窄的窗口宽度下检查摘要;编译成功无法证明文本能够完整显示。测试本地化

迁移完成后,每个调用处都有真正的 Swift 成员,每个变量都有记录在案的作用,并且保留了一条经过检查、通往预期目录条目的路径。将编译器检查和窗口检查结合起来:前者验证访问器约定,后者确认读者看到的是预期消息。

来源