iphoneioslocalizationinternationalizationios5

iOS: How to do I18N/Localization in-app?


How can I do I18N within my app leaving the language setting of the device out?

I want to have a screen after the splash screen asking the user for the language he want to use the app in. This should be independent from the system language.

Is there an easy way to just set the language setting in the apps context? Something like:

[[UIApplication sharedApplication] setLocale/setBundle/setLanguage]

Thanks for any advice.

EDIT

Ok, I made some progress. Is there a way to override NSLocalizedString()? The problem is that setting the NSUserDefaults to another language code will only be recognized after restarting the app. That is of course no option for me.


Solution

  • I ended up with this solution. I first define a static class to set my In-App language on:

    @implementation I18NUtil
    
    static NSBundle *_bundle;
    static NSString *_language;
    
    + (id)alloc 
    {
        [NSException raise:@"Cannot be instantiated!" format:@"Static class 'ClassName' cannot be instantiated!"];
        return nil;
    }
    
    + (void)setLanguage:(NSString *)languageCode 
    {
        [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:languageCode, nil] forKey:@"AppleLanguages"];
    
        NSString *path = [[NSBundle mainBundle] pathForResource:languageCode ofType:@"lproj"];
        _bundle = [NSBundle bundleWithPath:path];
        _language = languageCode;
    }
    
    + (NSString *)localizedString:(NSString *)key
    {
       return [_bundle localizedStringForKey:key value:@"" table:nil];
    }
    
    @end
    

    You could easily use:

    [I18NUtil localizedString:@"myLocalizedString"]
    

    in your whole project now.

    But I found it a lot easier to override the NSLocalizedString macro and use the i18n like I am used to it. You have to include this into your AppName-Prefix.pch:

    #ifdef __OBJC__
        ...
    
        // Override native NSLocalizedString(key,message) to achieve in-app and on-the-fly i18n
        // Needs to be defined AFTER importing Foundation.h
        #import "I18NUtil.h"
    
        #ifdef NSLocalizedString
            #undef NSLocalizedString
        #endif
    
        #define NSLocalizedString(key, message) \
            [I18NUtil localizedString:(key)]
    #endif
    

    Have fun!