[android] 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

This question is related to android string string-formatting android-resources

The answer is


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.


Kotlin version of the accepted answer...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)

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


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. :)


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 )

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".


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.


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);

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-string-reference

Usage

Your strings:

<resources>
    <string name="app_name">My App Name</string>
    <string name="template_welcome_message">Welcome to ${app_name}</string>
</resources>

The generated string after building:

<!--resolved.xml-->
<resources>
    <string name="welcome_message">Welcome to My App Name</string>
</resources>

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

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.


Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to string-formatting

JavaScript Chart.js - Custom data formatting to display on tooltip Format in kotlin string templates Converting Float to Dollars and Cents Chart.js - Formatting Y axis String.Format not work in TypeScript Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to left align a fixed width string? Convert Java Date to UTC String Format a Go string without printing?

Examples related to android-resources

Failed linking file resources Execution failed for task ':app:processDebugResources' even with latest build tools getResources().getColor() is deprecated getColor(int id) deprecated on Android 6.0 Marshmallow (API 23) Android getResources().getDrawable() deprecated API 22 Android Studio cannot resolve R in imported project? Android XXHDPI resources Android ImageView setImageResource in code format statement in a string resource file Lint: How to ignore "<key> is not translated in <language>" errors?