Go Back   iPod touch Fans forum - iPad, iPhone, and iPod users > iPhone OS / iOS Ecosystem > iPhone OS Development

What are you waiting for? Be member #461204!

Discuss the latest apps and accessories, or post your question on the forums! All visitors must register before they can post and answer questions and participate in our lively community, so register for free today!
Reply
 
Thread Tools Search this Thread
  #1  
Old 08-19-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Default Localizing your iPhone OS applications in Xcode.

Original post at: skylarcantu.com

Localization from within Xcode is a little unnatural at first. And to tell you the truth, I still don't like it is handled. But that's neither here nor there. This post will show you how to add support for localization within your own application.

Localizing


The first thing you need to do is localize your application into your native language. To do that, you must first create a Localizable.strings file. What you will do is select "New File..." from Xcode's dropdown menu. Highlight the "Other" menu and select "Strings File." Name this file "Localizable.strings."


Next, go ahead and move the Localizable.strings file into your Resources group in your project. Right click on the file and select "Get Info." When the info window pops up, select the "General" section and then the "Make file localizable" button on the bottom left of the window. You will see that "English" is added already. That means we're done with this part.




Go back into Xcode, and you will see that your Localizable.strings file now has an arrow next to it, similar to a standard folder or group. Go ahead and expand this folder, and you will see a new file named "English." As you'd expect, this is how Xcode is referring to the English translation of our Localizable.strings

Of course, this is worthless without some text to translate. Let's go quickly add some labels to our view. Open LocalizeMeViewController.m and add the following code to the -loadView method.
Objective C Code:
- (void)loadView {
    [super loadView];
   
    self.view.backgroundColor = [UIColor blueColor];
   
    CGRect labelFrame = CGRectMake(0, 0, 320, 40);
    CGPoint labelCenter = CGPointMake(320/2, 140);
   
    for (int i = 0; i < 5; i++) {
        UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
        label.tag = i + 1;
        switch (i) {
            case 0:
                label.text = @"One";
                break;
            case 1:
                label.text = @"Two";
                break;
            case 2:
                label.text = @"Three";
                break;
            case 3:
                label.text = @"Four";
                break;
            case 4:
                label.text = @"Five";
                break;
            default:
                break;
        }
       
        label.center = labelCenter;
        labelCenter.y += label.frame.size.height;
       
        [self.view addSubview:label];
        [label release];       
    }   
}


The result will look like this:

To localize these five strings, we're going to have to make use of the NSLocalizedString() macro. NSLocalizedString takes two parameters. The first one is a key that will be used to look up the string in your Localizable.strings file. The second parameter is a comment, to help you remember. I choose to use the English translation as the comment, that way I know exactly what the string is supposed to say in my native language. Both parameters should be NSStrings. The macro should look like this when completed:
NSLocalizedString(@"Key", @"Comment");

So, let's update our -loadView method. I'm going to go ahead and make my keys all in capital letters. That way, if we miss any keys, or err in our Localizable.strings file, we will know instantly. Update your -loadView method with the following code.
Objective C Code:
- (void)loadView {
    [super loadView];
   
    self.view.backgroundColor = [UIColor blueColor];
   
    CGRect labelFrame = CGRectMake(0, 0, 320, 40);
    CGPoint labelCenter = CGPointMake(320/2, 140);
   
    for (int i = 0; i < 5; i++) {
        UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
        label.tag = i + 1;
        switch (i) {
            case 0:
                label.text = NSLocalizedString(@"ONE", @"One");
                break;
            case 1:
                label.text = NSLocalizedString(@"TWO", @"Two");
                break;
            case 2:
                label.text = NSLocalizedString(@"THREE", @"Three");
                break;
            case 3:
                label.text = NSLocalizedString(@"FOUR", @"Four");
                break;
            case 4:
                label.text = NSLocalizedString(@"FIVE", @"Five");
                break;
            default:
                break;
        }
       
        label.center = labelCenter;
        labelCenter.y += label.frame.size.height;
       
        [self.view addSubview:label];
        [label release];       
    }   
}


Don't compile yet, we still have to set up our .strings file. Go back and open the English Localizable.strings. This should be an empty file now. To fill this out, we need to add an entry for each of the keys that we defined in our code. You will also want to put one key on each line. Start by placing the key in quotation marks. Do not use the @ sign in front of your quotation marks. Follow your key with an equals sign. Then, you will write your translation, also in quotes. Once again, omit the @ sign. End the line with a semicolon. Your key entry will look like this:
"Key" = "This is the translation!";

Follow this pattern to add the keys from our application. Your entries should look like this:
Objective C Code:
"ONE"   =  "One";
"TWO"   =  "Two";
"THREE" =    "Three";
"FOUR"  = "Four";
"FIVE"  = "Five";


Once you have this, save the file and compile. Your application should look exactly the same as it did before.



