Getting a String from Plurals to use in XML? - android

I am using Plurals to simplify my code. e.g., I used to have
<string name="cat">Cat</string>
<string name="cats">Cats</string>
Using Plurals instead of multiple strings, I now have
<plurals name="cats">
<item quantity="one">Cat</item>
<item quantity="other">Cats</item>
</plurals>
However, I used to retrieve strings to use as titles or summaries in my XML.
e.g.,
android:title="#string/cats"
Having removed that string in favor of a Plural, I am now unsure how to retrieve my string from XML. I did make a naive attempt with
android:title="#plurals/cats"
but this just gives me #1234567890 instead of Cats (or Cat).
Anyone know if it is possible to retrieve a string out of a Plural from XML?

You have to set it by code:
...setText(yourContext.getResources().getQuantityString(R.plurals.cats, catsCountVar));

You can have the run-time benefits of Plurals and the static benefit of string resources by leaving your string resources where they are and referring to them in your plural resources.
From https://developer.android.com/guide/topics/resources/string-resource.html#Plurals (emphasis added).
<item>
A plural or singular string. The value can be a reference to another string resource. Must be a child of a element. Beware that you must escape apostrophes and quotation marks. See Formatting and Styling, below, for information about to properly style and format your strings.
Example:
<string name="cat">Cat</string>
<string name="cats">Cats</string>
<plurals name="cats">
<item quantity="one">#string/cat</item>
<item quantity="other">#string/cats</item>
</plurals>
Now you can use android:title="#string/cats" in XML files and also use
getQuantityString(R.plurals.cats, numberOfCats)
at runtime.

This can now be done in XML, using a data binding expression:
android:text="#{#plurals/cats(catCount)}"
See this page in the docs for more information: https://developer.android.com/topic/libraries/data-binding/expressions#resources

This is now possible from xml. If you have arguments in the plural forms, you have to remember to pass the quantity variable twice. Like in the below example.
<plurals name="number_of_students_in_topic">
<item quantity="zero">None are currently in this topic.</item>
<item quantity="one">One student is currently in this topic.</item>
<item quantity="other">%d students are currently in this topic.</item>
</plurals>
In xml with data binding.
android:text="#{#plurals/number_of_students_in_topic(count, count)}"
This is because, the plurals with arguments are converted in code (In *BindingImpl classes) using getResources().getQuantityString(int id,
int quantity,
Object... formatArgs)
The first count is to select the right plural form, and the second one is to format the String with right values.

If your string includes string formatting with a number then you need to sent the integer variable twice, example
strings.xml
<resources>
<plurals name="numberOfMinute">
<item quantity="one">%d minute</item>
<item quantity="other">%d minutes</item>
</plurals>
</resources>
in java
int min = getNumberOfMinute();
Resources res = getResources();
String formattedStr = res.getQuantityString(
R.plurals.numberOfMinute,
min,
min
); //this will return "20 minutes" or "1 minute" depending on variable
Kotlin File
resources.getQuantityString(
R.plurals.numberOfMinute, //plural from strings.xml file
min, //quantity
min //var arg
)

Here is a way to use a plural resource as an attribute of your custom View.
src/main/res/xml/layout.xml
<com.mypackage.MyView
app:foo="#plurals/cats"/>
src/main/res/values/attrs.xml
<resources>
<declare-styleable name="MyView">
<attr name="foo"/>
</declare-styleable>
</resources>
MyView.java
public class MyView extends View {
private int fooResId;
private int quantity;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
fooResId = a.getResourceId(R.styleable.MyView_foo, 0);
a.recycle();
}
// this will return "Cat" or "Cats" depending on the value of quantity
private String getFooString() {
return getContext().getResources().getQuantityString(fooResId, quantity);
}
}

updated answer for Kotlin
strings.xml
<plurals name="lbl_items_selected">
<item quantity="one">%d item Selected</item>
<item quantity="other">%d items Selected</item>
</plurals>
Kotlin File
resources.getQuantityString(
R.plurals.lbl_items_selected, //plural from strings.xml file
size, //quantity
size //var arg
)
this will return :
if size = 1 : 1 item selected
if size = 2 (or more) : 2(given size) items selected

Related

How to link android resource values together?

