Mane_87
Mane_87

Reputation: 35

switching language app with the same localized button

I'm developing an iOS app with two languages. I localized the main storyboard for each language and now I'm trying to switch between languages using the same button (toggled button text).

I found many codes for changing the app language with buttons for each one like this and Advance-Localization-in-ios-apps but I don't know how to reload the storyboard with its .strings depending on the selected language in the button. Any help please? thanks

localized Main.storyboard English strings file

Upvotes: 2

Views: 3326

Answers (1)

Ducky
Ducky

Reputation: 2754

I am afraid that you can't use Main.strings files. You will end up moving all localisable texts in the storyboard to Localizable.strings and load the them from there using a method like NSLocalizedString(key, comment).

Here is a Working sample project on GitHub. It works as in the screenshot below:

enter image description here

Complete code for the demo view controller

#import "ViewController.h"

//--------------- Modify NSBunle behavior -------------
#import <objc/runtime.h>

@interface CustomizedBundle : NSBundle
@end

@implementation CustomizedBundle
static const char kAssociatedLanguageBundle = 0;

-(NSString*)localizedStringForKey:(NSString *)key
                            value:(NSString *)value
                            table:(NSString *)tableName {

    NSBundle* bundle=objc_getAssociatedObject(self, &kAssociatedLanguageBundle);

    return bundle ? [bundle localizedStringForKey:key value:value table:tableName] :
    [super localizedStringForKey:key value:value table:tableName];
}
@end

@implementation NSBundle (Custom)
+ (void)setLanguage:(NSString*)language {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        object_setClass([NSBundle mainBundle], [CustomizedBundle class]);
    });

    objc_setAssociatedObject([NSBundle mainBundle], &kAssociatedLanguageBundle, language ?
                             [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

//--------------- Demo ---------------------------------
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIButton *button;

@property (nonatomic, assign) BOOL usingArabic;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self localizeTexts];
}

- (void)localizeTexts {
    self.label.text = NSLocalizedString(@"explanation_message", nil);
    [self.button setTitle:NSLocalizedString(@"language_switch_title", nil) forState:UIControlStateNormal];
}


- (IBAction)switchLanguageTouched:(id)sender {
    _usingArabic = !_usingArabic;
    NSString *targetLang = _usingArabic ? @"ar" : @"en";

    [NSBundle setLanguage:targetLang];

    [[NSUserDefaults standardUserDefaults] setObject:targetLang forKey:@"selectedLanguage"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [NSBundle setLanguage:targetLang];

    [self localizeTexts];
}

@end

Your Localizable files will look like this:

enter image description here

Hope this helps. Happy coding!

Edit: Without calling a method like 'localizeTexts' in the example above to 'refresh' the text value being displayed, it's impossible to reflect the currently selected language. The object is in memory so you must recreate or update its value.

Upvotes: 4

Related Questions