25

我正在本地化我的 iOS 应用程序,并且在模拟器中它每次都能以我选择的语言正确运行。

在我的 iPhone 5 上进行测试时,它只会在应用程序第一次运行时正确检测到语言。每隔一次我在设备上重新编译和运行我的应用程序时,它都会检测到“en”作为语言,即使我正在选择 Español(“es”)进行测试。

我使用以下方法检测语言:

[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]

我也用过:

[[NSLocale preferredLanguages] objectAtIndex:0]

结果相同。

如果我在第一次运行后终止应用程序,然后在设备上重新启动它,它会继续正确检测语言。

但是,如果我终止应用程序,然后在初始运行后通过 Xcode 重新编译/重新启动,它将加载检测到“en”(英文)。

之后,除非我完全删除该应用程序并通过 Xcode 重新编译/重新安装/运行该应用程序,否则杀死并重新启动该应用程序会不断检测为英语。然后循环重复......随后的重建/重新启动而不首先从设备中删除应用程序会导致错误检测。

我设备上的所有其他应用程序始终以西班牙语显示。整个用户界面以西班牙语显示。

更新:我现在已经在运行 iOS 6 的 iPad(第 3 代)上进行了测试,并且遇到了相同的行为。

更新 2:

在 didFinishLaunchingWithOptions 中,我有这段代码来检测语言:(语言是 NSString*):

language = [[NSLocale preferredLanguages] objectAtIndex:0];

接下来是这个调试语句,比较我得到的值,以及检测它的稍微不同的方式,只是为了调试:

NSLog(@"Detected language: %@ / %@", language, [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);

当应用程序在西班牙语模式下正常工作时,输出显示为“检测到的语言:es / es”,然后在没有时显示为“检测到的语言:en / en”。仍然不知道为什么它有时决定加载为英语......

更新4:感谢大家的回答,我尝试了各种建议。不幸的是,我无法授予+100 赏金,因为似乎没有任何建议可以解决问题。如果有人最终找到了适合我的解决方案,届时我将再奖励他们 +50 赏金。

更新 5:我已经从 Xcode 4.5 更新到 4.5.2,并且遇到了同样的问题。

更新 6:我现在从头开始创建了一个新的测试项目,它工作得非常好!显然,我的项目布局方式或其中一个数据文件中一定有问题。我想我的下一个旅程将是从头开始重新创建项目,一个一个地复制文件数据......

更新 7(几个月后):可悲的是,在通过煞费苦心地重新创建我的项目暂时解决它(似乎)之后,我再次面临这个问题。在第一次加载时,语言会正确呈现,但在后续加载时,它会恢复为英语。

已解决请参阅下面的最终解决方案。感谢大家的帮助。我可能会发放一些赏金,因为无论如何它都会浪费掉。

4

5 回答 5

8

几个月后我终于解决了这个问题!感谢所有人的帮助(我还通过开发渠道与 Apple 开发人员进行了一些很好的交流)。

TL;DR:我不小心使用我的应用程序的 iCloud 键值存储(通过 MKiCloudSync)在设备之间同步语言首选项(以及许多其他意想不到的事情)!继续阅读...

我正在使用一个名为 MKiCloudSync 的第三方类,它有助于同步[NSUserDefaults standardUserDefaults]到我的应用程序的 iCloud 键值存储。当我开始使用它时,我的意图是让它在后台处理一些用户收藏的同步。

但是,不了解它是如何standardUserDefaults工作的,我没有意识到standardUserDefaults除了我自己的自定义应用程序设置之外,还有很多其他的东西被写入!

所以发生的事情是这样的:

  1. 首次启动应用程序。新鲜standardUserDefaults,并且根据当前设备选择,存储有序语言首选项列表的内部“AppleLanguages”键是正确的。

  2. 应用程序以指定的语言正确显示。

  3. 在后台,MKiCloudSync 将 ALL 同步standardUserDefaults到 iCloud。相反,如果您在其他地方运行此应用程序,例如使用英语设备,该设备也会将其语言设置同步到 iCloud。所以现在这个当前正在运行的应用程序实际上已经覆盖了它的语言首选项。

  4. BOOM ...下次运行应用程序时,无论您在设备上选择了什么,它都是从 iCloud 中拉出的任何内容,将用作默认语言!

我打算通过下一次应用更新来解决这个问题:

  1. 使用MKiCloudSync 的分支版本,它只允许同步列入白名单的密钥名称。

  2. 添加将进行一次性清理的代码,首先清理我的应用程序的 iCloud 密钥库,然后(基于此 SO 答案),调用此代码以重置用户默认值:

    NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];

