65、iOS 应用程序本地化全解析

iOS 应用程序本地化全解析

1. 字符串文件的作用与结构

在源代码中,字符串字面量和常量是很常见的。例如下面这段代码:

let alertController = UIAlertController(title: "Location Manager Error",
                            message: errorType, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "OK", style: .Cancel,
                             handler: nil)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true,
                           completion: nil)

当我们对应用程序进行本地化时,显然不希望弹出的提示框使用开发时的基础语言。解决办法是将这些字符串存储在特殊的文本文件——字符串文件中。

字符串文件实际上是 Unicode 文本文件,包含一系列由注释标识的字符串对。以下是一个应用程序中字符串文件的示例:

/* Used to ask the user his/her first name */
"LABEL_FIRST_NAME" = "First Name";

/* Used to get the user's last name */
"LABEL_LAST_NAME" = "Last Name";

/* Used to ask the user's birth date */
"LABEL_BIRTHDAY" = "Birthday";

注释部分( /* */ 之间的内容)是给翻译人员看的,在应用程序中不会使用,但添加注释有助于翻译人员理解字符串的用途。每行由等号分隔成两部分,等号左边的字符串作为键,无论使用何种语言,其值始终不变;等号右边的值则会被翻译成当地语言。例如,将上述字符串文件本地化到法语后可能如下:

/* Used to ask the user his/her first name */
"LABEL_FIRST_NAME " = "Prénom";

/* Used to get the user's last name */
"LABEL_LAST_NAME" = "Nom de famille";

/* Used to ask the user's birth date */
"LABEL_BIRTHDAY" = "Anniversaire";
2. 本地化字符串函数

我们通常不会手动创建字符串文件,而是使用 NSLocalizedString() 函数来获取所需字符串的本地化版本。当源代码最终确定并准备好进行本地化时,Xcode 会搜索所有代码文件中该函数的使用情况,提取所有唯一的字符串并嵌入到一个文件中,我们可以将这个文件发送给翻译人员,或者自己添加翻译内容。完成后,让 Xcode 导入更新后的文件,并使用其内容为我们提供翻译的语言创建本地化字符串文件。

下面是传统字符串声明和使用 NSLocalizedString() 函数的对比:

// 传统字符串声明
let myString = @"First Name"

// 使用 NSLocalizedString() 函数使字符串可本地化
let myString = NSLocalizedString("LABEL_FIRST_NAME",
              comment: "Used to ask the user his/her first name")

NSLocalizedString() 宏接受五个参数,但在大多数情况下,其中三个参数有默认值,所以通常只需要提供两个参数:
- 第一个参数是用于查找本地化字符串的键。如果没有包含该键对应文本的本地化内容,应用程序将使用该键作为本地化文本。
- 第二个参数用作注释,解释文本的用途。该注释将出现在发送给翻译人员的文件中,以及导入后的本地化字符串文件中。

NSLocalizedString() 会在应用程序包内的适当本地化文件夹中查找名为 Localizable.strings 的字符串文件。如果未找到该文件,它将返回第一个参数(即所需文本的键)。如果找到字符串文件,它会在文件中搜索与第一个参数匹配的行。

虽然可以使用基础语言文本作为 NSLocalizedString() 函数的键,但不建议这样做,原因有两点:一是很难在第一次尝试时就为应用程序想出完美的文本,后续修改字符串文件中的所有键既繁琐又容易出错;二是使用大写键可以让我们在运行应用程序时,通过查看界面就能立即发现是否有文本忘记本地化。

3. 创建并设置 LocalizeMe 应用程序

接下来,我们将创建一个名为 LocalizeMe 的小应用程序,用于显示用户的当前区域设置。具体步骤如下:
1. 创建项目 :在 Xcode 中使用单视图应用程序模板创建一个新项目,并将其命名为 LocalizeMe
2. 添加图像资源 :在示例源代码的 22 – Images 文件夹中,找到 flag_usa.png flag_france.png 这两个图像文件。在 Xcode 中选择 Images.xcassets 项,然后将这两个图像文件拖入其中。
3. 添加标签出口 :在项目的视图控制器中添加一些标签出口。我们需要为视图顶部的蓝色标签创建一个出口,为显示旗帜的图像视图创建一个出口,以及为右侧所有单词创建一个出口集合。打开 ViewController.swift 文件,进行如下修改:

