String localization for framework - ios

I'm building a framework that includes UI components. I'm retrieving localized strings with:
var bundle = Bundle(identifier: "com.my.identifier")
bundle.localizedString(forKey: "myKey", value: nil, table: nil)
The problem I'm seeing is whatever parent application integrates with my framework, must also have localization enabled for my same localizations (e.g. if I have localizations for es-ES, the parent application must also turn on localization for es-ES in project settings:
Otherwise my localized strings always default to english.
I have found a workaround by manually grabbing a language bundle based on the device's preferred language:
var bundle = Bundle(identifier: "com.my.identifier")
guard let deviceLanguage = Locale.preferredLanguages.first else {
return notFound
}
guard let languagePath = bundle.path(forResource: deviceLanguage, ofType: "lproj") else {
return notFound
}
guard let languageBundle = Bundle(path: languagePath) else {
return notFound
}
return NSLocalizedString(self, tableName: "Localizable", bundle: languageBundle, value:"KEY_NOT_FOUND", comment: "")
But the issue with this workaround solution is that I lose the built-in iOS language fallback (e.g. if the device preferred language is es-MX it will auto-choose the es-ES string over the en string I have).
For my framework, is there a way to avoid forcing parent applications to turn on localization for all my localized strings, yet still keep iOS language fallback logic?

Why do you want your framework to use a localization not supported by the app? This is a terrible user experience.
Imagine app that uses your framework only supports English and Spanish. Now imagine that a user of the app have their device setup to use German first, and English second.
Since the app doesn't support German, the app shows English. The entire app should show English. If your app framework manages to show German in this case, the app's user experience is now very confusing because much of the app is in English but the parts supported by your framework appear in German.
tl;dr - Don't do anything. Let the default behavior work as-is. It makes for a much better user experience.

Related

Using the wrong Localizable.string

I have an iOS app with a default language (English).
It also has a French localization and works as expected in both languages.
Here is the problem I am having:
When setting the device to a language other than English(default) or a language for which localization is provided (for example setting the device to Japanese); the app does not fall as expected in the default language. But it keeps the last language used for the app.
Why is that? And how can I fix it?
I have found a few post with a similar issue, but the solutions proposed did not work for me. For example this one, where the problem is similar to mine.
I am using Xcode version 11.1 and iOS version 12.4.2.
iOS will have a list of preferred language order based on the previously selected languages.
So, if you changed from English then to an unmapped language (e.g ko), the application will have as AppleLanguages the array:
[ko-(ZoneCode), en-(ZoneCode)].
You can avoid this procedure using this code below:
let defaultCultureCode: String = "en"
let defaults = UserDefaults.standard
let currentAppleLanguages = defaults.stringArray(forKey: "AppleLanguages")
if let currentLanguages = currentAppleLanguages {
if(!currentLanguages.isEmpty && !(currentLanguages.first?.contains(["en", "fr"]))!) {
defaults.removeObject(forKey: "AppleLanguages")
defaults.set([defaultCultureCode], forKey: "AppleLanguages")
defaults.synchronize()
}
}
I used this string extension to check if the current languages contain the available language:
extension String {
public func contains(_ elements: [String]) -> Bool {
var haveElementOnString = false
if elements.count == 0 { return false }
else { elements.forEach{ element in haveElementOnString = haveElementOnString || self.contains(element)} }
return haveElementOnString
}
}
The next step it's up to you to define the best strategy.
In my application context, it will always be defined as English by default because it is the only .strings file available. All the other supported strings will be downloaded and then a message will be displayed to the user warning that new languages are available and will be applied next time.
There's a lot of information on StackOverflow about bundle.localizedStringForKey or NSLocalizedString that could help you to found the best solution for what you need.
Also, this is only the validation and update for the current locale and the default language. this doesn't include the Region section (e.g. ko-KR (KR)).
I found an interesting text on this topic that could be useful
How not to do localization.
I hope it solves your problem!

Is there a way to set English as a default language

