How to get human friendly current local language name in iOS? - ios

The current language code can be retrieved via Locale.current.languageCode but what if I need a more human-friendly name like "English" or "Japanese"?
Does the developer must maintain a mapping in the app or there is a native way to get the language name?

You can use localizedString(forLanguageCode:) method on Locale object.
let locale: Locale = .current
locale.localizedString(forLanguageCode: "pl_PL") // "Polish"
along with other useful functions that can help you get localized region or currency names from codes.
locale.localizedString(forRegionCode: "pl") // "Poland"
locale.localizedString(forCurrencyCode: "PLN") // "Polish Zloty"
and to use different locale than the .current you can easily initialize it with one of the available identifiers.
let japanese = Locale(identifier: "ja_JP")
japanese.localizedString(forLanguageCode: "pl_PL") // "ポーランド語"
japanese.localizedString(forRegionCode: "pl") // "ポーランド"
japanese.localizedString(forCurrencyCode: "PLN") // "ポーランド ズウォティ"

Related

how to localize a picker to another language?

#State var selectedSpace : FreeSpace = .Big_Bag
Picker("", selection: $selectedSpace) {
ForEach(FreeSpace.allCases) { FreeSpace in
Text(FreeSpace.rawValue.capitalized)
}
}.environment(\.locale, Locale.init(identifier: "az-Arab"))
.foregroundColor(Color("Color"))
.padding(.trailing)
Knowing that the pickerValues
enum FreeSpace: String, CaseIterable, Identifiable {
case Big_Bag, Small_Bag
var id: Self { self }
}
i'm trying to convert what is inside the picker to arabic and can't find a solution it is always displayed in english.
From apple doc :
If you intialize a text view with a variable value, the view uses the init(:) initializer, which doesn’t localize the string. However, you can request localization by creating a LocalizedStringKey instance first, which triggers the init(:tableName:bundle:comment:) initializer instead:
// Don't localize a string variable...
Text(writingImplement)
// ...unless you explicitly convert it to a localized string key.
Text(LocalizedStringKey(writingImplement))
That means that you must use :
Text(LocalizedStringKey(FreeSpace.rawValue.capitalized))
I think you misunderstood the concept of iOS localization. In you app you need to provide localizable strings file (usually it is named Localizable.strings), which holds localization values for your supported languages.
So basically in your project settings, you need to enable desired languages (English and Arabic on the screenshot).
Then you create Localizable.strings file and add it as a resource of your app. Then just make it localizable by clicking localize in File Inspector.
This will let you choose what language you want to use for the current file. Once you make it localizable you can tick what languages to use and you can switch them in Project Navigator.
Since now you will put localized texts in its appropriate Localizable file and use its key to access it.
Then if you use Text(String(localized: "key").uppercased()) you should be fine.

How can I get the variant of the language on ios?

I have my Iphone set to English (UK) and I am trying to get the UK part in my flutter ap by doing this.
final languageCode = Platform.localeName.split('_')[0]; //prints en
final countryCode = Platform.localeName.split('_')[1]; //prints NL where I want UK
But my country code is alway NL which is my region. How can I get UK?
Its look like you want to access ISO Country Code
You can acces your device language country code with :
//Your device's all locales
final List<Locale> systemLocales = WidgetsBinding.instance!.window.locales;
//Your device's first(current) locale country code.
String? isoCountryCode = systemLocales.first.countryCode;
Following are the 3 ways I know to get locales:
Localizations.localeOf(context);
WidgetsBinding.instance.window.locale;
Platform.localeName;
Make sure to have the supportedLocales correctly setup in your MaterialApp which is only en_US by default, in order to have all available locale.
supportedLocales: [
const Locale('en', 'UK'),
const Locale('fr', 'CA'),
],
You may need to import and add to your pubspec.yaml 'package:flutter_localizations/flutter_localizations.dart';

ios application Localization

