MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Objective-C中的国际化与本地化方案

2022-09-123.9k 阅读

国际化与本地化基础概念

在软件开发领域,国际化(Internationalization,常缩写为 i18n,因为在首字母 “I” 和尾字母 “n” 之间有 18 个字母)和本地化(Localization,常缩写为 l10n)是让软件适应不同地区和语言用户需求的重要手段。

国际化指的是设计和开发软件的过程,使其能够适应不同语言、地区和文化习俗,而无需对软件进行大量修改。这涉及到将软件中的可本地化元素,如文本字符串、日期格式、数字格式等,从代码逻辑中分离出来,以便能够根据用户的区域设置进行动态加载和显示。

本地化则是基于国际化的基础,针对特定地区或语言对软件进行定制的过程。这包括翻译文本、调整日期和数字格式、使用特定地区的图像和图标等,以使软件能更好地融入当地用户的使用习惯和文化环境。

Objective-C 中的国际化与本地化支持

Objective-C 作为苹果公司开发 macOS 和 iOS 应用程序的主要编程语言,提供了一系列强大的功能来实现国际化和本地化。

NSLocalizedString 宏

在 Objective-C 中,最常用的国际化手段之一是使用 NSLocalizedString 宏。这个宏允许开发者将需要本地化的字符串提取出来,放到相应的本地化文件中。

下面是一个简单的示例:

NSString *greeting = NSLocalizedString(@"Hello", @"A greeting message");

在这个例子中,NSLocalizedString 宏接受两个参数。第一个参数是要本地化的字符串键值,在这个例子中是 “Hello”。第二个参数是注释,主要用于帮助翻译人员理解该字符串在应用中的上下文含义,在这个例子中注释为 “A greeting message”。

当应用运行时,系统会根据用户的当前语言设置,从相应的本地化文件中查找与 “Hello” 键值对应的本地化字符串。如果当前语言是中文,本地化文件中对应的翻译可能是 “你好”,这样 greeting 变量就会被赋值为 “你好”。

本地化文件(.strings 文件)

本地化文件是存储不同语言翻译的地方。在 Xcode 项目中,可以通过以下步骤创建本地化文件:

  1. 在项目导航器中,选择项目文件,然后在 “Info” 选项卡中,找到 “Localizations” 部分。
  2. 点击 “+” 号添加需要支持的语言,例如中文、英文、法文等。
  3. 对于需要本地化的文件,比如 Main.strings,在项目导航器中选中它,然后在右侧的 “File Inspector” 中,点击 “Localize...” 按钮。选择需要本地化的语言,Xcode 会为每种语言创建对应的本地化文件。

Main.strings 文件为例,英文版本的 Main.strings 可能如下:

"Hello" = "Hello";

而中文版本的 Main.strings 则可能是:

"Hello" = "你好";

这样,当应用根据用户的语言设置加载本地化文件时,就能正确显示相应语言的字符串。

日期和数字格式的本地化

除了文本字符串,日期和数字格式也需要根据不同地区进行本地化。

日期格式本地化

在 Objective-C 中,可以使用 NSDateFormatter 类来实现日期格式的本地化。以下是一个示例:

NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSString *formattedDate = [dateFormatter stringFromDate:now];
NSLog(@"Formatted Date: %@", formattedDate);

在这个示例中,首先创建了一个 NSDateFormatter 对象,并设置了日期和时间的显示风格,这里使用了 NSDateFormatterMediumStyleNSDateFormatterShortStyle。然后通过 setLocale: 方法将日期格式设置为当前用户区域的本地化格式。最后,使用 stringFromDate: 方法将当前日期格式化为本地化的字符串并输出。

如果用户的区域设置为美国,输出可能类似于 “Oct 15, 2023, 3:30 PM”;如果区域设置为中国,输出可能类似于 “2023年10月15日 下午3:30”。

数字格式本地化

对于数字格式的本地化,可以使用 NSNumberFormatter 类。示例如下:

NSNumber *number = @1234567.89;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setLocale:[NSLocale currentLocale]];
NSString *formattedNumber = [numberFormatter stringFromNumber:number];
NSLog(@"Formatted Number: %@", formattedNumber);

