Hussain Chhatriwala
Hussain Chhatriwala

Reputation: 849

Right to left language change localization on run time. Unable to toggle the UI have to restart app again

The problem is that we want to toggle the language at run time. We have an application supporting English and arabic.

What I am doing is changing the "AppleLanguages" and then reseting the root view controller. I have used following code :

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* languages = [userDefaults objectForKey:@"AppleLanguages"];
NSString *language = nil;
if([[languages objectAtIndex:0] isEqual:@"en"]) {
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar", @"en",nil] forKey:@"AppleLanguages"];
    language = @"ar";
} else {
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"en",@"ar", nil] forKey:@"AppleLanguages"];
    language = @"en";
}
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[appDelegate.window setRootViewController:initViewController];
appDelegate.window.rootViewController = [storyBoard instantiateViewControllerWithIdentifier:@"Home"];

appDelegate.window.backgroundColor = [UIColor whiteColor ];
[appDelegate.window makeKeyAndVisible];

The native localization changes but have to restart the app to see the effect on UI.

Thanks in Advance.

Upvotes: 2

Views: 440

Answers (1)

Hussain Chhatriwala
Hussain Chhatriwala

Reputation: 849

The problem was that the language change was not reflecting on bundle. So I was unable to change the UI as well as localized text. We can use following code to change the bundle settings. The following code will toggle the language at run time. Need to subclass the NSBundle class as shown bellow:- @implementation BundleEx

- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle *bundle = objc_getAssociatedObject(self, &kBundleKey);
if (bundle) {
    return [bundle localizedStringForKey:key value:value table:tableName];
}
else {
    return [super localizedStringForKey:key value:value table:tableName];
}

}

@end

@implementation NSBundle (Language)

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

BOOL appleTextDirection = NO;
BOOL rightToLeftWritingDirection = NO;

if ([language isEqual:@"ar"]) {
    rightToLeftWritingDirection  =YES;
    appleTextDirection = NO;

    if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
        [[UIView appearance] setSemanticContentAttribute:
         UISemanticContentAttributeForceRightToLeft];
    }
}else {
    rightToLeftWritingDirection  =NO;
    appleTextDirection = YES;

    if ([[[UIView alloc] init] respondsToSelector:@selector(setSemanticContentAttribute:)]) {
        [[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
    }
}
[[NSUserDefaults standardUserDefaults] setBool:appleTextDirection forKey:@"AppleTextDirection"];
[[NSUserDefaults standardUserDefaults] setBool:rightToLeftWritingDirection forKey:@"NSForceRightToLeftWritingDirection"];
[[NSUserDefaults standardUserDefaults] synchronize];

id value = language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil;
objc_setAssociatedObject([NSBundle mainBundle], &kBundleKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

And the code used to toggle:-

-(void)toggleTheLanguageWith:(NSString *)identifier{
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray* languages = [userDefaults objectForKey:@"AppleLanguages"];
NSString *language = nil;
if ([[languages objectAtIndex:0] rangeOfString:@"en"].location != NSNotFound) {
    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"ar",@"en",nil] forKey:@"AppleLanguages"];
    language = @"ar";
}else  if ([[languages objectAtIndex:0] rangeOfString:@"ar"].location != NSNotFound) {

    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"en",@"ar", nil] forKey:@"AppleLanguages"];
    language = @"en";

}

[[NSUserDefaults standardUserDefaults]synchronize];
[NSBundle setLanguage:language];

UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
self.window.rootViewController = [mystoryboard instantiateViewControllerWithIdentifier:identifier];
[self.window makeKeyAndVisible];
    [UIView transitionWithView:self.window duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{

    } completion:^(BOOL finished) {

    }];

}

Upvotes: 2

Related Questions