iOS9 AppleLanguages different from older iOS - ios

How I get now the actual system language? It seems that they put regional suffix after last dash. So before cs is now cs-DE if the language is Czech and regional setting is German. But there are some languages which don't have the suffix like GB language is en-GB but regional setting is German.
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* language = [defs objectForKey:#"AppleLanguages"];
NSString* preferredLang = [language objectAtIndex:0];
NSLog(#"localeIdentifier: %#", preferredLang);

Use the componentsFromLocaleIdentifier method from NSLocale class
Here is the documentation
You can do like this:
NSString* localeID = [NSLocale currentLocale].localeIdentifier;
NSDictionary* components = [NSLocale componentsFromLocaleIdentifier:localeID];
NSString* languageID = components[NSLocaleLanguageCode];
EDIT
Getting the language this way will create some issues if the language the app is currently translated in is not the device's language. Indeed,
components[NSLocaleLanguageCode] will return the device's language.
To get the app's current language, you should use [[NSBundle mainBundle] preferredLocalizations].firstObject.
To get the device's region, you can still use components[NSLocaleCountryCode]

I just run into this problem recently. According to Apple's documentation, you will get the locale id with region designator which for like [language designator]-[region designator] on iOS 9.
I found a solution if you just wanna get the locale id, you could use
[[NSBundle mainBundle] preferredLocalizations].

One more solution, If any of you like,
NSArray *languages = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
NSString *currentLanguage = [languages objectAtIndex:0];
if ([[currentLanguage componentsSeparatedByString:#"-"] count] == 2)
currentLanguage = [[currentLanguage componentsSeparatedByString:#"-"] objectAtIndex:0];
// Only for chinese Language.
else if ([[currentLanguage componentsSeparatedByString:#"-"] count] == 3)
currentLanguage = [NSString stringWithFormat:#"%#-%#", [[currentLanguage componentsSeparatedByString:#"-"] objectAtIndex:0],
[[currentLanguage componentsSeparatedByString:#"-"] objectAtIndex:1]
];
"currentLanguage" Will give you your current langauge so you can use it for localise or any further use.

Related

Is there a way to change the iphone application language during runtime?

My app supports localization for english and hungary languages.
I want to make default language as hungary instead of english if user sets default language other than english or hungary from phone settings .
For eg.If user's phone settings language is French,as my app is not support for french localization , so it should be launched in hungary as default not in english.
I have used following code in didFinishLaunchingWithOptions method in app delegate :
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"AppleLanguages"];
[NSUserDefaults resetStandardUserDefaults];
NSLog(#"%#",[NSLocale preferredLanguages]);
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([language isEqualToString:#"en"])
{
NSArray *langOrder = [NSArray arrayWithObjects:#"en", nil];
[[NSUserDefaults standardUserDefaults] setObject:langOrder forKey:#"AppleLanguages"];
}
else
{
NSArray *langOrder = [NSArray arrayWithObjects:#"hu", nil];
[[NSUserDefaults standardUserDefaults] setObject:langOrder forKey:#"AppleLanguages"];
}
So, after the change in the language from phone setting [[NSLocale preferredLanguages] objectAtIndex:0] immediately returns the string for the new language , ie. correct current language and also entered in correct condition in code.
But language will change only at second time relaunch of the app , not in first time launch.
So how can i do this ?
Thanks..

Speech Synthezis API : which locale is used by NSLocalizedString?

I want to use iOS 7 new speech synthezis API, and my application is localized in french & english.
For this to work, 2 things have to be localized :
speech text : I put it in usual localizable.string file, and retrieve it in code using NSLocalizedString macro.
speech language : AVSpeechSynthesisVoice has to be chosen for corresponding language.
Class instanciation method is AVSpeechSynthesisVoice voiceWithLanguage:(NSString *)lang.
I'm currently using [NSLocale currentLocale].localeIdentifier as parameter for this method.
Problem : if user's device language is Portuguese, [NSLocale currentLocale] select portuguese prononciation, while text resolved by NSLocalizedString is english.
How can I know which locale is currently read by NSLocalizedString ?
Ok, I finally managed to make sense of Apple APIs :
[NSLocale currentLocale] : DOESN'T return current language picked by User in Settings > General > international, but returns the region code selected by user in same screen.
[NSLocale preferredLanguages] : This list DOES give device language, it's the first string in this list
[[NSBundle mainBundle] preferredLocalizations] return language bundle resolved by application. I guess this is what NSLocalizedString uses. It only has 1 object in my case, but I wonder in which cases it can have more than one.
[AVSpeechSynthesisVoice currentLanguageCode] returns the system predefined language code.
[AVSpeechSynthesisVoice voiceWithLanguage:] class instanciation method needs complete language code : with language AND region. (e.g. : passing #"en" to it will return nil object, it needs #"en-US", or #"en-GB"... )
[AVSpeechSynthesisVoice currentLanguageCode] gives default voice, determined by OS.
So this is what my final code looks like
// current user locale (language & region)
NSString *voiceLangCode = [AVSpeechSynthesisVoice currentLanguageCode];
NSString *defaultAppLang = [[[NSBundle mainBundle] preferredLocalizations] firstObject];
// nil voice will use default system voice
AVSpeechSynthesisVoice *voice = nil;
// is default voice language compatible with our application language ?
if ([voiceLangCode rangeOfString:defaultAppLang].location == NSNotFound) {
// if not, select voice from application language
NSString *pickedVoiceLang = nil;
if ([defaultAppLang isEqualToString:#"en"]) {
pickedVoiceLang = #"en-US";
} else {
pickedVoiceLang = #"fr-FR";
}
voice = [AVSpeechSynthesisVoice voiceWithLanguage:pickedVoiceLang];
}
AVSpeechUtterance *mySpeech = [[AVSpeechUtterance alloc] initWithString:NSLocalizedString(#"MY_SPEECH_LOCALIZED_KEY", nil)];
frontPicUtterance.voice = voice;
This way, a user from NewZealand, Australien, GreatBritain, or Canada will get the voice that correspond most to his usual settings.
Vinzzz's answer was a great start -- I've generalised it to work with any language:
NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
NSString *voiceLangCode = [AVSpeechSynthesisVoice currentLanguageCode];
if (![voiceLangCode hasPrefix:language]) {
// the default voice can't speak the language the text is localized to;
// switch to a compatible voice:
NSArray *speechVoices = [AVSpeechSynthesisVoice speechVoices];
for (AVSpeechSynthesisVoice *speechVoice in speechVoices) {
if ([speechVoice.language hasPrefix:language]) {
self.voice = speechVoice;
break;
}
}
}

Is it possible to "redirect" localizations on iOS?

What I want is simple:
My app has only two languages: English and Simplified Chinese. And I hope that if the system language is Simplified or Traditional Chinese, then Simplified Chinese is used; otherwise English is used.
It seems that most user don't know they can set their secondary preferred language. So I cannot rely on them.
You can use this code to retrieve the user language and set the app language:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Reset system defaults to get the complete language list.
[defaults removeObjectForKey:#"AppleLanguages"];
// Default language choosen by user.
NSString *defLanguage = [defaults objectForKey:#"Language"];
NSArray *sysLangugages = [defaults arrayForKey:#"AppleLanguages"];
// System default language: first element of array.
NSString *sysLanguage = [sysLangugages objectAtIndex:0];
NSArray *array = [NSArray arrayWithObjects:defLanguage, sysLanguage, nil];
LocalizationSetLanguage(defLanguage);
[defaults setObject:array forKey:#"AppleLanguages"];
//To set and get the saved language
// in the .h
#define LocalizationSetLanguage(language) \
[[LocalizationSystem sharedLocalSystem] setLanguage:(language)]
//in the .m
- (void) setLanguage:(NSString*) language
{
lang = language;
}
- (NSString*) getLanguage
{
if (!lang) {
NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
NSString *preferredLang = [languages objectAtIndex:0];
lang = preferredLang;
}
return lang;
}
Use AMLocalizedString, you can use this to set your local Language.

iOS localization - won't recognize es-US vs es-MX

I'm trying to show a different string for Mexican Spanish than US Spanish. The app always displays the US Spanish phrase. FYI - English, French and Portuguese work fine - but they don't have locales specified.
I created the localization folder in Build Settings->Localizations by clicking the + button, and selecting Spanish (Mexico)(es-MX) and Spanish (United States)(es-US) from the "Other" menu. I then updated the phrases appropriately. In the project I see 5 Localizable.strings files, including (Spanish-Mexico) and (Spanish-United States). Similarly I see the expected folders in Finder, including es-MX and es-US.
I put some NSLog messages in application didFinishLaunchingWithOptions:
NSLog(#"preferredLocalizations=%#", [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);
NSLog(#"localization array=%#, count=%d", [[NSBundle mainBundle] preferredLocalizations], [[[NSBundle mainBundle] preferredLocalizations] count]);
NSLog(#"preferredLanguage = %#", [[NSLocale preferredLanguages] objectAtIndex:0]);
NSLog(#"language array=%#, count=%d", [NSLocale preferredLanguages], [[NSLocale preferredLanguages] count]);
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:#"AppleLanguages"];
NSString *current = [languages objectAtIndex:0];
NSLog(#"user default language=%#", current);
The output is:
2013-07-30 22:21:24.911 ecatalog[33497:907] application:didFinishLaunchingWithOptions
2013-07-30 22:21:24.918 ecatalog[33497:907] preferredLocalizations=es
2013-07-30 22:21:24.920 ecatalog[33497:907] localization array=(
es
), count=1
2013-07-30 22:21:24.922 ecatalog[33497:907] preferredLanguage = es
2013-07-30 22:21:24.924 ecatalog[33497:907] language array=(
es,
en,
fr, <snipped a bunch for brevity>
ms,
"en-GB",
ca,
hu,
vi
), count=34
2013-07-30 22:21:24.926 ecatalog[33497:907] user default language=es
The language array seems to the list of available languages on the phone, in my preferred order - i.e., if I set the phone for French, fr will be at the top of the list.
I don't know if its related, but my project includes two 3rd party frameworks which support Spanish, but just the es.lproj variation - not es-MX.lproj or es-US.lproj.
One other "symptom" - running the app in the simulator alternates between English and whatever language I have set the simulator to.
Thanks!
In my case I only have one string that needs to be different between Mexican and US Spanish, and it is only used in one place. So my work-around is to manually check the locale and hard-code the Mexican Spanish string:
NSString *startString;
// HACK - to diferentiate between Mexican Spanish and all others
NSLocale* curentLocale = [NSLocale currentLocale];
NSString *localId = [curentLocale localeIdentifier];
if ([localId isEqualToString: #"es_MX"]) {
// hard code a string
startString = #"Para seleccionar un folleto da clic +";
} else {
startString = NSLocalizedString(#"Click + to start!", nil);
}
It doesn't feel right, so if anyone has "the right way" I'd appreciate it.

iOS: How to Get the Device Current Language Setting?

There are some features within my application that are supposed to be based on the language settings of the device where it's running.
I want to get the actual language and not some country settings. Foe example, if the language is English, I don't care if it's US, UK, Australia, etc...
I'm familiar with the NSLocale object, but it seems to relate to the Region Format setting and not to the Language setting (see screen shot below) so when I try to retrieve the language out of it using [locale displayNameForKey:NSLocaleIdentifier value:[locale localeIdentifier] I get things like English (United States) instead of English; also, I think that what I need is the Language data and not the Region Format (am I right?).
Can anyone direct me to how to retrieve the language setting?
User preferred languages are stored can be retrieved from locale as array and current language identifier is the first object in that array:
NSString *currentLanguage = [[NSLocale preferredLanguages] objectAtIndex:0];
If you want language in more readable form then use displayNameForKey:value: method of NSLocale:
NSString *langID = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString *lang = [[NSLocale currentLocale] displayNameForKey:NSLocaleLanguageCode value:langID];
Try this:
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSArray* arrayLanguages = [userDefaults objectForKey:#"AppleLanguages"];
NSString* currentLanguage = [arrayLanguages objectAtIndex:0];
Getting language and region in Swift:
LF.log("language", NSLocale.preferredLanguages())
LF.log("locale", NSBundle.mainBundle().preferredLocalizations)
In my case I'm getting:
language: '(
"zh-Hans"
)'
locale: '(
en
)'
In Swift 4:
let currentLanguage = Locale.current.languageCode
It will give you just the language code, no country code.
Swift:
let language = NSBundle.mainBundle().preferredLocalizations[0] as NSString
Working solution:
let language = NSLocale.preferredLanguages()[0]
let languageDic = NSLocale.componentsFromLocaleIdentifier(language) as NSDictionary
//let countryCode = languageDic.objectForKey("kCFLocaleCountryCodeKey")
let languageCode = languageDic.objectForKey("kCFLocaleLanguageCodeKey") as! String
print(languageCode)
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
Find the solution in XCode's helper document, it wrote:
Getting the Current Language
To get the language that the app is using from the main application bundle, use the preferredLocalizations method in the NSBundle class:
NSString *languageID = [[NSBundle mainBundle] preferredLocalizations].firstObject;
Use below code to fetch Localised language without having trouble to the en-india, en-us etc..
NSString *Ph = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
In and After ios9 this code need to take in cosideration
To know the current language selected within your localizations use
[[NSBundle mainBundle] preferredLocalizations]
Example:
NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
To get two letter word
NSString *language = [[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0] substringToIndex:2];
Swift:
let language = NSBundle.mainBundle().preferredLocalizations.first as NSString

Resources