I have trouble finding a pattern to create constants that point to a collection of resource values.
Let's say I have four TextViews, in each corner of the layout. I then have four different sets of constant content to randomly assign to these four TextViews. That content comes with a text and a background color for the TextView. Those values are defined in the strings.xml and colors.xml. Let's say the strings.xml looks like this:
<resources>
<string name="A">Text for A</string>
<string name="B">Text for B</string>
<string name="C">Text for C</string>
<string name="D">Text for D</string>
</resources>
and my colors.xml like this:
<resources>
<color name="A">#AAAAAA</color>
<color name="B">#BBBBBB</color>
<color name="C">#CCCCCC</color>
<color name="D">#DDDDDD</color>
</resources>
In the Activity class I then want to write a method to assign these values randomly to the TextViews. I could do this by creating lists for each type of value, then picking a random TextView out of these four, remove the first value out of each list and assign it to the TextView:
List<Integer> colors = Arrays.asList(R.color.A,
R.color.B,
R.color.C,
R.color.D);
List<String> strings = Arrays.asList(R.string.A,
R.string.B,
R.string.C,
R.string.D);
for (int i = 4; i > 0; i--) {
int randomNumber = // get a random number between 0 and i
TextView tv = // get text view based on i (by switch case)
tv.setText(string.remove(0));
tv.setBackgroundColor(getResources().getColor(colors.remove(0));
}
This solution doesn't seem good to me because the relationship between the string and the color values is not obvious at first sight. Also it is a lot of code to write.
I then thought of an enum, where each enum-value has a reference to its associated resources.
enum TextViewContent {
A(R.string.A, R.color.A),
B(R.string.B, R.color.B),
C(R.string.C, R.color.C),
D(R.string.D, R.color.D);
public final String string;
public final int color;
private TextViewContent(String string, int color) {
this.string = string;
this.color = color;
}
}
This solution looked fine to me until I saw this page https://android.jlelse.eu/android-performance-avoid-using-enum-on-android-326be0794dc3 where they recommend to avoid using enums in android code. In the examples of that page the enums to avoid were all replacable by a set of constants of a primitive type. I am not sure if using an enum is still a good idea. On the other hand I am running out of ideas how to solve this problem.
Is the use of an enum the best solution in this case? If not: What is the best solution here?
Prepare your resources in such a way that can be used as arrays:
<string-array name="texts">
<item>Text for A</item>
<item>Text for B</item>
<item>Text for C</item>
<item>Text for D</item>
</string-array>
<color name="A">#AAAAAA</color>
<color name="B">#BBBBBB</color>
<color name="C">#CCCCCC</color>
<color name="D">#DDDDDD</color>
<integer-array name="colors">
<item>#color/A</item>
<item>#color/B</item>
<item>#color/C</item>
<item>#color/D</item>
</integer-array>
Then all you have to do to retrieve them is:
String[] strings = getResources().getStringArray(R.array.texts);
int[] colors = getResources().getIntArray(R.array.colors);
It is not a lot of coding.
It also is easy to maintain because if you want to change the texts or colors, or to add new items, or delete items you only have to work in the resources.
As for the relationship between the string and the color values it's more than obvious.

How to write a string with space by dataBinding

I want to make the app show me the string like "24 girls";
but when I use dataBinding , the space in string can't be shown,the string change like "24girls".
This is my code:
I would suggest you to use plurals for this.
In your strings.xml add this:
<plurals name="scores">
<item quantity="one">%d Girl</item>
<item quantity="other">%d Girls</item>
</plurals>
and in your layout file
android:text="#{#plurals/scores(setScore.score, setScore.score)}"
The first setScore.score is used to decide which string should be used from the plurals.
And the second setScore.score is for argument %d we mentioned in plurals.
You may make this in layout:
android:text="#{setScore.score + ' ' + #string/score_string}"
But as for me better variant is create a special getter in viewmodel which will return string.
For example:
String getScoreFormatted() {
return String.format(getString(R.string.score_string), score);
}
And use it in your layout:
android:text="#{setScore.scoreFormatted}"
Why is better? Because you may code any logic by java or kotlin in you method and your layout will be cleaner.
Create a string resource:
<string name="score_string">%1d girls</string>
and then use it like this:
android:text="#{String.format(#string/score_string, setScore.score)}"
just give whitespace +' '+ in between score and score string

In French, plural system treats 0 as "other" instead of "one"

In res/values/strings.xml, I have
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="days_amount">
<item quantity="one">%d day EN</item>
<item quantity="other">%d days EN</item>
</plurals>
</resources>
And in res/values-fr/strings.xml, i have
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="days_amount">
<item quantity="one">%d jour FR</item>
<item quantity="other">%d jours FR</item>
</plurals>
</resources>
With English locale res.getQuantityString(R.plurals.days_amount, 0, 0) returns:
"0 days"
which is okay per English rules (aka zero quantity <=> several quantities).
But with a French locale, it returns:
"0 jours"
which is NOT okay per French rules (aka zero quantity <=> singular quantity).
It should have returned "O jour"
French rules: http://www.unicode.org/cldr/charts/25/supplemental/language_plural_rules.html#fr
So, is this a bug, or am I doing something wrong ?
Your code looks correct to me. Here's why:
The Android documentation contains the text zero, one, two, few, many, and other, which exactly matches the wording of the Unicode language plural rules. This suggests that Android uses them.
These plural rules state that the French case of 0 books is handled by the one case.
Since the Android documentation doesn't explicitly mention the Unicode language plural rules, you should request clarification from the Android support.
Before you do that, you should consult this other question, where the French rules obviously worked.
Indeed your concern is right, in French amount 0 should be treated as 'one' instead of 'other'. The issue is in some Android APIs: API <= 16
So in case you want still to support API 16 just add an extra string key for the zero amount. Let's assume you have:
<plurals name="label_message_reminder_text">
<item quantity="other">Vous avez %1$s nouveaux messages</item>
<item quantity="one">Vous avez %1$s nouveau message</item>
</plurals>
Just add an extra string:
<string name="label_message_reminder_text_zero">Vous avez %1$s nouveau message</string>
And then when retrieving plurals can do something like:
String newMessagesText = getMyString(context, resourceId, amount);
messageTextView.setText(String.format(newMessagesText, amount));
And you can have a method to do the getMyString():
public String getMyString(Context context, int resourceId, int amount){
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
if(amount == 0) {
switch (resourceId) {
case R.plurals.label_message_reminder_text:
return context.getResources().getString(R.string.label_message_reminder_text_zero);
}
}
}
return context.getResources().getQuantityString(resourceId, amount);
}
You're doing something wrong. It's doing exactly what you're telling it to.
Your rules say that when the value is other, use "days" or "jours". You then pass in the value 0, which is other, so it uses "days" and "jours", as requested.
You could try setting a third value for quantity "zero" which has the language-specific rules.

