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

Objective-C 在 iOS 应用国际化与本地化中的应用

2023-04-213.2k 阅读

一、iOS 应用国际化与本地化基础概念

(一)国际化(Internationalization)

国际化指的是设计和开发应用程序,使其能够适应不同语言、地区和文化的过程。在 iOS 开发中,这意味着应用的代码结构和资源文件需要以一种通用的方式编写,以便可以轻松地为不同地区的用户提供相应的内容。例如,应用的文本、日期格式、货币符号等元素不应硬编码为特定地区的形式,而是应该根据用户设备的设置动态加载。

(二)本地化(Localization)

本地化是国际化的具体实现,它针对特定的语言和地区对应用进行定制。这包括翻译应用中的文本字符串,调整日期、时间、数字和货币格式,以及提供适合特定地区文化的图像、音频和视频等资源。在 iOS 中,本地化主要通过创建特定语言和地区的资源文件(如 .strings 文件用于文本,.lproj 文件夹用于图像等)来实现。

二、Objective-C 中的本地化字符串

(一)创建本地化字符串文件

  1. 新建工程时自动生成 当创建一个新的 iOS 工程时,Xcode 会自动生成一个基础的本地化字符串文件。在工程导航栏中,展开 Supporting Files 文件夹,可以看到 Localizable.strings 文件。这个文件默认是英文的,并且位于 Base 本地化中。Base 本地化是一个特殊的本地化,它包含了应用中所有语言通用的字符串。
  2. 手动添加语言支持 要为应用添加其他语言的支持,打开工程设置,选择 Info 标签,在 Localizations 部分点击 + 按钮,然后选择需要支持的语言,如中文、法语、德语等。添加语言后,Xcode 会为每种语言生成对应的 Localizable.strings 文件。

(二)使用 NSLocalizedString

在 Objective-C 代码中,使用 NSLocalizedString 宏来获取本地化字符串。该宏有两个参数,第一个参数是要查找的键(key),第二个参数是一个注释,用于帮助翻译人员理解该字符串的上下文。例如:

NSString *title = NSLocalizedString(@"app_title", @"The title of the application");
self.navigationItem.title = title;

在上述代码中,app_title 是键,@"The title of the application" 是注释。当应用运行时,系统会根据用户设备的语言设置,在相应语言的 Localizable.strings 文件中查找 app_title 对应的翻译字符串,并将其赋值给 title 变量。

(三)本地化字符串文件的格式

本地化字符串文件(.strings 文件)是一种简单的文本文件,每行包含一个键值对,格式为 key = "value";。例如,在英文的 Localizable.strings 文件中可能有:

app_title = "My Application";

而在中文的 Localizable.strings 文件中可能有:

app_title = "我的应用";

(四)复数形式的本地化

在某些语言中,名词的复数形式会根据数量的不同而变化。Objective-C 通过 NSLocalizedStringFromTableFormat 宏来处理复数形式的本地化。例如,假设有一个表示消息数量的字符串,在英文中可能有以下情况:

NSInteger messageCount = 5;
NSString *messageString = NSLocalizedStringFromTableFormat(@"Messages", nil, nil, messageCount, messageCount == 1? @"1 message" : @"%ld messages", @"Number of messages");

Localizable.strings 文件中,对于复数形式的本地化字符串,格式如下:

"Messages" = "%#@message_plural@";
"message_plural" = {
    "one" = "1 message";
    "other" = "%ld messages";
};

这样,当 messageCount 为 1 时,messageString 会显示 1 message,当 messageCount 大于 1 时,会显示 %ld messages 格式的字符串,其中 %ld 会被实际的消息数量替换。

三、本地化图像与其他资源

(一)图像本地化

  1. 创建图像资源文件夹 在工程导航栏中,右键点击项目,选择 New Group。然后将新创建的组命名为与语言相关的名称,如 en.lproj(英文)、zh-Hans.lproj(简体中文)等。
  2. 添加图像资源 将不同语言或地区特定的图像文件拖放到相应的 .lproj 文件夹中。图像文件名应保持一致,这样在代码中加载图像时,系统会根据用户设备的语言设置自动加载正确的图像。
  3. 在代码中加载本地化图像 在 Objective-C 代码中,使用 UIImageimageNamed: 方法加载图像时,系统会自动查找与当前语言设置对应的图像。例如:
