now I encounter a doubt about % in android string resource. The question as follow:
If I want to use % symbol in other language, such as in chinese. I must add resource string formatted="false" in /values-zh-rCN/strings.xml.
Yes, the string tag must have ther formatted attribute.
However, it could not add this formatted attribute in /values/strings.xml in english language. it compile successfully, and work well.
Why?
I can't find any answer in android developer website.
ps: how i write Angle brackets in stackoverflow editor. I'm a freshman.
Java code:
autoDownloadLayout.findViewById(R.id.setItemContent)).setText(R.string.setting_auto_update_title_1_subtitle);
/values/strings.xml :
<string name="setting_auto_update_title_1_subtitle">Automatically download updates when connected to Wi-Fi, when the battery level is greater than 30% and CPU usage is less than 50%</string>
/values-zh-rCN/strings.xml :
<string formatted="false" name="setting_auto_update_title_1_subtitle">"仅在 WLAN 网络,手机电量高于 30% 且 CPU 占用率低于 50% 时,预先下载游戏更新包"</string>
It seems that Android Lint has different ideas when checking translated strings as compared to default strings. There's an open issue (Issue 74959) about this (although it's not exactly your problem). It would seem that technically you should be adding formatted="false" to the strings in /values as well as to those in /values-zh-rCN.
Alternatively, you could encode all literal percent signs as % (or %). That might be the simplest (and least risky) approach.
Related
It is known that Androd string resources support xliff namespace to annotate non-translatable string formatting placeholders, like this
<string name="max_file_size_exceeded_template">File
<xliff:g example="some_image.jpg" id="file_name">%1$s</xliff:g>
is too big and could not be uploaded.</string>
It helps translators to undestand what parts of string should not be modified. But sometimes I need to annotate some strings max length it they are used in UI control with limited size. What I want is add text length limit to warn translators about this. Something like max-length="24" max-lines="2" length-unit="char" Maybe, xliff supports such thing or it can be achieved in other way.
I use Weblate for translations if it matters.
You can set this in Weblate, the Andoid format does not support this directly.
Click on edit (pencil) icon next to flags on the string.
Enter max-length:LENGTH as check flag.
See also https://docs.weblate.org/en/latest/admin/translating.html#additional-information-on-source-strings
I have to maintain an app translated into more than 10 different languages. Whenever a new version is developed, new strings are added to the source values.xml . The translation editor helps me to get an overview about which strings are missing in other languages, but at the moment, it looks like there is no option to get a diff xml with just the new strings added for each language. Since we use translation services we have to pay per translated word. Therefore I always have to manually create the files with the missing translations, which is very time consuming.
I can't imagine I'm the only one needing this particular feature. Is there a workaround / script / plugin which does solve this problem?
Back in the steam age I faced similar problem while trying to keep like 14 translations in sync, so I created small PHP script to to help me with this.
As I said it's pretty dated (2010 :) yet it should work. I just made it available on GitHub: https://github.com/MarcinOrlowski/android-strings-check
Basically what it does is diff two translation XMLs and generate human readable report:
./strings-check.php values/strings.xml values-pl/strings.xml
It will give you the output like this:
Missing in LANG (You need to add these)
File: values-pl/strings.xml
------------------------------------------------------
show_full_header_action
hide_full_header_action
recreating_account
Not present in BASE (remove it from your LANG file)
File: values/strings.xml
------------------------------------------------------------------
provider_note_yahoo
Summary
----------------
BASE file: 'values/strings.xml'
LANG file: 'values-pl/strings.xml'
3 missing strings
1 orphaned strings
Ok, I guess I found the solution to my problem, a python script called android-localization-helper:
https://github.com/jordanjoz1/android-localization-helper
I'm writing small app and I need to write duration of sport event in i18n. Im using PrettyTime library for date, but when I attempt to use DateUtils or PrettyTime, I have issues..
For example I want to say that duration is 2 minutes. I need some way to pass it to library which supports i18n and accept milliseconds and return Chars.
In android we have:
com.android.internal.R.plurals.duration_minutes
But I can't access to it from my App. Is there any way to make it using correct way and not writing own plurals for all languages?
Thank you
I am not sure which issues you are talking about in context of Android-DateUtils and PrettyTime-library. But I know for sure that Android-DateUtils does not perfectly manage the plural rules of various languages (especially not slavish languages or arabic because it only knows singular and one plural form which is too simple). See for example this Android-issue. About the PrettyTime-library, the same objection is valid if you consider Arabic - see the source.
My recommendation:
Try out my library Time4A (a new AAR-library). Then you can use this code to process a millisecond-input and to produce a localized minute-string:
// input
long millis = 1770123;
// create a duration
Duration<ClockUnit> duration = Duration.of(millis, ClockUnit.MILLIS);
// normalization to (rounded) minutes
duration = duration.with(ClockUnit.MINUTES.rounded());
String s = PrettyTime.of(Locale.ENGLISH).print(duration, TextWidth.WIDE);
System.out.println(s); // 30 minutes
Example for Korean (answer to comment of #Gabe Sechan):
String s = PrettyTime.of(new Locale("ko")).print(duration, TextWidth.WIDE);
System.out.println(s); // 30분 (korean translation of "30 minutes")
Example for Arabic (right to left):
String s = PrettyTime.of(new Locale("ar")).print(duration, TextWidth.WIDE);
System.out.println(s); // ٣٠ دقيقة
This solution currently supports ~90 languages (more than in PrettyTime-library) and three text widths (full, abbreviated or narrow). Accurate pluralization handling is automatically included. Time4A uses its own language resources based on CLDR-data (independent from Android). But you are free to override those resources by defining your own assets (in UTF-8).
About normalization: I just showed the variant which you have described in your question. However, there are many more ways how to normalize durations in Time4A(J). This page will give you more ideas how to use that feature.
If you still miss some languages then just tell me, and I will support it in the next versions of Time4A. Currently supported languages can be found in the tutorial.
I want to use Emojis in my app's strings. All strings reside, of course, in strings.xml
The problem is that not all Emojis are 16 bit friendly. Some Emojis can be represented as "normal" 16 bit hex: '\u26FF' but some are 32 bit hexes (UTF-16), usually represented as: '\x1F600'. I have no problem dealing with those inside the app, in code. But the strings.xml resource file is UTF8 encoded, and does not deal properly with non 16 bit escape chars.
I tried using '\x1F600' - because I saw that '\u26FF' works just fine. But it seems not to devour the 'x' escape char. Nor did it like the regexp notation '\x{1F600}'
So I ended up using a string placeholder '%1$s' and filling in the Emoji in code like this:
// greeting_3 is defined as: "hello there %1$s!"
String s = context.getString(R.string.greeting_3, "😜");
// OR:
String s = context.getString(R.string.greeting_3, new String(Character.toChars(0x1F61C)));
This is not a very elegant solution... is there a proper way to put 32 bit UTF-8 chars in strings.xml ?
But the strings.xml resource file is UTF8
If it's UTF-8 encoded, you can put your emojis directly. But then you risk that your editor or another piece of software destroys them.
If you are putting them in XML, you can try using XML entities: 😀, I'm not sure how well Android supports them though.
You can also use surrogate pairs: convert the emoji to UTF-16 and use standard \u escape. You can for example check out this page, it even tells you how to create a string litaral in Java: http://www.fileformat.info/info/unicode/char/1F600/index.htm
😜 → U+1F600 → "\uD83D\uDE00"
The easiest way it just copying and pasting the emoji, it works from Android Studio 3.0 and newer
Add the resource like follows:
<string name="string_title">This is a emoji example <U+1F642></string>
In Android Studio 3.0 you can copy and paste an emoji:
And here how it looks:
I am using Plural strings provided by android-sdk. I have used following code to create a plural string:
<plurals name="valuestr">
<item quantity="zero">Choose a value.</item>
<item quantity="one">%d unit.</item>
<item quantity="other">%d units.</item>
</plurals>
Java Code:
textView.setText(getResources().getQuantityString(R.plurals.valuestr,0,0));
When i am setting any value other than '0', this is working fine but when i am setting '0' it is showing '0 unit.'.
Please help!
Update
While searching more on the internet i came across a workaround which uses java.text.MessageFormat class:
<resources>
<string name="item_shop">{0,choice,0#No items|1#One item|1<{0} items}</string>
</resources>
Then, from the code all you have to do is the following:
String fmt = resources.getText(R.string.item_shop);
textView.setText(MessageFormat.format(fmt, amount));
You can read more about the format strings in the javadocs for MessageFormat
A post was recently made on G+ about this.
In short, it is because this will not pick the closest match by Integer ( 0 = zero), but because it will look for the best grammatical pick.
In your example, you use units.
The correct usage would be;
0 units
1 unit
2 units
Making, zero equal to pretty much any other quantity above 1
Read the full story here;
https://plus.google.com/116539451797396019960/posts/VYcxa1jUGNo
Plurals defined in <plurals> sections of resource files are only to be used for a grammatical distinction with respect to singular/plural strings. You should not use them for other display logic, as you did. You should add some checking logic in your code instead.
The Android developer's guide clearly states this:
Although historically called "quantity strings" (and still called that
in API), quantity strings should only be used for plurals. It would be
a mistake to use quantity strings to implement something like Gmail's
"Inbox" versus "Inbox (12)" when there are unread messages, for
example. It might seem convenient to use quantity strings instead of
an if statement, but it's important to note that some languages (such
as Chinese) don't make these grammatical distinctions at all, so
you'll always get the other string.
Your workaround - although working technically for your current implementation - does not appear like a clean solution either, in my opinion. Future business requirements may make it necessary to include more sophisticated logic than just displaying a different text. Or you may have a generic "no items selected" string in your resource file used at different locations, which could be reused only if you did not stick to your solution.
Generally, I would avoid using two different formatting techniques (String.format style formatter %d vs. MessageFormat style formatter {0} and pick one that you'd stick to in your whole application.