Android Pluralization not working, need help

I've been attempting to utilize the plurals resource with Android but have not had any luck.
Here is my resource file for my plurals:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="meters">
<item quantity="one">1 meter</item>
<item quantity="other">
<xliff:g id="count">%d</xliff:g>
meters
</item>
</plurals>
<plurals name="degrees">
<item quantity="one">1 degree</item>
<item quantity="other">
<xliff:g id="count">%d</xliff:g>
degrees
</item>
</plurals>
</resources>
...and then here is the code I am using when I attempt to extract the quantity string from my resources:
Resources res = this.getResources();
tTemp.setText(res.getQuantityString(R.plurals.degrees, this.mObject.temp_c.intValue()));
...but the text in the TextView remains to be %d degrees and %d meters.
Does anyone know what is happening? I've debugged the code and the res.getQuantityString(...) call is returning a String whose value is %d degrees or %d meters. Though when the quantity happens to be 1 it does correctly evalute to 1 degree or 1 meter.
Thanks in advance for any help!
Regards, celestialorb.
It appears that you need to specify the count twice, the first is used to determine the string to use, and the second is the one that is replaced into the string. e.g.
Resources res = this.getResources();
int tv = this.mObject.temp_c.intValue();
tTemp.setText(res.getQuantityString(R.plurals.degrees, tv, tv));
And at least in my testing so far, the xliff:g elements in the resource aren't needed.
Android "supports" the use of plurals by use of R.plurals which is practically undocumented. Diving into the source code reveals that you should be able to have the following possible versions of a string:
"zero"
"one"
"few" (for exactly 2)
"other" (for 3 and above)
However, I've found that only "one" and "other" actually work (despite the others being used in the android source!).
To use plurals you want to declare you pluralizable strings in a similar way to normal string resources:
<resources>
<plurals name="match">
<!-- Case of one match -->
<item quantity="one">1 match</item>
<!-- Case of several matches -->
<item quantity="other">%d matches</item>
</plurals>
</resources>
Then to actually use them in code, use code similar to what superfell suggested above:
String text = getResources().getQuantityString(R.plurals.match, myIntValue, myIntValue);
myTextView.setText(text);
Same problem here! I guess it is just a flaw in the documentation. The "pure" getQuantitiyString(int, int) method does just get a text resource, without any formatting. As superfell stated: just use the getQuantityString(int, int, Object...) method and hand over your integer value twice.
I'd hoped this worked the same way you did, but it simply doesn't!!
PS: maybe check an answer as the correct one? ;-)