UIImage *image = [UIImage imageNamed:@"icon"];
self.imageView.image = image;

如果用户设备设置为英文,系统会在 en.lproj 文件夹中查找 icon.png(或其他支持的图像格式);如果设置为简体中文,则会在 zh-Hans.lproj 文件夹中查找。

(二)其他资源本地化

除了图像,其他资源如音频、视频、文本文件等也可以进行本地化。方法与图像本地化类似,将特定语言或地区的资源文件放在对应的 .lproj 文件夹中。例如,如果应用中有一个帮助文档,可以将英文的帮助文档放在 en.lproj 文件夹中,中文的放在 zh-Hans.lproj 文件夹中。在代码中加载这些资源时,系统会根据语言设置自动选择正确的文件。

四、日期、时间、数字和货币格式的本地化

(一)日期和时间格式

  1. 使用 NSDateFormatter NSDateFormatter 类用于将 NSDate 对象格式化为字符串,并且可以根据用户设备的语言和地区设置自动调整日期和时间格式。例如:
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
NSString *formattedDate = [dateFormatter stringFromDate:now];

上述代码中,NSDateFormatterMediumStyleNSDateFormatterShortStyle 是预定义的样式,会根据用户设备的设置显示合适的日期和时间格式。如果用户设备设置为美国英语,日期可能显示为 Mar 15, 2024, 3:00 PM;如果设置为中文,可能显示为 2024年3月15日 下午3:00。 2. 自定义日期和时间格式 除了使用预定义样式,还可以自定义日期和时间格式。例如:

NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *formattedDate = [dateFormatter stringFromDate:now];

在上述代码中,@"yyyy-MM-dd HH:mm:ss" 是自定义的日期和时间格式字符串,yyyy 表示四位数的年份,MM 表示两位数的月份,dd 表示两位数的日期,HH 表示 24 小时制的小时,mm 表示分钟,ss 表示秒。这种自定义格式在不同语言和地区设置下不会自动调整格式,但可以满足特定的显示需求。

(二)数字格式

  1. 使用 NSNumberFormatter NSNumberFormatter 类用于格式化数字,使其符合用户设备的语言和地区设置。例如:
NSNumber *number = @12345.67;
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSString *formattedNumber = [numberFormatter stringFromNumber:number];

在上述代码中,NSNumberFormatterDecimalStyle 会根据用户设备的设置显示合适的数字格式。在美国英语中,数字可能显示为 12,345.67;在法语中,可能显示为 12 345,67。 2. 货币格式 要格式化货币,使用 NSNumberFormatter 的货币样式。例如:

NSNumber *amount = @123.45;
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *formattedCurrency = [currencyFormatter stringFromNumber:amount];

根据用户设备的语言和地区设置,货币格式会自动调整。例如,在美国英语中可能显示为 $123.45,在欧元区可能显示为 €123,45

五、本地化应用界面

(一)XIB 和 Storyboard 的本地化

  1. XIB 文件本地化 如果应用使用 XIB 文件来设计界面,打开 XIB 文件,在 File Inspector 中选择 Localization 部分,勾选需要支持的语言。Xcode 会为每种语言生成对应的 XIB 文件,位于相应的 .lproj 文件夹中。在 XIB 文件中,可以使用 NSLocalizedString 宏来本地化文本标签、按钮标题等元素。例如,对于一个按钮,可以在 Attributes Inspector 中,将 Title 属性设置为 NSLocalizedString(@"button_title", @"The title of the button")
  2. Storyboard 文件本地化 Storyboard 文件的本地化方法与 XIB 文件类似。打开 Storyboard 文件,在 File Inspector 中选择 Localization 部分,勾选需要支持的语言。然后在 Storyboard 中,同样可以使用 NSLocalizedString 宏来本地化界面元素的文本。此外,还可以通过创建不同语言版本的约束来调整界面布局,以适应不同语言文本长度的差异。例如,对于一个包含长文本标签的界面,在中文版本中可能需要调整标签的高度或宽度,以完整显示文本。

