8

I'm trying to add an option for the user to switch between Arabic & English language from inside the app (without having to re-set the language of the whole iPhone), I managed to do it correctly by using this method in the AppDelegate.m file:

 -(void)switchTolanguage:(NSString *)lang{

    [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:lang] forKey:@"AppleLanguages"];
     NSBundle *bnd = [NSBundle bundleWithPath:[[NSBundle mainBundle]pathForResource:lang ofType:@"lproj" ]];
     UIStoryboard *storyBoard;
     storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:bnd];
     UIViewController *initViewController = [storyBoard instantiateInitialViewController];
     self.window.rootViewController = initViewController;
}

I placed two UIButtons on one of the view controllers in the app to test the method and it worked well: all UILabels, strings, etc ... in the new loaded (localized) storyboard appear with the correct selected language but with one exception: the new loaded storyboard does not take (load) its localized images, it takes the images for the old storyboard (old bundle), i.e. if the app currently runs on English bundle and the user tapped on the button that switches the language to Arabic, the app will appear with the correct Arabic controls and strings but with English images, switch back to english everything will be OK (english strings, labels and images ...)

here's how my storyboard is localized:

enter image description here

and here's how each image is localized:

enter image description here

How can I load the correct bundle images when the user switches app language ?

UPDATE:
Here's a link to a sample project for what I mean, run the sample and you will notice when you change the language from inside the app, you will notice that the image is not changeable ... and you will also notice that the localized storyboard does not load the right image in its design editor ...

P.S. do not add comments for why I use such scenario to switch language, because it is a customer requirement.

JAHelia
  • 6,934
  • 17
  • 74
  • 134

3 Answers3

2

I had same issue :(.. and what worked for me (for such scenarios to switch language) ..

You have 2 possibilities..

1) If you want to change the storyboard (hot change), you must modify all your Outlets in the each Storyboard. Choose in your storyboard the desired image (with different names), labels, etc.. For me, with localized images (same name) - only worked after restart of the application.. For the same img_name, I' tried ... to "call" the specific image.. from the specific lproj folder (languageBundle).. but it did not work at changed the storyboard from AppDelegate..

2) You can have only one storyboard... and change only labels, image, etc... (according to Localizable.strings), something linke this... https://stackoverflow.com/a/12149553/1702413 Also, you must have different file name for images (for "hot changing")

I don't know if a bug... or what is...

UPD

You have a little project https://dl.dropbox.com/u/19438780/test5%20copy2.zip with both..

If you are changing the storyboard (like you) you will have the same path for languageBundle until you restart the application. So.. you must do the changing right in your storyboard..

For the second.. you can change/recall outlets .. from specific languageBundle (lproj folders)..

For 1) .. I found a "trick" to overwrite the languageBundle until restart:

-(id) initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        NSArray* languages = [[NSUserDefaults standardUserDefaults]      objectForKey:@"AppleLanguages"];
        Lang2 = [languages objectAtIndex:0]; //NSString
    }
    return self;
}

and init the Outlets:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];

      NSString *path;
   if([Lang2 isEqualToString: @"ro"])
    {
        path = [[NSBundle mainBundle] pathForResource:@"ro" ofType:@"lproj"];
        NSLog(@"enc ro");
   }
    else{
        path = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
        NSLog(@"enc en");
    }

    NSBundle* languageBundle = [NSBundle bundleWithPath:path];
    //find and return the desired string
    self.label.text=[languageBundle localizedStringForKey:@"kLabelText" value:@"" table:nil];
    self.img.image = [UIImage imageNamed:[languageBundle localizedStringForKey:@"myImage" value:@"" table:nil]];
}
Community
  • 1
  • 1
TonyMkenu
  • 7,597
  • 3
  • 27
  • 49
  • I do not deal with UI elements from code at all, I deal with them from inside storyboard, so both solutions do not work for my request! my problem not with changing the language, my problem is with loading the correct language images inside the localized storyboard. – JAHelia Feb 07 '13 at 14:43
  • 1
    is working if you will restart the app.. ImageNamed does cache the image so I tried with imageWithData or dataWithContentsOfFile... same behavior. So.. my only solution was to localized the different_img_name for specific storyboard. If you will find another answer... please ... let me know :) anyway ... + 1 for your question – TonyMkenu Feb 07 '13 at 15:11
  • I'm trying to solve it without using IBOutlets ... because I have a project with tens of UI elements without IBOutlets so it will be a nightmare to setup and IBOutlet for each UI element just for the sake of language switching !!! – JAHelia Feb 07 '13 at 19:31
  • Make diferent image-name, let's say bg_en.png and bg_fr.png ... for each storyboard ... – TonyMkenu Feb 08 '13 at 14:50
  • I've tried such thing, but when you run the app it will not display the image because it will not be localized after you put it with a different name, localization means same image name inside each language folder. – JAHelia Feb 08 '13 at 16:25
  • localization mean also different "strings" for labels, but your labels are not :) .. So... easy way: make o "common" folder for your images (in bandle), like this https://dl.dropbox.com/u/19438780/project38%202.zip – TonyMkenu Feb 08 '13 at 16:49
  • So... my last example (above) ... Is not ok .. neither :(. You don't have other choices (if you want ... without app restart). This was my last comm. All the best! – TonyMkenu Feb 16 '13 at 05:10
1

You have to reload all the views that contains multilingual text which can't be done as if the view has referenced objects in the controller then the result is unknown and most probably it will crash.

A correct and efficient approach will be to have a dictionary for each language that you can switch based on language selected. Draw all the static text this way you can easily draw it back when the language changes. On language change post a notification to controllers to redraw the view. For images you can do similar draw them or have reference to them that you can change.

One there thing you can do for images is to have a custom image view class that also observe the language change notification and automatically loads the appropriate image. Same you can do for labels.

I can code something for you if you need an example.

SAPLogix
  • 1,744
  • 1
  • 11
  • 9
  • this will be a nightmare for my big project which contains hundreds of images that are not hoocked up with IBOutlets, so they are not accessible by code, and it's impractical to deal with each sinlge image by code. – JAHelia Feb 15 '13 at 08:27
  • @JAHelia i am suggesting you do this with notification not having reference to each of the image, but still you have to do a lot of work but at least it will be logical and you could use that later on. If it wasn't planned or known from the start of the project then you will have to, if its necessary. – SAPLogix Feb 15 '13 at 17:46
  • @JAHelia i have tested out loading different nib when the language is changed it doesn't crashes and everything is loaded perfectly but IBOutlets has issue as they will be replaced with new reference, so in short you will lose the old values if any. – SAPLogix Feb 17 '13 at 11:14
-1
NSBundle *bundle = [LocalizationSystem sharedBundle];  //this get your current bundle

NSString *imgPath = [bundle pathForResource:@"btn-Image" ofType:@"png" inDirectory:nil];
[self.btnTest setImage:[UIImage imageWithContentsOfFile:imgPath] forState:UIControlStateNormal];
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
Ning
  • 41
  • 1