Localizely logo
  • Home
  • Getting started
  • How it works
  • Pricing
  • FAQ
Sign up

I18n questions · Android

How do I insert a variable into a localized string in Android? 

Put a positional placeholder in the resource and pass the value as a format argument. Do not build the sentence from concatenated pieces.

<string name="welcome">Hello, %1$s! You have %2$d new messages.</string>
// In an Activity, Fragment or anything else with a Context
val text = getString(R.string.welcome, userName, mailCount)

// In Jetpack Compose
Text(text = stringResource(R.string.welcome, userName, mailCount))

Both calls run String.format() with the current locale, using java.util.Formatter syntax: %s for strings, %d for integers, %.2f for decimals. The number before $ is the argument position, so %2$d always takes the second argument wherever it appears in the sentence. That is what makes the string translatable: a translator can write "Du hast %2$d neue Nachrichten, %1$s!" and the code stays the same. Unpositioned %s %d only works while every language keeps the same order, and aapt2 warns when a string has several unpositioned placeholders.

Concatenation such as getString(R.string.you_have) + count + getString(R.string.messages) breaks as soon as a language puts the words in another order or inflects them differently, and it gives translators fragments they cannot translate in context.

When the variable is a count, the whole sentence changes with the number, so use a quantity string instead of a single string with %d:

<plurals name="new_messages">
    <item quantity="one">You have %d new message.</item>
    <item quantity="other">You have %d new messages.</item>
</plurals>
val text = resources.getQuantityString(R.plurals.new_messages, count, count)

// In Jetpack Compose
Text(text = pluralStringResource(R.plurals.new_messages, count, count))

The count is passed twice: once to select the plural form and once as the %d argument. Other languages need forms such as few and many; see the plural rules per language.

Finally, wrap each placeholder in <xliff:g> so translators do not alter it: <xliff:g id="name" example="Ana">%1$s</xliff:g>. How that works is covered in What is xliff:g in Android strings.xml and when should I use it?. The official reference is the Format strings section of the string resource guide.

Published Oct 9, 2026 · Markdown version

Related Android localization questions:

Android localization files:

Learn about Android XML string resources
Localizely logo
About
Free tools
Boring stuff
  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • Compare
Newsletter
Copyrights 2026 © Localizely