blog.devgenius.io Open in urlscan Pro
162.159.153.4  Public Scan

Submitted URL: https://blog.devgenius.io/how-to-force-change-app-language-programmatically-without-breaking-your-app-1c73be9608e0?gi=c1d9...
Effective URL: https://blog.devgenius.io/how-to-force-change-app-language-programmatically-without-breaking-your-app-1c73be9608e0?gi=81cd...
Submission Tags: falconsandbox
Submission: On May 03 via api from US — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

Open in app

Sign In

Get started


Home
Notifications
Lists
Stories

--------------------------------------------------------------------------------

Write




RESPONSES



What are your thoughts?

Cancel
Respond

Also publish to my profile

There are currently no responses for this story.

Be the first to respond.

Published in

Dev Genius

You have 2 free member-only stories left this month.

Sign up for Medium and get an extra one



Mukesh Mandora
Follow

Dec 5, 2020

·
4 min read
·

Listen



Save







HOW TO FORCE CHANGE APP LANGUAGE PROGRAMMATICALLY WITHOUT BREAKING YOUR APP


GIVEN THAT YOUR APP SUPPORTS MULTIPLE LOCALIZATION, ALSO SCENARIOS WHERE WE
SHOULD TAKE CARE WHEN WE FORCE SET USERDEFAULTS KEY “APPLELANGUAGE” AND ITS SIDE
EFFECTS IN IOS 13 AND 14


Photo by Greg Rosenke on Unsplash



NO OF WAYS TO SET APP LANGUAGE

 1. Setting UserDefaultskey “AppleLanguage” (singular)
 2. Setting UserDefaultskey “AppleLanguages” (plural)(Apple PreferredLanguages
    array)
 3. Create a custom AppLanguageManager




SETTING UP

Before we start to look in to each way to set App Language we will need some
helpers function which will be the same in all these methods.

> Note: This extension is just for this demo, there are many nice helper
> extension you will find in iOS community

 * Bundle extension





1. SETTING USERDEFAULTSKEY “APPLELANGUAGE”

let lang = "th"
let defaults = UserDefaults.standard
defaults.set(lang, forKey: "AppleLanguage")
defaults.synchronize()
Bundle.setLanguage(lang)
// Restart your app by setting window rootViewcontroller


ADVANTAGES

 1. No side effects.
 2. You can give feature inside your app and let the user select the app
    language instead of changing system language and then see the result so
    kinda good UX for the user.


DISADVANTAGES

 1. Every time at app launch you have to set the last app language code to
    preserve the language setting and for this you have to save language code in
    the other UserDefaults key.
 2. Your app doesn’t change or detect to OS or system language change, But let’s
    consider that’s very unlikely to happen from user perspective.




2. SETTING USERDEFAULTSKEY “APPLELANGUAGES” (PREFERREDLANGUAGES)

There are several other similar ways to force set the App language let’s
consider with basic one. Also, The intention of this article is to know the side
effects of doing this.

When you use the following piece of code your app language gets change in this
case it’s Thai.

let lang = "th"
let defaults = UserDefaults.standard
defaults.set([lang], forKey: "AppleLanguages")
defaults.synchronize()
Bundle.setLanguage(lang)
// Restart your app by setting window rootViewcontroller




ADVANTAGES

 1. You don’t have set the language code at app launch
 2. You don’t have set to save language code in other UserDefaults key like we
    have to do in previous one
 3. You can give feature inside your app and let the user select the app
    language instead of changing system language and then see the result so
    kinda good UX for the user.


DISADVANTAGES

Following are some main issues

 1. Your app doesn’t change or detect to OS or system language change, But let’s
    consider that’s very unlikely to happen from user perspective.
 2. Serious Date formatting side effects. (Note: This issue is found only in iOS
    13 and 14 till now not in older iOS versions like 10, 11, 12)

Now this is important, Suppose your app uses DateFormatter to convert a date
from string, Here comes a major problem because now things starts behaving
weirdly

Consider you are setting your app language to “th”(Thai) with your current
system calendar set to “Gregorian”, Now you are trying one simple task of
getting date from string withDateFormatter Let see the output

> Note: You will find users in Thailand to use both the calendar “Gregorian” and
> “Buddhist”

let format = DateFormatter()
print(format.date(from: "2020-11-22"))// Output
1477-11-22 // Weird

I am not sure why this is giving the wrong calendar, As the results of this
Apple API varies from OS to OS. But this is the main reason that made me think
to deep dive in to this problem.

Following is the output when you print below properties

 1. Locale.current It gives you “th” as identifier
 2. Calendar.current.dictionary?[“identifier”] it gives you “Buddhist” even
    though you are using “Gregorian” calendar

Now you may say that we can set locale, timezone and other properties of
DateFormatterand get the desired output, But it’s a good practice to use the
system Locale, Calendar and other properties from user perspective instead of
hard coding these properties, Also it is a huge side effect if your app is
localized for such countries where people use more than one calendar.




3. CREATE A CUSTOM APPLANGUAGEMANAGER

For this we need following things

 1. AppLanguageManager class which will maintain current language and Bundle
    path.
 2. Setting language code in UserDefaults to preserve last saved language and
    when app restart or relaunch we show the updated language
 3. Helper function to get localize string of current language


LET’S START

 1. Below is AppLanguageManager code which will maintain current language and
    Bundle path, It also helps in setting language code in UserDefaults to
    preserve last saved language.



2. Helper String extension to get localized string

extension String {
        fileprivate func localized(bundle: Bundle = AppLanguageManager.shared.bundle, tableName: String = "Localizable") -> String {
        return NSLocalizedString(self,
                                 tableName: tableName,
                                 bundle: bundle,
                                 comment: "")
    }
}

