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.
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
In an android project, im trying to validate a password that the user inputs, and it must follow some rules
The rules are:
it must have 7 characters and 3 of the following conditions
**
-One lowercase character
-One uppercase character
-One number
-One special character
**
for example:
asd123!!!
PPPppp000
TTT999###
i was trying with this regex
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{7,}+$
but this enforces all rules at same time.
The approach is wrong here. The regex you created looks like a monster from under the bed, and is highly illegible even for someone regex-literate.
Why not split it into 4 (or as much as there are rules) regexes and check against whether 3 of them return a match? Not only will you make your regexes cleaner, but you will be able to add more rules if need be without changing whole regex.
You can also use inbuilt methods for checking (if applicable under Android development kit).
Some pseudocode would look like this:
result1 = Regex.IsMatch(password, rule1regex)
result2 = Regex.IsMatch(password, rule2regex)
...
resultN = Regex.IsMatch(password, rule3regex)
if(three_out_of_four_rules_apply)
password_valid = true
You can also apply method suggested in comments by #pskink and iterate over each character of a password and set the output accordingly.
Without going into the details of your lookaheads (which seem correct), here's how you would need to implement "three out of four criteria" in pure regex :
(?=.*A)(?=.*B)(?=.*C)|(?=.*A)(?=.*B)(?=.*D)|(?=.*A)(?=.*C)(?=.*D)|(?=.*B)(?=.*C)(?=.*D)
You can test it here.
Factorizing doesn't really make it better :
(?=.*A)(?:(?=.*B)(?=.*(?:C|D))|(?=.*C)(?=.*D))|(?=.*B)(?=.*C)(?=.*D)
I obviously recommend using a higher level language to implement these sorts of constraints.
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.
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.
Could somebody tell me what is better in terms of performance?
Is it better to save 2 strings at string.xml, like 'abc' and 'abc:'
Or should I save only the first one and concatenate ':' when needed at Java coding ???
Very difficult to answer depending on what your strings will represent and what you need to append. Localization is also an issue, for example...
Dog // English
Chien // French
Hund // German
Using string resources allows you to create different resource files depending on the locale of the device and Android will automatically use the right localized string resource file. If all you need to do is append a single character such as : then you'll double every string for every language.
If you choose to only save the basic strings and append the character using code, then the code will be universal and you'll simply need to append the character to whatever localized word - potentially a lot more efficient.
Both from storage perspective and performance you should save only "abc";
getting extra data from disk takes far longer as some quick in-memory actions.
storing the same data twice is bad practice in general
If you have to concatenate multiple strings you should use StringBuilder - http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html
It's much faster then using '+' or '.concat()'