如何使用 Xcode 字符串目录本地化 App

在 Apple 技术术语中,捆绑包只是一个文件夹,其中包含一些特殊的文件系统位,这些位告诉操作系统该文件夹将被视为代码包 – 应用程序、框架、驱动程序或系统扩展或安装程序。还有其他类型的捆绑包。

在 Apple 编程中,捆绑包由 Objective-C 类定义,我们稍后会用到它。NSBundle

这是在 macOS 和 iOS 中通过磁盘上每个捆绑包中存储的捆绑包和 .strings 文件完成的。

捆绑包可以包含其他捆绑包,从本地化的角度来看,通常按语言将捆绑包存储在应用中,并带有语言扩展名,例如,“.en”表示英语,“.jp”表示日语,“.de”(德语表示)。

每个语言包可以包含并行资源,但使用不同的语言。

.strings 文件实际上是 XML 文件

Apple 还定义了一种称为 .plist(属性列表)文件的特殊文件,它本质上只是一个包含键值对的 XML 文件。Xcode 有一个内置的 .plist 文件编辑器,因此它知道如何在图形编辑器中编辑键值对。

.plist 文件还可以包含字符串(可以本地化),也可以包含指向捆绑包中其他位置的其他字符串文件的条目。

一个名为 Info.plist 的特殊文件包含 Apple 定义的键,Finder 会在您打开 App 时读取这些键。Info.plist 文件包含特殊键和值,这些键和值告诉操作系统在启动应用时要使用哪些设置。

字符串文件包含使用 “” 和 XML 标记的键集和相应的字符串。例如:

“kAlertOKButtonStringKey”

“还行”

58217-118784-dict-xl
Xcode 中的 .strings 文件。

文本通常是开发人员定义的常量值,只要不干扰 XML,就可以是任何内容。

该值包含运行时要在用户界面中显示的实际字符串文本。

创建 .strings 文件后,可以将文件本身移交给翻译人员以复制成多种不同的语言。这种设计使本地化整个应用程序或捆绑包变得容易。

传统上,Apple 平台上应用程序中的默认 .strings 文件名为“Localizable.strings”。

NeXT的编程语言被称为Objective-C,至今仍被苹果公司使用。

Objective-C 可以追溯到 1980 年代后期,当时它是在 NeXT 为该计算机平台开发的。Objective-C 源自一种更早的称为 C 的语言,该语言于 1970 年在贝尔实验室用于开发 UNIX。

事实上,C语言是为了编写UNIX而创建的。

在基于 Objective-C 的应用中,开发人员通常会为每个字符串文件包含一个 .h(头)文件,其中包含与 .strings 文件中定义的键匹配的常量定义。这使得在 Objective-C 应用程序中更改密钥变得容易。

大多数现代 TCI/IP 网络堆栈仍是用 C 语言编写的。h 文件是为 C 语言创建的。这一切都发生在面向对象编程(OOP)发明之前。

在 Objective-C 和 NeXT 的开发环境出现之前,本地化和重新本地化软件要求每次更改字符串时都要对每个应用程序进行完全重新编译。

苹果公司最新的编程语言 Swift 取消了 C 头文件,但字符串仍然像以前一样本地化和加载。

58217-118794-plist-xl
Xcode 中的 .plist 编辑器。

来自 Apple 的特殊字符串类

为 Apple 平台构建 App 后,生成的 App Bundle 将包含程序执行所需的所有代码、资源和字符串。

在 OOP 中,未编译对象的代码定义称为类。类是将代码和数据绑定在一起以便于重用的代码包。类可以被子类化 – 允许后代类继承其祖先类的属性和方法。

Apple 编程中的中心字符串类是 NSString (Objective-C) 或简称为 String (Swift)。