How can I set ios application supported languages?
e.g I use NSDate to get current day. If the device language is other than my supported languages NSDateFormatter returns "day" in device's language but I want to get in English if I don't support that language.
I know there is a way to get day in specific language using NSLocal but I don't want to do that way because I need to convert other strings as well.
The Apple documentation covers this pretty clearly. I know all you need is the word "day", but the following will help you include any word for any language if you do as follows:
1) You need to place all of the words (Strings) in your application into a single .swift file. Each word should be returned in a function that converts this string into the localized string per the device's NSLocal set in the device settings:
struct Localization {
static let all: String = {
return getLocalized("All")
}()
static let allMedia: String = {
return getLocalized("All Media")
}()
static let back: String = {
return getLocalized("Back")
}()
// ...and do this for each string
}
2) This file should also contain a static function that will convert the string:
static func getLocalized(_ string: String) -> String {
return NSLocalizedString(string, comment: "")
}
Here, the NSLocalizedString( method will do all of the heavy lifting for you. If will look into the .XLIFF file (we will get to that) in your project and grab the correct string per the device NSLocale. This method also includes a "comment" to tell the language translator what to do with the "string" parameter you passed along with it.
3) Reviewing all of the strings that you placed in your .swift file, you need to include each of those into an .XLIFF file. This is the file that a language expert will need to go over and include the proper translated word per string in the .XLIFF. As I stated before, this is the file that once included inside your project, the NSLocalizedString( method will search this file and grab the correct translated string for you.
And that's it!

How to retrieve a value for NSLocale .scriptCode in Swift

I'm trying to print some basic infos from NSLocale, but I'm not able to get a value back from the .scriptCode property.
Currently, the relevant bits are
let localeIdent = NSLocale.autoupdatingCurrent.identifier
let userLocale = NSLocale(localeIdentifier: localeIdent)
let languageScript = userLocale.scriptCode //not sure why this doesn't seem to return anything.
print("Language script code: \(languageScript)")
the print always returns 'nil'.
The locale returns the rest of the set of information for me, region and language and such, so I'm not sure why this wouldn't be stored / returning.
Not all locales have a script code. See the Language and Locale IDs section of the Internationalization and Localization Guide.
Locale identifiers can contain various parts such as the language code, script code, and region code. The script and region codes are optional.
Look at the documentation for Locale scriptCode for an example:
For example, for the locale “zh-Hant-HK”, returns “Hant”.
Simpler locales such as en_US or de_DE don't have a script code.

iOS strings file collision - Same string in source langage, different in target

So, I'm localizing an app from japanese to english.
In japanese, there is no distinction between (say) "Mr." and "Ms."(/"Mrs."), so I need to do something like this:
/* Salutation format for user (male) */
"%#様" = "Mr. %#";
/* Salutation format for user (female) */
"%#様" = "Ms. %#";
As you can see, the Japanese localization uses the same string in both cases. I was under the impression that, when the strings file contains more than one entry with the same 'source' (i.e., left side) string, the 'comment' was used to determine which one was employed. It turns out I was wrong, and the comment parameter is just an aid for human translators, totally ignored by NSLocalizedString().
So if I run the app, both of the code paths below produce the same string, regardless of the user's gender:
NSString* userName;
BOOL userIsMale;
/* userName and userIsMale are set... */
NSString* format;
if(userIsMale){
// MALE
format = NSLocalizedString(#"%#様",
#"Salutation format for user (male)");
}
else{
// FEMALE
format = NSLocalizedString(#"%#様",
#"Salutation format for user (female)");
}
NSString* salutation = [NSString stringWithFormat:format, userName];
So, how should I deal with a case like this?
Well, actually “left side” of the NSLocalizedString is a key. So you could do something like:
NSLocalizedString(#"SalutForUserMale", #"Salutation format for user (male)");
NSLocalizedString(#"SalutForUserFemale", #"Salutation format for user (female)");
Then in your base *.strings file (Japanese I presume) you would have:
"SalutForUserMale" = "%#様";
"SalutForUserFemale" = "%#様";
And in your English *.strings file you would have:
"SalutForUserMale" = "Mr. %#";
"SalutForUserFemale" = "Ms. %#";
The Localizable.strings files are nothing more than key value lists. You are using the Japanese phrases as keys which is unusual but I guess it works. I assume this is because the original app was developed in Japanese(?). I usually use English phrases keys, but whatever.
The point is that if you want two different phrases in even just one translation you have to have two different keys in all your translations. If there is something in your base language that is not distinguished but in the translations it is, then you can just "split" an existing key in two new ones. Just change it slightly or add a number, see below:
/* english .strings file */
"hello_world_key" = "Hello World";
"Yes1" = "Yes"; // same in english but different values in german
"Yes2" = "Yes";
/* german .strings file */
"hello_world_key" = "Hallo Welt";
"Yes1" = "Ja";
"Yes2" = "Jawohl";

Resources