XLIFF file, keys and long strings with NSLocalizedString - ios

I want to move to xliff instead of translating Localizable.strings and Main.strings files but I found out that I'm using NSLocalizedString in an improper way (and I did it for 5 years actually...).
I don't like to have the translations directly inside my code, so I use a generic key and I do not write any comments:
NSLocalizedString("general.error", comment: "")
Then I include the string into the Localizable.strings
"general.error" = "An error occured";
So far so good (maybe). Now when I export xliff files I see that the source is just my generic key and obviously a translator cannot guess what to write as target for that key :/
So my question is: Is the only solution to move all the translations directly inside the NSLocalizedString?
NSLocalizedString("An error occured", comment: "")
or inside the comment... (I really don't like this solution)
And what if the string is really long? it seems so strange to put a string of 3 rows directly into the code :/
Any other interesting solution out there?
EDIT
I've already tried to use constants, but it seems that this solution doesn't work in swift. I've created a String.swift file where I've added constants:
let thisIsMyLonStringID = "An here I can put the long translation";
And I can use it in this way:
NSLocalizedString(thisIsMyLonStringID, comment: "")
When I export to XLIFF this string is not available in the xliff files though :(

I put here an answer with my temporary solution. It seems to work pretty well actually.
Instead of using a Base language for the Localizable.strings file I've used English, so I've just deselected Base from the file inspector -> Localizations area in Xcode and I've been prompt with a question like "which language would you like to use as base"... I've selected english.
Now I can continue using NSLocalizedString using a generic key and putting the translations in Localizable.strings when I export to xliff automatically the source is filled with the right translation and not with the key.

You need to make the call to NSLocalizedString directly in your Strings.swift file. For example:
// Strings.swift
let myString = NSLocalizedString("some very long string", comment: "")
// Usage
print(myString)
That way, the string export process will be able to determine the string literal that is passed in to NSLocalizedString.

Yes there is very elegant solution to your problem. Problem is very long string's are getting part of our code, making it harder to read and messy.
Solution:
Create LocalizationKeys.h
#ifndef Project_LocalizationKeys_h
#define Project_LocalizationKeys_h
static NSString *const LocalizationKeyForVeryLongString =
#"Your Very Very Long String";
#endif
In your code: ViewController.m
NSLocalizedString(LocalizationKeyForVeryLongString, "");
So above solution separated very long messy strings and replaced them with elegant and readable Key Strings, moreover now we have separate file for key strings, so whenever someone is needed to change or to lookup, directly refer to LocalizationKeys.h

Related

NSLocalizedString comment parameter in Swift [duplicate]

What is the *comment parameter in:
NSString *NSLocalizedString(NSString *key, NSString *comment)
If I do this:
NSLocalizedString(#"Hello_World_Key", #"Hello World")
and have two versions of a Localizable.strings (English and Spanish), does each need the entry:
English.lproj/Localization.strings: #"Hello_World_Key" = #"Hello World";
Spanish.lproj/Localization.strings: #"Hello_World_Key" = #"Hola Mundo";
Isn't the English one redundant?
The second parameter is a comment that will automatically appear in the strings file if you use the genstrings command-line utility, which can create the strings file for you by scanning your source code.
The comment is useful for your localizers. For example:
NSLocalizedString(#"Save",#"Title of the Save button in the theme saving dialog");
When you run genstrings, this will produce an entry in the Localizable.strings file like this:
/* Title of the Save button in the theme saving dialog */
"Save" = "Save";
The comment string is ignored by the application. It is used for a translator's benefit, to add meaning to the contextual usage of the key where it is found in your application.
For example, the Hello_World_Key key may take different values in a given language, depending on how formal or informal the Hello World phrase needs to be in that language ("What's up World", "Yo World", "Good Day World", etc.).
You can add a string in the comment field to hint this usage to the translator, who will (one would presume) be better able to localize your application.
The comment parameter is used for ease in translation. It has nothing to do with output of NSLocalizedString function. It will help just translator to translate nothing else.
According to Localizing Your App documentation, you can export localizations for a localization team. The comments you put in NSLocalizedString are included in the exported files.
Exporting localizations creates files with xliff extension, which contains XML like the code below.
<trans-unit id="Settings">
<source>Settings</source>
<target>설정</target>
<note>Label of the button to Settings screen</note>
</trans-unit>
<trans-unit id="Take Photo">
<source>Take Photo</source>
<target>사진 찍기</target>
<note>No comment provided by engineer.</note>
</trans-unit>
XLIFF files can be edited using app localization tools like XLIFFTool.
It's for just developer understanding on the translation, that is you are giving a key to get corresponding string from the corresponding strings file.
The comment parameter enables developer to understand what the key represents...

NSLocalizedString in Spritekit SKLabelNode

I've been searching all over the internet and there doesn't seem to be a clear explanation on how to localize strings using SpriteKit. Only seeing tutorials for people using the interface builder, but all I really want is, imagine this:
I have an SKLabelNode called label. And I define the text like:
labl.text = NSLocalizedString("titleOfTheScreen",nil)
So basically what I think I have to do is add the new language in the Project settings. Then, I add a new Strings file called Localized, and add it to the new folder.
But what happens to my English language? There's no file for the original one
First you have to add a Strings File:
Then open the project settings and add a new language:
Mark your added strings file as target:
Find the newly added localising file. (English is automatically added)
From your screenshots I can see that you have "File.strings" file. You should have created "Localizable.strings" file.
Also, I can see that you have the (Base), (English) and (German) strings version. Why do you think English is not there?
In each of the files you should put strings like that:
"titleOfTheScreen" = "blah-blah";
Replace "blah-blah" with the proper translation in each of the strings files. It's important to note that the semi-colon at the end of the lines in strings files are mandatory, otherwise Xcode would issue some really funny error messages. This is easy to overlook if you're programming in Swift and trailing semi-colons are not mandatory.

Xcode Localization: Keep translation in sync with Storyboard

Here's our localization workflow:
Build stuff in interface builder
Export project for localization
Translator looks at xliff files and applies translations for new strings (Only new untranslated strings)
Import xliff into project
This works fine for building new stuff. But if the developer changes the text in a label in storyboard that has already been translated, he will have to remember to delete the translation for that label, so the translater sees that string as untranslated. If the developer forgets to delete that translation, the translation will be wrong, which is a very hard error to find.
When code is localized like this:
var testString = NSLocalizedString("Some text in english", comment: "just a test string")
The string ("Some text in english") defines the key in the xliff-file, which means that if the string is changed, then the exported xliff file will automatically have a new string that needs to be translated.
I've tried to solve the problem with xcode's "export for localization..." function, with genstrings, and with BartyCrounch, but all methods seems to use the UI Element's Object ID as a key for the .strings-files. Which means it won't react to changes in the actual string.
The only solution I've found so far, is to set every string that need translation in the storyboards in code via a IBOutlet, but this is a quite comprehensive solution.
Do you know any tools or methods that solve this problem?
I tried what you said and understood what you meant. I think the solution is straightforward.
First, I added a new button in storyboard, named it "Test". Then I translated it in Chinese, imported the translation. Changed "Test" to "GoGo" and exported the translation again. The xliff part was changed from
<trans-unit id="jso-qF-Z1t.title">
<source>Test</source>
<target>测试</target>
<note>Class = "NSButtonCell"; title = "Test"; ObjectID = "jso-qF-Z1t";</note>
</trans-unit>
to
<trans-unit id="jso-qF-Z1t.title">
<source>GoGo</source>
<target>测试</target>
<note>Class = "NSButtonCell"; title = "GoGo"; ObjectID = "jso-qF-Z1t";</note>
</trans-unit>
What to do next
I don't know if there is a ready-tool for this. But you can use Git as it can always find the diffs.
Steps:
add you translation folder to git
commit current files
export new translations from Xcode
look at diffs with git
As you can see in the picture, git already shows what changes, that is where you should translate again.

Best way to utilize strings in iOS

I am new to coding in Objective-C, but am coming from the Java world of mobile development. In Android, we use a strings resource, and then point to those in the Java class. Is there an analogous process in iOS that we should be using, or do we "hard-code" the strings into the implementation files? I haven't yet found a good tutorial using the localizable string (and .strings) file.
You can use the NSLocalizedString macro from Foundation to retrieve a localized string. Read here:
http://www.icanlocalize.com/site/tutorials/iphone-applications-localization-guide/
Example: build a bilingual (English-French) app.
Whenever you encounter a string to be displayed to the user, use NSLocalizedString instead of the actual string constant. For example:
instead
self.title = #"Welcome";
use
self.title = NSLocalizedString(#"Welcome");
Create two directories inside your app bundle as follows:
MyApp.app
English.lproj
Localizable.strings
French.lproj
Localizable.strings
In the first Localizable.strings file you can write key-value pairs like this:
"Welcome" = "Welcome";
In the second one:
"Welcome" = "Bienvenus";
When you add these files and folders to your application, an recompile it using the NSLocalizedString macro, you'll be able to use your app in French also when the system language is French.
Sure, there's a way to do that.
Take a look at the Apple doc here - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html
There's not much more to it than that really. Although I tend to just hard code a lot of strings but it's definitely worth taking the time to learn about string resources because it's the basis of internationalisation.

What is the second parameter of NSLocalizedString()?

What is the *comment parameter in:
NSString *NSLocalizedString(NSString *key, NSString *comment)
If I do this:
NSLocalizedString(#"Hello_World_Key", #"Hello World")
and have two versions of a Localizable.strings (English and Spanish), does each need the entry:
English.lproj/Localization.strings: #"Hello_World_Key" = #"Hello World";
Spanish.lproj/Localization.strings: #"Hello_World_Key" = #"Hola Mundo";
Isn't the English one redundant?
The second parameter is a comment that will automatically appear in the strings file if you use the genstrings command-line utility, which can create the strings file for you by scanning your source code.
The comment is useful for your localizers. For example:
NSLocalizedString(#"Save",#"Title of the Save button in the theme saving dialog");
When you run genstrings, this will produce an entry in the Localizable.strings file like this:
/* Title of the Save button in the theme saving dialog */
"Save" = "Save";
The comment string is ignored by the application. It is used for a translator's benefit, to add meaning to the contextual usage of the key where it is found in your application.
For example, the Hello_World_Key key may take different values in a given language, depending on how formal or informal the Hello World phrase needs to be in that language ("What's up World", "Yo World", "Good Day World", etc.).
You can add a string in the comment field to hint this usage to the translator, who will (one would presume) be better able to localize your application.
The comment parameter is used for ease in translation. It has nothing to do with output of NSLocalizedString function. It will help just translator to translate nothing else.
According to Localizing Your App documentation, you can export localizations for a localization team. The comments you put in NSLocalizedString are included in the exported files.
Exporting localizations creates files with xliff extension, which contains XML like the code below.
<trans-unit id="Settings">
<source>Settings</source>
<target>설정</target>
<note>Label of the button to Settings screen</note>
</trans-unit>
<trans-unit id="Take Photo">
<source>Take Photo</source>
<target>사진 찍기</target>
<note>No comment provided by engineer.</note>
</trans-unit>
XLIFF files can be edited using app localization tools like XLIFFTool.
It's for just developer understanding on the translation, that is you are giving a key to get corresponding string from the corresponding strings file.
The comment parameter enables developer to understand what the key represents...

Resources