这两个类的工作方式相似,并且具有相同的函数(在 OOP 中称为 methods()。Swift 也有自己的标准库,其中包含许多字符串函数,尽管它们与传统的 C 标准库截然不同。

Apple 字符串类有几种创建字符串的方法。您可以从 .strings 文件加载它们,可以从 C 字符串或 Unicode 字符串创建它们,并且可以使用提供的数十种“init”方法初始化 NSString 或 String。

您还可以转换其他 Apple 数据类型(如日期、原始数据、字节)或来自 URL 或其他文件类型(如.txt和.rtf文件)。

若要了解如何创建 Apple 字符串类,请访问 Apple 开发人员网站上的 NSString 类参考页面。从那里,您可以在 Swift 和 Objective-C 语法之间切换。

NSString 曾经有几十种方法将 NSStrings 转换回 C 字符串,但这些方法现在已被弃用,因为 Apple 不建议使用 C 字符串,除非出于兼容性原因必须这样做。

您还可以使用 @“” 语法在 Objective C 中定义 NSString 常量,如下所示:

@"NSVisualEffectView"

这告诉编译器在编译时将文本字符串本身存储在代码中。常量通常仅用作方法参数的标志,但您也可以将它们传递到需要 NSString 或 String 的任何位置。

您还可以使用字符串常量在运行时获取任何已编译的 Objective-C 或 Swift 对象的类,方法是使用如下关键字:Class

Class vibrantClass = NSClassFromString( @"NSVisualEffectView" );

Class是 Objective-C 和 Swift 中一种特殊类型的保留变量,用于将任何对象的类存储在内存中。普通 C 函数返回对象的实际类,并将其存储在您定义的 Class 变量中。NSClassFromString()

在上面的示例中,传递了常量,函数返回类并将其存储在名为 的变量中。NSClassFromString( )@"NSVisualEffectView"Class'vibrantClass'

传递给 NSClassFromString() 的字符串常量是 Apple 文档中定义的类的名称。还有一个 for Swift 版本:NSClassFromString()

NSClassFromString(_:)

Apple 还提供了一个未实现的类,您可以实现该类以提供有关对象的更高级详细信息。NSClassDescription

Apple 有一个姊妹字符串类,它允许您操作和编辑字符串内容本身。字符串还具有编码,用于告诉软件如何处理字符串中的数据。NSMutableString

有罗马语、西里尔语、亚洲语、阿拉伯语和其他语言的字符串编码。

大多数其他 NSObject 继承的基类称为 NSObject。

NSString 是一个庞大的类,您需要彻底查看文档。

在 Apple App 中以编程方式加载字符串

有几种方法可以在 Apple 应用程序中加载字符串。

处理 .strings 文件时的常用方法是使用该函数。这个 C 函数(它实际上是一个 C 宏)需要两个参数:NSLocalizedString()

// Load localized message string

NSString *suggestionString = NSLocalizedString( messageStringKey, kEmptyStringKey );

这将加载由从应用捆绑包中的文件中传入第一个参数的键指示的字符串。如果传入的密钥在 .strings 文件中不存在,则返回。Localizable.stringsnil

第一个参数是要加载的 .strings 文件中的字符串键。您可以将其作为字符串常量、C 或 Swift 编译器定义常量或包含字符串键的 NSString 变量本身传递。

无论采用哪种方式,都返回您从字符串文件中请求的字符串,并将其存储在表达式左侧的 NSString 变量中。NSLocalizedString()

请注意,必须使用“*”语法将返回的 NSString 变量声明为指针变量。NSLocalizedString()

C、Objective-C 或 Swift 中的指针只是内存中的一个变量,其中包含另一个变量或内存位置的地址。在这种情况下,编译器需要一个指针变量,因为它在创建 NSString 对象时必须知道在内存中的哪个位置存储该对象。

从函数调用返回到您定义的指针时,指向内存中的该位置。NSLocalizedString()

的第二个参数是“建议”或注释字符串,可以是空字符串 (@“”)、您选择的内容或 .在 Objective-C 和 Swift 中,表示“无”——一个空指针。NSLocalizedString()nilnil

在上面的示例中,是在头文件中定义的预编译器宏,如下所示:kEmptyStringKey

#define kEmptyStringKey @""

这告诉编译器:在编译过程中遇到“kEmptyStringKey”的任何地方,将其替换为 @“”。 在 C 中称为“磅定义”(用于“#”符号)。#define

你可以像这样轻松地写出同样的一行:

NSString *suggestionString = NSLocalizedString( messageStringKey, @"" );

#defines因此,当需要更改常量值时,只需在标头中的一个位置更改该值,并且下次重新编译应用时,更改就会在代码中使用的任何位置发生。#define

在 Swift 中,对 NSLocalizedString() 的调用如下所示:

let suggestionString = NSLocalizedString( messageStringKey, nil )

在这两种语言中,它似乎都是一个 C 函数,但它实际上是 NSBundle 类的 Apple 头文件中一个巧妙定义的宏:NSLocalizedString()

#define NSLocalizedString(key, comment) \

[NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]

事实证明,它有自己的方法,用于按键从应用程序的主捆绑包加载字符串,带有可选的第二个参数和一个参数。该参数可用于通过在第三个参数中传入另一个 .strings 文件的名称,从 Localizable.strings 文件以外的 .strings 文件加载字符串。NSBundletabletable

这允许您在应用或捆绑包中使用多个字符串文件,而不仅仅是默认字符串文件。

在预编译时,编译器将整个宏压缩到 syntax to shorten the code and make it look like a plain C function.

使用 NSBundle 以编程方式加载字符串

从文件加载字符串的另一种方法是直接使用,使用其方法从文本文件加载字符串:NSBundlepathForResource:ofType:

NSString *fileName = [ [ NSBundle mainBundle ] pathForResource:@"readme" ofType:@"txt"];

if (文件名)

{

NSString *contentsString = [ NSString stringWithContentsOfFile:fileName ];

}

使用此方法,可以在第二个参数中传入文本文件的名称或路径,并将文件扩展名作为 传入。如果指定的位置和名称中存在可读文本文件,则 NSBundle 将加载该文件并将路径作为 .NSStringNSString

然后,将返回的文件路径字符串从 to 方法传递。pathForResource:ofType:NSString's stringWithContentsOfFile:

如果一切按计划进行,则在返回时,上面声明的变量将指向文本文件的整个文本内容 – 作为字符串。stringWithContentsOfFile:*contentsString

NSBundle需要一点时间来适应,但一旦你掌握了它,就会有很大的力量。

NSBundle 上实际上有几个类似的宏,它们是从捆绑包加载字符串的变体。您甚至可以从其他捆绑包中的 .strings 文件加载它们:

  1. NSLocalizedStringFromTable
  2. NSLocalizedStringFromTableInBundle
  3. NSLocalizedStringWithDefaultValue
  4. NSLocalizedAttributedString
  5. NSLocalizedAttributedStringFromTable
  6. NSLocalizedAttributedStringFromTableInBundle
  7. NSLocalizedAttributedStringWithDefaultValue

An 是一个字符串类,除了字符串可以设置属性,例如字体、面孔、超链接和其他排版详细信息之外,字符串类。您还可以在线或本地从 HTML 文件加载。 NSAttributedString NSString NSAttributedString

使用 NSDictionary 以编程方式加载字符串

另一个调用的 Objective-C 类可用于从磁盘或 URL 加载字符串文件。本质上是一组键/值对,与 XML 或 .plist 文件非常相似。NSDictionaryNSDictionary

事实上,您可以将 .plist 文件直接加载到对象中,并将其填充到字典的键/值对中。该类知道如何从磁盘读取 .plist 文件,并使用文件中的数据填充对象。NSDictionaryNSDictionary

由于存储在 .plist 或 XML 文件中的值是字符串,因此您可以从文件中加载一个字符串或整个字符串集,只需使用文件的 XML 键进行搜索:只需使用 or 方法在加载字典后检索字典中的所有条目。valueForKey:allValues:

还可以使用该方法检索字典中的所有键。allKeys:

Xcode 15 的字符串目录

传统上,在 Apple App 开发中,您需要创建 .string 文件,将它们添加到 Xcode 项目中,设置您希望它们包含在哪些构建目标中,然后在运行时需要它们时从代码中加载字符串。

这种设计几十年来一直运行良好,但有一些局限性。

首先,从 .strings 文件加载字符串不能很好地处理字符串文本(即代码中用引号括起来的字符串)。不幸的是,SwiftUI 严重依赖字符串文字,因此除了编辑源文件中的字符串外,没有其他简单的方法可以本地化它们。

其次,以前更难走另一个方向:创建字符串并以编程方式将它们写回 .strings 文件。这是可以做到的,但这不是一个优雅的解决方案,你可能会发现自己编写了大量多余的代码来用多种语言写出字符串。

字符串目录解决了这些问题,并针对当今的需求对 Xcode 中的字符串基础设施进行了现代化改造。字符串目录还专门设计用于处理基于 SwiftUI 的项目。

首次在 Xcode 中创建字符串目录时,它将为空。除非您显式添加字符串,否则 Xcode 不会填充字符串目录,直到您实际构建项目。

字符串目录设计为在构建时组装。这不仅使字符串可以包含在 SwiftUI 代码中,而且还可以在构建时写出它们,更新在编译过程中修改的任何字符串,这样您就不必在构建捆绑包后手动更改它们。

字符串目录还允许在 Xcode 本身中指定默认语言和多种其他语言。Xcode 知道如何在构建捆绑包时为您查找和组装所有必需语言的所有字符串。

目录还消除了每次向捆绑包添加新语言时不断向项目添加其他 .strings 文件的需要。

Xcode 中的字符串目录文件的扩展名为 .xcstrings,它们会像 .strings 文件一样添加到您的 Xcode 项目中。

正如您可能猜到的那样,Xcode 项目中的默认字符串目录文件的名称为 Localizable.xcstrings。

至少苹果保持了一致性。

当您在 Xcode 项目窗口左侧的 Xcode 导航器中选择 .xcstrings 文件时,Xcode 的字符串目录编辑器将显示在右侧。

让我们看一个例子。

58217-118790-empty-xl
Xcode 字符串目录编辑器。

字符串目录的示例 Xcode 项目

首先,打开 Xcode,然后从显示屏顶部的 Xcode 菜单栏中选择 File->New Project

从 Xcode 项目模板选取器中选取一个 iOS 或 macOS App 项目。单击“下一步”,为项目指定产品名称、组织标识符,然后选择语言。

单击“下一步”,然后将项目保存到磁盘。

当 Xcode 项目出现时,您会注意到左侧的项目导航器中没有 .xcstrings 文件。那是因为还没有创建任何内容。

接下来,单击项目窗口左下角的 + 按钮,然后选择“新建文件…从弹出菜单中。这将打开新的文件模板选择器:

58217-118791-Screenshot-4-xl
选择“新建文件…”从弹出菜单中。

向下滚动到“资源”部分,单击“字符串目录”,然后单击“下一步”。这将打开一个标准的“保存”面板 – 继续将新的字符串目录文件保存到项目中的默认位置。

默认文件名预设为“可本地化”。

58217-118793-Screenshot-5-xl
选择“字符串目录”。

存储文件后,您会看到它自动添加到 Xcode 项目中,并且 Xcode 将在项目导航器中选择它。当它出现时,你会看到字符串目录编辑器出现在右侧。

请注意编辑器中的“空字符串目录”消息。

在目录编辑器中,您可以单击编辑器顶部的 + 按钮向目录添加新键,也可以单击目录编辑器左下角的 + 按钮向目录添加新语言。

58217-118792-lang-add-xl-1
在目录编辑器中添加语言。

如果你点击编辑器左下角的+,你会得到一个弹出菜单,里面有所有可能的语言列表。从菜单中选择任何语言以将其添加到目录中。执行此操作时,它将显示在目录列表顶部的默认语言下。

设置目录后,当您在 Xcode 中单击“生成”按钮时,编译器将自动扫描您的源代码文件,并将其找到的任何字符串添加到字符串目录中。字符串文本将作为每个字符串的键和值添加到目录中。

当您单击在目录编辑器中添加的其他语言之一时,该语言将显示在默认语言旁边的每一行中。然后,您可以单击每个语言名称下的文本,并为该语言键入新文本。

每个字符串中还有一个注释和一个状态字段。为每个键添加翻译后,状态列会显示一个绿色复选标记,指示字符串具有本地化。

没有本地化字符串的键在状态列中显示红色的“新建”标签。

若要在应用运行时查看应用中的每个本地化字符串,可以转到“Apple 设置”应用并更改系统语言,也可以转到 Xcode 项目中的应用架构并更改运行时的语言。下次运行应用时,你将看到任何本地化字符串的正确语言。

如果您在 iOS 或 iPadOS App 中使用自定 Xcode 预览,则还可以在结构的属性中设置标识符字符串,以指定要在运行时使用的语言。#Preview.locale.environmentContentView()

您可以为每种语言和区域设置设置一个宏,以便在运行时正确显示本地化字符串。预览的语言名称通常是完整的语言名称,区域设置通常由 2 个字符的 ISO 国家/地区代码指定,例如“DE”(德国)或“JP”(日本)。#Preview

您需要查找要使用的每种语言的特定语言名称和区域设置代码。

将旧的 .strings 文件转换为字符串目录

如果您的 Xcode 项目中有现有的 .strings 文件,只需在 Xcode 项目导航器中按住 Control 键点按它们,然后从弹出菜单中选择“迁移到字符串目录”,即可将它们转换为字符串目录

将本地化的 .strings 文件迁移到目录的一个很酷的功能是,如果你的 .strings 文件已经有本地化的副本,Xcode 会立即将它们全部迁移到字符串目录中 – 将所有字符串移动到正确的本地化中。

Xcode 还会在目录编辑器中每种语言的名称旁边显示一个完成百分比指示器 – 显示在整个语言完成之前还剩下多少字符串需要完成。

在 SwiftUI 中使用“verbatim”键

如果您正在构建 SwiftUI 项目,则可以将关键字放在元素中的任何字符串之前,当您构建项目时,Xcode 不会本地化并将这些字符串包含在字符串目录中。verbatim:Text

这是一种方便的方法,可以排除您不希望本地化的文本,或者您只想在开发过程中用于测试目的的文本。

使用 LocalizedStringResource

从 iOS 16 开始,Apple 推出了一个新的 Swift 结构,允许您延迟本地化字符串资源。这意味着你可以告诉编译器你想加载什么,但让它在以后加载一个本地化版本 – 例如,只有在需要它的时候,或者当其他一些进程(如XPC程序)需要它时。LocalizedStringResource

在分布式网络环境中,可能会发生这种情况,其中某个进程正在运行的计算机上运行,其区域设置与运行调用进程的计算机不同。 也被 Apple 的 Intents Framework for SiriUI 使用。LocalizedStringResource

另外,请务必查看 SwiftUI 文档的“文本输入和输出”部分中的讨论。LocalizedStringKey

Info.plist 文件的字符串目录

您还可以为应用的 Info.plist 文件创建新的字符串目录。为此,请在项目导航器中选择它们,然后按住 Control 键单击,就像对本地化的 .strings 文件所做的那样,然后像以前一样再次选择“迁移到字符串目录”。

Xcode 知道如何将 Info.plist 文件转换并导入到新的 .xcstrings 文件。确保新文件的名称为 Info.xcstrings,就像 Info.plist 文件一样。

转换后,您可以本地化和更新 Info.xcstrings 文件,就像对 .strings 文件所做的那样。

字符串目录中的“过时”消息

字符串目录的另一个很酷的功能是,Xcode 现在不仅可以为您导入和设置字符串目录,而且如果您在目录文件中引入了与源代码中的内容不匹配的错误,目录编辑器会在状态列中用黄色的“过时”标记标记该行,让您知道某些内容不同步。

有了这个功能,只需滚动和浏览目录,就可以用多种语言扫描整个目录以查找错误。

以前,对于字符串文件,很容易在 .strings 文件中拼写错误,并使字符串键与头文件中的匹配常量或代码中的文本不同步。以前,您必须花时间搜索以找到不匹配的内容并纠正它。

现在,只需查看目录中的状态列即可找到错误。

字符串目录是 Xcode 中一个受欢迎的新功能,它们在开发过程中节省了大量时间。字符串存储、汇编和本地化现在都位于 Xcode 中的一个地方,并且位于一个字符串文件中。

您不再需要创建和管理多个 .strings 文件。

这种巨大的简化加上新的目录编辑器意味着本地化不再是一件繁重的苦差事。过去需要几个小时才能完成的工作,现在只需几分钟。

内置的编辑器安全检查可帮助您立即发现错误,因此您不再需要搜索多个文件来解决问题。

请务必查看 Xcode 文档中的三个主要部分,以了解有关字符串目录的更多信息:

  1. 使用字符串目录本地化和更改文本
  2. 本地化包含复数的字符串
  3. 导入本地化

阅读 Swift 的类及其方法以及具有字符串函数的 Swift 标准库也是一个好主意。String

未经允许不得转载:表盘吧 » 如何使用 Xcode 字符串目录本地化 App