jueves, 15 de mayo de 2014

iOS Localization of Strings in C++

Hi all!

I've been playing around with localization lately and I want to share what I learned.

First of all, I've tried to be very specific in the title. This post is about externalizing strings to external files instead of hard-coding them. This means that I won't deal here with images and other types of files localization. Neither will I discuss here internationalization, which is a broader topic.

Picture from Freemake.com (http://www.freemake.com/blog/interview-with-founder-of-crowdin-net/)

Let's suppose that we're creating a super fantastic game and we want, at the beginning, to show a welcome message to the players: "Welcome!"

In a non-localized app, you'd do something as simple as the following (in C++):

std::cout << "Welcome!; (Note: we'd actually embed this string in a label or other high-level structure that presents the information on the device screen rather than on the IDE console).

Our goal is that the message is shown in the language that players have configured in their devices. How do we achieve this? The overall idea is the following: we create a special kind of file (with .strings extension) and we localize it, meaning that Xcode will take care of creating different directories for each language. Then, in our code, instead of hard-coding strings like in the previous example, we make references to these strings in the .strings file. Finally, when the app is launched in the device, the app will be able to pick the correct language depending on the device settings.

The process can be divided in two steps, the first one focused on configuration and the second one on programming.

1. Configuring the environment

In Xcode (note that I'm using Xcode 5.1), choose: 

1) File -> New -> File...
2) In the iOS section, choose Resource and Strings File
3) Name the new file as Localizable.strings (this is a default name; you can change it, but then each time you want to access the file, you have to provide the name).
4) Save the file in some of your app directories.
5) Select the file and in File Inspector, click in Localize. Choose the languages that you want to support. You can add new languages at any time.
6) Even if you haven't seen it, Xcode has created as many folders as the number of languages. These folders follow the same name convention: en.lproj (for English localized strings), es.lproj (for Spanish localized strings), etc. Each language has a unique code. You can check all the codes here.
7) I advise you to drag these folders to Xcode, uncheck the option "Copy items into destination group's folder (if needed)" and to check "Create folder references for any added folders". This way, your file system is synchronized with what you see in Xcode and any changes are reflected in one another.

Now, you can fill out these files according to the following format:
"key" = "value"; 

Following the welcome example, in the Localizable.strings under the en.lproj folder, we would write:
"WelcomeMessage" = "Welcome!";

Whereas in the Localizable.strings under the es.lproj folder, we would write:
"WelcomeMessage" = "¡Bienvenido!";

And so on with the rest of languages that we want to support. Don't forget the ";" at the end.

2. Programming

Now we're ready to make the appropriate changes to the code. In Objective-C, this is pretty straightforward as the Cocoa framework offers localization methods. In particular, we're interested in the following one:

NSLocalizedString("key", nil)

This method returns a NSString* with the value associated to the NSString passed as first argument. Therefore, if we called the method as NSLocalizedString("WelcomeMessage", nil), it would return "Welcome!" in English-configured devices, and "¡Bienvenido!" in Spanish ones. 

The problem is that given that we're assuming that we're using C++, we cannot directly access this method. For example, in my case I'm working with Cocos2d-x, which is a C++ framework. What can we do to access this Cocoa functionality from C++? 

Well, given that Objective-C and C++ have common roots, it's not difficult to pave a bridge between them. Therefore, I created a C++ wrapper over the aforementioned Objective-C method. The code of the header and implementation files are listed next:


#ifndef __Limball__LocalizationManager__
#define __Limball__LocalizationManager__

#include <iostream>
#include <string>
class LocalizationManager
    static LocalizationManager* getInstance();
    std::string getLocalizedString(const std::string& key);
    static LocalizationManager* lm;



#include "LocalizationManager.h"

LocalizationManager* LocalizationManager::lm = nullptr;
LocalizationManager* LocalizationManager::getInstance()
   if (!lm)
       lm = new LocalizationManager();
    return lm;

LocalizationManager ::~LocalizationManager()
    if (lm)
        delete lm;

