Is it possible to have my app running in a different language than the one that is set in the OS? I want to have a language switch in my app’s setting menu, where the user can e.g. select german for the app, while his system is running in english.
From what I’ve already read, it seems it’s not possible without having my own localization mechanism…
What do you think?
it can be done easily although it took me weeks to work out how ;-)
I have an iPhone app called iDEX which is a Romanian dictionary. On the iPad, Romanian is not available as a UI language, so I wanted to give the user the option of selecting Romanian in the application settings, as the device settings do not include it.
What you have to do is internationalize the app and localize it as usual. Then, in the main method, set the AppleLanguages key of the standard NSUserDefaults to the language and country of your choice, like so
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSArray arrayWithObject:#"ro_RO"] forKey:#"AppleLanguages"];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool drain];
return retVal;
}
It is imperative that you set the AppleLanguages key before you run UIApplicationMain(), because it is at that point that the UIKit framework is loaded and the default language determined.
It also important that you specify both language and country (eg, #"ro_RO" and not just #"ro") otherwise your app might crash when setting the key.
By doing this, all calls to NSBundle that support localization will look for the language that you have programatically established, as opposed to the one set on the device.
Hope that helps...
You need to implement your custom resource loading mechanism to achieve that. For example you will no longer be able to use NSLocalizedString macro or [NSBundle pathForResource:]. You will always have to specify paths including the localization (as in de.lproj/MyStrings.strings instead of just MyStrings.strings). I would suggest against doing this unless absolutely necessary.
Related
I use the following code in my app to print the preferred languages at startup:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defaults objectForKey:#"AppleLanguages"];
NSLog(#"%#", languages);
}
The list only contain one item though. Changing the language in the simulator has no effect. The strange thing is that if I start over with a new project the exact same code above prints a full list of languages. How come my app doesn't get the full list of languages? Is there a setting in XCode I might have switched?
I found a solution:
I had most probably played around with the NSUserDefaults and changed the list myself, not knowing it would stick permanently. Removing the app from the simulator and letting XCode upload it again solved the problem. Good to know when running into similar problems.
In my iPhone app, I can successfully change language inside the app's Settings (just the user have to restart the app). I use the trick mentioned in this post: link. I made some modification. I store the selected language in NSUserDefaults, and in main.m:
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if ( [[NSUserDefaults standardUserDefaults] objectForKey:#"language"] == nil ) {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:#"hu"] forKey:#"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:[[NSUserDefaults standardUserDefaults] objectForKey:#"language"]] forKey:#"AppleLanguages"];
}
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
The "default" Info.plist file is in english, I placed it in the root of the project. I made a hungarian translation of this, because of app name. This file is InfoPlist.strings, and I placed it in hu.lproj folder. In this file:
CFBundleDisplayName = "Sör";
If I change the language, after restart the app, everything is work fine (nib files, strings), except of app name. It doesn't change...
Can someone tell me what is the problem?
You have done almost everything you need to do.
You also need to instruct your app that it has a localized app name. You do this by adding the following key to your app's info.plist
LSHasLocalizedDisplayName
set it's type as boolean and it's value to true.
Once you have done this, your app should localize it's name.
You can read more here
EDIT:
One more thing you need to do is create an InfoPlist.strings file in the en.lproj folder and add the same key to it with the English equivalent
CFBundleDisplayName = "<Replace Me>";
Credit for this addition goes to this link
Well the app name is read by iOS which is not set to the language that your app is set to.
So it will display the name of the app which is set for the system language.
Is it possible to read key codes of non-standard keys using an special iOS API or via the generic TextInput field? I have a multimedia keyboard with special buttons & like to make my iPad app aware of these key codes.
I know iOS can use some of them already (i.e. volume up/down, next/prev track).
You might want to try subclassing UIApplication and overriding sendEvent: to see what events pass through there. Given that UIEvent doesn't document keyboard event support on iOS (as opposed to NSEvent in AppKit), I'm skeptical that you'll see keyboard events... but it's worth a try. I don't have a BT keyboard to try it out myself.
To use a UIApplication subclass, edit main.m and pass your subclass as the third argument to UIApplicationMain:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, YourApplicationSubclass, nil);
[pool release];
return retVal;
}
This strategy isn't uncommon in desktop Cocoa apps and is also explained here:
http://cocoawithlove.com/2009/05/intercepting-status-bar-touches-on.html
i had done localisation by changing the language of iPhone through localisableString and by different xib which works only with NSLocale method ,but the requirement of app is to localised it by changing the language in app setting view irrespective of iPhone language..
Sounds like a stupid requirement, but anyway: You can change the language of your app by setting an array with the order of preferred languages for the user defaults key #"AppleLanguages", e.g.:
//Set language to German:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSArray arrayWithObject:#"de"]
forKey:#"AppleLanguages"];
Note however that this only affects strings/nibs you load afterwards, so you might need to reload your UI after changing the setting.
I'm developing an application that should support two languages: English and French. However because English translation is not done yet we want to deploy it in French only and later on add English translation later on.
The problem is that I don't want to strip English language out of my code since some parts are already done, there are different NIBs for that language etc. Instead I'd just want english language to be temporary disabled in my app.
What I did is I put this code as the first instruction of
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSArray arrayWithObjects:#"fr", nil] forKey:#"AppleLanguages"];
[defaults synchronize];
It works fine except for one thing. When you launch the application for the first time after installation it's still in English. That's probably because AppleLanguages preference was not yet set for it. After I quit the application and start it again it's being displayed correctly in French.
Does anyone knows a fix so that French language was applied also on the first run?
I ran into the same issue, and the only way I could fix it was to have the piece of code at the earliest stage in the app, i.e. in main.c:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSArray arrayWithObjects:#"fr", nil] forKey:#"AppleLanguages"];
[defaults synchronize];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
I'm not really sure it's a good practice but it worked as expected in my case.
Sounds messy. Why not just uncheck the unfinished English resources from the target, so they won't get deployed? Also, have you looked into the CFBundleDevelopmentRegion setting in Info.plist?