要解析框架的本地化键,请同时传入其资源包和字符串表。本指南将说明如何让框架拥有的标签在 Mac 应用中正确显示,然后检查结果是否来自字符串表,而非回退文本。

这个任务刻意保持简单:从框架的 Panel.xcstrings 目录中显示合成标签 Open panel。你需要一个 Xcode 中的 Mac 应用项目,以及一个由你控制的框架目标。主要示例使用 Xcode 26 或更高版本,目标平台为 macOS 12 或更高版本;Apple 文档说明,本地化字符串初始化器从 macOS 12 起可用。Swift 初始化器文档。

更改代码前,先确定资源包、表和键

将本地化消息视为具有三个明确坐标的查找。资源包标识资源所有者,表标识该资源包中的一组字符串,键标识该表中的一个条目。Apple 的本地化 API 将资源包和表分别公开,因为框架目标和应用目标都可以包含字符串资源。准备应用文本以便翻译。

在本例中,打开目录前先记下以下约定。这些名称仅用于示例,并非 Apple 要求的名称。

部分 示例值 用途
资源所有者 你的框架目标 包含目录
目录文件 Panel.xcstrings 存储表的源文本和译文
表参数 Panel 选择该目录,不包含扩展名
键 PANEL_OPEN_ACTION 标识消息
英文源值 Open panel 提供可读的界面文本
注释 Label for the action that opens the panel. 说明消息的用途

传入 table: \"Panel\" 会选择由 Panel.xcstrings 表示的表。未设置表时,会选择 Localizable。同样,未设置资源包时,字符串初始化器会搜索主应用资源包。因此,框架目录中的匹配键除了正确的表之外,还需要框架的资源包。Swift 本地化字符串参数。

这为你提供了一个实用的诊断顺序:先确认所有者,再确认表,最后确认条目。如果消息属于框架,那么在查找指向应用资源时,搜索键的其他拼写形式并不能解决问题。

将字符串目录添加到框架目标

在 Xcode 中,选择 File > New > File from Template,选择平台,筛选 string,然后选择 String Catalog。将文件命名为 Panel。确保该目录属于框架目标,并与之后会引用它的框架源文件位于同一目标中。Apple 的目录工作流允许使用自定义目录名称,其框架演示也在框架目标中创建了目录。使用字符串目录进行本地化和文本变体处理、Apple 的框架本地化演示。

本例使用语义键,而不是直接用显示文本作为键。标识符为 PANEL_OPEN_ACTION,默认值为 Open panel,代码会明确写出这两部分。Apple 通过接受静态键和单独默认本地化值的初始化器支持这种做法。Swift 静态键初始化器。

添加下面的源代码后,构建框架目标。Xcode 会在构建期间发现可本地化的 API 调用,并更新相关目录。打开 Panel.xcstrings,确认其中包含 PANEL_OPEN_ACTION、英文源值 Open panel 以及说明性注释。如果缺少该条目,请检查源文件是否属于该目标,以及包含该源文件的目标是否已构建。Apple 还提供 Editor > Assistant,用于检查与目录条目关联的代码。填充并检查字符串目录。

在框架内部解析消息

将这个完整源文件放入框架目标中。它定义了本地化字符串和一个小型 SwiftUI 标签,包含该框架的 Mac 应用可以显示此标签。它还包含下一节使用的诊断方法。代码已对照 Apple 的文档签名检查;由于此处没有 Swift 编译器,因此未执行代码。

import Foundation
import SwiftUI

public enum PanelMessages {
    public static var openPanel: String {
        String(
            localized: "PANEL_OPEN_ACTION",
            defaultValue: "Open panel",
            table: "Panel",
            bundle: #bundle,
            comment: "Label for the action that opens the panel."
        )
    }

    public static func lookupReport() -> String {
        let missingMarker = "__PANEL_LOOKUP_MISSING__"
        let result = #bundle.localizedString(
            forKey: "PANEL_OPEN_ACTION",
            value: missingMarker,
            table: "Panel"
        )

        if result == missingMarker {
            return "No entry resolved from the selected bundle and table."
        }

        return "Resolved table value: \(result)"
    }
}

public struct PanelActionLabel: View {
    public init() {}

    public var body: some View {
        Text(verbatim: PanelMessages.openPanel)
    }
}