Adding support for other languages will be easy, now that you have all the hard work done. Just like before, right click on Localizable.strings, select "Get Info" and finally "Add localization." On the iPhone, you may notice that your dropdown box with languages comatains fewer languages than the iPhone supports. That's okay. To enter support for another language, just enter its two letter country code. Ex, nl for the Netherlands. We're going to have to do that right now for Spanish. Enter the letters "es" and click "Add."

You'll notice that under Localizable.strings in your Xcode project, you have a new file called es. Opening it reveals that it is identical to your English.lproj. This is to easily translate the new keys without having to reenter all the keys again. Let's go ahead and add the Spanish translations now.
Objective C Code:
"ONE"   =  "Uno";
"TWO"   =  "Dos";
"THREE" =    "Tres";
"FOUR"  = "Cuatro";
"FIVE"  = "Cinco";

Save this file and compile. On the iPhone Simulator, change the language to Spanish and reopen your application. It should now have the Spanish translation.


Localizing a .xib

Setting up localization for any other resource works exactly the same as on Localizable.strings. Right click the resource, click "Make Localizable," and add the localizations you require. Just like before, Xcode will generate a new file for each language your resource needs to be in. In this case, that means we will wind up with several .xib files. It also means that our .xib files will be moved from the main directory in our app bundle to the appropriate .lproj directory within the application. Don't worry, Xcode does all this automatically.

For the reason that localizations on xibs create several xibs, I recommend localizing them last. Once everything is set up exactly how you want it. Otherwise, you will need to reopen each xib and modify it, creating the possibility of error. So, we won't localize the xib yet.

The first thing we must do is comment out the labels that we already added from the -loadView method. Next, open your LocalizeMeViewController.xib and recreate the labels. Once finished, compile. The finished product should look like it did when compiling via code.


Now that we have that all set and working, we are going to go back into Xcode and create a localized xib. Again, right click on LocalizeMeViewController.xib and select "Get Info." Click its "Make Localizable" button, and enter "es" for the localization. Open the newly created "es" file that appears when you expand "LocalizeMeViewController.xib" in Xcode and translate all the labels. Compile once more and switch the Simulator's language. Reopen your application, and it should be translated.


Quote:
Tip: Make sure to "Clean All" in Xcode before you build. Else when compiling, the original non localized nib will also be included in the application bundle and the Spanish nib will never load.
Quote:
Tip: If you don’t want to distribute your xib files to your localizers (whether they might not have Interface Builder, or whether you simply want to keep your application secrets), the include the xibs strings in your Localizable strings that you distribute. When you get the translated copies back, take those translated strings and insert them into your xibs yourself.
__________________

Last edited by SkylarEC; 08-19-2009 at 11:06 PM..
  #2  
Old 08-19-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Localizing a Settings bundle

Localizing a Settings.bundle is more involved than it should be. To see how to do this, we must first create a Settings bundle. Go ahead and do so now. From the Xcode "File" menu, select "New File." In the "Resource" menu in the "iPhone OS" section, select "Settigns bundle." Leave this named "Settings.bundle."

Expand the Settings bundle and you'll see Root.plist and an en.lproj directory. Let's take everything our of the Root.plist except for the "group" and the "switch." Now, expand the en.lproj and open Root.strings. Leave only the "Group" and "Enabled" keys. Compile, and open Settings in the Simulator. Perfect : )

Uh-oh! Right clicking on either the Settings.bundle or the Root.plist in Xcode and clicking on "Get Info" shows us that the option to make either localizable is disabled. I don't know why this is, but it can be worked around. We will have to add the localizations manually.

What you will need to do is open Finder and navigate to where you have your project saved. Right click on the Settings.bundle and select "Show package contents." Copy the en.lproj and rename the copy es.lproj.



Go back into Xcode and close and re-expand your Settings bundle. You should now see the es.lproj. Translate the Root.strings, recompile, and enojoy!



Calling Different Resources

All this is well and good so far. But, what about if you need to call a different image based on the localization? If you are designing your interface in a xib, just substitute images there. If you are using code, you will need to do a little bit of work.

Let's go back and edit the LocalizeMeViewController's -loadView method. Knowing that the current language will always be at the beginning of the list of the user's prefered languages, we can figure out very easily which language is selected. Use NSLocale's preferredLanguages array to get the string contained in the first position. This is the two letter ISO 6901 Language Code Simply check that against the values that you will be localizing for and load the correct image.
Objective C Code:
UIImageView *languageImage;
   
    if ([[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:@"en"]) {
        languageImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"English.png"]];
    } else if ([[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:@"es"]) {
        languageImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Espanol.png"]];
    } else {
        languageImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"English.png"]];
    }

    languageImage.center = CGPointMake(320/2, 480 - 20 - (languageImage.bounds.size.height / 2));
   
    [self.view addSubview:languageImage];
    [languageImage release];




Quote:
Tip: Don't forget to include a default image in case the user has their phone set to a language that you haven't localized support for.
Quote:
Tip: If you are doing a lot of work based on the localization, you might want to save some effort by enumerating the languages that you support and set a variable accordingly. That way, you can simply refer to the language you are using without having to recheck the language each time.
Original post at: skylarcantu.com
  #3  
