How to get Localized NSError - ios

I have done a lot of google search without success.
I would like to use the system localization of NSError (In my case in french)
I have try many things but the wording are always in english.
The configuration off my app :
In the plist :
CFBundleDevelopmentRegion = fr_FR
In the pbxproj:
developmentRegion = fr;
knownRegions = (
fr,
Base,
);
When I call the property "localizedDescription" I always get english version like this link (NSError localizedDescription always returns english error message) but the solution doesn't work for me...
I don't found what I'm missing.
In this other link NSURLConnection returns NSError with only english as language? they copy the strings but I don't think it's the better way, we should be able to access the file without copy it.
For information when I use an UIBarButtonItem like Cancel, it's localized in french.
Thanks in advance for your help.

First you should have a localisation file with key and value strings.
Now when you want to show the localisation error, you can use following method
NSLocalizedString(<#key#>, <#comment#>)

I have had the same issue the solution was to set the info.plist attribute Localization native development region to your region: France in this case

Related

Localization of the googleCast framework not working

I'm trying to find a way to localize the google cast sample app.
When I look at the documentation I see that we need to set some launch options when we create the sharedInstance. So in the sample app his appdelegate I changed the setSharedInstance part to this:
let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
options.physicalVolumeButtonsWillControlDeviceVolume = true
let launchOptions = GCKLaunchOptions(languageCode: "fr", relaunchIfRunning: false)
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
I also tried fr-FR and other language codes and also tried to set 'relaunchIfRunning' to true. But It seems that none of that is working.
Anybody succeeded in changing the language of the googlecast screens?
Kind regards,
Stef
You must localize the Setting.bundle as well. And this is done manually using text edit :(
Settings.bundle:
Root.plist
en.lproj:
Root.strings
fr.lproj:
Root.strings
en.lproj, ru.lproj folders
Root.strings - file
Add the language in your project file, that worked for me.

How to always get english string from NSError?

I've got an iOS application that is designed with English-only strings. When running on an iOS device that is using another language for display (i.e. Settings/General/Language/iPhoneLanguage is something non-English) I would like to also show system errors in English since my font can't display non-english characters at the moment.
Is there a way to always get the english error message from NSError? Or to lookup the english error string in the system somehow manually?
After digging around I found a potential workaround.
First, it turns out that in most cases, iOS is returning English strings from [myNSError localizedDescription] when I'm running on a system that has the region set to, say, France, with the language set to, say, French. I believe this is because I have CFBundleDevelopmentRegion set to "en" in my info.plist. This is what I wanted to happen since I am trying to build an app that runs fully in English everywhere (for the moment).
However, in some cases, like if you try to buy something in the app and the network is off (this is my most reliable repro case), I will get NSErrors that return a localized error from [myNSError localizedDescription]. In this case: "Connexion à l’iTunes Store impossible."
When I get an error like this, a workaround that kinda works is to create an NSError manually using the domain and error code from the original. If you then ask it for the localizedDescription it will give you one in English, but it seems to be more general. In this case: "The operation couldn’t be completed.". What appears to be happening is that the system is filling in more detailed errors using the local language.
string GetEnglishLocalizedDescription(NSError *originalError)
{
if(originalError == nil)
{
return "";
}
else
{
NSString *originalNSErrorString = [originalError localizedDescription];
string originalUtf8String = originalNSErrorString == nil ? "" : [originalNSErrorString UTF8String];
// If we have a character outside of the US Ascii range
// Our font won't display it properly and this is probably
// a localized description
// https://tools.ietf.org/html/rfc3629
bool isUSAscii = true;
for(uint8_t c : originalUtf8String)
{
if(c > 0x7F)
{
isUSAscii = false;
break;
}
}
if(!isUSAscii)
{
// Has non-US Ascii characters, probably localized, get the standard error instead
NSString *englishNSErrorString = [[NSError errorWithDomain:originalError.domain code:originalError.code userInfo:nil] localizedDescription];
string englishUtf8String = englishNSErrorString == nil ? "" : [englishNSErrorString UTF8String];
return englishUtf8String;
}
else
{
return originalUtf8String;
}
}
}
Then, the trick is to figure out when you want to do this because you can't really tell in an obvious way that you got an error in the local language. In my case, I can just look for characters that my font can't display and convert it. If my font can display it, I guess I'm OK displaying it since either:
a) it is in english and the whole app is so nothing surprising or
b) it is actually localized just happens to be a string that has characters that are all also English characters. In this case, presumably the user will be able to read it in their local language.
One final gotcha using the code/algorithm above: It turns out the English error messages that Apple uses don't stick to the normal ASCII character set. They will use the fancy apostrophe in Unicode as opposed to the ASCII "'". So, the code above will think that is a "localized" message. Unclear what other characters they do this with. So this isn't really a full solution. It does solve the original question of "How do I always retrieve an English error message", but it doesn't fully solve my problem since i have no idea how to build a font that will even show all English error messages. Sigh.
Still have to decide the best approach here, but it is something.