class ViewController: UIViewController {
    @IBOutlet var localeLabel : UILabel!
    @IBOutlet var flagImageView : UIImageView!
    @IBOutlet var labels : [UILabel]!
}
  1. 编辑界面 :选择 Main.storyboard 文件,在 Interface Builder 中编辑图形用户界面。具体操作如下:
    • 展开视图控制器,将其视图名称更改为 Main View
    • 从库中拖动一个标签到视图顶部,使其与顶部蓝色参考线对齐,并调整标签大小使其占据整个视图宽度。
    • 选择标签,打开属性检查器,点击字体控件中的小 T 图标,选择 System Bold 使标题标签更加突出,然后将文本对齐方式设置为居中。
    • 使用 Control - 拖动从视图控制器图标到新标签,选择 localeLabel 出口。
    • 再从库中拖动五个标签到左侧边距,依次将它们的文本更改为 First Second Third Fourth Fifth
    • 拖动另外五个标签到右侧边距,使用属性检查器将它们的文本对齐方式设置为右对齐。使用 Control - 拖动从视图控制器到这五个新标签,将它们连接到 labels 出口集合,并确保按从上到下的正确顺序连接。
    • 从库中拖动一个图像视图到视图底部,使其与底部和左侧蓝色参考线接触。在属性检查器中,为视图的 Image 属性选择 flag_usa ,并水平调整图像大小使其从蓝色参考线延伸到蓝色参考线,垂直调整使其约为用户界面高度的三分之一。将 Mode 属性从当前值更改为 Aspect Fit ,以确保图像的本地化版本显示正常。使用 Control - 拖动从视图控制器到该图像视图,选择 flagImageView 出口。
  2. 设置自动布局约束
    • 对于顶部标签,使用 Control - 拖动从它到文档大纲中的 Main View ,按住 Shift 键,选择 Leading Space to Container Margin Trailing Space to Container Margin Top Space to Top Layout Guide ,然后点击弹出窗口外的区域。
    • 对于每一行标签,使用 Control - 拖动从带有 First 文本的标签到文档大纲中的 Main View ,选择 Leading Space to Container Margin Top Space to Top Layout Guide ,然后点击弹出窗口外的区域。再使用 Control - 拖动从该标签到同一行右侧的标签,选择 Baseline ,接着使用 Control - 水平拖动从右侧标签到文档大纲中的 Main View ,选择 Trailing Space to Container Margin 。对其他四行标签执行相同操作。
    • 按住 Shift 键并点击右侧的五个标签,选择它们,然后选择 Editor ➤ Size to Fit Content 。可以清除这些标签的文本,因为我们将通过编程方式设置它们。
    • 对于旗帜标签,使用 Control - 拖动从它到文档大纲中的 Main View ,选择 Leading Space to Container Margin Trailing Space to Container Margin Bottom Space to Bottom Layout Guide ,然后点击弹出窗口外的区域。仍然选择旗帜标签,点击 Pin 按钮,在弹出窗口中勾选 Height 复选框,然后按下 Add 1 Constraint
  3. 添加代码到 viewDidLoad() 方法
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let locale = NSLocale.currentLocale()
    let currentLangID = (NSLocale.preferredLanguages() as [String])[0]
    let displayLang = locale.displayNameForKey(NSLocaleLanguageCode, value: currentLangID)
    let capitalized = displayLang?.capitalizedStringWithLocale(locale)
    localeLabel.text = capitalized

    labels[0].text = NSLocalizedString("LABEL_ONE", comment: "The number 1")
    labels[1].text = NSLocalizedString("LABEL_TWO", comment: "The number 2")
    labels[2].text = NSLocalizedString("LABEL_THREE", comment: "The number 3")
    labels[3].text = NSLocalizedString("LABEL_FOUR", comment: "The number 4")
    labels[4].text = NSLocalizedString("LABEL_FIVE", comment: "The number 5")

    let flagFile = NSLocalizedString("FLAG_FILE", comment: "Name of the flag")
    flagImageView.image = UIImage(named: flagFile)
}