Old 08-19-2009
Pelaez-1's Avatar
Multi-Touch Lover
Join Date: May 2008
 
iPhone 3G (Black) 8GB
3.1.2 jailbroken
Thanks, quite useful.

Just to point a couple of things I noted.

Objective C Code:
NSLocalizedString(@"Key", "Comment"); //Missing '@' on "Comment" string
 

and then use like this:
Objective C Code:
case 0:
                label.text = NSLocalizedString(@"ONE", "One"); //Missed '@' too
                break;

They are supposed to be NSStrings, so I assume the @ is missing
Sponsored Links
  #4  
Old 08-19-2009
Steaps's Avatar
Multi-Touch Maniac
Join Date: Oct 2007
 
iPod touch 16GB
3.0 jailbroken
Could be completely wrong with this (Minds a little out of it), but wouldn't label be undeclared outside the for loop?
Objective C Code:
- (void)loadView {
    [super loadView];
   
    self.view.backgroundColor = [UIColor blueColor];
   
    CGRect labelFrame = CGRectMake(0, 0, 320, 40);
    CGPoint labelCenter = CGPointMake(320/2, 140);
   
    for (int i = 0; i < 5; i++) {
        UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
        label.tag = i + 1;
        switch (i) {
            case 0:
                label.text = NSLocalizedString(@"ONE", "One");
                break;
            case 1:
                label.text = NSLocalizedString(@"TWO", @"Two");
                break;
            case 2:
                label.text = NSLocalizedString(@"THREE", @"Three");
                break;
            case 3:
                label.text = NSLocalizedString(@"FOUR", @"Four");
                break;
            case 4:
                label.text = NSLocalizedString(@"FIVE", @"Five");
                break;
            default:
                break;
        }
       
        label.center = labelCenter;
        labelCenter.y += label.frame.size.height;
       
        [self.view addSubview:label];
        [label release];       
    }
  #5  
Old 08-19-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Quote:
Originally Posted by Pelaez-1 View Post
Thanks, quite useful.

Just to point a couple of things I noted.

Objective C Code:
NSLocalizedString(@"Key", "Comment"); //Missing '@' on "Comment" string
 

and then use like this:
Objective C Code:
case 0:
                label.text = NSLocalizedString(@"ONE", "One"); //Missed '@' too
                break;

They are supposed to be NSStrings, so I assume the @ is missing

Good catch! I will fix this now.

Quote:
Originally Posted by Steaps View Post
Could be completely wrong with this (Minds a little out of it), but wouldn't label be undeclared outside the for loop?
Objective C Code:
[[CODEZ alloc] init];
It doesnt' matter, as we are not referencing the UILabels outside of the loop. If we need to, then we can refer to the tags that we have set on the labels.




PS, I undeleted your post because it is a valid question.

Last edited by SkylarEC; 08-19-2009 at 09:25 PM.. Reason: Postscript.
  #6  
Old 08-19-2009
Steaps's Avatar
Multi-Touch Maniac
Join Date: Oct 2007
 
iPod touch 16GB
3.0 jailbroken
Quote:
Originally Posted by SkylarEC View Post
Good catch! I will fix this now.



It doesnt' matter, as we are not referencing the UILabels outside of the loop. If we need to, then we can refer to the tags that we have set on the labels.




PS, I undeleted your post because it is a valid question.
Yeah no worries, I tested it and felt like an idiot .
  #7  
Old 08-19-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Quote:
Originally Posted by Steaps View Post
Yeah no worries, I tested it and felt like an idiot .
If you click the link to the original posting, you can doanload a copy of the Xcode project.
  #8  
Old 08-19-2009
Steaps's Avatar
Multi-Touch Maniac
Join Date: Oct 2007
 
iPod touch 16GB
3.0 jailbroken
Quote:
Originally Posted by SkylarEC View Post
If you click the link to the original posting, you can doanload a copy of the Xcode project.
Favourited. Will they're be tutorials on there that aren't on here?
  #9  
Old 08-19-2009
SkylarEC's Avatar
Super Moderator Emeritus
Join Date: Sep 2007
 
None
Quote:
Originally Posted by Steaps View Post
Favourited. Will they're be tutorials on there that aren't on here?
Possibly. They are a lot of work to write up, then convert over. It's easier to take the WP format and make it fit this forum's format, as opposed to the otherway around. My last tutorual and this one were written in Wordpress first, and I think it shows with a better quality of post.

It just depends on whether or not I have time to do both versions in one sitting; and if in case I don't, whether I forget to come back later.
Reply

Tags
tutorial

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



All times are GMT -7. The time now is 08:19 PM.

Recent blog posts Recent threads




Powered by vBulletin®
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 2007 - 2010 Vigorous Media LLC - All Rights Reserved.
Page generated in 0.16042 seconds with 8 queries