Change localizable file - ios

I'm currently developing an application for IOS and I have four Localizable.strings files, each representing a different language. The thing is, i want to be able change the file that is being used without having to restart the application.

You can't do it without restarting the App.
A work around is store the language and it's values in a database file or in a plist file. Then use the data from there. (Basically it is not a good idea)

Related

How to check which localization strings are really used in iOS Application?

We have a legacy application for iOS translated to two languages. After checking the localization files we realized, that there are a lot of strings that are not really used in the application, though, we cannot be sure which ones.
Is there some way (maybe some utility) that can check objective-c project and localization files and check which strings re really in use and which are not so we can delete the from the localization files?
Thanks
You could use genstrings to generate a new strings file from your project and then use one of the string-files comparison/merge tools to find the differences.

Xcode storyboards: Load localizable strings from different file

I'm trying to build a library that will allow for dynamic loading of Localizable.strings files. If the views are being developed programmatically, then it's not a problem, as I could build a separate NSBundle, store the .strings files inside, and use NSLocalizedStringFromTableInBundle.
The problem I'm having lies with Storyboards. I haven't managed to find a way to specify which .strings file to load from (rather than using the default .strings that Apple uses).
Does anyone know of a solution for this? It doesn't even have to follow the same approach, as long as I can dynamically update the strings on a Storyboard. (The strings will be pulled down from an external source via API call upon app launch)
Loading strings from a separate bundle/strings source
In order to overcome the issue I had, I created IBOutlets for each object on the Storyboard's collection of views. Within each view's implementation file, I programmatically set the text/values of each object by using NSLocalizedStringFromTableInBundle, which allows me to specify a custom bundle, which can be populated with strings files.
In the event that a project has both programmatic and storyboard developed views, this approach also allows for the usage of only one Localizable.strings file, rather than mixing Storyboard-generated files, and files used only for programmatic views (if applicable).
Loading strings into an app via API call
Unfortunately, the above approach doesn't allow for strings to be downloaded from an external source via API call. The reason for this being, Apple doesn't allow for any files in the app bundle to be edited after being built.
Because of this, the solution would be to build out a data structure within the app's DocumentsDirectory, and edit this whenever necessary, then force the app to use this file/library in order to get localized strings. Not a pretty solution, but it's the best approach I can think of.

Is there a good way to externalize user-facing strings out of objective C files?

I have read a few tutorials about iOS's tools and processes for i18n/l10n, and am unpleasantly surprised with what I'm seeing. It seems there isn't a solid way of externalizing user-facing strings out of objective C files. Am I missing something?
Description of the problem:
There is a tendency to place English strings directly into the .m file, and the Apple documentation seems to encourage this. While this is also possible in Android, as least in Android there is a clear distinction between externalized and non-externalized strings. With iOS, on the other hand, code that calls for a string tends to look like this:
NSLocalizedString(#"There was an error loading the image.", nil)
In this case, "There was an error loading the image." is the key for this string resource. Therefore if I want to make another reference to the same string in some other place we have to again write code like this:
NSLocalizedString(#"There was an error loading the image.", nil)
But now I have to make sure that I spelled these two strings the same and there is no compile time check to help me confirm that. I could write a helper function called createErrorString, but that's not fun. And I could replace "There was an error loading the image." with a more sensible key like "ERROR_IMAGE_LOAD", but that does not seem to be a common practice, and Apple seems to discourage this sensible behavior. Here is what their documentation states:
"A common convention when developing applications is to use a key name
that equals the value in the language used to develop the
application."
It looks like Apple is recommending that you put the full English string in your source code. So I'll have to try to convince my colleagues to go against Apple's guidance.
Now that I've got all of these user-facing English strings (or keys) in the source code, Apple includes a tool called genstrings that parses the .m files, and spits out a Localizable.strings file that I can then send out for translation. This might work if you are only going to get your app localized one time, but in our company localization is an ongoing iterative process. Look at what the Apple documentation recommends:
"For subsequent runs, it is a good idea to save a copy of your current
strings files before running genstrings. You can then diff the new and
old versions to determine which strings were added to (or changed in)
your project. You can then use this information to update any already
localized versions of your strings files, rather than replacing those
files and localizing them again."
That doesn't seem very good. In Android and Windows8, you internationalize your source tree one time, and from that moment on your externalized strings are owned in the xml files where they belong; in iOS they are owned in source code (sort of) and then tabulated into some intermediate file (or is it?) by some crazy tool. Is the Localizable.strings file an intermediate file or should it be committed into git - we are still debating this at my company.
(And from what I can tell, this is only the beginning. In xib-land, which is where 90% of your user-facing strings live, there also seems to be an inefficient mechanism for l10n. Wil Shipley's article describes this at length.)
Does anyone have any suggestions on a good way to externalize strings in iOS? My main question concerns objective-C strings, but answers pertaining to xib files would also be much appreciated. Thanks!
I found the recommendation to name the key like the english string strange, too.
I name the keys, value e.g "Menu1SettingsTitle" = "Settings".
I dont need genstrings tool, just externalize manually.
And no, the string files is not an intermediate step, they should be in git.
However with that approach i noticed three drawbacks:
1) I detected duplicate names, but that can be moved to a common section for strings like "cancel, delete"
2) If you forget to put a string into that language file, it cannot be found and then the key is displayed, which looks very strange, of course. Otherwise with apples reccomendation, If the key is the english word, it looks "only english" but not worse.
3) The translation process is easier if english is always left, instead of "Menu1SettingsTitle". to solve that i put a comment above, but dont know if the translation service would be happy with that.
After a couple of hours searching I decided to use two different approaches: one for the storyboards and one for the text inside the .m files. The result are two files Localizable.strings for the Objective C text and the internationalized storyboard.
The update_storyboard_strings.sh can automatically extract translatable strings from storyboards and update strings files. The source code (by mikezang) can be found at:
http://forums.macrumors.com/showpost.php?p=16060008&postcount=4
For the objective C NLS I use another script around the xcode-tools by Frédéric Sagnes:
https://github.com/ndfred/xcode-tools
I had to call it for each language in order to get the desired results:
python scripts/xcode-tools/update_strings.py --import=MyProject/Base.lproj/Localizable.strings MyProject/Base.lproj/Localizable.strings
python scripts/xcode-tools/update_strings.py --import=MyProject/de.lproj/Localizable.strings MyProject/de.lproj/Localizable.strings
Now put both in one script and add it to your Xcode project as a last build phase.

