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.
Related
Well, I would just like to know is it possible to know the path of the app? I used the following code
[NSBundle mainBundle] executablePath];
It retrieved the below value. That is correct.
/var/mobile/Applications/FBE187F1-256D-495D-852B-53AECD4F4C23/Test_Data_Fetch.app
And I would like to know, is it possible to check the existence of other app? The problem is FBE187F1-256D-495D-852B-53AECD4F4C23 this particular directory value changes for every app. I would really like to know if it is possible!!
Your application cannot access anything outside sandbox so you can't search file system directly for a given application.
One possible solution is if application you are interested in handles custom url scheme, then you can check if that url scheme can be opened:
NSURL *url = [NSURL URLWithString:customScheme];
BOOL appProbablyExists = [[UIApplication sharedApplication] canOpenURL:url];
Update: This article describes several possible approaches, but it seems there's no definite way to get list of installed applications using public API
Finally, using the Mac program iExplorer we can look at any App’s data. This is not related to my question, though it is quiet useful!! Was able to achieve my goal!! :]
While it is clear we cannot retrieve a list of installed applications on iOS, are there any tricks to allow us to determine the list of apps registered for a given file type? That is, the list the user will see in the Open In... menu for that particular file type. canOpenURL only returns a boolean, but ideally it would return us a list of supported installed applications.
Open in is certainly possible by the UIDocumentInteractionController You just need to instantiate UIDocumentInteractionController instance:
//Following in header file:
UIDocumentInteractionController *docInteractionController;
Implement the delegate:
<UIDocumentInteractionControllerDelegate>
.m:
//Here the url is the document URL that you want to open (or you want to apply open in functionality)
self.docInteractionController = [UIDocumentInteractionController interactionControllerWithURL:url];
self.docInteractionController.delegate = self;
Open In method will be like following:
- (void) openIn: (id) sender {
[self.docInteractionController presentOptionsMenuFromBarButtonItem:sender animated:YES];
}
and once you are done:
[self.docInteractionController dismissMenuAnimated:YES];
and that's it. This will list down the list of application supported for document and on selection of them will launch the corresponding application with the document URL we instantiated with.
I doubt either of your two questions ("determine list of apps for a given file type" or "how to implement 'open in...'") is possible in current versions of iOS as users don't see individual files on the home screens that show apps. Nor can an app do a "open a separate app with this specific file" event (which is something easily doable on a Macintosh with Apple Events).
But these do sound like a great feature requests that you can file with Apple at http://bugreporter.apple.com (which you can log into, if you're a registered Apple developers). If enough people ask for these features (and the potential "open in..." functionality is indeed a frequently requested feature), Apple will strongly consider including them in future iOS releases.
You can see this sample program. It might help you. It has used UIDocumentaInteractionController class instance with its property UTI (Unique Type Identifier). It helps in retreving list of installed apps on your phone that support the file type you have opened in your app. You might need to rewrite the UTI property a little bit as per your convience
http://developer.apple.com/library/ios/#samplecode/DocInteraction/Introduction/Intro.html
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.
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
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.