In my previous blogpost I described the process of localisation in a step-by-step walkthrough to cooperate with a translator in a Xcode-project using the XLIFF-format. This blogpost is meant as a useful tool while translating by providing a checklist of all the steps needed to have a fully translatable iOS-application.

This post is written with the following thought in mind

Ideally there is a clear division of labour between the developer (us) and the translator. The developer should only mark certain elements of the UI as ‘user-facing text-elements’ and the translator determines what the exact texts for these elements should be.

Our workflow follows this principle almost to the letter. It deviates a a bit from an ideal scenario because of the limitations of the XLIFF-format and translation platforms (the ones we have tried out, at least) for texts that are dynamic and can have multiple plurals. For example, Xcode’s ‘Export for localisation’-functionality completely ignores plurals.

Of course there is workaround to get it working (and without use of external libraries), however, it does make it a bit more tedious.

Step 1: Use adaptive layouts and UI-elements

Having a multilingual app starts with giving your UI the flexibility it needs. Sentences and words do not have the same length in each language, so your UI should be able to adapt to that. This should be done on two levels:

  1. Create an adaptive UI by making use of StackViews and Auto Layout (and as little fixed widths and heights of UI-Elements as possible).
  2. Give your UILabels the ability to determine how many lines it will need to fit its text by setting label.numberOfLines = 0.

Luckily localisation is not the only reason for iOS-developers nowadays to build a flexible UI, because of the differences in screen sizes of the current iPhones.

So, this should not be a big game changer. ;)

Step 2: Determining the right way to localise your user-facing texts

There are two ways of preparing each UI-element which contains user-facing text for localisation. The best way of preparing each UI-element can be determined by answering these questions:

If the answer for any of these questions is ‘yes’ you should localise the UI-element programmatically (i.e. in code). If the UI-element is created in a storyboard, only occurs once and the text-value is static the UI-element can be localised by localising your storyboard(s).

Step 3: Localising your UI-elements…

Localising your UI-elements is actually nothing more than making sure the text-value of that UI-element is a localised String and not an ordinary String. As I already mentioned, this can be done in two ways; programmatically and through localising your storyboard(s).

… Programmatically

In order to set the text-value of an UI-element there is a need for a reference in your code. If your UI-element is created in a storyboard the way to do that is by making use of an IBOutlet. This allows you to set the text-value as a

NSLocalizedString(key: String, comment: String)


A NSLocalizedString has (at least) two properties; A key and a comment. The key is used to link the translation in your .strings-files (and .stringsdict-files) to the right UI-element. The comment allows the developer to give the translator some extra information.

Our (best) practices for keys and comments

Setting the right key is key ( ba dum tss ). We want our keys to be descriptive enough to make clear which UI-element it refers to. To achieve this we use the following guidelines:

  1. A key should not look like a class-name, method-name or variable-name.

    • So no CamelCasing, instead use _ as a seperator between words.

    • Do not use a - as seperator, because our keys will then become incompatible with Android making cooperation between the two platforms difficult.

  2. Keys should be clearly structured, while keeping them flexible enough to not have to change them if you make minor adjustments to your UI. At Noodlewerk, we use the following structure: userflow_subflow_element

So, by sticking to these guidelines, a key could look something like this:


The userflow of this example is rate_app. The subflow is dialog and the UI-element is option_write_review.

This leaves the comments for use to communicate preferred linguistic nuances; for example the tone of the text or if this text should have multiple plurals.

Ofcourse, a much simpler text that occurs rather frequently, such as ‘Cancel’, does not need a very descriptive key. In those cases we prefer to just use ‘cancel’ as key, because of its reoccurence.

… by localising your storyboard(s)

If you do not want to make IBOutlet’s to your UI-elements only to set a static localised string as a text-value you can also let Xcode generate keys for you for each UI-element in your storyboard(s). The keys are the property of the object which contains the localisable text. For example a Label would have ObjectID.text, but a button would have ObjectID.normalTitle. Here’s an example of a localised string generated by Xcode:

/* Class = "UILabel"; text = “Label”; ObjectID = "YEO-0o-1QJ"; */
"YEO-0o-1QJ.text" = “Label";

applying our (best) pratices to localised storyboard(s)

As you might have noticed, in the last example the keys are not as descriptive as we would like them to be, simply because Xcode does not take our (best) practices in account when generating the ObjectIDs of our UI-elements. However, we could still apply our logic to the localised storyboard(s).

However, Xcode does use NSLocalizedString(key: String, comment: String) when you localise your storyboard(s). Xcode does something like this:

comment: "Class = \"UILabel\"; text = \"Label\"; ObjectID = \"YEO-0o-1QJ\"; "

So, the placeholder value of the text can be found in the comment. That could be your additional comment for the translator. However, this is not ideal.

Even though ‘Localising your storyboards’ spares your custom classes from some ‘abundant’ clutter, it also has three clear downsides:

  1. Every time an element is created in a storyboard Xcode generates a new ID for that element. This also happens when you cut (CMD + X) and paste (CMD+V) an element. So, such an act would break any previous localisation of that element.
  2. It is not possible to give multiple elements localised with this method the same key, because every localised string from a storyboard has an unique key. In other words: if you are using this method you might accidentally ask your translator to translate ‘Cancel’ twenty times (while translators often charges by the word).
  3. And the biggest downside: It is not possible to give your localised strings a custom key.

(FYI: we do not prefer localising storyboards)

Step 4: Exporting your keys + comments and importing your translations

Exporting your keys is done by selecting the project in the Project Navigator and, after adding languages to your project and with your project selected in the Project Navigator, you should select Editor > Export for Localization… in the taskbar. For more in-dept information about this process I would like to refer you to my previous blogpost.

This will prompt a Save Dialog Box to select a location for Xcode to create a folder with a separate XLIFF-file for each language you have selected in your project file, ready to be send to your translator. :)

Importing translations from your translator works similar; select your project file in the project Navigator and this time choose Editor>Import Localizations… in the task bar.

Step 5: Plurals, the tricky part…

Sometimes, your translator sends you translations for your app with sentences that can vary from singular to plural, do to the value of some integer. For example when you have a label that tells the user how many days there are left until a certain event. In that case I have some good news and bad news:

In case you are prepared to do the necessary manual work for localising plurals I recommend you read this blogpost. We are searching for a suitable solution and will ofcourse share this the moment we are happy enough about it. ;)

Wrapping it up

Localisation is something that occurs in every project we encounter. We found that having a list of useful tips that cover each aspect of localisation is extremely useful, so that is why we created this blogpost. We hope it is as useful for you as it is for us.