Sunday, 23 September 2012

How to localize (Internationalization/i18n) an iPhone application.

Localization inside the application without using iPhone language settings.

Today we will start with the internationalization of an iPhone app from within the application. This is something most of us want to do as it not only helps the user experience but also prevents us from changing the iphone's language setting every time we want a different language for the app.

So quickly lets get started. We create a project in xcode and name it as you like it.

Now, the way to go about localizing the app is to create a ".strings" file in the app which can be created from resource like this:
Create a  Localizable.strings  file from resource

By default the name of our created language resource string file is 'Localizable.strings '

What we have our app title at the moment is like this:

self.titleLabel.text = @"Welcome to CodeHunk!";
But we want to create our localization string taking values from our ".strings" file so we actually use a macro for this task which is NSLocalizedString and we use it like this:

self.titleLabel.text = NSLocalizedString(@"title", nil);
Now if you go deep into NSLocalizedString in the definition you will find that it actually issomething like this:

#define NSLocalizedString(key, comment)
    [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]

this is responsible for getting the default strings file and search for the localized string we have passed in the method NSLocalizedString. The comment parameter is nothing but just to let you(as a translator) understand the use of key in our string file. So don't worry about that you can even leave it nil. More information can be found here in the Apple's reference doc.

Now is the most important and precise part of the application according to our demand. How do we manually guide the localizedStringForKey to pick our localized string from the ."strings" file(s) we have already created?

now if you look more into it you will find that the 'Localizable.strings' file has the following architecture.

Alright, now it is time we add our second language, let's take Spanish.
we need to create a second file for Spanish. So there's a project folder created for each of our language like 'en.lproj' and 'es.lproj' and inside we have our Localizable.strings files.

Our motive is to make use of these files as and when the user desires to change the language  from within the application. 

Here comes the most interesting part.

We will create a method lets say languageSelectedStringForKey and pass a NSString parameter called 'key'
Our method is created in place of default NSLocalizedString to be able to pick a specific language bundle from within the application which is actually our prime focus!

Consider this:

Let's say we are getting our language from some LanguageManager class of say ConfigurationManager class in our application or for the time being we can simply take en or es. 
So we take the language in a

NSString *lang = [ ConfigurationManager  language];
Next, based on the language received we pick the pathForResource i.e en.lproj or es.lproj and take the value in an another

NSString *path =  [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];

and that's it, 

finally we providethe NSBundle to pick the localized string as per the lang that was provided from the user like this:

NSBundle* languageBundle = [NSBundle bundleWithPath:path];
and make use of localizedStringForKey like this:

NSString* str=[languageBundle localizedStringForKey:key value:@"" table:nil];
Simple isn't it?
 return the 'str' string for the value of the localized string.

So finally our custom method looks like this, you can now call this method where ever you need to localize a string in your app:

  @param: key(gives value of the key from Localizable.strings file)

+(NSString*)languageSelectedStringForKey:(NSString *)key{
 NSString *lang = [ ConfigurationManager   language];
 NSString *path;
 if([lang isEqualToString:@"en"])
  path = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
 else if([lang isEqualToString:@"es"])
  path = [[NSBundle mainBundle] pathForResource:@"es" ofType:@"lproj"];
 NSBundle* languageBundle = [NSBundle bundleWithPath:path];
 NSString* str=[languageBundle localizedStringForKey:key value:@"" table:nil];
 return str;

Hope you've enjoyed the post!
Follow CodeHunk for more.


Alexander Barrel said...

I use this tool for ios app localization It has helped me a lot since I discovered it, it's nice to use because it has a simple work space and useful functions such as the translation memory and the API.

Post a Comment

Twitter Delicious Facebook Digg Stumbleupon Favorites More

Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Best Web Hosting