在这段代码中,首先获取代表用户当前区域设置的 NSLocale 实例,然后获取用户的首选语言。接着使用 displayNameForKey(_, value:) 方法获取所选语言的实际名称,并将其转换为大写形式,用于设置视图顶部的标签。之后,使用 NSLocalizedString() 函数设置其他五个标签的文本,最后查找要使用的旗帜图像名称并设置图像视图。

4. 测试 LocalizeMe 应用程序

我们可以使用模拟器或设备来测试 LocalizeMe 应用程序。应用程序启动后,由于使用了 NSLocalizedString() 函数而不是静态字符串,它已经为本地化做好了准备,但目前还未进行本地化。如果在模拟器或 iOS 设备的设置应用程序中更改语言或区域,除了视图顶部的标签外,其他部分的显示结果基本相同。

5. 对项目进行本地化

下面是对项目进行本地化的具体步骤:
1. 在 Xcode 的项目导航器中,单击 LocalizeMe ,在编辑区域中单击 LocalizeMe 项目(而不是其中一个目标),然后选择项目的 Info 标签。
2. 在 Info 标签中查找 Localizations 部分,这里会显示一个本地化设置,即开发语言的本地化(在示例中为英语),这通常被称为基础本地化,是 Xcode 创建项目时自动添加的。
3. 点击 Localizations 部分底部的加号(+)按钮,从弹出列表中选择法语( fr )。
4. 接下来,会被要求选择要本地化的所有现有可本地化文件,以及新的法语本地化要从哪个现有本地化开始。在当前情况下,只有两个文件需要本地化,且起始语言只有基础语言这一个选择,所以保持所有设置不变,点击 Finish

添加法语本地化后,在项目导航器中可以看到 Main.storyboard 文件现在旁边有一个展开三角形,展开后可以看到它包含两个子项:一个是标记为 Base Main.Storyboard ,另一个是标记为 French Main.strings 。这些文件实际上位于两个不同的文件夹中: Base.lproj fr.lproj

当要求 Xcode 创建法语本地化时,它会在项目中创建一个名为 fr.lproj 的新本地化文件夹,并在其中放置包含从 Base.lproj/Main.storyboard Base.lproj/LaunchScreen.xib 中提取的值的字符串文件。Xcode 不会复制这两个文件,而是提取其中的每个文本字符串并创建准备好进行本地化的字符串文件。在应用程序编译和运行时,本地化字符串文件中的值将被用于替换故事板和启动屏幕中的值。

以下是整个本地化流程的 mermaid 流程图:

graph LR
    A[创建项目] --> B[设置界面和代码]
    B --> C[测试未本地化应用]
    C --> D[添加新语言本地化]
    D --> E[选择本地化文件和起始语言]
    E --> F[生成本地化字符串文件]
    F --> G[编译运行应用使用本地化内容]

通过以上步骤,我们可以完成 iOS 应用程序的本地化工作,让应用程序能够适应不同语言和地区的用户。

iOS 应用程序本地化全解析

6. 本地化文件的结构与原理

在完成项目的本地化设置后,了解本地化文件的结构和工作原理有助于我们更好地管理和维护本地化内容。

当我们在 Xcode 中添加新的本地化语言(如法语)时,Xcode 会为每种语言创建一个对应的本地化文件夹,例如 fr.lproj 。这些文件夹中包含了从基础本地化文件夹(如 Base.lproj )中提取的字符串文件。

文件夹名称 说明
Base.lproj 基础本地化文件夹,包含开发语言的原始文件,如 Main.storyboard LaunchScreen.xib
fr.lproj 法语本地化文件夹,包含从 Base.lproj 中提取的文本字符串,以 .strings 文件形式存在,如 Main.strings

