【问题标题】:Localize an iOS app inside application dynamically?动态本地化应用程序内的iOS应用程序?
【发布时间】:2013-02-15 09:58:34
【问题描述】:

目前,我有三个独立的 .strings 文件 - 分别用于英语、法语和德语。

我在首选项部分有一个UISegmentedControl,我想根据选择的段更改默认使用的.strings 文件。

当我测试它时,本地化已经在应用程序之外工作,我什至设法根据选择的段来本地化单个对象(如果选择了法国,下面的标签文本从“South”变为“Sud” ,如果重新选择英语,则再次返回)使用:

if(German segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"de" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

    // Returns german version of localised string as label text.
    self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

    // I would like to set the default .strings file to 'de' here.
}

else if(French segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"fr" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

   // Returns french version of localised string as label text
   self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

   // I would like to set the default .strings file to 'fr' here
}

else if(British segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

    // Returns english version of localised string as label text
    self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

    // I would like to set the default .strings file to 'en' here.
}

现在,由于我已经在单击按钮时本地化了单个字符串,我想知道是否可以一次性本地化每个 .strings 文件中的 ALL 字符串(这样我'正在更改使用的默认 .strings,具体取决于所选的段)或至少在可接受的代码量中尽可能多地定位。

显然,目前我可以一个接一个地键入它们,但由于应用程序中使用的本地化字符串的数量,这并不是一个真正的选择。

任何帮助将不胜感激。

【问题讨论】:

  • “我想知道是否可以本地化每个文件中的所有字符串”,您能澄清一下吗?您是否意味着选择语言段时,在整个应用程序中的所有字符串都会更新? span>
  • @WDUK 就是这样。应用程序中几乎所有的字符串都是 NSLocalizedStrings,并且一次性更改所有字符串,会将应用程序中几乎所有字符串的显示更改为该特定语言。
  • .. 或者...你可以使用不同的 XIB/Storyboard.. :) stackoverflow.com/a/14742213/1702413

标签: iphone ios objective-c cocoa-touch localization


【解决方案1】:

您可以将这种本地化方法包装在 LocalizationSystem 类中:

@interface PLLocalizationSystem : NSObject

@property (strong, nonatomic) NSString *language;

+ (PLLocalizationSystem *) sharedLocalizationSystem;
- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)comment;

@end

@implementation PLLocalizationSystem {
    NSBundle *_bundle;
}


- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment {
    return [_bundle localizedStringForKey:key value:comment table:nil];
}

- (void)setLanguage:(NSString *)newLanguage {
    ...
    NSString *path = [[NSBundle mainBundle] pathForResource:newLanguage ofType:@"lproj"];
    if (path) {
        _bundle = [NSBundle bundleWithPath:path];
        _language = newLanguage;
    } else {
        [self resetLocalization];
    }
    ...
    [[NSNotificationCenter defaultCenter] postNotificationName:kLocalizationChangedNotification object:nil];
}

并为更简单的访问做一些定义(在 LocalizationSystem 头文件中定义):

#define PLLocalizedString(key, comment) \
[[PLLocalizationSystem sharedLocalizationSystem] localizedStringForKey:(key) value:(comment)]

#define PLLocalizationSetLanguage(language) \
[[PLLocalizationSystem sharedLocalizationSystem] setLanguage:(language)]

#define PLLocalizationGetLanguage \
[[PLLocalizationSystem sharedLocalizationSystem] language]

您也可以从 AppName-Prefix.pch 文件中导入此文件,以便从任何地方访问。

接下来,您可以在控制器中观察本地化变化并调用适当的方法。

所以现在,你可以像使用 NSLocalizedString 一样使用它。

附:我不会在这里写所有的实现,但是如果有人想要我以后可能会在 githab 上分享它

更新。使用示例。

例如,您有 UIViewController 想要动态本地化:

@implementation MyCustomViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   //first of all - register for localization changes
   //i made for this purposes category for UIViewController(localizable)
   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(localize)
                                                name:kLocalizationChangedNotification
                                              object:nil];
}

//here you should apply all localization
- (void)localize {
    [self setTitle:PLLocalizedString(@"myTitle", nil);
    [label setText:PLLocalizedString(@"labelTitle", nil)];
    ....
}

@end

并且在您的偏好中,当您更改语言时调用 PLLocalizationSetLanguage(language), 并且为此事件注册的所有控制器都将自动本地化。当然,这种方法需要所有本地化都应用在localize方法中。

并且不要忘记在控制器释放或卸载时移除观察者

【讨论】:

  • 这与 Tjirps 链接中的示例中的代码相同 - 它使用大约多个类/文件来完成我在 3/4 行代码中已经完成的事情。它实际上并没有更新语言,因为您仍然需要单独手动输入所有本地化对象。我现在已经可以做到了..
【解决方案2】:

您可以阅读:How to force NSLocalizedString to use a specific languagehttp://aggressive-mediocrity.blogspot.nl/2010/03/custom-localization-system-for-your.html 看看您是如何做到的(第二个更适合您的需求)。

但请阅读(也来自第二个链接):

一般来说,您不应在应用程序中更改 iOS 系统语言(通过使用 AppleLanguages 首选项键)。这违背了在设置应用程序中切换语言的基本 iOS 用户模型,并且还使用了未记录的首选项键,这意味着在将来的某个时候,键名可能会更改,这会破坏您的应用程序。

如果您想在应用程序中切换语言,可以通过手动加载捆绑包中的资源文件来实现。为此,您可以使用 NSBundle:pathForResource:ofType:inDirectory:forLocalization:,但请记住,您的应用程序将负责所有本地化数据的加载。

【讨论】:

  • 我已经阅读了第二个链接,但这并不是我真正想要做的。电话设置是否设置为法语并不重要——如果用户选择英国国旗,我想用英语显示所有本地化字符串,就像我在上面的一个字符串示例中所做的那样。我只需要一种方法来一次性定位 .strings 文件中的所有字符串,而不是一个一个地做。
  • 我假设您为每种语言使用多个字符串文件,对吗?第二个链接(如果您下载源代码)定义了他们自己的 NSLocalizedString 版本,它使用 LocalizationSystem.m 方法从正确的文件中读取字符串。更改语言就像调用 LocalizationSetLanguage(@"French") 一样简单,然后使用 AMLocalizedString 再次更新所有字符串
  • 是的,3 个单独的文件,每种语言一个。我会检查一下并回复你,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多