Как задать строку с подстановкой переменной в ресурсах Android?
Что проверяют
Знаете ли вы форматированные строковые ресурсы и понимаете ли, зачем они нужны при локализации. Сама подстановка занимает одну строку, поэтому ждут подробностей: позиционные аргументы, множественные числа, экранирование. Следом часто спрашивают, как вывести «5 файлов» на русском и английском.
Как отвечать
В res/values/strings.xml строку объявляют с позиционными спецификаторами формата, как в String.format:
<string name="greeting">Привет, %1$s! Новых сообщений: %2$d</string>В коде это getString(R.string.greeting, name, count) у Context или Resources, в Compose stringResource(R.string.greeting, name, count). Важные детали:
- позиционные номера:
%1$s,%2$dпозволяют переводчику менять порядок слов. На несколько аргументов без номеров инструменты сборки ругаются и предлагаютformatted="false", но правильный выход это позиции; - типы:
%sстрока,%dцелое,%.1fдробное с одним знаком. Несовпадение типа даётIllegalFormatConversionExceptionв рантайме; - экранирование: одиночный апостроф aapt2 не пропустит, его пишут
\', а литеральный процент в строке с аргументами пишут%%; - множественные числа:
<plurals>иresources.getQuantityString(R.plurals.files, count, count), в ComposepluralStringResource. Для русского нужны формыone,few,manyиother; - подсказки переводчикам: тег
xliff:gвокруг плейсхолдера помечает часть, которую нельзя переводить.
Если в строке есть HTML-разметка и аргументы, в ресурсе экранируют < как <, аргументы пропускают через TextUtils.htmlEncode, а результат через HtmlCompat.fromHtml.
Где спотыкаются
Склеивают строку в коде: getString(R.string.hello) + name. В языках с другим порядком слов перевести такое нельзя.
В getQuantityString передают count один раз. Первый аргумент выбирает форму, второй подставляется в %d, и без него в тексте остаётся сырой %d.
Пишут в XML шаблон Kotlin вида $name и ждут подстановки. Ресурсы про строковые шаблоны Kotlin ничего не знают, работает только синтаксис String.format.