How to show language version in an iOS app - ios

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.

Related

How to get Localization languages from strings file programmatically in Swift?

How do I grab all of the checked languages for Localization programmatically in Swift with Xcode 12?
I want to have these languages in an array that I can display as a picker view so the user can seamlessly change the language without having to change the language of their device. I want to avoid hard coding this.
Screenshot of the Localization check boxes in Xcode from my .strings file
This might do the trick:
func localizations() -> [String] {
guard let contentsURLs = try? FileManager.default.contentsOfDirectory(at: Bundle.main.bundleURL, includingPropertiesForKeys: nil) else { return [] }
let identifiers = contentsURLs.compactMap { anURL -> String? in
guard anURL.pathExtension == "lproj" else { return nil }
return anURL.deletingPathExtension().lastPathComponent
}
let humanReadableNames = identifiers.compactMap { anIdentifier in
return Locale.current.localizedString(forIdentifier: anIdentifier)?.localizedCapitalized
}
return humanReadableNames
}
I even transformed them into human readable languages names, instead of having for instance "zh-Hans" for "Chinese (Simplified)".
Of course, if you handle yourself your locale, your might want to use a different Locale.current, but you get the idea...

Localisation Settings Not Changing the System Defined Text in Swift 4.2

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.

Swift - how to get ios device current language

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.

Set Language in Swift 3 failed [duplicate]

This question already has answers here:
How to force NSLocalizedString to use a specific language
(28 answers)
Closed 5 years ago.
Sir.
I am trying to create an app of multi-language support. I use the abbreviations like zh-Hant, en , jp to save as user default. And change the language of the app. Taking place holder of textfield as an example, if I click the collection view item, the text of place holder of textfield will change. However , I can't do this. The simulator language is English as default
Here is my work in-progress :
Localisation File : Japan (jp)
"User Email"; = "ユーザーメール";
Set Text method
let lcode : String = self.langList[indexPath.item].code
print("You selected cell #\(indexPath.item) and code : \(lcode)")
UserDefaults.standard.setValue(lcode, forKey: "lang")
txtUsername.placeholder = "User Email".localized(lang: lcode)
String exntension
extension String {
func localized(lang:String) ->String {
if let path = Bundle.main.path(forResource: lang, ofType: "lproj") {
if let bundle = Bundle(path: path) {
return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
}
}
return "";
}
The language of the app is dependant on the device language. To test the localized string, change your device language. Otherwise, though this is not recommended, you can change your app language on runtime by adding UserDefaults.standard.set("zh", forKey: "AppleLanguages") to your ViewController. But you will have to restart the app to see the language changes.

iOS: How to retrieve locale strings for a specific locale than what the user has set in OS?

Is it possible to retrieve strings for a specific locale programmatically regardless of what locale the phone is set to? For example, users may be running the phone in English, but I want to retrieve French strings instead without changing the OS locale setting.
Note: This is not a duplicate of the above question. I do not want to override the current setting within my app, I merely want to have the ability to retrieve language values of whatever locale I wish programatically. My app contents may be displaying English text, but I want a specific component of my app to display a different language instead.
I solved this by extending String with this method. You can get localized string for any locale you have in your app this way.
extension String {
func localized(forLanguageCode lanCode: String) -> String {
guard
let bundlePath = Bundle.main.path(forResource: lanCode, ofType: "lproj"),
let bundle = Bundle(path: bundlePath)
else { return "" }
return NSLocalizedString(
self,
bundle: bundle,
value: " ",
comment: ""
)
}
}
Example (get localized string for ukrainian language when system language is english):
"settings_choose_language".localized(forLanguageCode: "uk")

Resources