1

Currently, I have three separate .strings files - for English, French and German respectively.

I have a UISegmentedControl in the preferences section, where I would like to change the default .strings file used depending on which segment is selected.

enter image description here

Localisation is already working outside the application when I test it, and I've even managed to localise individual objects depending on which segment is selected (If france is selected, the label text below changes from "South" to "Sud", and then back again if English is re-selected) using this:

if(German segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"de" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

    // Returns german version of localised string as label text.
    self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

    // I would like to set the default .strings file to 'de' here.
}

else if(French segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"fr" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

   // Returns french version of localised string as label text
   self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

   // I would like to set the default .strings file to 'fr' here
}

else if(British segment) {
   NSString *path= [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
   NSBundle* languageBundle = [NSBundle bundleWithPath:path];

    // Returns english version of localised string as label text
    self.defaultName.titleLabel.text = [languageBundle localizedStringForKey:@"PREF_WEATHER_NORTH" value:@"" table:nil]; 

    // I would like to set the default .strings file to 'en' here.
}

Now, as I've already got individual strings being localised on button click, I was wondering if I could localise ALL strings in each of the .strings files in one go (so that I'm changing the default .strings used depending on which segment is selected) or at least target as many as possible in an acceptable amount of code.

Obviously, at the moment I could type them one-by-one, but that isn't really an option due to the amount of localised strings used in an application.

Any help would be appreciated.

dsgriffin
  • 66,495
  • 17
  • 137
  • 137
  • "I was wondering if I could localise ALL strings in each of the files", can you clarify? Do you mean when a language segment is selected, all strings throughout the application are updated? – WDUK Feb 15 '13 at 10:13
  • @WDUK That's exactly it. Pretty much all the strings in the application are NSLocalizedStrings, and changing all of them in one go, would change the display of pretty much all the strings in the application to that particular language. – dsgriffin Feb 15 '13 at 10:23
  • .. or... you can use different XIB/Storyboard.. :) http://stackoverflow.com/a/14742213/1702413 – TonyMkenu Feb 19 '13 at 14:25

2 Answers2

2

You can wrap this localization approach in LocalizationSystem class:

@interface PLLocalizationSystem : NSObject

@property (strong, nonatomic) NSString *language;

+ (PLLocalizationSystem *) sharedLocalizationSystem;
- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)comment;

@end

@implementation PLLocalizationSystem {
    NSBundle *_bundle;
}


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

- (void)setLanguage:(NSString *)newLanguage {
    ...
    NSString *path = [[NSBundle mainBundle] pathForResource:newLanguage ofType:@"lproj"];
    if (path) {
        _bundle = [NSBundle bundleWithPath:path];
        _language = newLanguage;
    } else {
        [self resetLocalization];
    }
    ...
    [[NSNotificationCenter defaultCenter] postNotificationName:kLocalizationChangedNotification object:nil];
}

And make some defines for more simpler access (define in LocalizationSystem header file):

#define PLLocalizedString(key, comment) \
[[PLLocalizationSystem sharedLocalizationSystem] localizedStringForKey:(key) value:(comment)]

#define PLLocalizationSetLanguage(language) \
[[PLLocalizationSystem sharedLocalizationSystem] setLanguage:(language)]

#define PLLocalizationGetLanguage \
[[PLLocalizationSystem sharedLocalizationSystem] language]

Also you can import this file from your AppName-Prefix.pch file to get access from anywhere.

Next in your controllers you can observe for localization changes and call appropriate method.

So for now, you can use it in the same way as NSLocalizedString.

P.S. i'm not write here all implementation, but if somebody wants i may later share it on githab

Update. Usage sample.

For example, you have UIViewController which you want to localize dynamically:

@implementation MyCustomViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   //first of all - register for localization changes
   //i made for this purposes category for UIViewController(localizable)
   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(localize)
                                                name:kLocalizationChangedNotification
                                              object:nil];
}

//here you should apply all localization
- (void)localize {
    [self setTitle:PLLocalizedString(@"myTitle", nil);
    [label setText:PLLocalizedString(@"labelTitle", nil)];
    ....
}

@end

And in your preferences, when you change language call PLLocalizationSetLanguage(language), and all controllers registered for this event will be localized automatically. Of course, this approach needs that all localization applies in localize method.

And don't forgot to remove observer when controller dealloced or unloaded

Mikhail
  • 4,271
  • 3
  • 27
  • 39
  • This is the same code from the example in Tjirps link - it uses about multiple classes/files to do the same thing I have already done in 3/4 lines of code. It doesn't actually update the language so much as you still have to manually enter all the localisation objects individually. I can already do that now.. – dsgriffin Feb 15 '13 at 15:57
0

You can read: How to force NSLocalizedString to use a specific language and http://aggressive-mediocrity.blogspot.nl/2010/03/custom-localization-system-for-your.html to see how you could do it (the 2nd one is more suited for what you want).

But read this (also from the second link):

In general, you should not change the iOS system language (via use of the AppleLanguages pref key) from within your application. This goes against the basic iOS user model for switching languages in the Settings app, and also uses a preference key that is not documented, meaning that at some point in the future, the key name could change, which would break your application.

If you want to switch languages in your application, you can do so via manually loading resource files in your bundle. You can use NSBundle:pathForResource:ofType:inDirectory:forLocalization: for this purpose, but keep in mind that your application would be responsible for all loading of localized data.

Community
  • 1
  • 1
Tjirp
  • 2,435
  • 1
  • 25
  • 35
  • I've read the second link, but it's not really what I'm trying to do. It doesn't matter if the phone settings are set to French - if the user selects the British flag I want to display all localised strings in English, as I've done with one string example above. I just need a way to target all strings in .strings files in one go, instead of doing it one by one. – dsgriffin Feb 15 '13 at 10:19
  • I am assuming your using multiple string files for each language right? The 2nd link (if you download the source code) defines their own verison of NSLocalizedString which uses the LocalizationSystem.m methods to read the string from the correct file. Changing the language is as easy as calling LocalizationSetLanguage(@"French"), and then update all your strings again with AMLocalizedString – Tjirp Feb 15 '13 at 10:25
  • Yeah, 3 seperate files, one for each language. I'll check it out and get back to you, thanks. – dsgriffin Feb 15 '13 at 10:27