UIWebview not loading the correct localized version of website - ios

In my app I have a link in the menu that takes the user to our FAQ page online. I'm using a webview to load the page and so far so good.
But the problem is, my online page auto detects the user language and loads the correct localized version of the page.
If I open safari on the simulator and load my url, it gets redirected to the correct localized version of it, but using UIWebview on the app it loads the english (default) language.
I've done some research online, but couldn't find anything related to this matter.
Is there something I can/need to pass in order to the correct localized version to be loaded?
Thanks
EDIT:
I'm currently getting the phone language and passing in the URL, but what I'm looking for is for the UIWebview to behave like safari does, by calling the main URL and having the website choose the version based on your language.

You can get the app supported languages as an array of strings with [[NSBundle mainBundle] localizations]; and compare it with the system language like this:
+ (NSString *)preferredLanguage {
NSString *res = #"en";
NSArray *appSupportedLanguages = [[NSBundle mainBundle] localizations];
NSArray *appleLanguages = [NSLocale preferredLanguages];
if (appleLanguages && appleLanguages.count > 0) {
NSString *shortLangId = [appleLanguages.firstObject substringToIndex:2];
if ([appSupportedLanguages containsObject:shortLangId]) {
res = shortLangId;
}
}
return res;
}
The reason i'm using the shortened version here is that iOS 9 changed some languages' ids and it breaks my app — you should probably make some minor changes here. Nevertheless, this method allows you to get the language id you can use to open the proper FAQ page either like https://.../faq_fr.htm or with some server-side processing like https://...?lang=fr.

Related

Creating Custom URL Scheme in iOS using Objective C

