views:

3075

answers:

7

on iPhone NSLocalizedString returns the string in the language of the iPhone. Is it possible to force NSLocalizedString to use a specific language to have the app in a different language than the device ?

+3  A: 

You could build a sub-bundle with the set of localized strings that you want to do this with, and then use NSLocalizedStringFromTableInBundle() to load them. (I'm assuming that this is content separate from the normal UI localization you might be doing on the app.)

Sixten Otto
+10  A: 

NSLocalizedString() (and variants thereof) access the "AppleLanguages" key in NSUserDefaults to determine what the user's settings for preferred languages are. This returns an array of language codes, with the first one being the one set by the user for their phone, and the subsequent ones used as fallbacks if a resource is not available in the preferred language. (on the desktop, the user can specify multiple languages with a custom ordering in System Preferences)

You can override the global setting for your own application if you wish by using the setObject:forKey: method to set your own language list. This will take precedence over the globally set value and be returned to any code in your application that is performing localization. The code for this would look something like:

[[NSUserDefaults standardUserDefaults] setObject:[NSDictionary dictionaryWithObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"]];

This would make German the preferred language for your application, with English and French as fallbacks. You would want to call this sometime early in your application's startup. You can read more about language/locale preferences here: Internationalization Programming Topics: Getting the Current Language and Locale

Brian Webster
thanks. exactly what I needed
CodeFlakes
This does not work for me, it will use the default language no matter what.
quano
This didn't work for me, so I used,[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
Panagiotis Korros
Didn't work for me either, but [[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"]; *did*. (NB. you have to restart the App for it to take affect)- Thanks Panagiotis Korros![[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"]; to undo, and go back to the default language
William Denniss
Denniss; It seems to work better if you set the language preference *before* the app is launched. I do it in the main() function, before UIApplicationMain() is called. Once it is actually running, it won't change the used language, but just set the preference for the next time.
geon
+8  A: 

I usually do this in this way, but you MUST have all localization files in your project.

@implementation Language

static NSBundle *bundle = nil;

+(void)initialize {
 NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
 NSArray* languages = [defs objectForKey:@"AppleLanguages"];
 NSString *current = [[languages objectAtIndex:0] retain];
 [self setLanguage:current];

}

/*
  example calls:
  [Language setLanguage:@"it"];
  [Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l {
 NSLog(@"preferredLang: %@", l);
 NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
 bundle = [[NSBundle bundleWithPath:path] retain];
}

+(NSString *)get:(NSString *)key alter:(NSString *)alternate {
 return [bundle localizedStringForKey:key value:alternate table:nil];
}

@end
Mauro Delrio
Nice, works excellently. I changed the initialize method to just do bundle = [NSBundle mainBundle]; instead. That way, you don't need to have all localization files in your project.
quano
+1. This is a really nice trick that I haven't seen anywhere else. By creating a "sub bundle" from one of the localization folders, you can get the string stuff to work fine as long as you wrap NSLocalizedString with something that detours here.
quixoto
+2  A: 

As said earlier, just do: [[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];

But to avoid having to restart the app, put the line in the main method of main.m, just before UIApplicationMain(...).

Frédéric Feytons
+1 great suggestion!
Dave DeLong
A: 

it's possible to use the method of Mauro Delrio to work with nib files? just strings?

Thanks ;)

Sergio Andreotti
+1  A: 

As Brian Webster mentions, the language needs to be set "sometime early in your application's startup". I thought applicationDidFinishLaunching: of the AppDelegate should be a suitable place to do it, since it's where I do all other initialization.

But as William Denniss mentions, that seems to have an effect only after the app is restarted, which is kind of useless.

It seems to work fine if I put the code in the main function, though:

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

    // Force language to Swedish.
    [[NSUserDefaults standardUserDefaults]
     setObject:[NSArray arrayWithObject:@"sv"]
     forKey:@"AppleLanguages"];

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

I'd appreciate any comments on this.

geon
in my implementation it's a user-settable thing – so I just pop up a dialog telling them they'll need to restart :)
William Denniss
A: 

Wouldn't Mauro Delrio method affect the language of the Iphone ? Or of other games?

UnrealAZ