Is it possible to have placeholders in strings.xml for runtime values?
Solution 1
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.
Solution 2
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$
, and3$
. 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
is12
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 usecontext.getResources().getString(...)
if it is not available. -
String.format()
will also format a String. - The
1$
and2$
terms don't need to be used in that order. That is,2$
can come before1$
. 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
Solution 3
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.
Solution 4
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. :)
Solution 5
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.
SoftReference
Updated on December 15, 2021Comments
-
SoftReference over 2 years
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