I am working on custom URL scheme basically i am new with us functionality.
What i done before?
I implemented this successfully,i create simple url "myApp" now when i hit this url on safari like (myApp://) its launch my application.
My code
i used:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
What i want?
Basically i want to implement two things that is:
when an user hit a link on safari if an application is installed on device,through that link application should launch.That point i already done successfully.
The second point which i can't done yet,after trying a lot but i couldn't found any solution yet,that is:
If an application is not installed on device that link should redirect to app store where user can installed application.
If it is possible,then please tell me how to do that,please refer me any link,example or your answer also help me.Thanks in advance
What you are describing is called Deep Linking. It's a very common app feature to implement — most apps have it — and conceptually, it seems like an easy thing to build. However, it's complicated to get right, and there are a lot of edge cases.
You basically need to accomplish two things:
If the app is installed: open the app and route users to the correct content inside it.
If the app is NOT installed: forward users to the App Store so they can download it. Ideally, also route users to the correct content inside the app after downloading (this is known as 'deferred deep linking').
While not required, you'll also probably want to track all of this activity so you can see what is working.
If the app is installed
Your existing custom URI scheme fits into this category. However, Apple has decided that custom URI schemes are not a good technology, and deprecated them with iOS 9 in favor of Universal Links.
Apple is right about this. Custom URI schemes have a number of problems, but these are the biggest:
There is no fallback if the app isn't installed. In fact, you get an error.
They often aren't recognized as links the user can click.
To work around these, it used to be possible to use a regular http:// link, and then insert a redirect on the destination page to forward the user to your custom URI scheme, thereby opening the app. If that redirect failed, you could then redirect users to the App Store instead, seamlessly. This is the part Apple broke in iOS 9 to drive adoption of Universal Links.
Universal Links are a better user experience, because they are http:// links by default and avoid nasty errors. However, they are hard to set up and still don't work everywhere.
To ensure your users end up inside the app when they have it installed, you need to support both Universal Links and a custom URI scheme, and even then there are a lot of edge cases like Facebook and Twitter which require special handling.
If the app is NOT installed
In this case, the user will end up on your http:// fallback URL. At this point, you have two options:
Immediately forward the user directly to the App Store.
Send the user to your mobile website (and then use something like a smart banner to give them the option of going to the App Store).
Most large brands prefer the second option. Smaller apps often go with the first approach, especially if they don't have a website.
To forward the user to the App Store, you can use a Javascript redirect like this:
<script type="text/javascript">
window.onload = function() {
window.location = "https://itunes.apple.com/app/id1121012049";
};
</script>
Until recently, it was possible to use a HTTP redirect for better speed, but Apple changed some behavior in Safari with iOS 10.3, so this no longer works as well.
Deferred deep linking
Unfortunately there's no native way to accomplish this last piece on either iOS or Android. To make this work, you need a remote server to close the loop. You can build this yourself, but you really shouldn't for a lot of reasons, not the least of which being you have more important things to do.
Bottom line
Deep linking is very complicated. Most apps today don't attempt to set it up by building an in-house system. Free hosted deep link services like Branch.io (full disclosure: they're so awesome I work with them) and Firebase Dynamic Links can handle all of this for you, and ensure you are always up to date with the latest standards and edge cases.
See here for a video overview I made of everything you need to know about this.
In AppDelegate.m call this:
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options;{
NSLog(#"url recieved: %#", url);
NSLog(#"query string: %#", [url query]);
NSLog(#"host: %#", [url host]);
NSLog(#"url path: %#", [url path]);
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(#"query dict: %#", dict);
if ([[url host] isEqualToString:#"login"]) {
[self setupHomeScreen:NO type:#"" entityId:#""];
[self _endSession];
return YES;
} else if ([[url host] isEqualToString:#"smartoffice"]) {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSRange needle = [url.absoluteString rangeOfString:#"?" options:NSCaseInsensitiveSearch];
NSString *data = nil;
if(needle.location != NSNotFound) {
NSUInteger start = needle.location + 1;
NSUInteger end = [url.absoluteString length] - start;
data = [url.absoluteString substringWithRange:NSMakeRange(start, end)];
}
for (NSString *param in [data componentsSeparatedByString:#"&"]) {
NSArray *keyvalue = [param componentsSeparatedByString:#"="];
if([keyvalue count] == 2){
[result setObject:[keyvalue objectAtIndex:1] forKey:[keyvalue objectAtIndex:0]];
}
}
NSString *entityID = ([result objectForKey:#"secondparameter"]);
NSString *type = [result objectForKey:#"parameter"];
[self setupHomeScreen:YES type:type entityId:entityID];
//[self setupHomeScreen:YES type:#"TASK" entityId:#"160315"];
return result;
} else {
NSLog(#"myApp is not installed");
[self setupHomeScreen:NO type:#"0" entityId:#"0"];
}
return NO;
}
Open Xcode, got to Project Settings -> Info, and add inside ‘The URL Types” section a new URL scheme.
That is the scheme ://resource. So we go ahead and type com.myApp://
Fo me its backofficeapp://
Now use this link on Safari
backofficeapp://smartoffice/1?parameter=TASK&secondparameter=157536
Where
parameter = “TASK”
secondparameter = “taskID” // #iOS Mobile 2020 = 157536
This parameter is for landing on a specific screen.
Remember this URL won’t work if the app is not installed.

How to translate app in to another language in iOS?

I am developing an ecommerce app. Initially the app is in the English language and now I want to convert it into the Chinese and French language. I referred to this link
So what I have understood is that every text we need to convert into French and Chinese, in the respective string files for the static data, but I am getting data from the backend. So then how do I convert that text dynamically?
You can use this code. And in Project you can add localisations in info.plist.Hope it will help you.Thank You
NSLocale* curentLocale = [NSLocale currentLocale];
namearray=[NSMutableArray arrayWithObjects:NSLocalizedString(#"Hellokey1",#""),NSLocalizedString(#"Hellokey2",#""),NSLocalizedString(#"Hellokey3",#""),NSLocalizedString(#"Hellokey4",#""),NSLocalizedString (#"Hellokey5",#""),NSLocalizedString(#"Hellokey6",#""),NSLocalizedString(#"Hellokey7",#""),NSLocalizedString(#"Hellokey8",#""),NSLocalizedString(#"Hellokey9",#""),NSLocalizedString(#"Hellokey10",#""),NSLocalizedString(#"Hellokey11",#""),NSLocalizedString(#"Hellokey12",#""),NSLocalizedString(#"Hellokey13",#""),NSLocalizedString(#"Hellokey14",#""),NSLocalizedString(#"Hellokey15",#""),NSLocalizedString(#"Hellokey16",#""),NSLocalizedString(#"Hellokey17",#""),NSLocalizedString(#"Hellokey18",#""),NSLocalizedString(#"Hellokey19",#""),NSLocalizedString(#"Hellokey20",#""),NSLocalizedString(#"Hellokey21",#""),NSLocalizedString(#"Hellokey22",#""),NSLocalizedString(#"Hellokey23",#""),NSLocalizedString(#"Hellokey24",#""),NSLocalizedString(#"Hellokey25",#""),NSLocalizedString(#"Hellokey26",#""),NSLocalizedString(#"Hellokey27",#""),nil];
[curentLocale displayNameForKey:NSLocaleIdentifier
value:[curentLocale localeIdentifier]];
// NSString *path = [[NSBundle mainBundle] pathForResource:#"fr" ofType:#"lproj"];
// NSLog(#"path:%#",path);
NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
If the text received is truly dynamic (i.e. there's no way to know ahead of time what the possible variations are), there's no way to do it. If you know what the possibilities are, you embed the translations just as you do for static text, and you have the server send the localization key. This is the scheme used by iOS for translating notification alerts.
(You could theoretically use a translation API, such as Google Translate, but that has many downsides, and few upsides.)

Why does my iOS app only detect the current language properly on first run?

I am localizing my iOS app, and in the Simulator it runs correctly in my chosen language every time.
When testing on my iPhone 5, it only detects the language properly the first time the app runs. Every other time I recompile and run my app on the device, it detects "en" as the language, even though I am testing with Español ("es") selected.
I detect the language using:
[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]
I've also used:
[[NSLocale preferredLanguages] objectAtIndex:0]
Same result.
If I kill the app after the first run, and restart it on the device, it continues to detect the language properly.
But if I kill the app and then recompile/restart via Xcode after the initial run, it will load with "en" (English) detected instead.
After that, killing and re-starting the app continuously detects as English unless I delete the app completely, and recompile/reinstall/run the app via Xcode. The cycle then repeats... subsequent rebuild/restart without first deleting the app from the device results in misdetection.
All other apps on my device display with Spanish language the entire time. The entire UI shows in Spanish.
UPDATE: I've now tested on my iPad (3rd gen) also running iOS 6, and am experiencing the same behavior.
UPDATE 2:
In didFinishLaunchingWithOptions, I have this code to detect language: (language is an NSString*):
language = [[NSLocale preferredLanguages] objectAtIndex:0];
Followed by this debugging statement, to compare the value I'm getting, as well as a slightly different way of detecting it, just for debugging:
NSLog(#"Detected language: %# / %#", language, [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);
The output shows as "Detected language: es / es" when the app works properly in Spanish mode, and then shows as "Detected language: en / en" when it doesn't. Still no idea why it decides to load as English sometimes...
UPDATE 4: I appreciate everybody's answers, and I've tried the various suggestions. Unfortunately I was unable to award the +100 bounty as none of the suggestions seemed to fix the issue. If someone does ultimate find a solution that works for me, I will award another +50 bounty to them at that time.
UPDATE 5: I have updated from Xcode 4.5 to 4.5.2, and experiencing this same issue.
UPDATE 6: I have now created a new test project from scratch, and it works perfectly fine! Obviously something must be wrong in the way my project is laid out, or perhaps in one of the data files. I guess my next journey will be to re-create the project from scratch, copying file data over one by one...
UPDATE 7 (MONTHS LATER): Sadly, I am again facing this issue after temporarily resolving it (seemingly) by painstakingly recreating my project. On first load, the language is correctly rendered, but on subsequent loads, it reverts back to English.
SOLVED See my final solution below. Thanks for the help everyone. I may dole out some of the bounty since it will go to waste anyway.
I have FINALLY solved this problem after many months! Thanks to all for the help (I also had some good back and forth with an Apple developer via the dev channels).
TL;DR: I was accidentally syncing language preferences (among many other unexpected things) between devices, using my app's iCloud key value store (via MKiCloudSync)! Read on...
I am using a third-party class called MKiCloudSync, which helps with syncing [NSUserDefaults standardUserDefaults] to my app's iCloud key value store. My intention when I began using it was to let it handle some user favorites syncing in the background.
However, not understanding how standardUserDefaults works, what I didn't realize is that there are a lot of other things being written into standardUserDefaults other than just my own custom app settings!
So what was happening was this:
Start the app up for the first time. Fresh standardUserDefaults in place, and the internal "AppleLanguages" key that stores the ordered list of language preferences is correct based on the current device choices.
App displays properly in the designated language.
In the background, MKiCloudSync syncs ALL standardUserDefaults to iCloud. Conversely, if you had run this app elsewhere, say with an English set device, that device would have also synced it's language settings up to iCloud. So now this current running app is actually having it's language preferences overwritten.
BOOM ... next time the app is run, no matter what you have selected on the device, it's whatever was pulled down from iCloud that will be used as the default language!
What I plan to do to solve the issue with my next app update:
Use a forked version of MKiCloudSync that allows for syncing only whitelisted key names.
Add code that will do a one-time cleanup, first cleaning out the iCloud keystore for my app, then (based on this SO answer), calling this code to reset the user defaults:
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
In my testing so far, this sort of solves the issue... unfortunately, the user would have to restart the app for the language fix to kick in. However, my guess is most users are not experiencing this issue, as they are unlikely to be using multiple devices with different default languages.
In settings->general->international, there is an option to set the location language etc. if you set that to the language you are trying to test it will work if your code is correct.
I tested your steps on my iPhone 5 without issues. This leads me to think there's something else at play here: most probably there's something interferring with the way in which you're reading the locale value.
The steps I'd recommend you take to help you debug this issue are:
Post the complete code of the method in which you're obtaining the preferred language value. Make sure the method is executed each time the app is run.
Make sure the code you post includes the location of the NSLog directive you're using to test for the language setting.
Are you storing the preferred language somewhere else after the first run?
Try with following code:
LocalizationSystem.h===
#import <Foundation/Foundation.h>
#define AMLocalizedString(key, comment) \
[[LocalizationSystem sharedLocalSystem] localizedStringForKey:(key) value:(comment)]
#define LocalizationSetLanguage(language) \
[[LocalizationSystem sharedLocalSystem] setLanguage:(language)]
#define LocalizationGetLanguage \
[[LocalizationSystem sharedLocalSystem] getLanguage]
#define LocalizationReset \
[[LocalizationSystem sharedLocalSystem] resetLocalization]
#interface LocalizationSystem : NSObject {
NSString *language;
}
+ (LocalizationSystem *)sharedLocalSystem;
//gets the string localized
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment;
//sets the language
- (void) setLanguage:(NSString*) language;
//gets the current language
- (NSString*) getLanguage;
//resets this system.
- (void) resetLocalization;
#end
LocalizationSystem.m===
#import "LocalizationSystem.h"
#implementation LocalizationSystem
//Singleton instance
static LocalizationSystem *_sharedLocalSystem = nil;
//Current application bundle to get the languages.
static NSBundle *bundle = nil;
+ (LocalizationSystem *)sharedLocalSystem{
#synchronized([LocalizationSystem class])
{
if (!_sharedLocalSystem){
[[self alloc] init];
}
return _sharedLocalSystem;
}
// to avoid compiler warning
return nil;
}
+(id)alloc{
#synchronized([LocalizationSystem class])
{
NSAssert(_sharedLocalSystem == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedLocalSystem = [super alloc];
return _sharedLocalSystem;
}
// to avoid compiler warning
return nil;
}
- (id)init{
if ((self = [super init]))
{
//empty.
bundle = [NSBundle mainBundle];
}
return self;
}
// Gets the current localized string as in NSLocalizedString.
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment{
return [bundle localizedStringForKey:key value:comment table:nil];
}
// If this function is not called it will use the default OS language.
// If the language does not exists y returns the default OS language.
- (void) setLanguage:(NSString*) l{
NSLog(#"preferredLang: %#", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:#"lproj" ];
if (path == nil)
//in case the language does not exists
[self resetLocalization];
else
bundle = [[NSBundle bundleWithPath:path] retain];
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:l, nil] forKey:#"AppleLanguages"];
}
// Just gets the current setted up language.
// returns "es","fr",...
//
// example call:
// NSString * currentL = LocalizationGetLanguage;
- (NSString*) getLanguage{
NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:#"AppleLanguages"];
NSString *preferredLang = [languages objectAtIndex:0];
return preferredLang;
}
// Resets the localization system, so it uses the OS default language.
//
// example call:
// LocalizationReset;
- (void) resetLocalization{
bundle = [NSBundle mainBundle];
}
#end
This code works perfectly as you mentioned.
It worked for me and that game is live now app store, if you want to check(HueShapes).
Do you by chance use NSUserDefaults to save something language related?
Look into your Simulator App directory -> Library -> Preferences -> <YourAppBundleName>.plist
See: How to force NSLocalizedString to use a specific language for description of the NSUserDefaults method of setting a language.
Perhaps you just save your language and thus detection just returns the saved value.

Change app language in iOS without restarting the app

I have seems some apps can change the language internally within the app without the need of restarting the app, I am wondering how they are implemented.
For example, for us using NSLocalizedString, I know it is possible to set the language at runtime at main.m when your AppDelegate is not initialized, but once it is initialized (particularly your view controller is created), change it has not effect until the next restart
[[NSUserDefaults standardUserDefaults]
setObject:[NSMutableArray arrayWithObjects:language, nil]
forKey:#"AppleLanguages"];
Anyone have idea how those dynamic language change can be done without restarting the app?
There's some discussion of other approaches here, in particular a notification based approach:
iOS: How to change app language programmatically WITHOUT restarting the app?
In my view there are really three tasks here:
(1) re-localization of resources automatically loaded from nibs. (for example if you dynamically instantiate another custom UIView from a nib, the "old" language strings and settings (images, text direction) will still be loaded)
(2) re-localization of strings currently displayed on the screen.
(3) re-localization of strings inserted by the developer (you) in program code.
Let's start with (3). If you look for the definition you will notice that NSLocalizedString is a macro. So if you don't want to change existing code too much, you can probably solve the problem of (3) by creating a new header file. In that header file, #undef and then re-#define NSLocalizedString to pick the localized string from the appropriate place--not the one that iOS defaults to, but one that you keep track of in some global variable (e.g., in an app delegate ivar). If you don't want to redefine NSLocalizedString but you still make your own alternative , you should probably still #undef NSLocalizedString if you don't want future developers to accidentally call it instead of the macro you replace it with. Not an ideal solution, but maybe the most practical.
As for (1), if you haven't done your localization in Interface Builder, but rather you do it dynamically in viewDidLoad, etc., no problem. You can use the same behavior just discussed (i.e., the modified NSLocalizedString, etc.). Otherwise you can either (a) implement a notification system as described in the link above (complicated), or (b) consider moving localization from IB to viewDidLoad, or (c) try overriding initWithNibName: and swap out the object loaded with the old language resources, with one loaded with the new language resources. This was an approach mentioned by Mohamed at the very bottom of this discussion: http://learning-ios.blogspot.ca/2011/04/advance-localization-in-ios-apps.html. He claims it causes problems (viewDidLoad isn't called). Even if it doesn't work, trying it out might point you towards something that does.
Finally, (2) is presumably the easiest task: just remove and re-add the current view (or in some cases, just redraw it).
the idea is to write a new macro like NSLocalizedString which should check if to take the translation from another specific bundle or not.
The method 2 in this article explain exactly how to do it.
In this particular case, the author doesn't use a new macro, but directly set a custom class for [NSBundle mainBundle].
I hope that #holex will understand the problem reading this.
I'm always using this way, it works perfectly, it might help you as well.
you should set all the texts with NSLocalizableString(...) for the UI for the current language in the -viewWillAppear: method of your every UIViewController.
using this way you (I mean, the users) don't need to restart the application after changing the language of iOS in the Settings.
of course, I'm using the Apple's standard localisation architecture.
UPDATE on (24 Oct 2013)
I've experienced the –viewWillAppear: method won't be performed for the actual view when the application enters to foreground; to solve that issue I also commit the procedure (see above) when I receive UIApplicationWillEnterForegroundNotification notification in the view.
My implementation uses a class to change the language and access the current language bundle. It's an example so if you were to use different languages than I am then change the methods to use your exact language codes.
This class will access the preferred languages from NSLocale and take the first object which is the language being used.
#implementation OSLocalization
+ (NSBundle *)currentLanguageBundle
{
// Default language incase an unsupported language is found
NSString *language = #"en";
if ([NSLocale preferredLanguages].count) {
// Check first object to be of type "en","es" etc
// Codes seen by my eyes: "en-US","en","es-US","es" etc
NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([letterCode rangeOfString:#"en"].location != NSNotFound) {
// English
language = #"en";
} else if ([letterCode rangeOfString:#"es"].location != NSNotFound) {
// Spanish
language = #"es";
} else if ([letterCode rangeOfString:#"fr"].location != NSNotFound) {
// French
language = #"fr";
} // Add more if needed
}
return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:#"lproj"]];
}
/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
if (![NSLocale preferredLanguages].count) {
// Just incase check for no items in array
return YES;
}
if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:#"en"].location == NSNotFound) {
// No letter code for english found
return NO;
} else {
// Tis English
return YES;
}
}
/* Swap language between English & Spanish
* Could send a string argument to directly pass the new language
*/
+ (void)changeCurrentLanguage
{
if ([self isCurrentLanguageEnglish]) {
[[NSUserDefaults standardUserDefaults] setObject:#[#"es"] forKey:#"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:#[#"en"] forKey:#"AppleLanguages"];
}
}
#end
Use the class above to reference a string file / image / video / etc:
// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:#"my_image_name.png" ofType:nil]
// Access a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(#"StringKey", nil, [OSLocalization currentLanguageBundle], #"comment")
Change language in-line like below or update the "changeCurrentLanguage" method in the class above to take a string parameter referencing the new language code.
// Change the preferred language to Spanish
[[NSUserDefaults standardUserDefaults] setObject:#[#"es"] forKey:#"AppleLanguages"];
I was stuck in same issue, my requirement was "User can select language from drop down & application have to work according selected language (English or arabic)" What i have done i create two XIB and fetch XIB and Text according selected language. In this way user can select language. I used NSBundle for the same. like
For XIB
self.homeScreen = [[HomeScreen alloc] initWithNibName:#"HomeScreen" bundle:[CommonData sharedCommonData].languageBundle];
For Text
_lblHeading.text = [self languageSelectedStringForKey:#"ViewHeadingInfo"];
/**
This method is responsible for selecting language bundle according to user's selection.
#param: the string which is to be converted in selected language.
#return: the converted string.
#throws:
*/
-(NSString*) languageSelectedStringForKey:(NSString*) key
{
NSString* str=[[CommonData sharedCommonData].languageBundle localizedStringForKey:key value:#"" table:nil];
return str;
}
You need to load another bundle like this(where #"en" could be locale you need):
NSString *path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
NSBundle *languageBundle = [NSBundle bundleWithPath:path];
and make macros/function like NSLocalizedString which use your loaded bundle or use methods on that bundle directly like this
[languageBundle localizedStringForKey:key value:value table:tableName];
[[NSBundle mainBundle] localizations] lists all app localizations(including "Base").
Also I wrote helper class which does this(note that it has ReactiveCocoa as a dependency). It allows language change without app restart and sends current locale each time it's changed.

Localizing iPhone app for Region

I've got an app that has all content regardless of language displaying content in English. In the products section of the app product content is displayed based on a plist. Products available for purchased are based on location, not all products are available in every market.
In the settings of my simulator I've got my language set to English and my Region Format set to Singapore.
Above my loading of the plist which has been localized, I first do a log to check that I am in fact seeing SG (Singapore) as my region.
NSString *locale = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
NSLog(#"LOCALE: %#", locale);
if([locale isEqualToString:#"SG"]){
NSLog(#"singapore do something?");
productCategory = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"Products" ofType:#"plist"]];
}
The current result is showing my log statement logging LOCALE: SG which is expected, however my Singapore specific content is not loading.
I have tried both cleaning the project, and deleting the app from the simulator.
This is how my plist files appear in my project navigator
What am I doing incorrectly that is preventing my localized plist from being displayed?
Localization (the process of loading translated resources from the relevant language folders in your application bundle) is based exclusively on the language setting. So pathForResource only cares about the language setting and ignores the region format setting.
The region format setting affects the conversion between strings and locale-dependent data types (in both directions: parsing input and formatting output). For example if you convert a NSDate to a string for display, depending on the region format setting you might get the month before the day (as in the US) or the opposite (as in the UK).
[NSLocale currentLocale] refers to the region format, so you were simply looking at the wrong thing in your debugging.
There is plenty more info on this here: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPInternational/BPInternational.html#//apple_ref/doc/uid/10000171i
Edit
See the comments below, this appears to be more complex. It looks like Region does affect localisation when the language is set to a neutral language (e.g. "en" but not "en-US").
I had once the same problem, somehow a non-localized file was found. What worked for me was to use:
[[NSBundle mainBundle] pathForResource:#"Products" ofType:#"plist" inDirectory:nil]
This will always search for all localized files and return the correct one based on the users settings

Resources