#bundle 表达式会在你编写它的位置求值。在这段框架源代码中,它会提供与框架目标关联的资源包。如果将相同表达式移到应用目标的源代码中,它提供的就是应用的资源包。对于 Swift 包目标,Apple 的文档说明该宏会提供目标的资源包。让查找代码与其拥有的资源放在一起。Foundation 的资源包宏。

该声明会返回一个普通的 String,其本地化结果已解析完成。该视图使用 Text(verbatim:) 明确显示这个结果。这个公开视图只是一个标签;在需要显示文本的位置,将其添加到现有应用视图中。

宏不可用时,使用框架类

Apple 也支持通过框架中定义的类来定位框架资源包。对于包含自身资源的常规框架,以下是一个完整的替代消息提供程序。用它替换前面的 PanelMessages 声明,并保留上述目录和部署要求。

import Foundation

private final class PanelBundleAnchor: NSObject {}

public enum PanelMessages {
    public static var openPanel: String {
        String(
            localized: "PANEL_OPEN_ACTION",
            defaultValue: "Open panel",
            table: "Panel",
            bundle: Bundle(for: PanelBundleAnchor.self),
            comment: "Label for the action that opens the panel."
        )
    }
}

锚点类必须编译到你要获取资源的框架中。Apple 的文档说明,Bundle(for:) 会返回与所提供类关联的资源包;在适用情况下,也包括该类的框架资源包。若锚点类编译到应用中,定位到的就是应用。如果资源属于包资源或放在单独的资源包中,请选择实际的资源包;仅凭类的位置无法确定这些资源的所有权。基于类的资源包初始化器、使用宏选择资源包。

验证可读文本是否来自成功的查找

屏幕上显示 Open panel,不足以证明目录查找成功。查找失败时,初始化器会返回 defaultValue,因此同一段可见文本可能代表查找成功,也可能代表回退。这种行为有利于显示可读的界面文本,但在开发期间可能掩盖错误的资源包或表。Swift 默认值行为。

第一个源文件中的 lookupReport() 方法可以消除这种歧义。它会使用一个醒目的回退标记执行查找,该标记不得用作实际目录值。在运行中的应用或现有调试环境中检查其返回值。如果它报告没有解析到条目,请先检查所选资源,再编辑译文。

此诊断直接基于 Bundle.localizedString(forKey:value:table:) 的文档行为:当键不存在且提供的回退值非空时,该方法会返回此回退值。如果键不存在,而回退值为 nil 或空值,则返回键本身。这个标记可以更容易地区分查找失败和合法的源文本。资源包本地化字符串的返回值。

观察结果 下一步检查
诊断返回缺少条目的消息 确认目录已构建到所选资源包中,然后检查 Panel 和 PANEL_OPEN_ACTION
诊断解析出意外值 检查所选表中的确切条目,以及当前运行所用的语言
诊断解析正确,但界面显示不同 追踪界面实际显示的值
运行已翻译版本时显示英文源值 检查条目的译文和运行配置;仅仅成功查找到条目,并不能证明请求的译文存在

该表是根据查找约定整理出的故障排查步骤。标记测试成功,表示查找返回了一个条目,但并不能证明所有受支持语言都有完整译文。请分别检查资源解析和翻译完整性。

使用 Mac 应用选定的语言测试标签

对于支持其他语言的应用,请在目录侧边栏中选择相关语言,并在该条目的文本字段中输入译文。然后通过包含该框架的 Mac 应用进行测试。Apple 的文档说明,可以直接在目录编辑器中输入译文,并且每个条目的翻译状态会随着编辑过程更新。向字符串目录添加译文。

若要控制调试运行,请选择 Product > Scheme > Edit Scheme,选择 Run,然后打开 Options。将 App Language 设为项目支持的语言,关闭编辑器,然后重新运行 Mac 应用。若希望运行时遵循系统语言设置,请选择 System Language。运行应用时测试本地化。

不要使用字符串初始化器的 locale: 参数来替代此语言测试。Apple 的文档说明,该参数控制插值值(例如数字)的本地化,不会更改查找本地化字符串时所使用的区域设置。示例中省略此参数,因为该标签不包含插值值。Swift 本地化字符串的区域设置参数。

将最终约定保持简洁明确:Panel.xcstrings 由框架拥有,查找选择 Panel,PANEL_OPEN_ACTION 标识该标签。用诊断方法验证条目,再验证应用中所选运行语言对应的译文是否显示。按此顺序操作,你可以先修正资源查找,然后再花时间调整可能根本没有被应用读取的文本。

来源