How to localize a plist file

I appreciate your help in advance. I have searched high and low for an answer with no luck.
I have an app that uses very specialized sports terms which I store in a plist file. Those terms are then displayed in a UITableView. When the user taps on the skill, a video demo is played. The app works great, but I would very much like to localize it for other languages.
I have gotten the terms translated, and I was hoping I could localize the plist file by making a copy of it and just changing the sport-specific terms in each successive copy of the file, and then put it in its respective language folder. Is this possible and if so, can someone please point me to a good example or tutorial?
So far, I have I have tried to localize the plist file for Russian in Xcode and put it in its own ru.lproj folder, however, then when I run it in the simulator no data appears at all in the UITableView! Without the Russian file, it works fine. So my thought is that somehow Xcode is confusing the plist file because the name is the same, even though it is in a different directory (en.lproj and ru.lproj). The file is called Basic.plist in both directories. This process is totally confusing to me, and from what I gather it shouldn't be that difficult to figure out!
Again, thank you in advance. The localization concept is completely new to me and I am eager to learn it. I am quite sure I understand how the .strings files work with strings that are embedded in code, but I would like to know if it is possible to translate an entire pList file.
A lot of things could be wrong. One possibility is that the plist files don't get copied into the bundle (verify in your target's Build Phases page--it should say Basic.plist with "...in (localization).lproj" written next to it.
If you have manually created the ru.lproj, maybe you copied it in the wrong place, or left the original file in the wrong place (it should now be inside en.lproj). Rather than manually create the file, it's easiest to select the file Basic.plist in XCode and use the Localization control inside File Inspector to add localizations. As Kevin Grant mentions, if this doesn't show your file as having English and Russian, then something is wrong, and you could start again using the + control.
Finally, I'm not 100% sure about this but close enough: I believe your code probably needs to be updated to figure out where to load the plist file from. It it were a .xib or a .strings file, you wouldn't have to do this as this would be automatic and iOS knows to look inside the relevant .lproj folder first (when you load a .xib you only specify its name, not its exact location). But I assume you are loading the plist file through a specific path, therefore the path must now include the .proj folder.
If possible for you, I think a nicer approach to having different plist files per language would be to have just one plist, but instead of displaying the string from the plist you could use it as a key to your .strings file. You can retrieve the localization using the NSLocalizedString macro (which is defined as [[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]) which will give you the corresponding value in the localized .strings file at run time. Of course this would mean that when you update your plist, you would also have to update your .strings files to match. The good thing is that you wouldn't need to determine the path of the plist for your active language -- with NSLocalizedString, you don't provide a path at all.

iphone multilanguage support

I'm developing an Iphone app that has to support different languages.
I saw that the language has to be set within my app and not within iphone settings. So, do I have to force the language instead to take the current one? I didn't find examples over the internet. All examples need the current language of the application. I would like that the user choose his language when the application starts, then I will set a cookie and (in a way that iI don't know) the app refers automatically to my .lproj folders with different languages.
This is not possible using the default localization mechanisms in iOS. By default, the system chooses the .lproj folder according to the user's system language and does the localization automatically if you have localized NIBs and use NSLocalizedString() etc..
If you really want to change that behavior and "override" the system language, you have to implement your own version of NSLocalizedString that manually accesses the strings file in the .lproj folder you want. Be aware though that NIBs don't use your custom NSLocalizedString function. So either don't use NIBs at all or do the localizing of the NIBs in code instead of using different NIBs.
Your question isn't really very clear. There is nothing saying that "the language has to be set within my app and not within iphone settings" — it is in fact quite the opposite!
Cocoa has a pretty neat localization system that is quite easy to use (grumbles something about rotten localization workflows). Here's the full skinny on it — basically, have files in lproj folders, then use the NSBundle resource APIs to locate them (NIB loading and other subsystems use it automatically, so you don't even have to do work there!).
IIRC, you want NSLocalizedStringFromTable.
You create a .strings file for each language: eg "EN.strings", "JP.strings", etc...
These files will be loadable from the default bundle with the table parameter to NSLocalizedStringFromTable.
When the user picks a language, you switch which table (.strings file) to load the strings from.
One problem tho is that iOS strings will still be localized to the user's settings, or to whatever you have your app localized to in the Info.plist. So you might end up with a mix of languages.
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:#"it",#"en", nil] forKey:#"AppleLanguages"];
then if the iPhone language is set to english, my iPhone app will works always with "it". the first of the array.

Resources