I search around the web, but I can't find the answer, maybe this question is too simple.
In the app I developed, how to display those default items, such as back BarButtonItem, ImagePicker buttons, or in the UITextView, the pop-up menu with copy, paste, cut, replace and select all, I can't figure out how to display these items in other language, for example, Chinese, Japanese etc.
Thanks.
Attribute in *-Info.plist "Localization native development region" is responsible for another thing.
CFBundleDevelopmentRegion (String - iOS, Mac OS X) specifies the native region for the bundle. This key contains a string value that usually corresponds to the native language of the person who wrote the bundle. The language specified by this value is used as the default language if a resource cannot be located for the user’s preferred region or language.
(Source)
Solutions:
In my app I have custom localization (not standard mechanism with *.lproj). And to say the system that I can handle localization manually with some languages, I set the CFBundleLocalizations (in Xcode "Localizations"). It's array property where you can specify handled languages. In Xcode could be problems to set Localizations attribute to type 'array', solution here.
CFBundleLocalizations (Array - iOS, Mac OS X) identifies the localizations handled manually by your application. If your executable is unbundled or does not use the existing bundle localization mechanism, you can include this key to specify the localizations your application does handle.
Each entry in this property’s array is a string identifying the language name or ISO language designator of the supported localization.
(Source)
UIKit is a framework and has localized resources (such pop-up menu of uitextfield). In Bundle settings(*-Info.plist) you can set CFBundleAllowMixedLocalizations (set to YES) to retrieve those resources.
CFBundleAllowMixedLocalizations (Boolean - iOS, Mac OS X) specifies whether the bundle supports the retrieval of localized strings from frameworks. This key is used primarily by Foundation tools that link to other system frameworks and want to retrieve localized resources from those frameworks.
(Source)
Read up on the internationalization technology:
http://developer.apple.com/internationalization/
In particular, the thing you're talking about is known as "Localization".
I just found this tutorial via google:
http://www.switchonthecode.com/tutorials/a-simple-localization-example-for-the-iphone
N.B. "internationalization" is sometimes written as "I18N" because it is such a long word! (Weird acronym, but it's because the word is an 'I' followed by 18 letters and then an 'N')
I wrote a tutorial on this where I stepped through how to do this (based on an application I localized in six languages):
Developing localized iPhone applications
http://www.pushplay.net/2009/08/developing-localized-iphone-applications/
I also described some of the language/idiom issues I was dealing with, which might be useful to keep in mind. There is the technical problem of how to implement multiple languages, but there is also the communication problem of having things be nonsensical when directly translated out of context...
EDIT: to respond to your comment, I'd still do it the same way (localizing everything). If not, set it up to localize anyway, but only translate the specific strings you want (and leave the rest as English).
If you really want to do everything yourself, you can do this:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults objectForKey:#"AppleLanguages"];
NSString *currentLanguage = [languages objectAtIndex:0];
Then you can compare the currentLanguage variable and display the proper text in an if/then/else if/etc code block. I'd probably recommend having an "else display in english" at the end of the code block, just in case the language returned is different from what you were expecting.
EDIT: I just re-read what you were asking, and realized you meant localizing system functions. That's not something you can control -- when a user goes into their Settings and changes their language, all of those system interfaces (like "Cut/Copy/Paste") will automatically be localized. As long as they set their proper language in their Settings, that should work automatically.
Related
The application that I'm working on supports 3 languages: English, French and German.
How I can get the current application language (NOT the device language)?
The problem is that I have to get the current language of the application in order to send it with a request to the server and the respond should be in the right language. The device language is useless because if the user switch the os language to Italian, the app is running in English and I need to send english to the server.
Thanks
The accepted answer is a workaround.
Regarding language preferences in the device itself, you have the
[NSLocale preferredLanguages]
which will give you an ordered array of the preferred languages as defined in the system's General Settings.
The Cocoa Touch framework will take this list of preferred languages into account when loading the app's localization resources and filter it according to the translations you provide in the bundle.
This filtered and ordered list of localized languages can be obtained with
[[NSBundle mainBundle] preferredLocalizations]
Your server requests should match the first value in this array or you will have a language mismatch between app and server data.
What i always do:
Add a string entry into the Localizable.strings files.
I always use the key "lang"="de"; (or "lang"="en", etc.).
Then you can use it in your NSURLRequest by adding the language over NSLocalizedString(#"lang", #"")
With that method you have absolute control what is going to be sent to you backend.
You may use the preferredLocalizations method of the NSBundle class:
NSString *currentLocalization = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
Since iOS 13 the language can be set for each app individually.
In the session "Creating Great Localized Experiences with Xcode 11" at WWDC19 they showed two options for determining the user settings for the application.
Get the currently running application language:
Bundle.main.preferredLocalizations.first
Get the best language, given an external language code list:
let availableLanguages = Server.requestLanguages()
Bundle.preferredLocalizations(from: availableLanguages).first
The app language will change when the user change the device language and you can get it from the NSUserDefaults (i will show you how if you want to ) unless there are an option to change the language inside the app then you can easy save the current used language and send it to the server when ever you want.
This app has been under development for more than a year and has had multiple releases already. This development cycle I noticed that the "fallback" language doesn't seem to work anymore.
The app had 3 targets: CountryA, CountryB and CountryC.
Each target has the following localization directories:
CountryA: en.lproj, langA.lproj, langB.lproj
CountryB: en.lproj
CountryC: en.lproj, langC.lproj
In each targets info.plist a key "CFBundleDevelopmentRegion" with value "en" is specified.
The project.pbxproj file has both the following key/values specified in the PBXProject section:
developmentRegion = en;
knownRegions = (
English,
Japanese,
French,
German,
en,
fr,
dk,
da,
nl,
new,
pt,
de,
);
When I start the app on an iPhone or in the iPhone simulator with the system language set different from one of the specified localization directories the UI shows the NSLozalizedString identifiers instead of the localized strings. Even when I specify "English" as System Language in iOS!
So... for some reason the en.lproj file is not picked up, because if I use langA or langB as System Language for target CountryA everything is as expected.
Any help is appreciated!
Kind regards,
Niels R.
NOTE: The problem is caused by a plugin of an external company that we had to integrate and which has a Localizable.strings file too. This will cause that "our" Localizable.strings is overwritten.
Sorry to bother with this! Seems that I just had to look a little bit further before asking the question.
"the UI shows the NSLozalizedString identifiers instead of the localized strings" -- Are you adding the Localizable.strings file correctly for the individual targets?
Another problem could be the "region" setting for languages. You should try to change the region too in the Simulator. I have seen unexpected things happening to NSLocale when setting the region to something totally different than the language.
I want to make the language changeable from the application settings. For that I made a settings.bundle and i forced the langauge using this code How to force NSLocalizedString to use a specific language , I also put the UIApplicationExitsOnSuspend to YES to make my app reload every time it goes to the background.
It partially worked for me but I have 2 problems :
- The splash screen (which is localized) is not changing with this method.
- I must enter/goBack twice to make the language change effective on the application Views an this only on the OS 4 and higher.
Has anyone a solution for that?
You need to create you own translation framework for that ! Sorry !
Unfortunately there's no built-in way. What would be probably easiest would be integrate service like GetLocalization.com, so that your app would download language file via API (then it's easy to add new languages and translations even app is already released). Then what you need is just simple loader that loads that language file to memory and function that replaces the original string with translated one in run-time. You can calculate hash for original string so it's fast to search them, good algorithm for this is Peter Weinberger's hashPJW.
The trick to use specific language by selecting it from the app is to force the NSLocalizedString to use specific bundle depending on the selected language ,
here is the post i have written for this http://learning-ios.blogspot.com/2011/04/advance-localization-in-ios-apps.html
and here is the code of one sample app https://github.com/object2dot0/Advance-Localization-in-ios-apps
Has anyone written iPhone classes that mimic the behavior of the Application Settings? It would be nice to be able to define settings tables for use within my app using exactly the same XML structure, etc.
See Is there a library or framework for setting preferences from within an iPhone application?
Esp. the mySettings library mentioned there:
mySettings [...] uses a plist
configuration file like the one used
by the settings app, with some added
options.
[...]
By default the settings themselves are
stored in the standard user defaults
object ([NSUserDefaults
standardUserDefaults]), but you can
use any object that supports key-value
coding. This enables you to use your
model classes directly in the settings
view.
The application settings (or NSUserDefaults) is essentially a glorified NSDictionary. You add objects to the settings and associate them with keys, so you can retrieve them later on.
If you want to do this, just create a class which wraps a singleton instance of a NSDictionary. That way you could reference it throughout your app like:
[[MyAppSettings sharedInstance] objectForKey:key];
I'm working on a localized app and everything is working fine. The problem is I want to allow the user to specifically select the lenguage for the specific app, in the app settings folder. This should users that their phone is set to one language (e.g. french) to set the app to work in English.
I'm currently using NSLocalizedString to get localized string but looking through all variation of the macro I can't find one that will let me specify the language.
Any ideas on how to do it?
There are three issues here:
Strings
Other resources (including NIBs)
System messages
The last is almost certainly not fixable, so we will leave it be. They're going to show up in the device language.
The other two are solvable, but you will need to do more things by hand. For strings, instead of creating a single Localizable.strings and then localizing it, create completely separate tables (English.strings, French.strings, etc.) Then, use NSLocalizedStringFromTable(), passing the language as the table.
For NIBs, there are two approaches. You can put each set of localized NIBs into its own Bundle and then pass that Bundle rather than nil to -initWithNibName:bundle:. Alternately, you can hand-load the NIBs after finding them with [NSBundle -pathForResource:ofType:inDirectory:forLocalization:].
There is a better way to do this. You can force the language like so:
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
And undo this setting by:
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"AppleLanguages"];
NB. you will normally have to restart the app for this to take affect.
Consider if you need to call [[NSUserDefaults standardUserDefaults] synchronize];
I agree there is little need to allow the user to specify a language. However the one exception is being able to override the language and set it to the developer's native language. If the user can speak the developer's language (e.g. English for me) then they may wish to use the App in that language, if the translations are incorrect.
I reference this answer: How to force NSLocalizedString to use a specific language (the answer doesn't actually work for me, but following the ideas in the comments did. The undo stuff I worked out.
The trick to use specific language by selecting it from the app is to force the NSLocalizedString to use specific bundle depending on the selected language ,
here is the post i have written for this http://learning-ios.blogspot.com/2011/04/advance-localization-in-ios-apps.html
and here is the code of one sample app https://github.com/object2dot0/Advance-Localization-in-ios-apps
The correct "User experience" is for the user to select their language via the system preference panel; not your app (or your app's settings panel, etc.). There is no way to override this per-app and we wouldn't want any app changing the system wide setting.