Table of Content
- Introduction
- Basic Setting for Localization
- Adding a new language
- Make preview window with multi-language
- Make the app with dynamic changing language
Introduction
I have some years of experience on iOS development, but not continually. Whenever I go bak to iOS development, it changes a lot all the time. The most recent significant changes for me are M1 support, SwiftUI, and almost usable refactoring tool. Interestingly, you may find the changes from the beginning of NSxxx for Object-C, UIKit for Storyboard generation, and the last SwiftUI. After paying some attention on it, I can tell you what you think of SwiftUI maybe wrong. It is a totally new framework, has its own strict coding style and new features, and all of your previous experience on Object-C and Storyboard can’t apply to it, even previous 3rd party library of any UIView or UIImage. So let’s start to find out from scratch.
Suggested Requirement:
xcode: Version 12.4 (12D4e)
OSX: Big Sur 11.2.3
Swift: Version 5.x
select “Mutiplatform” → “App” → “Next”
type “Product Name” → uncheck “Use Core Data” → “Next” → “Create”
You’ll see a very simple project look like following:
The entry view is ContentView.swft, and called inside LocaleDemoApp.swift. Unlike what we have done in UIKit Storyboard, there are no UIViewController nor AppDelegate. Actually, the multi-language or localization structure underneath is similar, but has much different setting and way to display.
Let’s look at the default ContentView.swift. You can tell the major different is the preview window and it is live-reload! SwiftUI has built in multi-language, we can check the definition by press ⌘ + click “keyword of view” such as “Text”. You’ll see following definition. As you see, all View with String that comfort LocalizedStringKey. It means you only have to make localized string file, and the SwiftUI will do the localized for you.
Basic Setting for Localization
To set up locale string file, there are some basic setting we have to figure out. If you do know how to configure and add language file for SwiftUI, you may skip this section to next “Make preview window with multi-language” section.
- in the xcodeproj, look at “project” setting → “info” tab→ “Localizations” section. The default locales are “base” and “English Development Language”, but with no file associate with language strings file. This is the place to add more languages. The other is a checkbox “Use base Internationalization”, this is not really necessary in SwiftUI. What does “Use Base Internationalization” mean?
When you create a new iOS project based on Storyboard in Xcode, Xcode will auto generate the resources for the default language (which is the “base” language), like Main.storyboard and LaunchScreen.storyboard, and place them into the “Base.lproj” folder, but SwiftUI doesn’t need those files. - Add a string file to associate with English since there is no default language file. Click on “Shared” folder, open menu “File” → “New” → “File…”, in the search box type “string” and select “String File”. OK, the next part is VERY IMPORTANT, you have to name it “Localizable” to make localization work.
- Add a mapped string key with new value in Localizable.strings
”Hello, world!” = “Hello, world! in English”;
. As you see the key is “Hello, World!”, which is the same in the ContentView’s Text object’s string. After finish the next step, you’ll see the “Hello, World! in English” in your preview window. - Press “Localize…” button from the right “File inspector” panel of Localizable.strings, and select “English” to associate with it.
- Back to ContentView.swift, press “resume” button in preview window and you will see “Hello, World! in English” in the preview.
Adding a new language
After the basic setting of localization, to add a new language is quite simple. Let’s back to the xcodeproj, look at “project” setting → “info” tab→ “Localizations” section.
There is a “+” icon underneath, press to select the language you want such as “Spanish”.
SwiftUI will copy the one you have in “English” to the new language “Spanish”
You will see new languages with “Localizable.strings”. Then modify the Localizable.strings (Spanish) file for the key “Hello World!”’s value to
”Hello, world!” = “¡Hola Mundo! in Spanish”;
That’s all we have prepared for later section about dynamic changing locale.
Make preview window with multi-language
So far what we have done has not been validated. To validate all locales work properly, we can make our preview with all languages we defined has live presentation.
Before instructions, there is an important concept you need to know. The preview window is a standalone instance of SwiftUI framework.
It means it may crash or log errors, and resulting with no screen at all. Yes, it is annoying, but on the other hand, it reminds you have errors in code. In my opinions, it’s better to fix all preview’s errors for better performance and hidden risks, because some errors don’t affect your production build.
Modify ContentView_Previews of ContentView.swift with following:
The key to display in specific language is using environment to send locale identifier, the result shows English and Spanish at the same time.
OK, you may notice the significant difference of multi-language in Storyboard and SwiftUI. SwiftUI’s language is changed by environment’s initialized locale, and has ability to switch in the run time for showing more than one language at the same time. Unlike Storyboard, it has to be changed in the main bundle and reload the root view to take affect, and only one language at the same time. Now, the other question appears. Can we make app dynamic changing of locale? The environment was initialized by a local identifier, and then all the environment properties become read-only.
Make the app with dynamic changing language
Thanks to SwiftUI’s react-like mechanism, and there is a state-binding method for trigger the variable change event. So the first step is to make the language identifier as a variable, but it has to be a reference sending to environment. To make them state-binding, we modify our entry view in LocaleDemoApp.swift code ad follows:
Then modify ContentView.swift to meet lang variable reference from LocaleDemoApp.swift, and add 2 buttons for changing language identifier:
Because of @Binding var lang
, the preview fails to display. A small trick will fix this problem, and we may also make a UI test case for 2 language to display. Add a wrapper sending a state lang variable before calling preview will perfect solve the error.
That’s it! Maybe there is another way such as StateObject for creating language manager. Here is just a simple thought about quickly making your dynamic locales. It works, even simple than ever under SwiftUI. This is very easy to implement in your newly project, so I don’t push to GitHub for your reference. But if you really need it, just leave me a message.