How to get detailed language of device in swift - ios

I have a database on the server that contains all the languages keywords that I use inside my applications and these languages could be changed any time.
In the language table of database there is column for Language (id , key, value, lang).
In the android application I read the language from device and it returns for example en-GB or en-US.
But in the iOS application I can't get the language like the above example , It always returns just the language (en , es, fr).
So I can't query to database to get the language specified keywords on the iOS application. Because the languages on the database is en-GB, en-US style.
var langId: String? = NSLocale.preferredLanguages().first as? String
How can I get the language with more details ?

Start with the currentLocale() and ask questions about it. For example:
let lang = NSLocale.currentLocale().localeIdentifier
Or, at a finer level of granularity:
let langId = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode) as! String
let countryId = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as! String
let language = "\(langId)-\(countryId)" // en-US on my machine

Swift 3 does not have an NSLocaleCountryCode, this is replaced by regionCode
https://developer.apple.com/reference/foundation/nslocale.key/1417845-countrycode
solution in Swift 5:
let langCode = Locale.current.languageCode ?? ""
let regionCode = Locale.current.regionCode ?? ""
let language = "\(langCode)-\(regionCode)"
Another solution is NSLocale.current.identifier
This will return e.g. en_us
You could replace _ for -. it will look like this: NSLocale.current.identifier.replacingOccurrences(of: "_", with: "-")

No need an extra effort, just use the following as per your requirement.
Locale.current.identifier //en_US
Locale.current.collatorIdentifier //en-US

For Swift 4 use instead:
NSLocale.current.identifier //Output: en-US, pt-BR

Swift 5
Locale.currentLanguage.rawValue

just use this code line can solve:
let identifier = Locale.current.identifier

Related

Localizing a naturally-formatted list of API data