(二)动态更新界面语言

  1. 监听语言变化通知 在应用中,可以监听系统语言变化的通知,以便在用户切换语言后动态更新界面。使用 NSNotificationCenter 来注册语言变化通知,例如:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLocalization) name:NSCurrentLocaleDidChangeNotification object:nil];

updateLocalization 方法中,可以重新加载本地化字符串、图像等资源,以更新界面。例如:

- (void)updateLocalization {
    // 重新加载本地化字符串
    NSString *title = NSLocalizedString(@"app_title", @"The title of the application");
    self.navigationItem.title = title;
    
    // 重新加载本地化图像
    UIImage *image = [UIImage imageNamed:@"icon"];
    self.imageView.image = image;
}
  1. 手动切换语言 有些应用可能提供手动切换语言的功能。可以通过修改应用的 NSUserDefaults 中的语言设置,并重新加载界面来实现。例如:
- (IBAction)switchLanguage:(UIButton *)sender {
    // 假设切换到英文
    [[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:NSPreferredLanguages];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    // 重新加载界面
    [self updateLocalization];
}

六、国际化与本地化中的常见问题及解决方法

(一)翻译准确性问题

  1. 提供详细注释 在使用 NSLocalizedString 宏时,为翻译人员提供详细的注释非常重要。注释应清晰地描述字符串的上下文,例如它在应用中的位置、用途等。这样可以帮助翻译人员准确地翻译字符串。例如:
NSString *buttonTitle = NSLocalizedString(@"login_button", @"The title of the login button on the login screen");
  1. 多轮翻译和审核 对于重要的应用,建议进行多轮翻译和审核。可以先由专业翻译人员进行翻译,然后由目标语言的母语人士进行审核,确保翻译的准确性和自然度。

(二)布局适配问题

  1. 灵活的布局设计 在设计应用界面时,应采用灵活的布局方式,如使用 Auto Layout 或 Stack View。这样可以确保界面在不同语言文本长度不同的情况下,仍然能够正确显示。例如,对于一个包含文本标签和按钮的界面,使用 Auto Layout 可以设置标签和按钮之间的间距,以及标签的最大宽度等,以适应不同长度的文本。
  2. 测试不同语言布局 在应用开发过程中,要对所有支持的语言进行布局测试。在模拟器或真机上切换不同语言,检查界面是否显示正常,是否有文本截断、元素重叠等问题。如果发现问题,及时调整布局约束或界面设计。

(三)资源管理问题

  1. 清晰的文件结构 保持清晰的资源文件结构对于国际化和本地化非常重要。将不同语言和地区的资源文件放在相应的 .lproj 文件夹中,并确保文件命名规范统一。例如,图像文件都使用小写字母和下划线命名,避免使用特殊字符。
  2. 版本控制 使用版本控制系统(如 Git)来管理资源文件的变化。这样可以方便地跟踪翻译更新、资源添加或修改等操作,并且在多人协作开发时,能够避免文件冲突。

(四)特定地区差异问题

  1. 了解地区文化差异 不同地区除了语言不同,可能还有文化、习俗等方面的差异。例如,颜色在不同文化中有不同的含义,某些图像或图标在特定地区可能有负面意义。在本地化应用时,要充分了解目标地区的文化差异,避免使用可能引起误解或不适的元素。
  2. 提供地区特定功能 有些应用可能需要提供地区特定的功能。例如,电商应用可能需要根据不同地区显示不同的支付方式。可以通过检测用户设备的地区设置,在代码中动态加载相应的功能模块。例如:
NSLocale *currentLocale = [NSLocale currentLocale];
NSString *countryCode = [currentLocale objectForKey:NSLocaleCountryCode];
if ([countryCode isEqualToString:@"CN"]) {
    // 显示支付宝、微信支付等中国地区的支付方式
} else if ([countryCode isEqualToString:@"US"]) {
    // 显示信用卡、PayPal 等美国地区的支付方式
}

通过以上在 Objective - C 中对 iOS 应用进行国际化与本地化的详细介绍,开发者可以使应用更好地适应全球不同地区用户的需求,提升用户体验,扩大应用的市场覆盖范围。在实际开发过程中,需要综合考虑各种因素,遵循最佳实践,确保国际化和本地化的质量和效果。