I localized my app for 2 languages (EN, FR). When iPhone language set to English, app shows up in English. When iPhone language set to French, app shows up in French. But when iphone language set to another language lets say Spanish app shows up in French not in English.
I set "Localization native development region" to "en" or "United States" in my Info.plist file but didn't help.
Main.storyboard (Base) also in English.
Solution:
One way to do it is to get the English string from en.lproj if the preferred language does not match en or fr.
This is how you get the preferred language:
let preferredLanguage = Locale.preferredLanguages[0]
This is how you get the English string using your localized key:
if let enPath = Bundle.main.path(forResource: "en", ofType: "lproj") {
let enBundle = Bundle(path: enPath)
enBundle?.localizedString(forKey: "your_key_here", value: nil, table: nil)
}
Explanation of your problem:
In iOS native Settings App -> General -> Language & Region, there is a Preferred Language Order list.
Apps and websites will use the first language in this list that they
support.
For example:
Set "French" as your iPhone Language.
Open the App and everything is localized in French because your app does support French.
Set "Spanish" as your iPhone Language.
Open the App and everything is localized in French because your app does not support Spanish and it'll fall through your next preferred language which is French in this case.
Just set developer language to English
YOURPROJECT.xcodeproj -> show package content -> Editing the .pbxproj file directly using a text editor - look out for the developmentRegion property
And change the Localizations native development region property in the Info.plist accordingly en Or bellow image
once your result like this then you setup successfully :
]1

Is it advisable to implement changing app language from settings in a native iOS app?

Will my app be rejected from app approval in App store if it is implemented?
No #Doj Yias, It is not necessary that you have to change our app-language according to device's setting app.
You can give the option of selecting language with-in your app like most of the e-commerce application does that. It will not get your app rejected.
How to implement multi-linguality:
You just need to localized to your project according to different languages and add the lingual strings to the respective lingual files.
To choose language, you have to use:
if let mainP = Bundle.main.path(forResource: "en", ofType: "lproj"), let bundle = Bundle(path: mainP) {
return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
}
You have to pass language code at the place of "en".

XIB localization failed in iPad

My app support Traditional Chinese and English
Now I set my device language as Japanese
Well... In iPhone everything is fine, but iPad localization failed
If I set text used code, it show English when app running
Since app doesn't support Japanese it use English as default language
theLabel.text = NSLocalizedString("theKey", tableName: nil, bundle: Bundle.main, value: "", comment: "")
But if I set text used xib localize
xib base file↓
// English String
"fKW-21-ZWh.placeholder" = "Please fill in your skype ID";
"hyL-A7-fx9.placeholder" = "Please fill in your paypal ...";
// Chinese String
"fKW-21-ZWh.placeholder" = "請填入你的skype";
"hyL-A7-fx9.placeholder" = "請填入你的paypal";
it shows Chinese text when app running
I hope it can use English as default language
do I missing something?
What I did
TARGET -> Info -> Localization native development region = United States
TARGET -> Info -> Localizations = [English, Chinese(traditional)]
PROJECT -> Localizations = [Chinese, English - Development Laanguage]
Delete DerivedData, APP
Clean Project
restart computer
Edit
Edit
I found a Apple tech QA, link
the language that app used is depend on user language preferences
Just select your storyboard/xib, go to File Inspector. In the Localization section, you can tick the language you want.

Reading Localized String

I have an app that I'd like to be able to get the localized string for a certain key, regardless of what my current localization on the iPhone is.
I have the following in an en.lproj localized strings file
"Black" = "Black";
In the es.lproj localized strings file I have
"Black" = "Negro";
So what I would like to do is get the Spanish string when my phone is in the US and set up accordingly
I'm using the following code:
let bpath:String = NSBundle.mainBundle().pathForResource("es", ofType: "lproj")! as String
let bundle = NSBundle(path: bpath as String)
let thisWord="Black"
let ourWord=NSLocalizedString(thisWord, bundle: bundle!, comment: "")
I'm expecting to get "Negro" in the value for ourWord, but I always get "Black"
Am I missing something obvious?
Localization settings apply based on the settings you set in your phone not the location. If your phone is setup to display an Application Language of Spanish then you will see the appropriate string. To configure Application Language settings so you can test this you need to edit your Scheme.
In Xcode 7.1+ Goto Product > Scheme > Edit Scheme
Then change the Application Language and/or Region to simulate what a user would see who has an iPhone configured for a region or language other than English in the US.
(Switch it to Spanish and then debug the app on the device again to see the updated localized strings).
Actually my code works fine. I had made the stupid mistake of not setting the "Localizable.strings" file as localized.
Feeling pretty dumb right now

Resources