iOS Localization Tutorial in SwiftUI using String Catalog

Hoyeon Lee
8 min readJan 6, 2024

--

Localization in the real world airport

What is localization and why we need it?

As app developers, we’re always looking for ways to make our apps open and easy for everyone in the world, no matter where they are.

To make this happen, we need to use localization.

Localization is the process of translating and adapting your app into multiple languages and regions. Localize your app to provide access for users who speak a variety of languages, and who download from different App Store territories.

This is Apple’s official documentation explaining what localization is and why you should use it.

In short, localization is more than just translating text. It is about not only words, but also making sure everything in the app feels right and respectful to app users’ cultures, follows local laws, and looks good.

In this post, we are going to experience localization processes in SwiftUI step by step. Make sure that your Xcode version is 15 or later.

Localization in SwiftUI

1. Create a new project file

Set the interface to SwiftUI and create a new project.

2. Make some code in ContentView

Write the above code in the ContentView file.

3. Add localization languages

Select the project and add the language you want to localize by clicking the + button in Localization. I added Korean, but you can add any language you want such as Spanish and Japanese etc.

4. Create a new String Catalog and build the project

Create new file (Command + N) and choose String Catalog. You can also use Strings File(Legacy), but we are not going to use it in this tutorial.

Source: Apple Documentation

This is because Apple recommends using String Catalogs in Xcode 15 and later. (+ Personally, I think String Catalog is easier to use)

In the file list, on the left side of the above image, you can see that the Localizable.xcstrings file has been created.

However, you have only created the file and there are no strings in the catalog list yet. Now, let’s build the project! (Command + B)

English (default)
Korean (other languages)

Then, Ta-Da! After building the project, all strings within the project were created in the catalog list. What a magical moment!

Likewise, one of the advantages of String Catalog is that when you build the project, strings are automatically listed.

In this project, English is the default language, and Korean has been newly added, so the catalog looks a little different. In particular, in the case of Korean, you can see that the state item is labeled “NEW”.

By the way, what are things like “%lld”, “%lf”, and “%@” that are highlighted in blue?

They are string format specifiers supported by the NSString formatting methods. Further details can be found here.

To put it easily and simply, %lld, %lf, %@ stands for Int, Double, String, respectively.

5. Fill in the blanks in the catalog

Before we fill in the blanks in the catalog, there is one more thing to explain.

Go back to the English catalog and look at the first blank space. You can check “%lld item(s)”. The reason why I write “item(s)” is because singular or plural expressions are required, such as “1 item”, “2 items”, “3 items”.

In this case, right-click and select “Vary by Plural”.

Then the catalog will be a little bit different. Now, there are multiple cases for one key, and in this case, there are “One” and “Other”.

We know that we should use “item” when there is only 1 and “items” when there are 2 or more.

So, let’s enter “%lld item” for One and “%lld items” for Other.

And if you go back to the Korean catalog, you will see that “%lld item(s)” has been automatically changed.

Here, you might wonder why there are two cases in English, “One” and “Other”, while there is only one case in Korean, “Other”?

That’s because Korean generally does not distinguish between singular and plural. In fact, English uses it like “1 item, 2 items, 3 items, …”, but Korean uses it like “1개의 아이템, 2개의 아이템, 3개의 아이템, …”.

Now, Let’s fill in the remaining blanks as above. You can see the green checkmarks on the right which means completion.

And “No Localization” is intentionally left blank since we do not want to do localization.

In this case, just right-click and select “Mark as Reviewed”.

Then, everything is finished and you can see green checkmarks in everywhere.

6. Change the device’s language setting

Before we build the app, we need to change the language settings of the device to check if the localization is applied properly.

How to change the language setting depends on whether you are testing on a simulator or a real device.

(1) Testing on a simulator

You can change the simulator’s language settings like above.
(Edit Scheme → Run → Options → App Language)

(2) Testing on a real device

You can change the device’s language settings like above.
(Settings → General → Language & Region)

Now it’s time to build and run the app (Command + R) with different language settings and feel the power of localization!

Left: English(default) and Right: Korean(localized)

Wow, everything is applied perfectly as we intended.

Localization in Info.plist

What we’ve covered so far is localizing all strings on the screen that are displayed when running the app.

Then, what should we do to localize the name of the app that appears on the wallpaper?

(1) Display Name

Default display name is LocalizationTutorial which is same with the project name. In this tutorial, we are going to localize it in English as “tutorial” and in Korean as “튜토리얼.”

Do you remember that there was no Info.plist in the file list when we created the new project file? Don’t panic haha!

We can add target properties like the above. Just click the + button.

Then, add “Bundle display name” key and enter “Tutorial” as a value.

Next, create a new Strings File in the project and the file name will be “InfoPlist”.

Now, you can see the “Localize…” Button on the right side. Just click this button and localize in Korean.

The left side is key and the right side is value.

Add key(CFBundleDisplayName) in default language and value(튜토리얼) in Korean, and try running the app with the language setting set to Korean.

Then the display name will have changed like this.

(2) Permession request message

When we first install and run an app, we often receive a message asking for permission — allowing notifications, app tracking transparency, Face ID, and access to album etc.

Therefore, when requesting permission from the user, it will be better if the message is provided in a localized language.

In this tutorial we will learn how to localize permission request messages related to app tracking transparency.

You must use the AppTrackingTransparency framework if your app collects data about end users and shares it with other companies for purposes of tracking across apps and web sites.

First, add some code in the LocalizationTutorialApp file as shown above.

Second, add the “Privacy — Tracking Usage Description” item in target properties and enter the value like “Activity information will be collected to improve your app experience”.

The left side is key and the right side is value.

Lastly, add key(NSUserTrackingUsageDescription) in default language and value(사용자의 앱 경험을 향상시키기 위해 활동 정보가 수집됩니다.) in Korean, and try running the app with the language setting set to Korean.

Left: English(default) and Right: Korean(localized)

When you run the app, a permission request message will pop up after 1 second like above.

Note that “Privacy — Tracking Usage Description” is not a real key.

If you want to check the raw key of the target property, right-click the key you want and select Raw Keys and Values.

Then the raw keys will appear and you should use them as the key value.

Summary

In this tutorial, we covered what localization is and how to implement it in your app.

Implementing localization into an app can be a bit bothersome for developers, but it can make users feel respected and cared for.

I hope this tutorial will be of some help to your localization work. Just embrace localization in your iOS app development and aim for the global market to get significant rewards!

The full code is on my Github.

--

--