I am working on an ios app which currently supports two languages English and Korean. I want to add a condition in the app delegate that If the phone language is supported by the app then the app will open in that language otherwise it will open in the english language. I have tried the following code in app delegate, but it is not working. Can anyone helps me in this.
if UserDefaults.standard.object(forKey: "lang") == nil {
let langCodeString = Locale.current.languageCode
let preferredLanguage = String(Locale.preferredLanguages[0].prefix(2))
if let languageCode = langCodeString {
if languageCode == "ko" && preferredLanguage == "ko" {
UserDefaults.standard.set(["ko"], forKey: "AppleLanguages")
UserDefaults.standard.set("korean", forKey: "lang")
UserDefaults.standard.synchronize()
} else {
UserDefaults.standard.set(["en"], forKey: "AppleLanguages")
UserDefaults.standard.set("english", forKey: "lang")
UserDefaults.standard.synchronize()
}
}
}
Thanks.
Just try to save the preferred language in KeyChain.
Please refer a link.
However, if you prefer API for it and a backend to store translation, that will be a better solution though it will take sometime to load initially.
Related
I have an iOS app where I'm trying to show the current selected language, but also include its variation, i.e. "English (Canada), English (US), ...", as seen in the attached image.
I am already using the preferred language from Bundle, like so:
guard let langCode = Bundle.main.preferredLocalizations.first else { return nil }
let locale = Locale.autoupdatingCurrent
guard let language = locale.localizedString(forLanguageCode: langCode)?.localizedCapitalized else { return nil }
But I also want to include the variation information (Canada, US, etc). Any ideas?
Thank you!
Found the answer.
Just get the identifier as you normally would from the bundle:
guard let langCode = Bundle.main.preferredLocalizations.first else { return nil }
Then use the locale's localizedString(forIdentifier:):
Locale.autoupdatingCurrent.localizedString(forIdentifier: langCode)
This will return "English (Canada)" or whatever the language code is, same like in the Settings app.
Currently I am facing weird issue with localization stuff. Whenever I type English numerals, they get changed to Arabic even when Apple Language is set to en in UserDefaults.
if langCode == ENGLISH_CODE {
defaults.set(["en","ar"], forKey: "AppleLanguages")
defaults.set(true, forKey: IS_LANGUAGE_ENGLISH)}
else {
defaults.set(["ar","en"], forKey: "AppleLanguages")
defaults.set(false, forKey: IS_LANGUAGE_ENGLISH)
}
I have 2 lang support for my app
1) English - en
2) German - de
I have done all the procedures for localization, the only issue is
whenever I change the language from "en" to "de" or vice versa then
after the system text is not changing to the latest lang, but it
reflects when I kill the app and reopen it.
For Example:
The popover Copy-LookUp-Share is not localsied to German Lang. but the other things from .string file are lcoalised properly.
My change lang code:
func setLanguage(languageCode:String) {
var appleLanguages = UserDefaults.standard.object(forKey: "AppleLanguages") as! [String]
appleLanguages.remove(at: 0)
appleLanguages.insert(languageCode, at: 0)
UserDefaults.standard.set(appleLanguages, forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
if let languageDirectoryPath = Bundle.main.path(forResource: languageCode, ofType: "lproj") {
bundle = Bundle.init(path: languageDirectoryPath)
} else {
resetLocalization()
}
}
func resetLocalization() {
bundle = Bundle.main
}
FYI: Similar thing happens in 'WeChat' iOS application.
Those are UIKit SDK private menu items and you cannot control them, probably they are just created once then kept cached.
The only thing you can try is to force update in the moment of language change, like
UIMenuController.shared.update()
Note: actually using "AppleLanguages" key for that purpose is not documented, so it is kind of hucky. L10N is system settings originated feature, by design.
My device running iOS 12 and has English language as its primary language and Hebrew as it's secondary language.
Now I'm opening my application with English as it's Base localization.
In the application I have list of three languages: English, Hebrew and French.
At first the attribute Locale.preferredLanguages result is: ["en-IL", "he-IL", "fr-IL"]
If I want to localize my entire application without to change the operating system language I'm changing only AppleLanguages array on UserDefaults like that:
func currentAppleLanguage() -> String {
return (UserDefaults.standard.object(forKey: "AppleLanguages") as? NSArray)?
.firstObject as? String ?? ""
}
func setAppleLanguageTo(lang: String) {
UserDefaults.standard.set([lang], forKey: "AppleLanguages")
}
And after I make that change I'm restarting my application and the language changes.
The thing is after I change AppleLanguages at UserDefaults for example to "he", the Locale.preferredLanguages attribute turns into: ["he"]
So now I don't have the preferredLanguages fallback localizations that set on the operating system at the settings application.
Moreover, I'd like to now how can I get the current running device language on the operating system even after I change the application language with AppleLanguages like facebook does
I'd like to mention I notice that when I edit the running scheme of Application Language to another language it changes the AppleLanguages as well.
Instead of replacing the array of "AppleLanguages" with just a single value, update the existing list so the specified language is moved to the top.
func currentAppleLanguage() -> String {
return UserDefaults.standard.stringArray(forKey: "AppleLanguages")?.first ?? ""
}
func setAppleLanguageTo(lang: String) {
// Get the current list
var languages = UserDefaults.standard.stringArray(forKey: "AppleLanguages") ?? []
// Get all locales using the specified language
let matching = languages.filter { $0.hasPrefix(lang) }
if matching.count > 0 {
// Remove those entries from the list
languages.removeAll { $0 == lang }
// Add them back at the start of the list
languages.insert(contentsOf: matching, at: 0)
} else {
// It wasn't found in the list so add it at the top
languages.insert(lang, at: 0)
}
UserDefaults.standard.set(languages, forKey: "AppleLanguages")
}
This keeps the full list. It just reorders the values so the desired language is first.
I have a requirement of detecting the first launch of app after the user upgrades the app to a newer version. I need to perform certain task only on first launch of app after the user upgrades the app to a new version. Many links available online but none answer clearly to my query. How to achieve this in Swift 2 , iOS 9.
Most of the answers available says to maintain a key in NSUserDefaults and set its value to false and after first launch make it true. But the problem is after I upgrade my app the variable still will be true and thus my scenario fails on app upgrade. Any help would be much appreciated. Thanks!
Try this:
let existingVersion = NSUserDefaults.standardUserDefaults().objectForKey("CurrentVersionNumber") as? String
let appVersionNumber = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
NSUserDefaults.standardUserDefaults().setObject(appVersionNumber, forKey: "CurrentVersionNumber")
NSUserDefaults.standardUserDefaults().synchronize()
//You can handle your code here
}
updating Yogesh's perfect, yet simple solution to swift 4
let existingVersion = UserDefaults.standard.object(forKey: "CurrentVersionNumber") as? String
let appVersionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
print("existingVersion = \(String(describing: existingVersion))")
UserDefaults.standard.set(appVersionNumber, forKey: "CurrentVersionNumber")
// run code here.
}