在 iOS 开发中支持 国际化(Internationalization, i18n) 是现代应用程序的一个重要功能,目的是让应用能够支持多种语言和文化区域,为全球用户提供更加本地化的体验。
以下是 iOS 应用实现 国际化 的主流解决方案和最佳实践:
1. 主流解决方案概览 #
解决方案 / 技术 | 适用场景 |
---|---|
Apple 本地化工具(本地化字符串、Localizable.strings ) | 应用内主要文本的国际化,适合较简单的需求。例如按钮文本、标签、提示语等。 |
Localizable.stringsdict | 用于文本中的复数形式和动态拼接处理。例如,「1个消息」vs「3条消息」。 |
NSLocalizedString 宏 | Xcode 提供的国际化标识符管理方式,可动态加载本地化内容。 |
Bundle 动态加载机制 | 文件、图片、多内容的动态本地化,例如根据语言加载不同的图片或 JSON 文件资源。 |
第三方库(Swiftgen、Lokalise、Crowdin 等) | 自动化管理国际化文件/资源,适合大规模或跨团队的国际化协作。 |
2. Apple 提供的本地化工具 #
2.1 基本流程 #
启用国际化支持 打开 Xcode 项目:
- 选择项目 -> Info -> 勾选
Use Base Internationalization
。 - 添加支持的语言,例如
English
,Chinese
,French
。
- 选择项目 -> Info -> 勾选
本地化字符串文件(
Localizable.strings
) 创建一个专门存放本地化字符串的文件Localizable.strings
:- 在 Xcode 中右键项目,选择
New File
-> iOS -> Strings File。 - 为每种语言创建一个版本。
- 在 Xcode 中右键项目,选择
示例: #
Localizable.strings
(英文版):
"greeting" = "Hello, welcome!";
"exit" = "Exit";
Localizable.strings
(中文简体版):
"greeting" = "你好,欢迎!";
"exit" = "退出";
- 使用
NSLocalizedString
加载本地化字符串
示例代码: #
Text(NSLocalizedString("greeting", comment: "Welcome message displayed to the user"))
Button(NSLocalizedString("exit", comment: "Exit button title")) {
print("Exit button tapped")
}
- 本地化用户界面(Storyboard/Xib 文件)
- 打开
Main.storyboard
。 - 在右侧的 File Inspector 中勾选 Localize。
- Xcode 会让你为该界面添加对应语言的翻译文本。
- 打开
2.2 本地化动态复数或字符串拼接 #
如果需要支持复数形式或动态值的拼接,可以使用 Localizable.stringsdict
文件。
示例: #
Localizable.stringsdict
:
<dict>
<key>messages</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@value@</string>
<key>value</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d new message</string>
<key>other</key>
<string>%d new messages</string>
</dict>
</dict>
</dict>
示例代码: #
let messageCount = 3
let message = String.localizedStringWithFormat(NSLocalizedString("messages", comment: ""), messageCount)
print(message) // "3 new messages"
2.3 本地化支持的文件类型 #
除了文本,Apple 提供的本地化机制也支持其他文件资源。例如:
- 图片本地化:可以为不同语言添加不同的图片。
- JSON 文件本地化:加载不同语言的配置文件。
2.4 按需切换语言(动态切换) #
iOS 默认使用系统语言,但也可以动态切换应用语言:
示例代码: #
func changeLanguage(to languageCode: String) {
UserDefaults.standard.set([languageCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
// 重启应用以应用语言切换
exit(0)
}
3. 第三方国际化工具 #
- SwiftGen
- 自动生成本地化代码(如
Localizable.strings
的命名空间)。 - 提高代码可维护性,避免使用硬编码的 Key。
- 自动生成本地化代码(如
示例: #
Text(L10n.greeting) // 自动生成的命名空间
Lokalise
- 云端管理国际化内容,支持团队协作翻译。
- 自动生成本地化文件并导入 Xcode。
Crowdin
- 类似于 Lokalise,但还集成了翻译 API 和自动化内容管理。
4. 国际化中需要注意的内容 #
4.1 UI 适配问题 #
多语言字数差异
- 比如英文短,但德文和法文会更长,阿拉伯语会从右往左显示。
- 可以使用
GeometryReader
动态布局或SwiftUI
的.multilineTextAlignment()
。
适配从右到左的语言
- 默认情况下,iOS 会根据语言自动调整布局。
- 如果需要手动检测语言方向,用
UIView.userInterfaceLayoutDirection(for:)
检查。
4.2 日期、时间和数字本地化 #
iOS 提供了强大的 DateFormatter
和 NumberFormatter
工具来处理区域化差异。
示例代码: #
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "fr_FR") // 目标语言
dateFormatter.dateStyle = .full
let today = Date()
print(dateFormatter.string(from: today)) // 法语的日期格式
5. 自动测试本地化 #
为确保应用的多语言支持正确,可以通过以下措施测试:
Xcode 中切换语言
- 在 Xcode 的 Scheme 设置中添加 App 的支持语言进行测试。
- 可以快速切换语言不用在系统设置中修改语言。
通过脚本遍历语言
- 编写自动化脚本加载所有语言以检查缺少的翻译内容。
6. 工作流优化建议 #
最佳实践 #
命名规范
- 以模块划分 Key,例如
home.greeting
、settings.logout
. - 避免使用硬编码的 Key。
- 以模块划分 Key,例如
自动检查漏翻译
- 可以用工具(如
Lokalise
或自定义脚本)检查未翻译的 Key。
- 可以用工具(如
双语言并列开发
- 在
Base
或默认语言旁边显示翻译语言,便于对比。
- 在
总结 #
对于小型应用: 使用 Apple 提供的
Localizable.strings
和NSLocalizedString
是最主流的解决方案。对于中大型应用或多团队协作: 可以引入第三方工具(如 SwiftGen 或 Lokalise)来提高自动化和协作效率。
国际化的核心是在 技术实现、翻译管理、UI 调整 上三者结合,做好这些步骤即可为你的全球用户提供优质的本地化体验!
SwiftUI 使用国际化 #
在 SwiftUI 中,国际化(Localization)是支持多种语言和地区的应用程序的核心功能。Swift 提供了强大的国际化工具和方法,结合 Xcode 的内置功能,可以轻松地在项目中实现本地化支持。
以下是 SwiftUI 国际化的完整指南,包括实现步骤和详细说明。
1. 什么是国际化(Localization)? #
在 SwiftUI 中,国际化涉及以下核心内容:
- 翻译文本(Strings Localization):将 UI 上的静态或动态文本翻译为不同语言。
- 本地化资源:支持不同语言版本的图像、文件等。
- 日期和货币的本地化格式:根据用户的地区显示日期、时间、货币等格式。
SwiftUI 使用系统提供的本地化机制,其基础是 Localizable.strings
文件和 Xcode 项目的本地化支持。
2. 快速实现本地化支持 #
下面是实现 SwiftUI 国际化的一个完整流程:
步骤 1:启用项目的本地化支持 #
- 在 Xcode 中打开项目文件。
- 选择你的项目 > 目标(Target) > Info 标签页。
- 找到 Localizations 部分。
- 点击 “+” 按钮,添加你需要支持的语言(例如 “English”,“Chinese (Simplified)” 等)。
- 添加后,Xcode 会为项目的主要资源(如
.strings
文件)创建语言分支。
- 添加后,Xcode 会为项目的主要资源(如
步骤 2:创建 Localizable.strings 文件 #
- 在 Xcode 工程中:
- 右击项目目录 > 新建文件(
New File
)。 - 在弹出的窗口中搜索
Strings
,选择Strings File
,并将其命名为Localizable.strings
。
- 右击项目目录 > 新建文件(
- 选中
Localizable.strings
文件,打开右侧的 File Inspector(⌥ + ⌘ + 1)。- 勾选你需要支持的语言(例如 English、Chinese)。
- Xcode 会自动为每个语言创建对应的
Localizable.strings
文件分支。
步骤 3:编辑 Localizable.strings 文件 #
打开每个语言版本的 Localizable.strings
文件,添加本地化字符串。键值对格式为:
"键" = "翻译内容";
示例: #
- 英文版 Localizable.strings:
"welcome_message" = "Welcome!";
"greeting_message" = "Hello, how are you?";
- 简体中文 Localizable.strings:
"welcome_message" = "欢迎!";
"greeting_message" = "你好,你好吗?";
步骤 4:在 SwiftUI 中使用本地化文本 #
通过 NSLocalizedString
或 Text
直接绑定关键字动态加载翻译。
示例: #
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// 使用 Text 时会自动加载本地化内容
Text("welcome_message") // 将根据语言显示本地化结果
// 直接使用 NSLocalizedString
Text(NSLocalizedString("greeting_message", comment: "Greeting message to user"))
}
.padding()
}
}
如果用户的设备语言设置为中文(简体),以上代码会显示:
欢迎!
你好,你好吗?
步骤 5:本地化图片和资源 #
Xcode 还支持本地化图像和其他静态资源。
为图像添加本地化版本: #
- 在
Assets.xcassets
中选择一个需要本地化的图像(如Logo
)。 - 右键图像 > Localization > 选择语言版本。
- 每种语言版本都会创建一个单独的图像文件夹,你可以为每个语言提供不同的图像。
示例:加载本地化图像 #
Image("Logo") // SwiftUI 会根据当前语言加载对应的 Logo 版本
6. 本地化日期、时间和货币格式 #
Swift 提供了 DateFormatter
和 NumberFormatter
来支持动态的地区格式。
日期的本地化显示 #
import SwiftUI
struct ContentView: View {
var body: some View {
let date = Date()
let formatter = DateFormatter()
formatter.dateStyle = .long // 显示完整的日期
Text("Today: \(formatter.string(from: date))")
}
}
根据用户的设备地区设置,将显示:
- 英文(美国):Today: January 1, 2023
- 中文(中国):Today: 2023年1月1日
货币本地化 #
import SwiftUI
struct ContentView: View {
var body: some View {
let price = 1234.56
let formatter = NumberFormatter()
formatter.numberStyle = .currency // 激活货币格式
formatter.locale = Locale.current // 使用设备地区设置
Text("Price: \(formatter.string(from: NSNumber(value: price)) ?? "")")
}
}
根据用户的地区显示:
- 英文(美国):Price: $1,234.56
- 中文(中国):Price: ¥1,234.56
7. 支持动态切换语言 #
在实际应用中,用户可能需要在应用内动态切换语言。这种情况下,可以使用自定义逻辑加载语言。
示例:动态切换语言 #
- 创建一个函数用于加载指定语言的
.strings
文件:
class Localizer {
static func setLanguage(_ language: String) {
UserDefaults.standard.set([language], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
- 在
App
启动或切换语言时调用:
Localizer.setLanguage("zh-Hans") // 设置为中文显示
- 重新启动
App
生效。
8. 调试本地化内容 #
在开发阶段,可以手动切换系统语言用于测试。操作如下:
- 点击设备的 设置 > 通用 > 语言与地区。
- 更改语言(比如英文 -> 中文)。
- 返回应用检查 UI 是否正确更新。
如果要更快速测试不同的语言,可以通过模拟器设置 环境语言:
- 在 Xcode 的 Scheme 配置中(
Edit Scheme
),添加-AppleLanguages
参数。
9. 本地化的最佳实践 #
不要硬编码字符串:
- 所有显示在 UI 上的文本都应该放入
Localizable.strings
文件。 - 避免直接在代码中写硬编码的文本(如
"Hello"
)。
- 所有显示在 UI 上的文本都应该放入
为每个语言版本提供完整资源:
- 确保所有支持的语言
Localizable.strings
文件都提供完整且精准的内容。
- 确保所有支持的语言
测试语言覆盖情况:
- 使用工具(如
Xcode Preview
或真实设备)测试所有语言和地区的显示效果。
- 使用工具(如
支持 Right-to-Left 语言:
- 比如阿拉伯语和希伯来语,应该在 UI 设计中测试 RTL(从右到左)的界面适配。
总结 #
SwiftUI 的国际化功能基于已有的 Cocoa 本地化机制,结合 Xcode 提供的开发工具非常简单高效。以下是本地化的关键流程:
步骤 | 动作 | 示例 |
---|---|---|
添加 Localizable 文件 | 在项目中创建 Localizable.strings 文件,并适配本地化语言。 | "key" = "value"; |
使用本地化翻译 | 在代码中通过 Text("key") 或 NSLocalizedString 加载翻译内容。 | Text("welcome_message") |
日期货币等动态本地化转换 | 使用 DateFormatter 、NumberFormatter 等进行格式转换。 | ¥123.45 |
测试国际化显示 | 通过模拟器语言环境或设备实际切换语言检查 UI 效果。 | 更改系统区域语言。 |
通过上述步骤可以轻松面向全球用户构建多语言的 SwiftUI 应用!
String(localized: “Hello”) #
确实,String(localized:)
是 Swift 中一个现代化的国际化方法,它是在 Swift 5.5 中引入的,结合了 Swift 的类型安全和简洁性,专门用于处理本地化字符串。相比传统的 NSLocalizedString
方法,它更简洁、更易用,尤其适合 SwiftUI 的开发场景。
感谢你的补充!下面我将详细介绍 String(localized:)
的使用及其与传统方法的对比。
1. 什么是 String(localized:)
#
String(localized:)
是 Swift 的一种新方式,用于加载本地化字符串。它结合了 Swift 的类型安全和现代化的 API,能够简化国际化代码,同时支持 Xcode 的 .strings
文件。
优点 #
- 简洁:不需要显式指定
tableName
或bundle
,只需提供键值即可。 - 类型安全:支持参数插值,避免拼接错误。
- 现代化:与 SwiftUI 的语法风格一致,适合 Swift 项目。
2. 使用 String(localized:)
的步骤
#
步骤 1:创建 Localizable.strings
文件
#
- 在 Xcode 项目中,右键项目目录 > 新建文件(
New File
)。 - 搜索
Strings File
,创建一个名为Localizable.strings
的文件。 - 在文件中添加本地化字符串:
示例: #
- 英文版 Localizable.strings:
"Today" = "Today";
"WelcomeMessage" = "Welcome, %@!";
- 简体中文版 Localizable.strings:
"Today" = "今天";
"WelcomeMessage" = "欢迎, %@!";
步骤 2:使用 String(localized:)
加载本地化字符串
#
在 SwiftUI 或其他 Swift 代码中,直接使用 String(localized:)
方法加载本地化的文本。
示例代码: #
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
// 加载简单的本地化字符串
Text(String(localized: "Today"))
// 加载带参数的本地化字符串
Text(String(localized: "WelcomeMessage", table: nil, bundle: .main, comment: "Welcome message"))
.font(.headline)
}
.padding()
}
}
运行效果: #
- 英文环境:
Today
Welcome, %@!
- 简体中文环境:
今天
欢迎, %@!
3. 动态参数插值 #
String(localized:)
支持动态参数插值,可以直接将参数嵌入到本地化字符串中。
示例:动态参数 #
import SwiftUI
struct ContentView: View {
var userName = "Alice"
var body: some View {
Text(String(localized: "WelcomeMessage", arguments: [userName]))
}
}
本地化文件内容: #
- 英文版 Localizable.strings:
"WelcomeMessage" = "Welcome, %@!";
- 简体中文版 Localizable.strings:
"WelcomeMessage" = "欢迎, %@!";
运行效果: #
- 英文环境:
Welcome, Alice!
- 简体中文环境:
欢迎, Alice!
4. 使用 String(localized:)
的高级功能
#
格式化日期和数字 #
String(localized:)
还支持日期、时间、货币等格式化内容的本地化。
示例:日期本地化 #
import SwiftUI
struct ContentView: View {
var body: some View {
let date = Date()
Text(String(localized: "\(date.formatted(.dateTime.month().day()))"))
}
}
运行效果: #
- 英文环境:
Jan 24
- 简体中文环境:
1月24日
自定义翻译表 #
如果你需要使用自定义的 .strings
文件,而不是默认的 Localizable.strings
,可以通过指定 table
参数加载。
示例: #
Text(String(localized: "CustomKey", table: "CustomStrings"))
- 在项目中创建
CustomStrings.strings
文件。 - 添加对应的键值对:
- 英文版 CustomStrings.strings:
"CustomKey" = "This is a custom key!";
- 简体中文版 CustomStrings.strings:
"CustomKey" = "这是一个自定义键!";
- 英文版 CustomStrings.strings:
指定 Bundle #
如果本地化资源不在主项目中(例如在动态库或模块中),可以通过 bundle
参数指定加载的资源包。
示例: #
let customBundle = Bundle(path: "path/to/your/bundle")!
Text(String(localized: "Key", bundle: customBundle))
5. String(localized:)
与 NSLocalizedString
的对比
#
特性 | String(localized:) | NSLocalizedString |
---|---|---|
语法简洁性 | 更简洁,直接使用 String(localized:) | 需要显式指定键值和注释 |
参数插值 | 支持类型安全的动态参数插值 | 需要手动拼接字符串 |
SwiftUI 兼容性 | 与 SwiftUI 风格一致 | 语法稍显冗长 |
自定义翻译表 | 支持通过 table 参数指定 | 支持通过 tableName 参数指定 |
现代化支持 | 更现代化,推荐用于新项目 | 传统方法,适合旧项目或兼容性需求 |
6. 动态切换语言 #
String(localized:)
同样支持动态切换语言的功能,结合 UserDefaults
和 AppleLanguages
可以实现。
示例:动态切换语言 #
class LanguageManager {
static func setLanguage(_ language: String) {
UserDefaults.standard.set([language], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
// 切换到中文
LanguageManager.setLanguage("zh-Hans")
注意: #
- 切换语言后,应用需要重新启动才能生效。
7. 注意事项和最佳实践 #
避免硬编码字符串:
- 将所有用户可见的文本放入
.strings
文件中,避免直接在代码中写硬编码文本。
- 将所有用户可见的文本放入
测试多语言支持:
- 使用 Xcode 的 模拟器语言设置 或设备的语言设置测试 UI。
- 在
Edit Scheme
中添加-AppleLanguages
参数快速切换语言。
使用动态参数插值:
- 动态参数插值可以减少拼接错误,提升代码的可读性和安全性。
支持 RTL(从右到左)语言:
- 确保 UI 适配阿拉伯语、希伯来语等从右到左的语言。
总结 #
String(localized:)
是 Swift 国际化的现代解决方案,它更简洁、更安全,特别适合 SwiftUI 项目。以下是它的核心特点:
- 简化了加载本地化字符串的代码。
- 支持动态参数插值和格式化。
- 与 Swift 的类型系统和 SwiftUI 风格高度一致。
- 更适合新项目的国际化需求。
如果你正在开发一个支持多语言的 SwiftUI 应用,建议优先使用 String(localized:)
,它可以让你的代码更加简洁和现代化!
国际化其他形式 #
当然,Swift 和 SwiftUI 在国际化(Localization)方面有几个相关的工具和方法,可以适用于不同的场景。除了 String(localized:)
和传统的 NSLocalizedString
方法外,还有一些技巧和方法可能会对你的项目有用,包括动态语言切换、本地化自定义类型、日期和数字本地化以及使用 SwiftUI 的特定支持工具。
以下是 SwiftUI 和 Swift 国际化的其他方法和高级用法:
8. 使用 Environment 的 Locale #
SwiftUI 提供了一个非常强大的 @Environment(\.locale)
属性,可以动态访问和修改设备的区域设置(Locale
),从而直接影响视图的显示语言和本地化内容。
示例:动态更新语言 #
import SwiftUI
struct ContentView: View {
@Environment(\.locale) var locale // 当前的区域
var body: some View {
VStack {
Text("Today") // 自动根据当前区域加载本地化
.padding()
Text("Current Locale: \(locale.identifier)") // 输出当前语言的标识符
}
.onAppear {
// 检查当前地区
print("Current Locale: \(locale)")
}
}
}
示例:手动切换语言 #
- 通过
environment
修饰符主动更改视图的区域设置。
import SwiftUI
struct ContentView: View {
@State private var selectedLocale: Locale = .current
var body: some View {
VStack {
Text("Today") // 根据区域设置加载本地化
Button("切换到中文") {
selectedLocale = Locale(identifier: "zh-Hans") // 切换到中文
}
Button("切换到英文") {
selectedLocale = Locale(identifier: "en") // 切换到英文
}
}
.environment(\.locale, selectedLocale) // 设置动态区域
}
}
说明: #
Locale(identifier:)
可以指定具体的语言,例如"en"
(英文)或"zh-Hans"
(中文)。- 使用
environment(\.locale, Locale)
动态切换语言,而无需重新启动应用。
9. 对自定义数据类型进行本地化 #
如果你的应用中存在自定义的数据类型(如 enum
或模型对象),也可以为这些类型实现本地化支持。
示例:对枚举进行本地化 #
import SwiftUI
enum TaskStatus: String, CaseIterable {
case todo = "To Do"
case inProgress = "In Progress"
case done = "Done"
}
extension TaskStatus: CustomStringConvertible {
var description: String {
switch self {
case .todo:
return NSLocalizedString("To Do", comment: "Task status: to do")
case .inProgress:
return NSLocalizedString("In Progress", comment: "Task status: in progress")
case .done:
return NSLocalizedString("Done", comment: "Task status: done")
}
}
}
struct ContentView: View {
var taskStatus: TaskStatus = .inProgress
var body: some View {
Text("Current Status: \(taskStatus.description)") // 将状态根据语言本地化
}
}
本地化文件内容 (Localizable.strings
):
#
"To Do" = "待办";
"In Progress" = "进行中";
"Done" = "完成";
10. 使用 LocalizedStringKey
#
当你需要将本地化字符串直接绑定到 SwiftUI 的 Text
时,LocalizedStringKey
是一个强大的工具。
LocalizedStringKey
是 SwiftUI 中的一个专用类型,用于解析字符串键并自动从 .strings
文件中加载对应语言的本地化内容。
示例:使用 LocalizedStringKey
#
import SwiftUI
struct ContentView: View {
let welcomeMessage: LocalizedStringKey = "welcome_message"
var body: some View {
Text(welcomeMessage) // 会直接显示对应语言的内容
}
}
优点: #
- 和 SwiftUI 组件如
Text
深度集成。 - 自动从本地化文件加载内容,避免手动调用
NSLocalizedString
或String(localized:)
。
缺点: #
- 不支持动态字符串拼接。如果需要动态内容,
NSLocalizedString
或String(localized:)
是更好的选择。
11. 支持动态语言切换(无需重启应用) #
大多数情况下,改变系统语言后,应用会重新启动以加载新的语言设置。但是,如果你希望用户在应用内动态切换语言,可以结合 UserDefaults
和 SwiftUI 的 @Environment(\.locale)
达成这一目标。
示例:动态切换语言 #
import SwiftUI
class LanguageManager: ObservableObject {
@Published var currentLocale: Locale = .current // 默认使用当前系统语言
func switchLanguage(to identifier: String) {
currentLocale = Locale(identifier: identifier)
}
}
struct ContentView: View {
@StateObject private var languageManager = LanguageManager()
var body: some View {
VStack {
Text("Today") // 动态语言切换
.padding()
Button("切换到中文") {
languageManager.switchLanguage(to: "zh-Hans") // 切换到中文
}
Button("切换到英文") {
languageManager.switchLanguage(to: "en") // 切换到英文
}
}
.environment(\.locale, languageManager.currentLocale) // 使用动态 Locale
}
}
12. 数字和日期的复杂格式化 #
当你需要格式化时间、日期或货币时,可以结合 Foundation
中的 FormatStyle
来完成自动化的本地化处理。
示例:本地化日期显示 #
import SwiftUI
struct ContentView: View {
var body: some View {
Text(Date().formatted(.dateTime.weekday().month().day().year()))
.padding()
}
}
输出样例: #
- 在英文环境下:Tuesday, January 24, 2023
- 在中文环境下:2023年1月24日,星期二
示例:本地化货币显示 #
import SwiftUI
struct ContentView: View {
var body: some View {
let price: Double = 1234.56
Text(price, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
.padding()
}
}
输出样例: #
- 在英文环境下:$1,234.56
- 在中文环境下:¥1,234.56
13. 使用 Swift Package 管理本地化 #
在大型项目中,如果本地化字符串较多,可能会使用单独的 Swift 包(Swift Package
)来管理本地化资源。
示例:创建自定义模块来管理本地化 #
- 创建一个
LocalizationManager
类或 Swift 包,集中管理所有本地化逻辑。 - 暴露 API 接口,通过自定义方法返回翻译:
struct LocalizationManager {
static func localizedString(for key: String) -> String {
NSLocalizedString(key, comment: "Custom localization manager")
}
}
- 在项目中调用:
Text(LocalizationManager.localizedString(for: "welcome_message"))
这种方式适用于多模块、大型项目的组织和管理。
14. 本地化单词的复数(Pluralization)支持 #
对于需要根据数量变化的文本,String.LocalizationValue
提供了极大的便利。
示例:处理复数文本 #
import SwiftUI
struct ContentView: View {
var itemCount: Int = 3
var body: some View {
Text("\(itemCount) item(s)")
.padding()
}
}
本地化配置(Localizable.stringsdict
文件):
#
创建一个 Localizable.stringsdict
文件,添加复数规则:
<key>item(s)</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@items@</string>
<key>items</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>No items</string>
<key>one</key>
<string>1 item</string>
<key>other</key>
<string>%d items</string>
</dict>
</dict>
总结 #
在 SwiftUI 中,本地化(Internationalization)的能力远不止简单的键值翻译。综合使用以下方法,可以实现更加现代化和复杂的本地化处理:
String(localized:)
简洁高效,是现代项目首选。- 动态切换语言:结合
@Environment(\.locale)
和ObservableObject
可实现实时切换。 - 本地化资源:支持
Strings
文件、图像资源等多种类型。 - 处理时间、货币等复杂格式化:利用
Foundation
的格式化工具。 - 支持复数形式:通过
.stringsdict
文件管理。
有了这些工具和方法,SwiftUI 项目可以轻松实现全球化支持,面向多语种、多地区用户。根据项目需求灵活运用吧!
bundle 参数 #
在 SwiftUI 中的 Text(String, bundle:)
是一个用于加载本地化字符串的构造方法,可以指定文本文字的来源 bundle(资源包)。这个方法允许你更精细地控制本地化文本的加载来源,尤其是在多模块项目或动态加载本地资源的场景下非常有用。
bundle
参数的意义
#
bundle
参数告诉 SwiftUI 从哪个 Bundle
中加载对应的本地化字符串。默认值为 .main
,即主应用程序的资源包。如果需要从某个自定义的模块或者动态加载的资源包中加载,本地化字符串需要传入特定的 Bundle
。
默认值为 .main
#
在大多数情况下,你的本地化资源(Localizable.strings
或其他文件)都存储在主项目的资源中,默认情况下的 bundle
就是主应用的 Bundle.main
。
用法示例:
Text("welcome_message")
等价于:
Text("welcome_message", bundle: .main)
如果在你的 Localizable.strings
文件(主资源包中)中有以下内容:
"welcome_message" = "Welcome!";
当当前语言为英语时,Text("welcome_message")
会显示:Welcome!
在多模块中的用法 #
如果你使用了多个模块(如使用 Swift Package Manager 或 CocoaPods 引入的库),有时需要从指定模块的资源中加载本地化内容。此时需要显式指定 bundle
参数。
示例:自定义 Bundle
import Foundation
import SwiftUI
let myCustomBundle = Bundle(identifier: "com.example.MyCustomModule")!
struct ContentView: View {
var body: some View {
Text("custom_message", bundle: myCustomBundle)
.padding()
}
}
这里的 myCustomBundle
是一个从其他模块加载的资源包(Bundle
),从中加载 custom_message
对应的本地化值。
如何确认正确的 Bundle
:
#
- 从模块中获取
Bundle
:- 如果是 CocoaPods 或 SDL 插件模块,通常可以通过其
Bundle.identifier
直接创建。 - 如果是 Swift Package Manager,可以通过自定义方法将资源文件附加至包管理并加载。
- 如果是 CocoaPods 或 SDL 插件模块,通常可以通过其
动态加载其他 Bundle
的场景
#
1. 动态加载不同的本地化资源 #
在某些复杂场景下(比如插件化架构),主应用需要从动态加载的资源包中获取对应的语言内容。
示例:动态获取具体语言版本的 Bundle
let dynamicBundlePath = Bundle.main.path(forResource: "CustomLocalization", ofType: "bundle")!
let dynamicBundle = Bundle(path: dynamicBundlePath)!
Text("welcome_message", bundle: dynamicBundle) // 指定动态加载的资源包
假设 CustomLocalization.bundle
是一个独立的资源包,包含以下内容:
CustomLocalization.bundle/
en.lproj/Localizable.strings
zh-Hans.lproj/Localizable.strings
这允许你动态从资源包中加载语言内容,而不是固定依赖在主应用程序中。
2. 在框架中加载本地化资源 #
如果你设计了自己的 Swift 框架并需要加载框架内部的本地化资源,则需要从框架的 bundle
中读取。
示例:加载框架里的本地化资源
// 在你的框架代码中
let frameworkBundle = Bundle(for: MyFrameworkClass.self)
// 通过指定 bundle 加载本地化资源
Text("framework_message", bundle: frameworkBundle)
在这个例子中,Bundle(for:)
确保从框架自身的资源中加载值。
如何使用 SwiftUI 的多模块本地化 #
Swift Package Manager 已支持局部资源清单声明。如果一个模块需要自己的本地化资源,可以在 Package.swift
中添加资源路径,并正确引用 bundle
。
示例:Package.swift
中声明资源
// Package.swift
let package = Package(
name: "MyLibrary",
defaultLocalization: "en",
targets: [
.target(
name: "MyLibrary",
resources: [
.process("Resources") // 把 Resources 文件夹下内容标记为资源
]
)
]
)
假设 Resources
文件夹下有以下内容:
Resources/
en.lproj/Localizable.strings
zh-Hans.lproj/Localizable.strings
在 SwiftUI 中加载资源:
import SwiftUI
let libraryBundle = Bundle.module
struct ContentView: View {
var body: some View {
Text("library_message", bundle: libraryBundle)
}
}
使用 .module
直接指向 SPM 的模块资源包。
小结和适用场景 #
需求场景 | bundle 参数值 | 说明 |
---|---|---|
主应用加载主资源中的本地化字符串 | .main (默认省略) | 如果 Localizable.strings 在主应用资源包中,可以省略 bundle 参数,直接传入 key。 |
动态加载其他资源包 | 显式传入 Bundle(path:) | 当本地化资源位于独立的动态包(如 .bundle 文件)中时,使用对应包的路径创建 Bundle。 |
多模块项目的模块资源 | 使用模块的 Bundle.module | 如果使用 Swift Package Manager 并声明了资源,使用 .module 从当前模块中加载本地化内容。 |
框架内的本地化资源 | 使用 Bundle(for: SomeClass.self) | 如果框架使用返回类方法,指定 for 参数为框架内类,确保获取框架内部的资源包。 |
使用 bundle
参数可以解决多模块、多资源包、本地化文件分散存储的场景,在复杂项目中非常重要。例如:
- 如果你有一个插件化系统,每个插件都有独立的语言文件,可以通过指定
bundle
进行加载。 - 如果你组织了多个 Swift Package 模块,各模块有独立的资源文件,你也可以精准定位语言资源。
bundle
参数结合 SwiftUI 的简洁语法,使得控制本地化资源变得更加灵活和强大。