3. Helper Localizable propertyWrapper and Strings enum

@propertyWrapper
struct Localizable {
 private let key: String
 var wrappedValue: String {
      return key.localized()
 } init(wrappedValue: String) {
   key = wrappedValue
 }
}enum Strings {                         
  @Localizable static var featureOneTitle = "featureOneTitle"                               
  @Localizable static var featureTwoTitle = "featureTwoTitle"                       }

This pieces together helps us to remove dependency from AppleLanguage
UserDefaults keys and it is much more flexible and scalable without any side
effects.


FINAL OUTPUT AND USAGE

print("\(Strings.featureOneTitle)")
// Output in current app language set in this case english
featureOneTitle




CONCLUSION

I believe there is always a downside if we try to solve a problem with hacks.

Setting the UserDefaults “AppleLanguage” and “AppleLanguages” key doesn’t feel
right to me and it has their own downside in recent iOS versions.

Also, do let me know in this article response section if you found any other
issues apart from Date if you implemented language change feature inside your
app using UserDefaults “AppleLanguage” and “AppleLanguages” key.

Thank you for reading. I hope this article will help you make your own custom
language manager.




24





24

24





SIGN UP FOR DEVGENIUS UPDATES


BY DEV GENIUS

Get the latest news and update from DevGenius publication Take a look.

Get this newsletter


MORE FROM DEV GENIUS

Follow

Coding, Tutorials, News, UX, UI and much more related to development

Yitaek Hwang

·Dec 5, 2020


NO, DOCKER ISN’T DEAD

Yes, Kubernetes is deprecating Docker support, but its impact may not be as
dramatic as it sounds. Sometimes one tweet is enough to get people to pay
attention. With Kubernetes v1.20 …

Kubernetes

3 min read





--------------------------------------------------------------------------------

Share your ideas with millions of readers.

Write on Medium

--------------------------------------------------------------------------------

John Au-Yeung

·Dec 5, 2020


VUETIFY — CUSTOMIZE AUTOCOMPLETE

Vuetify is a popular UI framework for Vue apps. In this article, we’ll look at
how to work with the Vuetify framework. Custom Filter on Autocomplete We can add
a custom filter with the v-autocomplete component. For example, we can write:
<template> <v-container> <v-row> <v-col…

Programming

4 min read





--------------------------------------------------------------------------------

John Au-Yeung

·Dec 5, 2020


CHART.JS — CHART TOOLTIPS AND LABELS

We can make creating charts on a web page easy with Chart.js. In this article,
we’ll look at how to create charts with Chart.js. Tooltips We can change the
tooltips with the option.tooltips properties. They include many options like the
colors, radius, width, text direction, alignment, and more. For example, we…

Programming

3 min read





--------------------------------------------------------------------------------

El Akioui Zouhaire

·Dec 4, 2020


INVEST YOUR GOLDEN TIME IN TRANSFERABLE SKILLS

As the world of technologies goes very fast. We need to stay up to date with
technology. Every day, we learn programming languages, frameworks, and
libraries. The more modern tools we know “the better”. Time is limited,
nonrenewable and you cannot buy more of it. Technology is moving faster than…

Programming

5 min read





--------------------------------------------------------------------------------

Miloš Živković

·Dec 4, 2020


HOW TO MAKE VALUABLE TESTS, CAPTURE MORE BUGS AND MAKE UNIQUE ROBUST CODE

How To Save Your Life From Dangerous Bugs — I guess you had a few bugs due to a
lack of testing? You know testing is time-consuming and boring. So you avoid it
at all means possible. We all do. With no proper bug definition, you’ll spend
precious time debugging. What if you had all logic documented, all possible…

Java

3 min read





--------------------------------------------------------------------------------

Read more from Dev Genius


RECOMMENDED FROM MEDIUM

Yay! Official

FORCE LOGOUT ISSUE IN IOS VERSION



Alex Nekrasov

in

Better Programming

WORKING WITH EMOJI IN SWIFT



Mykola Harmash

SWIFTUI STATE MANAGEMENT FUNDAMENTALS



Transpire

in

Transpire TechBlog

GETTING STARTED WITH REUSABLE SOFTWARE LIBRARIES — LOCAL SWIFT PACKAGES



Tmod Apk

MESSAGES IOS 15 MOD APK 1.1.1



Cihat Gündüz

in

Better Programming

HIDING SECRETS FROM GIT IN SWIFTPM



E-Zou Shen

in

The Startup

SAVE YOUR ANIMATION CODE FROM CALLBACK HELL WITH COMBINE



Akshay Devkate

in

Nerd For Tech

OBJECT ORIENTED PROGRAMMING WITH SWIFT



AboutHelpTermsPrivacy

--------------------------------------------------------------------------------


GET THE MEDIUM APP


Get started

Sign In


MUKESH MANDORA



175 Followers



iOS Developer | https://github.com/mukyasa


Follow



MORE FROM MEDIUM

Kanan Abilzada

UPLOAD YOUR APPLICATION TO TESTFLIGHT USING FASTLANE



Nur Ahmad

HOW TO CONNECT FLUTTER IOS FIREBASE



Alessandro Manilii

in

Better Programming

BUILD UITABLEVIEW SECTIONS WITH NESTED TYPES



Ataberk Turan

FIREBASE IOS PUSH NOTIFICATIONS TUTORIAL



Help

Status

Writers

Blog

Careers

Privacy

Terms

About

Knowable

To make Medium work, we log user data. By using Medium, you agree to our Privacy
Policy, including cookie policy.