Reputation: 5542
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.
Upvotes: 1
Views: 3579
Reputation: 437
Using the latest Xcode15, you can use String Catalogs to add and manage localized key-value pairs, use NSLocalizedString to call, or use SwiftGen to automatically generate code. If you need to translate into multiple languages, you can use I18n Studio
Upvotes: 0
Reputation: 5542
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!
Upvotes: 3
Reputation: 19641
You can use an arbitrary strings file with NSLocalizedStringFromTable
.
For instance, you can have all your strings file organized like this:
localizable_buttons_english.strings
localizable_buttons_spanish.strings
...
localizable_errors_english.strings
localizable_errors_spanish.strings
...
Then, using user's chosen language in your app preferences to obtain the translation in any language:
NSString *lang = <# read user prefs #> // Example: spanish
NSString *table = [NSString stringWithFormat:@"localizable_buttons_%@", lang];
NSString *text = NSLocalizedStringFromTable(@"SendButtonLabel", table, nil);
sendButton.titleLabel.text = text;
// localizable_buttons_english.strings
"SendButtonLabel" = "Send";
// localizable_buttons_spanish.strings
"SendButtonLabel" = "Enviar";
Localizing NIB files is just a matter of loading the NIBs programmatically using the user chosen language to build the NIB name.
Upvotes: 1