How does Phrase work with Android XML and what to do prior to translation?
File Extensions | .xml |
API Extension | xml |
Import | Yes |
Export | Yes |
Pluralization support | Yes |
Descriptions support | Yes |
Format Options | convert_placeholder, escape_linebreaks, unescape_linebreaks, enclose_in_cdata, indent_size, indent_style |
Android XML is an Android-specific XML variation that can be used to load translated content into Android Apps. Its root element is a <resources> with numerous <string> elements nested under it that store strings pending translation. You may use Android Studio to generate these resource files and use Phrase to manage the translation.
Note: Phrase provides a more centralized way of managing Android XML files. Android Studio uses the property “translatable” to indicate whether the content needs to be translated. In Phrase, this property is ignored. There is no need to push these strings to Phrase.
Code Sample
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="boolean_key">--- true
</string>
<string name="empty_string_translation"/>
<!-- This is the beautiful description for this key! -->
<string name="key_with_description">Check it out! This key has a description! (At least in some formats)</string>
<string name="key_with_line-break">This translations contains
a line-break.</string>
<string name="nested.deeply.key">Hey, this key is nested even deeper.</string>
<string name="nested.key">This key is nested inside a namespace.</string>
<string name="null_translation"/>
<plurals name="pluralized_key">
<item quantity="one">Only one pluralization found.</item>
<item quantity="other">Hey, you have %s pluralizations!</item>
<item quantity="zero">You have no pluralization.</item>
</plurals>
<string-array name="sample_collection">
<item>first item</item>
<item>second item</item>
<item>third item</item>
</string-array>
<string name="simple_key">Just a key with a message.</string>
<string name="unverified_key">This translation is not yet verified and waits for it. (In some formats we also export this status)</string>
</resources>
Format Options
Convert Placeholder
Identifier | convert_placeholder |
Type | boolean |
Upload | No |
Download | Yes |
Default | false |
Description | Placeholder will be converted to match format specific requirements. Example: '$@' => '$s' |
Escape line breaks
Identifier | escape_linebreaks |
Type | boolean |
Upload | No |
Download | Yes |
Default | false |
Description | All line breaks will be escaped as '\n' |
Unescape linebreaks
Identifier | unescape_linebreaks |
Type | boolean |
Upload | Yes |
Download | No |
Default | false |
Description | All \n will be imported as true newlines |
Enclose in CDATA
Identifier | enclose_in_cdata |
Type | boolean |
Upload | No |
Download | Yes |
Default | false |
Description | Encloses translations containing HTML tags in CDATA |
Indent size
Identifier | indent_size |
Type | integer |
Upload | No |
Download | Yes |
Default | 4 |
Description | Specifies number of indentation characters |
Indent style
Identifier | indent_style |
Type | string |
Upload | No |
Download | Yes |
Default | space |
Description | Specifies indentation character. Allowed values are space and tab. |
Troubleshooting
I can not use placeholders in formatted text
To format text containing placeholders like “Hello <b>%1$s</b>”, you have two options.
1. Escape the HTML in Phrase
2. Escape the HTML in your code.
Set the text of the view like this to do it in the code,
SpannedString rawText = new SpannedString(getResources().getText(R.string.my_text));
String formattedString = String.format(Html.toHtml(rawText), "Jack");
SpannedString formattedText = new SpannedString(Html.fromHtml(formattedString));
view.setText(formattedText);
Which would result in the output “Hello Jack!”
Using a colorcode (#ff0000) in my font tag causes the text not to show
Escape the HTML in the string or use a method similar to the one above.
SpannedString rawText = new SpannedString(getResources().getText(R.string.my_text));
SpannedString text = new SpannedString(Html.fromHtml(Html.toHtml(rawText)));
view.setText(text);
Why is the ‘translatable=false’ tag ignored in Phrase?
The translatable=false attribute on the <string> element is not evaluated and persisted in Phrase. However if a string should not be translated, you can define all your non-translatable strings in a seperate resource file, for example donottranslate.xml. Since these strings should never be translated, there is no need to push this file to Phrase. More information can be found here.
How to escape your HTML in Phrase and use it
- Escape the HTML in Phrase (replace < with < and > with >)
-
Hello <b>World</b>!
-
- Use the translation center or the API Client to download your translations.
- Set the text in Java like so:
-
String rawString = getResources().getString(R.string.my_text);
SpannedString text = new SpannedString(Html.fromHtml(rawString));
view.setText(text);
-
- The output should be “Hello World!”
My HTML tags are not displayed when setting the text via view.setText
Set the text of the view with the following
SpannedString text = new SpannedString(getResources().getText(R.string.my_text));
view.setText(text);
How to share translations between iOS and Android
Keep the following in mind when sharing translations between iOS and Android:
- Use simple key names with no special characters and without white spaces - use underscores or hyphens instead. Most of the special characters are not supported in Android resource files. Rather than using the generated key names from Xcode like RMx-3f-FxP.title, use descriptive key names like ‘myniceapp_title’. This also makes them more readable.
- Avoid using CDATA tags because they are difficult to handle in iOS and can be avoided by correctly escaping the strings in most cases.
- Activate the “Escape line breaks” format option when exporting for Android to get an identical output on both platforms.