How to Localize iOS Apps

Localization?

The practice of adjusting a product functional properties and characteristics to accommodate the language, cultural , political and legal differences of a foreign market or country.

Localization of iOS Apps?

Making your app available in different languages based on the targeted users.
Apart from the Apps that are downloaded from App Store, there are decent number of iOS Apps that exists on your device by default.

E.g. Phone, Messages, Maps, Calendar, Music, Camera, Stocks, App Store, Game Center, Contacts, Whether, Photos, Notes etc.

The above default apps which are provided by Apple already support localization.

E.g.  Settings > General > International > Language

and the select the language you prefer, you can notice all the default apps provided by Apple will reflect the changes according to user preference. This is because all the apps are facilitated with the language and cultural specific content.

These changes might reflect in apps ( downloaded from App Store) also depending on the factor whether they are localized or not.

Approaches

In general there are two ways which are predominantly used to localize the iOS Apps.
  1. Default Approach
  2. Within the App 
Default Approach









Naming convention  "Localizable.strings" is must and should for default approach. Once that is done, next step is add the supported languages.



In the above step, check all and click on finish for time being. In the later part of this post, it will be clear why we need to check this files after adding each language.






Please check mark all the language in the above step, by default only english is checked.

Now look at the magic Xcode does, for every language you added Xcode automatically creates different version of the same file i,e "Localizable.strings" on the left hand side pane of project window as shown below.


Now Let us try to understand how iOS manages to display the appropriate content from those language specific string files.



 Xcode creates a separate .lproj directories for each new language you add. if you open those directories you will see the .string files related to specific language. Apart from .string files you can manually copy-paste all the other resources like images, audio files, video files etc into the directories.

Note: You also realize that the files you checked after adding each language are existing in each of this directories....you can check language specific XIB files over there to appear in this directory.




 In the run time iOS loads all the resources from respective directories based on the users language preference. Let us see with some simple example which contains Heading Label and Desc Label and see  how it works in real time.

Create Heading and Desc Label in ViewController.m as shown below.


Code Snippet for the above Screenshot:

    UILabel *headingLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 70, 300, 30)];

    


//The below line of code is responsible for retrieving the content from appropriate language specific .string file using NSLocalizedString.


    headingLabel.text =[NSString stringWithFormat:NSLocalizedString(@"HeadingLabel", nil)];
    
    headingLabel.textColor = [UIColor blackColor];
    headingLabel.textAlignment = NSTextAlignmentCenter;
    headingLabel.backgroundColor = [UIColor clearColor];
    headingLabel.font = [UIFont fontWithName:@"Arial-BoldMT" size:16.0];
    headingLabel.hidden = NO;
    headingLabel.highlighted = YES;
    headingLabel.lineBreakMode = YES;
    headingLabel.numberOfLines = 0;
    [self.view addSubview:headingLabel];
    
    UILabel *descLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 80, 300, 200)];

//The below line of code is responsible for retrieving the content from appropriate language specific .string file using NSLocalizedString.

    descLabel.text =[NSString stringWithFormat:NSLocalizedString(@"DescLabel", nil)];
    
    descLabel.textColor = [UIColor blackColor];
    descLabel.textAlignment = NSTextAlignmentLeft;
    descLabel.backgroundColor = [UIColor clearColor];
    descLabel.font = [UIFont fontWithName:@"" size:18.0];
    descLabel.hidden = NO;
    descLabel.highlighted = YES;
    descLabel.lineBreakMode = YES;
    descLabel.numberOfLines = 0;
    [self.view addSubview:descLabel];

Now go to Localizable.strings(English) file and paste the key value pairs for the above UI Elements.


"HeadingLabel" = "LOCALIZATION(ENGLISH)";
"DescLabel"= "Localization is the process of adapting a product to meet the language, cultural and other requirements of a specific target environment or market so that users can use their own languages and conventions when using the app.";

Repeat same thing for Localizable.strings(Spanish).

"HeadingLabel"= "LOCALIZACIÓN (SPANISH)";
"DescLabel"= "La localización es del proceso de adaptar un producto para cumplir los requisitos del lenguaje, culturales y otro de un ambiente o de un mercado específico de la blanco de modo que los utilizadores puedan utilizar sus propios lenguajes y";