Is it possible to have placeholders in strings.xml for runtime values?

Is it possible to have placeholders in string values in string.xml that can be assigned values at run time?
Example:
some string PLACEHOLDER1 some more string
Formatting and Styling
Yes, see the following from String Resources: Formatting and Styling
If you need to format your strings using String.format(String, Object...), then you can do so by putting your format arguments in the string resource. For example, with the following resource:
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
In this example, the format string has two arguments: %1$s is a string and %2$d is a decimal number. You can format the string with arguments from your application like this:
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
Basic Usage
Note that getString has an overload that uses the string as a format string:
String text = res.getString(R.string.welcome_messages, username, mailCount);
Plurals
If you need to handle plurals, use this:
<plurals name="welcome_messages">
<item quantity="one">Hello, %1$s! You have a new message.</item>
<item quantity="other">Hello, %1$s! You have %2$d new messages.</item>
</plurals>
The first mailCount param is used to decide which format to use (single or plural), the other params are your substitutions:
Resources res = getResources();
String text = res.getQuantityString(R.plurals.welcome_messages, mailCount, username, mailCount);
See String Resources: Plurals for more details.
Supplemental Answer
When I first saw %1$s and %2$d in the accepted answer, it made no sense. Here is a little more explanation.
They are called format specifiers. In the xml string they are in the form of
%[parameter_index$][format_type]
%: The percent sign marks the beginning of the format specifier.
parameter index: This is a number followed by a dollar sign. If you had three parameters that you wanted to insert into the string, then they would be called 1$, 2$, and 3$. The order you place them in the resource string doesn't matter, only the order that you supply the parameters.
format type: There are a lot of ways that you can format things (see the documentation). Here are some common ones:
s string
d decimal integer
f floating point number
Example
We will create the following formatted string where the gray parts are inserted programmatically.
My sister Mary is 12 years old.
string.xml
<string name="my_xml_string">My sister %1$s is %2$d years old.</string>
MyActivity.java
String myString = "Mary";
int myInt = 12;
String formatted = getString(R.string.my_xml_string, myString, myInt);
Notes
I could use getString because I was in an Activity. You can use context.getResources().getString(...) if it is not available.
String.format() will also format a String.
The 1$ and 2$ terms don't need to be used in that order. That is, 2$ can come before 1$. This is useful when internationalizing an app for languages that use a different word order.
You can use a format specifier like %1$s multiple times in the xml if you want to repeat it.
Use %% to get the actual % character.
For more details read the following helpful tutorial: Android SDK Quick Tip: Formatting Resource Strings
When you want to use a parameter from the actual strings.xml file without using any Java code:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
<!ENTITY appname "WhereDat">
<!ENTITY author "Oded">
]>
<resources>
<string name="app_name">&appname;</string>
<string name="description">The &appname; app was created by &author;</string>
</resources>
This does not work across resource files, i.e. variables must be copied into each XML file that needs them.
Was looking for the same and finally found the following very simple solution. Best: it works out of the box.
1. alter your string ressource:
<string name="welcome_messages">Hello, <xliff:g name="name">%s</xliff:g>! You have
<xliff:g name="count">%d</xliff:g> new messages.</string>
2. use string substitution:
c.getString(R.string.welcome_messages,name,count);
where c is the Context, name is a string variable and count your int variable
You'll need to include
<resources xmlns:xliff="http://schemas.android.com/apk/res-auto">
in your res/strings.xml.
Works for me. :)
If you want to write percent (%), duplicate it:
<string name="percent">%1$d%%</string>
label.text = getString(R.string.percent, 75) // Output: 75%.
If you write simply %1$d%, you will get the error: Format string 'percent' is not a valid format string so it should not be passed to String.format.
Or use formatted=false" instead.
In Kotlin you just need to set your string value like this:
<string name="song_number_and_title">"%1$d ~ %2$s"</string>
Create a text view on your layout:
<TextView android:text="#string/song_number_and_title"/>
Then do this in your code if you using Anko:
val song = database.use { // get your song from the database }
song_number_and_title.setText(resources.getString(R.string.song_number_and_title, song.number, song.title))
You might need to get your resources from the application context.
In your string file use this
<string name="redeem_point"> You currently have %s points(%s points = 1 %s)</string>
And in your code use as accordingly
coinsTextTV.setText(String.format(getContext().getString(R.string.redeem_point), rewardPoints.getReward_points()
, rewardPoints.getConversion_rate(), getString(R.string.rs)));
However, you should also read Elias Mårtenson's answer on Android plurals treatment of “zero”. There is a problem with the interpretation of certain values such as "zero".
For Multilingual Projects
As someone who has worked on a major white label solution with many and varying languages and configurations per variant, I can say that there's a lot to consider.
Text direction aside, grammar alone can give you some headaches.
For instance can the order of items change thus
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
is to be preferred over
<string name="welcome_messages">Hello, %s! You have %d new messages.</string>
but once you work with translators who often don't know what a string or an integer is, let alone what formatting character to use for each type, or people in general who have no idea in what order the parameters are applied in your code, or even you yourself forget that, or things change which then must be updated at multiple places at once, so using MessageFormat like
<string name="welcome_message">Hello, {0}! You have {1} new messages.</string>
MessageFormat(R.string.welcome_message).format("Name", numMessages)
isn't viable either and the idea of having non tech people try to figure out xlift can't even be entertained then the best solution I know so far is to use explicit, named placeholders as such
<string name="placeholder_data" translatable="false">DATA</string>
<string name="placeholder_data" translatable="false">$DATA</string>
<string name="placeholder_data" translatable="false">%DATA%</string>
..or whatever else doesn't conflict with your texts.
And while you could use DOCTYPE like
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
<!ENTITY placeholder_data "$DATA">
]>
<string name="text_with_data">Your data is &placeholder_data;.</string>
this will not work with separate files for each language.
Thus in your main/res/values/strings.xml provide the placeholders and default strings like this
<resources>
<string name="placeholder_data" translatable="false">$DATA</string>
<string name="placeholder_error" translatable="false">$ERROR</string>
<string name="app_name">The App</string>
<string name="content_loading">loading..</string>
<string name="content_success">success: $DATA</string>
<string name="content_error">error: $ERROR</string>
</resources>
and then in your variant variant/res/values-de/strings.xml
<resources>
<string name="app_name">Die Applikation</string>
<string name="content_loading">Ladevorgang..</string>
<string name="content_success">Erfolg: $DATA</string>
<string name="content_error">Netzwerkkommunikationsfehler: $ERROR</string>
</resources>
and to use it, write something like
textView.text = when (response) {
is Data -> getText(content_success).resolveData(response.data)
is Error -> getText(content_error).resolveError(response.error)
is Loading -> getText(content_loading)
}
with the use of some helper functions like
fun CharSequence.resolveData(data: JsonObject) =
toString().replace(getString(placeholder_data), data.toString())
fun CharSequence.resolveError(error: Throwable) =
toString().replace(getString(placeholder_error), error.toString())
for simply the reason of having a reference for the translation files and development. Hence there should not be a default file per build flavor. Only the single default file and then a file per language x variant.
Now there's also the issue of numeric grammar. This can be solved with plurals but here again the complexity of the xml file increases. And, as pointed out, zero does not work as one would expect. But also you may want to have a limit to which your app counts due to display size limitations or number of pre-rendered images for your UI and need to display 99+ instead of 100. A solution would be to use a helper function like
fun Context.getText(
quantity: Int,
#PluralsRes resIdQuantity: Int,
#StringRes resIdNone: Int? = null,
#StringRes resIdMoreThan: Int? = null,
maxQuantity: Int? = null,
): CharSequence {
if (resIdMoreThan != null && maxQuantity != null && quantity > maxQuantity)
return getText(resIdMoreThan)
return if (resIdNone != null && quantity == 0) return getText(resIdNone)
else resources.getQuantityText(resIdQuantity, quantity)
}
to override and extend the behavior of the plurals resolver.
And if you have optional features per variant then add a res/values/strings-beans.xml like:
<resources>
<string name="placeholder_name" translatable="false">$NAME</string>
<string name="placeholder_count" translatable="false">$COUNT</string>
<string name="beans_content_bean_count_zero">Hello $NAME! You have no beans.</string>
<string name="beans_content_bean_count_one">Hello $NAME! You have one bean.</string>
<string name="beans_content_bean_count_many">Hello $NAME! You have $COUNT beans.</string>
<string name="beans_content_bean_count_more_than_9000">Hello $NAME! You have over $COUNT beans!</string>
<string name="beans_content_bean_count_two">#string/beans_content_bean_count_many</string>
<string name="beans_content_bean_count_few">#string/beans_content_bean_count_many</string>
<string name="beans_content_bean_count_other">#string/beans_content_bean_count_many</string>
<plurals name="beans_content_bean_count">
<item quantity="zero">#string/beans_content_bean_count_zero</item>
<item quantity="one">#string/beans_content_bean_count_one</item>
<item quantity="two">#string/beans_content_bean_count_two</item>
<item quantity="few">#string/beans_content_bean_count_few</item>
<item quantity="many">#string/beans_content_bean_count_many</item>
<item quantity="other">#string/beans_content_bean_count_other</item>
</plurals>
</resources>
while the variant in variant-with-beans/res/value-en/strings-beans.xml only needs to contain
<resources>
<string name="beans_content_bean_count_zero">Hello $NAME! You have no beans.</string>
<string name="beans_content_bean_count_one">Hello $NAME! You have one bean.</string>
<string name="beans_content_bean_count_many">Hello $NAME! You have $COUNT beans.</string>
<string name="beans_content_bean_count_more_than_9000">Hello $NAME! You have over 9000 beans!</string>
</resources>
and language specific overrides can be provided on a per file basis.
To use this, the code can look like this
val name = "Bob"
val beanCount = 3
val limit = 9000
text = getText(
beanCount,
beans_content_bean_count,
beans_content_bean_count_zero,
beans_content_bean_count_more_than_9000,
limit,
)
.resolveCount(beanCount)
.resolveName(name)
which resolves to the outputs
beanCount = 0 -> "Hello Bob! You have no beans."
beanCount = 1 -> "Hello Bob! You have one bean."
beanCount = 3 -> "Hello Bob! You have 3 beans."
beanCount = 9001 -> "Hello Bob! You have over 9000 beans!"
and due to the resulting simplicity of the language specific resource files, they then can be generated with deployment tools from spread sheets or your company's own server endpoints, etc.
I hope you enjoyed my maddening ride into the world of dynamic string resources for Android and hopefully appreciate that you're not the poor fools having to get the same functionality to work on the iOS side of the product which from my experience required python scripts to modify .xcodeproj files and generate swift code.
in res/values/string.xml
<resources>
<string name="app_name">Hello World</string>
<string name="my_application">Application name: %s, package name: %s</string>
</resources>
in java code
String[] args = new String[2];
args[0] = context.getString(R.string.app_name);
args[1] = context.getPackageName();
String textMessage = context.getString(R.string.my_application,(Object[]) args);
You can use MessageFormat:
<string name="customer_address">Wellcome: {0} {1}</string>
In Java code :
String text = MessageFormat(R.string.customer_address).format("Name","Family");
API level 1:
https://developer.android.com/reference/java/text/MessageFormat.html
Yes! you can do so without writing any Java/Kotlin code, only XML by using this small library I created, which does so at buildtime, so your app won't be affected by it: https://github.com/LikeTheSalad/android-stem
Usage
Your strings:
<resources>
<string name="app_name">My App Name</string>
<string name="welcome_message">Welcome to ${app_name}</string>
</resources>
The generated string after building:
<!-- Auto generated during compilation -->
<resources>
<string name="welcome_message">Welcome to My App Name</string>
</resources>
A Direct Kotlin Solution to the problem:
strings.xml
<string name="customer_message">Hello, %1$s!\nYou have %2$d Products in your cart.</string>
kotlinActivityORFragmentFile.kt:
val username = "Andrew"
val products = 1000
val text: String = String.format(
resources.getString(R.string.customer_message), username, products )
Kotlin version of the accepted answer...
val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)

Categories

Resources