std::string LocalizationManager::getLocalizedString(const std::string& key)
    NSString *str = [NSString stringWithUTF8String: key.c_str()];
    std::string s([NSLocalizedString(str, nil) UTF8String]);
    return s;

What I do in the getLocalizedString method is basically transforming from NSString to std::string (using an intermediate C-style string), and viceversa. Note that the implementation file has no .cpp extension, but .mm extension. This is important as this file must be able to understand both C++ and Objective-C. You must change the type of this file to Objective-C++ Source in the File Inspector.

Now, in any class that needs to print a message, I only need to include the LocalizationManager.h, and I can use it as follows:

std::cout << LocalizationManager::getInstance() -> getLocalizedString("WelcomeMessage");

And that's all! Hope you find it useful.

17 comentarios:

  1. For iOS localization, I recommend https://poeditor.com/ which is a collaborative translation management platform to simplify work for translators, project managers and other contributors.

  2. japanese - chainese & vietnamese characters arent getting localised. help?!

  3. Very nice blog post, it is informative and i subscribed for all its future post. there are some useful links, i think i must share here:

  4. This is an informative blog. Keep it up. I am looking forward to this kind of blog. Thanks for sharing it with us norton.com/setup


  5. Really great article, Glad to read the article. It is very informative for us. Thanks for posting www.norton.com/setup

  6. Thankyou for Sharing The Awesome Blog Post I Found This Article
    To Be Very Infromative and Helpfull, I am a Web Developer and
    Graphic Designer From Canada and I Love to read and Write Blog About
    New Techonology Trends.
    Some Of My Web Blogs
    Click to Process
    norton support
    norton com setup
    norton chat support

  7. Awesome! I really enjoy and inspired with reading it. This post is very constructive produced by you. norton.com/setup


  8. The information you shared with us was very helpful, thank you very much. Great post, Thanks for providing us this great knowledge, Keep it up mcafee.com/activate

  9. Dear admin thank you so much for sharing this informative information with us, it's really useful for me. your blog is amazing. I wish you all the best for future comments. I have read it and I have also something here to share with you. norton.com/setup
    www.norton.com/setup, Norton product key

  10. Dear admin I really like the way you have to describe this blog it is awesome. All information is very informative I really appreciate your effort toward the reader. Thank you so much for this amazing content and I have also something to share here. www.office.com/setup, Office product key, office.com/setup


  11. I think I have never seen such blogs ever before that has complete things with all details which I want. So kindly update this ever for us.

  12. Interface your gadget to the Internet and go to the App Store.
    Search and "Download" the Amazon prime video application.
    When the document is downloaded and introduced, open the application.
    You will see an alternative – "Register on Amazon site", click on this.
    A 6 digit code will show up on the screen.
    Note down this code cautiously. This is amazon.com/mytv enter code.
    Presently open the Amazon site – Amazon.com/mytv.com and sign in with account subtleties.
    Presently enter the Amazon enactment code and snap on "Proceed".
    You will get the compliment message on your TV screen after the effective enactment.
    Start Enjoying the amazon prime videos on your device.
    If you are facing some issue in that process then you can visit :
    www.primevideo.com/mytv activation code |
    amazon mytv verification code |
    prime video.com/mytv download |
    www.amazon mytv verification code |
    primevideo.com/mytv register device

  13. Visit Amazon Prime Video App icon which is located in apps. Note down the amazon activation code login. Using the system, I got to Primevideo activate mytv. Want to know more about primevideo.com mytvvisit given link.

  14. Wow, This is one of the best blogs I have ever read I get So much useful information from this article. Thank you for sharing this with us. mcafee.com/activate, www.mcafee.com/activate, mcafee activation code

  15. Just head on over to www.amazon.com/mytv enter code and adhere to the on-screen guidelines. Simply go to the Amazon Instant Video application on your LG TV or Blu-beam Player and afterward Prime Instant Video to begin viewing.
    Read more…