Not separating model from view in our software makes our model not reusable for other applications. We have tight coupling between our logic and our presentation. Even within our view, however, we can have tight coupling. If we hardcode our American English into labels and currency and date formatting, we make our view not reusable in other locales.
One approach we could take to keep views flexible is to conditionally assign values to the interface text:
if locale is English one = "one" else if locale is French one = "un" else if locale is Spanish one = "uno" else if locale is Japanese one = "ichi" ... end
While this approach works, it’s not much fun to write all that code. The good news is that both Android and iOS provide a flexible system for pushing all these possible translations out into resources. Then, in your code or interface files, you symbolically refer to the resource text. The correct translation is looked up automatically according to the device’s locale.
The only thing stopping you from marketing your apps to the whole world is translating your interface elements!
Let’s see how to use the resource system on both iOS and Android.
Setting up your interface text in Android is all done via XML resource files. The default translations go in res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="one">one</string> <string name="two">two</string> </resources>
You then create similarly formatted files in other values-* directories. The suffix must be one defined by ISO 639-1, a standard establishing two-letter codes for languages. For example, to create the Spanish translation, we’d put this in res/values-es/strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="one">uno</string> <string name="two">dos</string> </resources>
And the Japanese translation in res/values-ja/strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="one">ichi</string> <string name="two">ni</string> </resources>
The payoff is this. In our interface files, @string/one or @string/two will resolve to the current locale’s translation:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/one" />
In code, R.string.one and R.string.two are integers that identify the current locale’s translation. We can get the actual text by calling
Some methods take a resource ID directly:
Toast.makeText(context, R.string.one, Toast.LENGTH_SHORT).show(); button.setText(R.string.two);
Switching the locale on your device constitutes a configuration change, which normally brings down your app and restarts it with the new resources loaded in. You can switch the locale in Settings. Different providers name the language activity differently. You’ll have to hunt around.
Check out Android’s documentation for more details:
Localizing for iOS is largely a matter of pressing the right buttons in Xcode. Create your storyboard like normal, go to the Project settings > Info > Localizations, and check Use Base Internationalization. Choose your storyboard. It will create a default set of string resources for you with whatever text is currently in the storyboard.
Next, click the + sign, and choose the additional languages you’d like to support. Once again, choose your storyboard. After doing so, you can expand the storyboard in your project navigator to reveal the *.strings files. Edit these with your translations.
Apple provides a much more detailed tutorial that provides a visual walkthrough.