Android TextView Do not concatenate text displayed with setText
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The Android Lint warning "Do not concatenate text displayed with setText" tells you to avoid building display strings by concatenating pieces in Java/Kotlin code (e.g., setText("Hello " + name)). Instead, use string resources with placeholders (getString(R.string.greeting, name)). This is critical for localization because different languages have different word orders, grammatical rules, and pluralization — a concatenated English string like "You have " + count + " items" cannot be correctly translated. String resources with format arguments let translators rearrange placeholders to fit each language's grammar.
The Problem: Concatenation in Code
The Fix: String Resources with Placeholders
The %1$s syntax means "first argument, as a string." %2$d means "second argument, as a decimal integer." Translators can reorder these placeholders without changing the code.
Handling Pluralization
Plurals cannot be handled by concatenation at all — different languages have different rules for which plural form to use based on the number.
Using Spans Instead of Concatenation
For styled text (bold, italic, colored), use string resources with HTML tags or SpannableStringBuilder. Concatenation drops formatting.
Jetpack Compose
In Jetpack Compose, stringResource() and pluralStringResource() are the composable equivalents of getString() and getQuantityString().
Suppressing the Warning (When Appropriate)
Suppress the warning only for text that will never be translated — debug views, developer tools, or internal-only screens. For anything user-facing, always use string resources.
Common Pitfalls
- Splitting sentences across multiple string resources:
getString(R.string.part1) + value + getString(R.string.part2)is just as bad as hardcoded concatenation. The sentence must be a single string resource with placeholders so translators can see and rearrange the full sentence. - Using String.format() without string resources:
String.format("Hello %s", name)avoids concatenation but still hardcodes the template in code. Move the format string tostrings.xmland usegetString(R.string.key, name). - Forgetting positional format specifiers:
%sand%dwork but do not allow reordering. Use%1$s,%2$dwith position numbers so translators can reorder arguments to match their language's grammar. - Passing the count argument only once to getQuantityString:
getQuantityString(R.plurals.id, count)usescountto select the plural form but does not substitute%din the string. You needgetQuantityString(R.plurals.id, count, count)— the firstcountselects the form, the second fills%d. - Ignoring right-to-left (RTL) languages: Concatenated strings with mixed LTR/RTL text display incorrectly. String resources with placeholders handle bidirectional text properly because the Android framework applies Unicode bidirectional formatting.
Summary
- Use string resources with
%1$s,%2$dplaceholders instead of concatenating strings insetText() - Use
getQuantityString()for pluralization — different languages have different plural rules - Translators need to see the full sentence to rearrange word order for their language
- Use
SpannableStringBuilderor HTML in string resources for styled text - In Jetpack Compose, use
stringResource()andpluralStringResource() - Only suppress the
SetTextI18nwarning for non-user-facing text (debug, logging)