在这个示例中,创建了一个 NSNumberFormatter 对象,并设置数字风格为 NSNumberFormatterDecimalStyle,表示常规的十进制数字格式。通过 setLocale: 方法设置为当前用户区域的本地化格式。最后,使用 stringFromNumber: 方法将数字格式化为本地化的字符串并输出。

在美国区域设置下,输出可能是 “1,234,567.89”;在德国区域设置下,输出可能是 “1.234.567,89”,因为德国使用点号作为千位分隔符,逗号作为小数分隔符。

图像和图标本地化

在应用中,图像和图标也可能需要根据不同地区或语言进行本地化。Xcode 提供了一种方便的方式来实现这一点。

图像资源目录

在 Xcode 中,可以使用图像资源目录(Asset Catalog)来管理本地化的图像。步骤如下:

  1. 在项目导航器中,右键点击项目文件夹,选择 “New File...”。
  2. 在弹出的对话框中,选择 “Resource” 类别下的 “Asset Catalog”,然后点击 “Next” 并命名后点击 “Create”。
  3. 打开创建好的图像资源目录,在目录中添加需要本地化的图像。例如,对于应用的 logo,可以添加英文版本的 logo 和中文版本的 logo。
  4. 选中图像,在右侧的 “Attributes Inspector” 中,点击 “Localize...” 按钮,选择需要本地化的语言。
  5. 对于每种本地化语言,在图像资源目录中替换相应的图像文件。

在代码中加载图像时,直接使用图像的名称即可,系统会根据用户的语言设置自动加载正确的本地化图像。例如:

UIImage *logoImage = [UIImage imageNamed:@"app_logo"];

如果当前用户语言是英文,系统会加载英文版本的 “app_logo” 图像;如果是中文,则加载中文版本的图像。

本地化故事板和 XIB 文件

故事板(Storyboard)和 XIB 文件是 iOS 和 macOS 应用中用于设计用户界面的重要工具,它们也支持本地化。

本地化故事板

  1. 在 Xcode 中打开故事板文件,选择需要本地化的视图控制器或视图元素。
  2. 在右侧的 “Attributes Inspector” 中,找到 “Localization” 部分,点击 “Localize...” 按钮,选择需要本地化的语言。
  3. 切换到相应语言的本地化版本,对视图元素的文本进行翻译。例如,对于一个按钮的标题,在英文版本中是 “OK”,在中文版本中可以改为 “确定”。
  4. 保存并运行应用,应用会根据用户的语言设置显示相应语言的故事板内容。

本地化 XIB 文件

本地化 XIB 文件的过程与故事板类似。

  1. 打开 XIB 文件,选择需要本地化的元素,如标签、按钮等。
  2. 在 “Attributes Inspector” 中,点击 “Localize...” 按钮,选择需要本地化的语言。
  3. 切换到相应语言的本地化版本,对元素的文本进行翻译。
  4. 代码中加载 XIB 文件时,系统会根据用户语言设置加载正确的本地化版本。例如:
MyViewController *viewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];

这里 MyViewController 对应的 XIB 文件如果有本地化版本,系统会根据用户语言加载相应版本。

应用名称和元数据的本地化

应用的名称和其他元数据,如应用描述、版权信息等,也需要进行本地化,以提供更好的用户体验。

应用名称本地化

在 Xcode 项目中,可以通过以下步骤本地化应用名称:

  1. 在项目导航器中,选择项目文件,然后在 “Info” 选项卡中,找到 “Localizations” 部分。确保已经添加了需要支持的语言。
  2. 在项目目录中,找到 InfoPlist.strings 文件。如果没有,可以手动创建。
  3. 打开 InfoPlist.strings 文件,添加相应语言的应用名称本地化。例如,对于英文版本,可以添加:
CFBundleDisplayName = "My App";

对于中文版本,可以添加:

CFBundleDisplayName = "我的应用";

这样,在不同语言设置下,设备主屏幕上显示的应用名称就会相应变化。

元数据本地化