当应用程序运行时, NSLocalizedString() 函数会根据用户的语言设置,在相应的本地化文件夹中查找 Localizable.strings 文件(如果存在),并从中获取对应的本地化字符串。如果找不到匹配的字符串,将使用函数的第一个参数(键)作为默认文本。

7. 进一步优化本地化

为了让应用程序的本地化更加完善,还可以考虑以下几点:
- 多语言资源管理 :除了字符串文件,还可以对图像、音频等资源进行本地化。例如,为不同语言准备不同的旗帜图像,通过 NSLocalizedString() 函数动态选择合适的资源。
- 处理特殊情况 :某些语言可能有特殊的语法、格式或文化习惯,需要在代码中进行特殊处理。例如,日期、时间和货币的显示格式可能因地区而异,可以使用 NSLocale 类提供的方法来确保正确显示。
- 测试与验证 :在不同的语言和地区设置下对应用程序进行全面测试,确保所有文本和资源都能正确显示和使用。可以使用 iPhone 模拟器或实际设备进行测试。

8. 示例代码解释

下面对 LocalizeMe 应用程序中 viewDidLoad() 方法的代码进行详细解释:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let locale = NSLocale.currentLocale()
    let currentLangID = (NSLocale.preferredLanguages() as [String])[0]
    let displayLang = locale.displayNameForKey(NSLocaleLanguageCode, value: currentLangID)
    let capitalized = displayLang?.capitalizedStringWithLocale(locale)
    localeLabel.text = capitalized

    labels[0].text = NSLocalizedString("LABEL_ONE", comment: "The number 1")
    labels[1].text = NSLocalizedString("LABEL_TWO", comment: "The number 2")
    labels[2].text = NSLocalizedString("LABEL_THREE", comment: "The number 3")
    labels[3].text = NSLocalizedString("LABEL_FOUR", comment: "The number 4")
    labels[4].text = NSLocalizedString("LABEL_FIVE", comment: "The number 5")

    let flagFile = NSLocalizedString("FLAG_FILE", comment: "Name of the flag")
    flagImageView.image = UIImage(named: flagFile)
}
  • 获取用户区域设置和首选语言
  • let locale = NSLocale.currentLocale() :获取代表用户当前区域设置的 NSLocale 实例。
  • let currentLangID = (NSLocale.preferredLanguages() as [String])[0] :获取用户的首选语言代码,如 en fr
  • 获取并设置语言显示名称
  • let displayLang = locale.displayNameForKey(NSLocaleLanguageCode, value: currentLangID) :使用 displayNameForKey(_, value:) 方法获取所选语言的实际名称,以当前区域设置的语言显示。
  • let capitalized = displayLang?.capitalizedStringWithLocale(locale) :将语言名称转换为大写形式(根据当前区域设置的规则)。
  • localeLabel.text = capitalized :将处理后的语言名称设置为视图顶部的标签文本。
  • 设置标签文本
  • 使用 NSLocalizedString() 函数为右侧的五个标签设置本地化文本,分别对应数字 1 到 5。
  • 设置旗帜图像
  • let flagFile = NSLocalizedString("FLAG_FILE", comment: "Name of the flag") :获取本地化的旗帜图像名称。
  • flagImageView.image = UIImage(named: flagFile) :根据获取的名称设置图像视图的图像。
9. 总结

通过以上步骤和方法,我们可以实现 iOS 应用程序的本地化,让应用程序能够适应不同语言和地区的用户。关键步骤包括:
1. 使用 NSLocalizedString() 函数将字符串进行本地化处理。
2. 在 Xcode 中添加新的本地化语言,并选择要本地化的文件。
3. 管理和维护不同语言的本地化文件,确保应用程序在各种语言设置下都能正常显示和使用。

以下是一个简单的总结流程图:

graph LR
    A[使用 NSLocalizedString() 函数] --> B[添加本地化语言]
    B --> C[管理本地化文件]
    C --> D[完成应用本地化]

希望这些内容能帮助你更好地理解和实现 iOS 应用程序的本地化。在实际开发中,可以根据具体需求对本地化过程进行调整和优化,以提供更好的用户体验。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值