Localizing Strings that contains plurals in Swift

jair moreno
4 min readSep 8, 2021

--

Photo by Djim Loic on Unsplash

Have you ever wondered what is the purpose of the .stringsdict file?
Have you ever had to deal with grammar rules for plurals in your iOS apps?

Well, if you answered yes to any of these questions, or if you are just curious about learning something new about localization in Swift this article is for you. In this article I will try to explain the utility of this powerful tool that Apple provides us.

Example: Localize a string for 3 different plural states

Then, let’s keep it simple and straight. For this example, we will use an app that basically allows us to select Mexican magic towns and remove them (the removal implementation will not be part of this article). This app contains a table with the towns, and you can switch to edit mode and select the towns manually or select all at once, then, with a tool bar element, you can delete the selected towns. Before the deletion happens, an alert will be shown with the title that we want to localize, it is just a confirmation step before the deletion. So, now that we know what the app is about, we can predict the scenarios that we will face:

  1. There is no selected town before deletion
1st scenario

2. There is only one town selected

2nd scenario

3. There are multiple towns selected (two or more)

3rd scenario

Of course, there are different ways of solving that, but one of the most common solutions would be using a couple of if/else statements

if/else statements

Introducing .stringsdict file

Although this is a perfectly valid solution, this can get more complicated if we are planning to support more than one language due to the differences that the grammar rules may have. So, this is where .stringsdict file comes to the rescue. This file is a property list and allows us to add different rules for our localized texts. Whether we want specific rules for empty values (in this case towns), a single value or multiple values, all that we need to change are the dictionary values of the file. Let’s go back to our app and make the changes to use .stringsdict

First, we need to add a new file of type .stringsdict

.stringsdict creation

This file has the following structure by default

Default implementation

Localized String Key: Is the string value to localize, just as you would do in a .strings file.
Localized Format Key: Has the value the name of the dictionary that contains the rules to apply; the value of the string must be preceded by %#@ and followed by @, in the image above, the string value is VARIABLE.
VARIABLE: After creating this string in the previous key, we are going to use the dictionary to apply the rules. The first key inside the dictionary NSStringFormatSpecTypeKey must stay as it is, it only says that we are specifying language rules, the second key NSStringFormatValueTypeKey is a string format specifier, the letter dindicates that we will use a decimal in our localized string every time we find a %d. And lastly, we will find different keys to represent the rules of the singular and plural texts. The English language only requires specifying the key for one and other, you can specify zero key but it is optional, after adding these values, we will ended up with something like this

Custom implementation

Now, our app is ready to handle the 3 states within this file. So, let’s remove the if/else statements and add the following code

Code after .stringsdict file

One thing worth mentioning is that grammar rules for plurals vary depending on the language. For example, Arabic has different plural forms for zero, one, two, few, many and other categories, then, if you are planning to support several languages, you should be careful and take into consideration these rules.

Having said that, let’s wrap up this article by adding support to a new language; since we are using Mexican towns in this example I think it is a good idea to support Spanish language in our app.

You can find source code in the following repo

https://github.com/JAIRMG/StringsDictExample

--

--