除了应用名称,应用的描述、版权信息等元数据也可以通过类似的方式进行本地化。在 InfoPlist.strings 文件中,可以添加如下内容: 英文版本:

NSHumanReadableCopyright = "Copyright © 2023 My Company. All rights reserved.";

中文版本:

NSHumanReadableCopyright = "版权所有 © 2023 我的公司。保留所有权利。";

这样,在应用的关于页面等显示版权信息的地方,就会根据用户语言设置显示相应的本地化内容。

处理复杂的本地化场景

在实际应用开发中,可能会遇到一些复杂的本地化场景,例如动态更新本地化内容、处理复数形式等。

动态更新本地化内容

有时候,应用需要在运行时动态更新本地化内容,而不需要重新启动应用。这可以通过重新加载本地化文件来实现。以下是一个简单的示例,演示如何在应用运行时切换语言:

// 切换到英文
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@[@"en"] forKey:NSPreferredLanguages];
[defaults synchronize];

// 重新加载本地化字符串
NSString *newGreeting = NSLocalizedString(@"Hello", @"A greeting message");
NSLog(@"New Greeting: %@", newGreeting);

在这个示例中,首先通过 NSUserDefaults 设置用户首选语言为英文,然后调用 synchronize 方法使设置生效。接着,重新获取本地化字符串 “Hello”,此时获取到的就是英文版本的字符串。

处理复数形式

在不同语言中,复数的表达形式可能不同。Objective-C 提供了处理复数形式的方法。例如,在英文中,“1 item” 和 “2 items” 的表达不同。可以通过以下方式在本地化文件中处理复数形式: 在 Main.strings 文件中,添加如下内容:

"item_count_format" = "%d item";
"item_count_format_plural" = "%d items";

在代码中,可以这样使用:

NSInteger itemCount = 3;
NSString *itemString = [NSString stringWithFormat:NSLocalizedStringFromTable(itemCount == 1? @"item_count_format" : @"item_count_format_plural", @"Main", nil), itemCount];
NSLog(@"Item String: %@", itemString);

在这个示例中,根据 itemCount 的值判断是单数还是复数,然后从本地化文件中获取相应的字符串,并使用 stringWithFormat: 方法格式化输出。

测试国际化与本地化

在完成国际化和本地化的开发后,需要进行全面的测试,以确保应用在不同语言和地区设置下都能正常运行。

模拟器和设备测试

可以使用 Xcode 的模拟器或实际设备来测试应用的国际化和本地化功能。在模拟器或设备的设置中,切换不同的语言和地区,然后运行应用,检查文本是否正确翻译、日期和数字格式是否符合当地习惯、图像和图标是否正确显示等。

自动化测试

对于一些关键的本地化功能,也可以编写自动化测试。例如,可以使用 XCTest 框架来测试本地化字符串是否正确加载。以下是一个简单的示例:

#import <XCTest/XCTest.h>

@interface LocalizationTests : XCTestCase

@end

@implementation LocalizationTests

- (void)testGreetingLocalization {
    NSString *greeting = NSLocalizedString(@"Hello", @"A greeting message");
    XCTAssertEqualObjects(greeting, @"你好", @"Greeting should be translated correctly in Chinese");
}

@end

在这个测试用例中,检查了 “Hello” 字符串在中文本地化环境下是否被正确翻译为 “你好”。通过编写类似的自动化测试,可以确保本地化功能的稳定性。

总结

通过以上介绍的各种方法,开发者可以在 Objective-C 应用中实现全面的国际化和本地化。从文本字符串的翻译,到日期、数字格式的本地化,再到图像、故事板和应用元数据的本地化处理,以及应对复杂场景和进行测试,每个环节都至关重要。通过良好的国际化和本地化设计,应用能够更好地服务全球用户,提升用户体验和市场竞争力。在实际开发过程中,需要根据应用的具体需求和目标用户群体,灵活运用这些技术和方法,打造出适应不同语言和文化背景的优质应用。同时,随着应用的不断更新和功能扩展,也要持续关注和维护国际化和本地化的内容,确保其始终保持准确和有效。