Manually set localization in your app
At the end of last week, I updated two of my existing apps on the App Store to support changing languages within the apps themselves. While I already have this functionality in two of my other apps, the apps I just added this to has a much solid use case, and is arguably something I should have done a long time ago.
Why
In most cases, this won’t be a part of an app’s core functionality; it will most likely be added convenience for a few users at best. This is most certainly true for my two utility apps, Sthlm Travel and Cryptoverter. But there are a few scenarios where this functionality could come in handy.
Accessing localized content
For my other two apps however, I’ve Never and The Blame Game, this could give a substantial boost to user experience. These two apps, which are mostly used as ice breakers at gatherings and parties, contains a large amount of localized content in English and Swedish.
Many Swedish people I know prefer to have their phone language set to English, which means that they will only have access to the app’s content in English. But in company with Swedish friends, they will most likely want to use the Swedish content. Being able to switch language in the app would come in very handy here!
Testing purposes
Another good use case is to make it easier for your testers. Through Xcode, it’s possible for us developers to deploy our apps in the localization of our choice. We can also deploy the app to the simulator, where we can easily set up multiple simulators; each with its respective localization set. But for the testers you want a simple and straightforward way for them to switch between languages.
How
As you may already know, the app per default will choose a localization based on your language settings, either by looking at your system language or the following languages you have prioritized. If none can be found, the default language set by the developer will be used.
Apple doesn’t recommend tampering with this functionality. Instead, they want you to access localized content by using NSBundle
.
Since each supported language gets its own language-specific folder with the .lproj
extension in a project, (i.e en.lproj
for English) accessing language specific content is quite simple:
To easily handle the switching between languages, I created a utility class:
Setting preferred language
To set the preferred language, one only needs to change the preferredLocalization
variable of the class.
And to add more supported languages, one can simply extend the PreferredLocalization
enum, with the raw string value as the language designator (more info can be found here).
Getting localized content
I went ahead and created a global function, to replace NSlocalizedString
, called LocalizedString
. This function simply calls the localizedString
function of LanguageHandler
, which in turn will check the preferred language set, and either use NSLocalizedString
or call its current bundle’s localizedString
function.
As for fetching other localized content, simply use LanguageHandler.default.currentBundle
instead of Bundle.main
.
Being notified on language changes
You may have noticed that this file contains a defined NSNotification
, PreferredLanguageDidChange
. This notification gets posted when the preferred localization has changed. Listening to such notification could look like this:
In a larger project however, this could get a bit annoying; having to identify all the places where views needs to dynamically update to language changes. To solve this, I chose to extend some work originating from a friend of mine. He originally created subclasses of UILabel
, UIButton
, and other classes that displays strings, to be able to avoid scenarios where you have to create an IBOutlet
just to set a localized string. Since I found his approach to be quite useful, I chose to further extend his work - by adding handling of language changes:
By using this LocalizableLabel
you only need to set the textIdentifier
, either in a Storyboard/Xib or programatically. The rest is taken care of by the label.
Sample project
I’ve put up a sample project on my Github to demonstrate everything in action. As always, I’m open to feedback and suggestions!