How to keep Storyboard strings up to date? - ios

I have the Storyboard, Base language and translated all the app into another language, so far it's working fine.
I would like to know, when I add new elements in the Storyboard that needs to be localized, how do you keep the strings file up to date.
I tried a suggestion, which is to switch this: to Interface Builder Cocoa Storyboard and then back to Localizable Strings, however the results are not good, most of the translation is lost and switched back to the Base language.
Is there a handy tool to regenerate and merge the strings in Storyboard? I tried few scripts but they always ended up wiping everything.

I've modified a skript that i've found here on stackoverflow to be able to also handle the localized strings in storyboards.
The skript only adds new key-value pairs to the .strings file, but keeps the ones that you have already translated.
You can get it from my github, for more details about my localization workflow read my blogpost

Related

How to change localisation from storyboard to strings file

TLDR: Xcode generated storyboards for each language, however I want the "old"(?) *.strings files. How?
I am currently in the process of localising my storyboards. After I enabled everything, Xcode generated another storyboard alongside the original (english) one for me to localise. I was surprised, I expected a Localizable.strings file, like the apple documentation still states as of April 3, 2021:
For storyboard and XIB interfaces, select the user interface files (files with a .storyboard or .xib filename extension). Xcode adds a strings file to the localization folder that contains the text to translate, as well as comments that describe the user interface components. For example, if you add German to an iOS app that uses storyboards, LaunchScreen.storyboard becomes a group containing a LaunchScreen.storyboard (Base) and LaunchScreen.strings (German) file.
I searched around the internet, in apple developer forums, watched both WWDC18 and 19 talks about localisation in Xcode, but did not find a single mention of translated storyboards.
After the initial translation, which works great due to the simplicity of just filling everything in, it gets frustrating however, since every layout change needs to be repeated for every language. This can't be intended, there must be a better way, right? Sadly, I didn't find anything. Even a hint to a piece of documentation regarding these storyboard copies would be greatly appreciated. Thanks!
There are some screenshots of the possibility to convert these two formats via a dropdown, like the third picture in this post. However for me, there is no dropdown next to the language item when I click the storyboard, neither on the group, nor individual base or localised ones:
Is this a bug or am I missing something here? I am using macOS Big Sur 11.2.3 with Xcode 12.4 (12D4e).
Turns out, you need to use the Base Localization feature, the dropdown then appears and you can convert existing storyboards to *.strings files.

Localization and User-Facing Text in Storyboards

I am learning from the iOS 9 AppCoda book on Swift (https://www.appcoda.com/swift/) and I am stuck in particular on the Localization section. So the author has gone through with changing some user-facing strings in code from just String to NSLocalizedString. That makes sense and the changes I made there were automatically updated appropriately with the XLIFF file. In the section about Localisation, the author mentions that you can also translate Storyboard user-facing Strings with the Export Localization feature of Xcode.
Because it's a book you work through, he provides an already translated XLIFF file into Chinese and German which includes the source code translated text and the Storyboard elements translated as well.
When I import the files into Xcode, I see three storyboards (Base and the Chinese/German.strings, etc) but when I run the app, none of the Storyboard elements are actually translated and only the elements from the source code.
When I click on the German Storyboard, I get the "no localized strings".
The app in his example works and the UI elements in storyboard are translated but they're not in my case. The entire app thus far has been followed with the exercises so there aren't really any differences. Or even if there are, the similarities themselves should be translated, but in the Storyboard elements, they're not.
Does anyone have any ideas on why the Storyboard elements wouldn't be updated with the Translated text in my case?
Any thoughts would be appreciated.
Here is my guess... Exporting localization strings from Storyboards works a little different from exporting those strings from code.
The localization file for strings from code gets the actual text from the NSLocalizedString macro and creates a mapping such as:
"Original string" = "Translated string".
So, you just have to use "Original string" in your code then Xcode knows it should translate it to "Translated string".
However, the storyboard localisation file uses the UI objects handles to set localized strings. For example:
/* Class = "UILabel"; text = "Ops..."; ObjectID = "fe4-zT-gjU"; */
"fe4-zT-gjU.text" = "Wait for it...";
In this example my storyboard has a UILabel, with the text "Ops...", and that label has an ObjectID equal to "fe4-zT-gjU".
The object IDs are kinda unique for each object in each project, so obviously the object IDs from the app coda tutorial will be unique for the project the author created; unless you have downloaded the author's original storyboard, your storyboard will have all different object IDs, so Xcode won't know how to associate the correct translations to the correct objects.
I don't think Xcode will import localisation for objects with objectIDs it doesn't recognise.
So what I think you should do is to perform an "Export for localisation" operation. This should update your storyboard .strings file. Then you copy each translation from the tutorial file into your .strings file using an xliff editor. Boring, I know. Welcome to the app development world. :-)
When you added your localization did you select the storyboard file?
If so, then check that your scheme is set to the correct language. This can be done under Product > Scheme > Edit Scheme
If that doesn't do it, then check that your simulator is set to the language you want to display. This can be done in the simulator's settings, same as an iPhone.
Hope this helps.

Having a language select option in an app using Swift

I have Googled this for hours but could find no advice for the following problem (using Swift).
I have seen in many apps an option to select the language from inside the app like this:
(source: unity3d.com)
I would like to achieve something similar, but am having trouble implementing it. I have localized my app and have my Localizable.strings files all set up. I'd imagine it has something to do with storing the language selected in NSUserDefaults, but how can I make the app use the appropriate Localizable.strings file once a language has been chosen? Or is that the wrong way to approach it?
How have others successfully implemented this feature in Swift?
I've already faced this issue on one of my project and found one solution :
When the user select a language from a list, post a NSNotification. All your UIViewController subclass must register to this notification and change the labels value according to the new language selected.
You can use the localized strings in order to set the labels, but NSLocalizedString(...) shouldn't be called since it's relying on the device language which is different from the application language.
You can find my implementation of a custom localisator on Github, available both on Swift and objective-C.

How to localize iOS (iPhone/iPad) app using only single storyboard?

I was wondering if somebody could explain in the details how I can localize an iOS app using only 1 storyboard. I know how to localize by creating several storyboards(one storyboard for each used language), however I'd like to find out another solution.
Thanks.
The tutorial on raywenderlich.com uses two forms of localization together. The reason is he also checks the storyboard when turning on localisation in image 3:
.
So then what?
NSLocalizedString is very useful, any text set programatically can (and should) be localised using this method. Ray's tutorial is still very useful.
However, it's not very desirable to create a clone of the storyboard(s) to do translation, it's just not very maintainable in the long run.
And what about storyboards?
The magic happens using the Base Localization feature. Base localization uses the generated objectId's to 'map' different languages to the storyboard.
Do note that this feature is only available using SDK 6.0 and above. Running the app on a lower iOS version will not cause any errors, it'll simply won't work.
Go to your project, and select Base Localization, then add any other language.
Open your storyboard file and check the new language as well. Note the icon is not a storyboard icon, but a simple text file icon. That's a good thing; it won't copy the whole storyboard this time :).
Note how there is now another file 'under' the storyboard. Xcode automatically generates a file for every language you select.
You can se Localization feature for this. You need to add the Localizable.strings file for each supported language and use it for locaization.
You need to use : NSLocalizedString() for fetcing data corresponding to each key.
Check this tutorial for details.

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.

Resources