Repeat same thing for Localizable.strings(Greek).

"HeadingLabel"= "ΕΝΤΟΠΙΣΜΟΣ(GREEK)";
"DescLabel"= "Ο εντοπισμός είναι πολιτιστικές και άλλες απαιτήσεις της διαδικασίας ένα προϊόν για να συναντήσει τη γλώσσα, ενός συγκεκριμένης περιβάλλοντος ή μιας αγοράς στόχων έτσι ώστε τον οι χρήστες μπορούν να χρησιμοποιήσουν.";


Checkout the below screenshot for reference.


Go ahead and run your project using iPhone (or) iPad Simulator.


How do i switch to Spanish or Greek?

 Settings > General > International > Language> Spanish or Greek,  then press Done

iOS Simulator will reboot the app with new user settings and we need to relaunch the app again to view the reflected changes.

Note: Do not select the language other than what u included, it shows English by default even if you does so.


Navigate to Screen where your app is and relaunch to view the content in Spanish.


Cons of this Approach
  • Users need to leave the app to change the preferences and relaunch it again.
  • Language change will be reflected on all other apps that supports Localization.
Pros of this Approach 
  • Easy to Implement because of Xcode built-in Intelligence
  • Not much of Coding is required.
Within the App Approach

Coming..soon!

Valid architectures of iOS devices?

iOS Devices are powered by the processors based on ARM architecture, comes in different in versions developed overtime, each one added with some improvements.
























iOS developers should ensure to include the valid architectures in project build settings before building the application just to make sure that application runs on all targeted devices.

Apple dropping support for old architectures over the time, the Xcode versions which supports armv7 and armv7s no longer supports armv6. There are some others ways to support all architectures though.

Can I force an iPhone user to upgrade an application?


        In general forcing the user to update our application mandatorily might not go well from user stand point.
        In-spite of the above fact,  Sometime you do have to force an Upgrade for security or other valid reasons. Lot of gaming applications in the market does this sought of updates.
        some of the Financial Enterprise apps which are right there in the App-Store were able to force app users to mandatorily update it to latest version.



How do i do this?

Get Version info Using Itunes web service 

NSURL *url = [NSURL URLWithString:@"http://itunes.apple.com/lookup?id=<Your app ID>"];
versionRequest = [ASIFormDataRequest requestWithURL:url];
versionRequest setRequestMethod:@"GET"]; 
versionRequest setDelegate:self];
versionRequest setTimeOutSeconds:100];
[versionRequest addRequestHeader:@"Content-Type" value:@"application/json"]; 
[versionRequest startSynchronous];

Response string of our REST call 


NSString* jsonResponseString = [versionRequest responseString];
NSDictionary *loginAuthenticationResponse = [jsonResponseString objectFromJSONString];
NSArray *configData = [loginAuthenticationResponse valueForKey:@"results"];
for (id config in configData)
{
    version = [config valueForKey:@"version"];
    
}

Compare Both Versions 


NSString *version = @"1.0";
if (![version isEqualToString:[itsUserDefaults objectForKey:@"version"]]) 
{
    UIAlertView *createUserResponseAlert = [[UIAlertView alloc] initWithTitle:@"New Version!!" message: @"A new version of app is available to download" delegate:self cancelButtonTitle:nil otherButtonTitles: @”Update", nil];
    [createUserResponseAlert show]; 
    [createUserResponseAlert release];//Avoid if using Automatic reference counting
}

Redirect User

-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    NSString *iTunesLink = @"itms-apps://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftwareUpdate?id=<appid>&mt=8";
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
}

Which object is create by UIApplicationMain function at app launch time?

The app delegate object is created by UIApplicationMain function at app launch time. The app delegate object's main job is to handle state transitions within the app.

How main function of an app gets called during the app launch cycle?

During app launching, the system creates a main thread for the app and calls the app’s main function on that main thread. The Xcode project's default main function hands over control to the UIKit framework, which takes care of initializing the app before it is run.

Name the application thread from where UIKit classes should be used?

UIKit classes should be used only from an application’s main thread.  Note: The derived classes of UIResponder and the classes which manipulate application’s user interface should be used from application’s main thread.

Does iOS support multitasking?

iOS 4 and above supports multi-tasking and allows apps to remain in the background until they are launched again or until they are terminated