Which NSLocale to use with uppercaseStringWithLocale:?

When I have an UI string with capital letters, i'm used to define them in lowercase as for all the others, and then to use uppercaseStringWithLocale:[NSLocale currentLocale].
But recently I happened to notice that the [NSLocale currentLocale] may not be the one used in your app. For example if your device is in Turkish but your app only support english, the currentLocale would be a Turkish locale while your app is localized in english.
With those settings, a direct effect of using [NSLocale currentLocale] is that my uppercaseString will be "İ LİKE İOS" instead of "I LIKE IOS".
So far, the only workaround I see is to create a category of NSLocale to add a +(NSLocale*) applicationLocale; and use it in all uppercaseStringWithLocale:.
+ (NSLocale*) applicationLocale
{
NSMutableDictionary<NSString*,NSString*>* localeComponents = [[NSLocale componentsFromLocaleIdentifier:[NSLocale currentLocale].localeIdentifier] mutableCopy];
localeComponents[NSLocaleLanguageCode] = NSBundle.mainBundle.preferredLocalizations.firstObject;
return [NSLocale localeWithLocaleIdentifier:[NSLocale localeIdentifierFromComponents:localeComponents]];
}
My question is simple: am I doing this the right way or did I miss something? I indeed wonder why Apple links to currentLocale while it won't work as expected in a lot of cases.
The most robust way to get the application locale is to edit your Localizable.strings files. In the English localization file add an entry
"lang"="en";
in the German localization file add an entry
"lang"="de";
in the French localization file add an entry
"lang"="fr";
and so on... You can get the localization code with NSLocalizedString(#"lang").

localizedStringForKey:value:table ignores Base localization

My application need to be localised in 2 languages: German and English. German should be Base language. It means that app should always localize to German except the language on device is english (in this case it should be on english)
I have custom *.string files for localisation and use localizedStringForKey:value:table to localise strings.
When I have only base localisation everything works fine. But in case if I add english localisation, in some reason localizedStringForKey:value:table just ignore Base localisation and always use English (for all languages)
Here how it looks like after I've added english:
and here is how I localise strings:
[[NSBundle mainBundle] localizedStringForKey:#"key" value:#"" table:#"Shared"]
I'm testing on simulator and here is my language screen:
Does anybody know what could be a problem? Thanks in advance!
As I mentioned in the comments, you need to set the Localization native development region (CFBundleDevelopmentRegion) in the Info.plist to your language code. Xcode seems to set it to a en_GB or de_DE style region code, setting it to de (no region) will fix it. Note that by default it is en, but selecting United Kingdom or Germany will change it to use the longer codes.
I have another solution, I think it works for you:
NSString* NSCustomLocalizedString( NSString *key , NSString *comment)
{
NSString *rs = nil;
if( [[NSUserDefaults standardUserDefaults] integerForKey:KEY_LANGUAGE ] == e_language_japanese)
{
rs = NSLocalizedStringFromTable(key,#"Localizable.strings-ja",nil);
}
else
{
rs = NSLocalizedStringFromTable(key,#"Localizable.strings-en",nil);
}
return rs;
}

Finding the current localization of iOS app in code

Connected issue: Non-English default language for iOS App?
I am wondering how to check the current localization of my app in code.
For example:
I want to check if the app is running with German localization (.strings, storyboard)
This line of code:
[[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:#"de"]
doesn't provide the correct answer. Because if a user's language list in device settings looks like this for example (french, german, english) and we have only localization for english and german, application is launched in german but the above condition isn't fulfilled.
My naive solution would be to create a localized string "LanguageCode" which is set to "de" in the german string file and to "en" in the english string file
e.g.:
if ([NSLocalizedString(#"LanguageCode", #"en, de etc.") isEqualToString:#"de"]) {
// german
}
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];
This will return a two letter code for the currently selected language. "en" for English, "es" for Spanish, "de" for German, etc. For more examples, please see this Wikipedia entry (in particular, the 639-1 column):
Check the first entry of Bundle's preferredLocalizations property, which is:
an array of NSString objects containing language IDs for localizations
in the bundle. The strings are ordered according to the user's
language preferences and available localizations.
For example, if you're checking to see if your German localization are being used:
if Bundle.main.preferredLocalizations.first == "de" {
// Is using German
}

Resources