开发者

iPhone App Localization - English problems?

开发者 https://www.devze.com 2023-01-08 22:26 出处:网络
I have an app that I am translating to a bunch of different languages. The problem is that the app will have a few different values in Australia than will in New Zealand, which are both English speaki

I have an app that I am translating to a bunch of different languages. The problem is that the app will have a few different values in Australia than will in New Zealand, which are both English speaking countries.

I have created an en_AU and an en_NZ language file, but they're both using the standard English file. I deleted the English language file, but it c开发者_如何学编程ontinues to happen...

Any ideas on how I can get this to work?

Thank you,

--d


iPhone localisations (or is that localizations?) do not take any notice of the Region the user sets (ie, UK, Aus, NZ). There is only one "English" language translation available by default. However, you can hack around with things to force it to use a different translation setting - I've just done this for choosing between "English" (US) and "en_GB" (British english).

In your main.m file, alter it so it looks something like below (put in your own tests for NZ or AU)

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// Set up the locale jiggery pokery
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString *locale = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
if ([language isEqualToString:@"en"] && [locale isEqualToString:@"GB"]) {
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"en_GB", @"en", nil] forKey:@"AppleLanguages"];
}

int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;

}

This pops the users language (eg "en") into the language NSString, and the users locale (eg, NZ, GB, AU) into the locale NSString. If they (in my case) match en and GB, then I set the users default language preference settings to be "en_GB", then "en".

Then, in your application delegates application:didFinishLaunchingWithOptions method you want to remove that NSUserDefaults setting you just set with the code

    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];

It's safe to remove at this point because all the bundle initialisation has been completed. Your app should now be using a Localization.strings file within the en_GB.lproj directory.

It's a bit of a horrible, hacky solution, but it works for me.


I've come up with what I think is a slightly improved version of rickerbh's accepted answer. The first thing to realize is that user defaults are organized into domains, and the @"AppleLanguages" key comes not from the app's domain, but from some domain higher up the hierarchy of domains. This means it is completely safe to remove it from user defaults:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:@"AppleLanguages"];

After calling this code, you'll notice that calling [defaults objectForKey:@"AppleLanguages"] still returns a value. So, rather than deleting @"AppleLanguages" at some point later, which could be problematic depending upon the complexity of your app, you want to do the opposite: delete @"AppleLanguages" immediately. Essentially, this resets it back to its default value and captures any changes to it the system has made, if, for instance, the user has changed her preferred language.

Here's what I do:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:@"AppleLanguages"];

NSMutableArray *appleLanguages = [[defaults objectForKey:@"AppleLanguages"] mutableCopy];
NSString *region = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
NSArray *languages = [appleLanguages filteredArrayUsingPredicateFormat:@"not (self contains '-')"];
for (NSString *language in languages) {
    NSString *languageAndRegion = [NSString stringWithFormat:@"%@-%@", language, region];
    [appleLanguages removeObject:languageAndRegion];
}
for (NSString *language in languages) {
    NSString *languageAndRegion = [NSString stringWithFormat:@"%@-%@", language, region];
    NSInteger index = [appleLanguages indexOfObject:language];
    [appleLanguages insertObject:languageAndRegion atIndex:index];
}
[defaults setObject:appleLanguages forKey:@"AppleLanguages"];

(Note that filteredArrayUsingPredicateFormat: is an extension method I wrote. It's not rocket science to figure out what it does or how it works.)

This creates localizations for every language in the list combined with the user's region. E.g., if the original list was es en en-GB and the user's region is AU, we'll get es-AU es en-AU en en-GB. Note that es-AU doesn't exist, but it makes no difference. Since the app finds no associated localizations or resources, it just ignores it.


Apple documents this missing iOS feature here.

Important: In iOS, the bundle interfaces do not take dialect or script information into account when looking for localized resources; only the language designator code is considered. Therefore if your project includes language-specific project directories with both a language and region designator, those directories are ignored. The bundle interfaces in Mac OS X do support region designators in language-specific project directories.


I had the same problems with German and think I found the "right" solution. The mistake was, that originally my base language was only "German (de)", when adding "German/Austria (de_AT)" localizations, the files were ignored. When changing the base language to "German/Germany (de_DE)" the austrian translations were not ignored.


Worth noting here that XCode is very misleading - you can go to Project (not Target), Info, Localizations, press the + button that appears under the list of languages, then scroll down to the bottom of the list of languages that appear in the popup until you get to "Other" (with right arrow next to it), this will open a nice big list which includes regional variants for languages. However, these regional variants do not work on the iPhone - you don't get anything (as documented by Apple and referenced in another answer that appears here). Evidently one of the code-based solutions listed above is necessary.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号