Say I've downloaded this list of data from an API:
[
"Anita",
"Jean",
"Peter"
]
I'd like to list this data in a natural sentece format. For example, in US English, this string should be displayed to the user:
Anita, Jean, and Peter
However, if the user is Swedish for example, they should see this string:
Anita, Jean och Peter
Notice that the Oxford comma is missing, and Swedish uses a different word for "and", which is what a Swedish user would expect to see. How can I format this data in a natural-language way that would respect the user's locality? There can be a variable amount of data, not necessarily just 3 items. My instinct is to subclass Formatter/NSFormatter, but I'd like to build this in a way I can easily expand it to support languages that I don't speak, so I'm wondering if there's an iOS-standard or 3rd party formatter that I haven't been able to find in my searches
Starting with iOS 13, Foundation has a ListFormatter type. According to your needs, you can use it in different ways to get a textual representation of your array.
The simplest way to use ListFormatter is to use its static localizedString(byJoining:) method. The following Swift 5.1 / iOS 13 Playground sample code shows how to implement this method in order to convert your array into a localized string representation:
import Foundation
let array = [
"Anita",
"Jean",
"Peter"
]
let string = ListFormatter.localizedString(byJoining: array)
print(string) // prints: Anita, Jean, and Peter (for en_US locale)
As an alternative to localizedString(byJoining:), you can create an instance of ListFormatter and use string(from:) method. This can be useful if you need to specify a locale for your textual representation:
import Foundation
let array = [
"Anita",
"Jean",
"Peter"
]
let listFormatter = ListFormatter()
listFormatter.locale = Locale(identifier: "fr_FR") // set only if necessary
let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("Anita, Jean et Peter")
If needed, you can also set the itemFormatter property of your ListFormatter instance with a specialized formatter type:
import Foundation
let array = [
55,
112,
8
]
let locale = Locale(identifier: "es_ES") // set only if necessary
let numberFormatter = NumberFormatter()
numberFormatter.locale = locale
numberFormatter.numberStyle = NumberFormatter.Style.spellOut
let listFormatter = ListFormatter()
listFormatter.locale = locale
listFormatter.itemFormatter = numberFormatter
let string = listFormatter.string(from: array)
print(String(describing: string)) // prints: Optional("cincuenta y cinco, ciento doce y ocho")
In previous versions of iOS, this question remains unsolved and I'd still appreciate an answer if you have one. However, iOS 13 exposes NSListFormatter, which can be used to do exactly this. For example:
Swift:
ListFormatter().localizedString(byJoining: ["Anita", "Jean", "Peter"])
Objective-C:
[[NSListFormatter new] localizedStringByJoiningStrings:#["Anita", "Jean", "Peter"]];

Set default language with localization

Is it possible to use a default language for the localization? for example if a key is not found for one language, than the system will look at it automatically in the English language? If it's not possible to do it automatically, would it be possible to do it manually? look for a key in the current language, if not found then force the system to look at it in the English language? In my current app, when a key is not set, the key name is returned.
Here is a method that do what you want (I didn't find an "official" way to do it).
func localizedString(_ key: String) -> String? {
let localeString = NSLocalizedString(key, comment: "")
// Base can be changed by en or the default language of your choice
if localeString == key,
let path = Bundle.main.path(forResource: "Base", ofType: ".lproj"),
let baseBundle = Bundle(path: path) {
return baseBundle.localizedString(forKey: key, value: nil, table: nil)
}
return nil
}

Wrong language code swift

I set the language of the simulator to French. To check the language code, I used a couple of solutions:
let lang = NSLocale.autoupdatingCurrent.languageCode
print(lang)
let pre = Locale.preferredLanguages[0]
print(pre)
The result are:
Optional("en")
fr-US
What I expected to get is:
fr
How can I achieve that?
Try below code,
let requiredString = pre.components(separatedBy: "-").first ?? pre //fr
/*if pre.contains("-"), then requiredString = before("-") else requiredString = pre*/
print(Locale.components(fromIdentifier: Locale.preferredLanguages[0])["kCFLocaleLanguageCodeKey"]!)
this will print language code only.
If you want the Language instead of the Language_Region, then I suggest to take the sub string before the _ from the string to neglect the Region.
(If the string contains no _ then take the entire string since it doesn't contain the region in it)

How to compare Localized string with the string from the database?

I have a to compare a string with the string from the db.
var variableFromDB = "test"
if "test" == variableFromDB{
print("Success")
}
It works fine in the English Language. I don't know how to compare it in the arabic language. Is the need to check in arabic language also. Please tell me know to check it.
In general it's a bad idea for your code to make decisions based on display strings. That goes double for display strings.
If your primary audience is Arabic-speaking, you could make your development language Arabic and then localize for other languages as needed.
In any case, I would suggest using a set of fixed strings as keys, and then calling NSLocalizedString(_:tableName:bundle:value:comment:) or one of it's variants to fetch a display string. Example:
Put this code somewhere central so the keys can be shared:
let screen1Prompt = "screen1Prompt"
Then when you need a localized string for display:
let prompt = NSLocalizedString(screen1Prompt)
Where the actual prompt string might be "Please select the date for your payment." in English, Arabic, etc.
Then if you need to match something in your database, look it up using the unlocalized key, not the localized display string.
That way if you later change the display string, your code still works.
var language: String
UserDefaults.standard.set("AE", forKey: "Apple") // manually set language
UserDefaults.standard.synchronize()
self.language = UserDefaults.standard.object(forKey: "Apple")as! String
// self.language = Locale.current.languageCode // your device language
extension String {
func stringlocalized(lang:String) ->String {
let path = Bundle.main.path(forResource: lang, ofType: "lproj")
let bundle = Bundle(path: path!)
return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
}}
// Check You Localization string from your current language
let str = “ test”.localized(lang: self.language! )
if str ==variableFromDB
{ // Your logic here
}

Can I use iOS9 Contacts Framework to get a formatted phone number?

I would like to be able to store a phone number in a standard way, e.g. just the digits (potentially with the '+' for the country code), something like these examples...
"17185555555"
"+17185555555"
"+447788888888"
... but I'd like to be able to DISPLAY it to a user in a properly formatted way, e.g.
"1 (718) 555-5555"
"+1 (718) 555-5555"
"+44 (7788) 888888"
...WITHOUT having to rely on a CNContactViewController to format it.
Obviously doing this just for US/Canada numbers would be easy - it's just one standard format - but I'd like it to be generic so it can work for numbers from any country. I know this question gives an answer for US/Can numbers only.
I know that I could use a CNContactViewController to display the number in the correct format, e.g.
let newContact = CNMutableContact()
newContact.givenName = "John"
newContact.familyName = "Smith"
newContact.phoneNumbers = [CNLabeledValue(label: CNLabelPhoneNumberiPhone, value: CNPhoneNumber(stringValue:"17185555555"))]
let contactView = CNContactViewController(forContact: newContact)
self.presentViewController(contactView, animated: true, completion: nil)
This will show the number on screen properly formatted, i.e.
1 (718) 555-5555
... so I know that something in the framework can do it. (This approach works for other country phone number formats, as long as you prefix the number with the right country code - e.g. "+44...")
From various other questions I know that I can get the raw digits and country code out of a CNContact, e.g. (following above example)
for pNumber: CNLabeledValue in newContact.phoneNumbers {
let value = pNumber.value as! CNPhoneNumber
let cc = value.valueForKey("countryCode") as? String
let digits = value.valueForKey("digits") as? String
print("cc:" + cc + ", " + digits)
}
... but this will just show the unformatted string again - not what I am looking for in this case.
Any help or other recommended approaches really appreciated!
My answer proposes another lib
You can format your numbers with this lib.
And you can use like this:
let phoneNumber: NBPhoneNumber = try phoneUtil.parse("17185555555", defaultRegion: yourRegion)
let formattedString: String = try phoneUtil.format(phoneNumber, numberFormat: .E164)

Resources