在我到目前为止的测试中,这种解决了问题......不幸的是,用户必须重新启动应用程序才能启动语言修复。但是,我的猜测是大多数用户都没有遇到这个问题,因为他们不太可能使用具有不同默认语言的多个设备。

于 2012-12-28T19:48:16.417 回答
3

在设置->通用->国际中,有一个选项可以设置位置语言等。如果您将其设置为您尝试测试的语言,那么如果您的代码正确,它将起作用。

于 2012-12-06T08:44:58.563 回答
2

尝试使用以下代码:

本地化系统.h===

#import <Foundation/Foundation.h>

#define AMLocalizedString(key, comment) \
[[LocalizationSystem sharedLocalSystem] localizedStringForKey:(key) value:(comment)]

#define LocalizationSetLanguage(language) \
[[LocalizationSystem sharedLocalSystem] setLanguage:(language)]

#define LocalizationGetLanguage \
[[LocalizationSystem sharedLocalSystem] getLanguage]

#define LocalizationReset \
[[LocalizationSystem sharedLocalSystem] resetLocalization]

@interface LocalizationSystem : NSObject {
    NSString *language;
}


+ (LocalizationSystem *)sharedLocalSystem;

//gets the string localized
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment;

//sets the language
- (void) setLanguage:(NSString*) language;

//gets the current language
- (NSString*) getLanguage;

//resets this system.
- (void) resetLocalization;

@end

LocalizationSystem.m===

#import "LocalizationSystem.h"

@implementation LocalizationSystem

//Singleton instance
static LocalizationSystem *_sharedLocalSystem = nil;

//Current application bundle to get the languages.
static NSBundle *bundle = nil;

+ (LocalizationSystem *)sharedLocalSystem{
    @synchronized([LocalizationSystem class])
    {
        if (!_sharedLocalSystem){
            [[self alloc] init];
        }
        return _sharedLocalSystem;
    }
    // to avoid compiler warning
    return nil;
}

+(id)alloc{
    @synchronized([LocalizationSystem class])
    {
        NSAssert(_sharedLocalSystem == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedLocalSystem = [super alloc];
        return _sharedLocalSystem;
    }
    // to avoid compiler warning
    return nil;
}

- (id)init{
    if ((self = [super init])) 
    {
        //empty.
        bundle = [NSBundle mainBundle];
    }
    return self;
}

// Gets the current localized string as in NSLocalizedString.

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

// If this function is not called it will use the default OS language.
// If the language does not exists y returns the default OS language.
- (void) setLanguage:(NSString*) l{
    NSLog(@"preferredLang: %@", l);

    NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];


    if (path == nil)
        //in case the language does not exists
        [self resetLocalization];
    else
        bundle = [[NSBundle bundleWithPath:path] retain];

    [[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:l, nil] forKey:@"AppleLanguages"];
}

// Just gets the current setted up language.
// returns "es","fr",...
//
// example call:
// NSString * currentL = LocalizationGetLanguage;
- (NSString*) getLanguage{

    NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];

    NSString *preferredLang = [languages objectAtIndex:0];

    return preferredLang;
}

// Resets the localization system, so it uses the OS default language.
//
// example call:
// LocalizationReset;
- (void) resetLocalization{
    bundle = [NSBundle mainBundle];
}


@end

正如您所提到的,此代码可以完美运行。它对我有用,如果你想检查(HueShapes),该游戏现在在应用商店上线。

于 2012-12-04T10:36:44.630 回答
2

我在 iPhone 5 上测试了您的步骤,没有出现任何问题。这让我认为这里还有其他东西在起作用:很可能有一些东西干扰了您读取语言环境值的方式。

我建议您采取的帮助您调试此问题的步骤是:

  1. 发布您获取首选语言值的方法的完整代码。确保每次运行应用程序时都执行该方法。
  2. 确保您发布的代码包含您用于测试语言设置的 NSLog 指令的位置。
  3. 第一次运行后,您是否将首选语言存储在其他地方?
于 2012-11-29T21:45:04.060 回答
0

您是否偶然使用 NSUserDefaults 来保存与语言相关的内容?

查看您的模拟器应用程序目录 -> 库 -> 首选项 -><YourAppBundleName>.plist

请参阅:如何强制 NSLocalizedString 使用特定语言来描述设置语言的 NSUserDefaults 方法。

也许您只是保存您的语言,因此检测只返回保存的值。

于 2012-11-30T09:13:00.327 回答