Строковый ресурс предоставляет текстовые строки для вашего приложения с возможностью стилизации и форматирования текста. Существует три типа ресурсов, которые могут предоставлять вашему приложению строки:
- Нить
- XML-ресурс, содержащий одну строку.
- Массив строк
- XML-ресурс, предоставляющий массив строк.
- Последовательности чисел (во множественном числе)
- XML-ресурс, содержащий различные строки для образования множественного числа.
Все строки могут быть стилизованы и иметь аргументы форматирования. Информацию о стилизации и форматировании строк см. в разделе « Форматирование и стилизация» .
Нить
Отдельная строка, на которую можно ссылаться из кода приложения (например, из составной функции) или из других файлов ресурсов.
- Местоположение файла:
-
res/values/ filename .xml
Имя файла произвольное. В качестве идентификатора ресурса используетсяnameэлемента<string>. - скомпилированный тип данных ресурса:
- Указатель ресурса на
String. - Справочный ресурс:
- В Kotlin:
R.string. string_name
В XML:@string/ string_name - синтаксис:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="string_name" >text_string</string> </resources>
- элементы:
- пример:
- XML-файл сохранен по адресу
res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello!</string> </resources>
Данный код приложения извлекает строку из составного объекта с помощью
stringResource():@Composable fun Greeting() { Text(text = stringResource(R.string.hello)) }
Примечание: Чтобы получить строку вне составной функции, используйте
Вы также можете ссылаться на строковые ресурсы из других XML-файлов, например, из файлаcontext.getString(R.string.hello).AndroidManifest.xml:<activity android:name=".MainActivity" android:label="@string/hello" />
Массив строк
Массив строк, к которым можно обращаться из приложения.
- Местоположение файла:
-
res/values/ filename .xml
Имя файла произвольное. В качестве идентификатора ресурса используетсяnameэлемента<string-array>. - скомпилированный тип данных ресурса:
- Указатель ресурса на массив
String. - Справочный ресурс:
- В Kotlin:
R.array. string_array_name
В XML:@[ package :]array/ string_array_name - синтаксис:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="string_array_name"> <item >text_string</item> </string-array> </resources>
- элементы:
- пример:
- XML-файл сохранен по адресу
res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="planets_array"> <item>Mercury</item> <item>Venus</item> <item>Earth</item> <item>Mars</item> </string-array> </resources>
Данный код приложения извлекает массив строк из составного объекта с помощью
stringArrayResource():@Composable fun PlanetList() { val planets: Array
= stringArrayResource(R.array.planets_array) // Render the array, e.g. inside a LazyColumn. } Примечание: Чтобы получить массив строк вне составной функции, используйте
context.resources.getStringArray(R.array.planets_array).
Последовательность чисел (во множественном числе)
В разных языках существуют разные правила грамматического согласования с количеством. Например, в английском языке количество 1 является особым случаем. Мы пишем "1 книга", но для любого другого количества мы бы написали " n книг". Это различие между единственным и множественным числом очень распространено, но в других языках существуют более тонкие различия. Полный набор слов, поддерживаемых Android, включает zero , one , two , few , many и other .
Правила определения того, какой регистр использовать для данного языка и количества, могут быть очень сложными, поэтому Android предоставляет вам такие методы, как pluralStringResource() для выбора подходящего ресурса.
Хотя исторически их называли «строками количества» (и до сих пор так называют в API), строки количества следует использовать только для множественного числа. Было бы ошибкой использовать строки количества для реализации чего-то вроде «Входящие» в Gmail и «Входящие (12)», когда есть непрочитанные сообщения, например. Может показаться удобным использовать строки количества вместо оператора if , но важно отметить, что в некоторых языках (например, в китайском) эти грамматические различия вообще не существуют, поэтому вы всегда получите other строку.
Выбор подходящей строки осуществляется исключительно на основе грамматической необходимости . В английском языке строка, обозначающая zero , игнорируется, даже если количество равно 0, поскольку 0 грамматически не отличается от 2 или любого другого числа, кроме 1 («zero books», «one book», «two books» и так далее). Напротив, в корейском языке используется только other строка.
Не стоит заблуждаться, думая, например, что слово two может относиться только к числу 2: в языке может быть установлено, что 2, 12, 102 (и так далее) рассматриваются одинаково, но по-разному по отношению к другим числам. Доверьтесь переводчику, он знает, какие именно различия требуются в его языке.
Если в вашем сообщении не указано количество, оно, вероятно, не подходит для использования во множественном числе. Например, в литовском языке единственное число используется как для 1, так и для 101, поэтому «1 книга» переводится как «1 knyga», а «101 книга» — как «101 knyga». При этом «книга» — это «knyga», а «много книг» — «daug knygų». Если в английском сообщении во множественном числе содержатся «книга» (единственное число) и «много книг» (множественное число) без указания фактического количества, его можно перевести как «knyga» (книга)/«daug knygų» (много книг), но по литовским правилам будет указано «knyga» (одна книга), если количество равно 101.
Часто можно избежать использования количественных строк, применяя нейтральные к количеству формулировки, например, "Книги: 1". Это упростит вашу работу и работу ваших переводчиков, если такой стиль приемлем для вашего приложения.
В API 24 и выше можно использовать гораздо более мощный класс ICU MessageFormat .
- Местоположение файла:
-
res/values/ filename .xml
Имя файла произвольное. В качестве идентификатора ресурса используетсяnameэлемента<plurals>. - Справочный ресурс:
- В Kotlin:
R.plurals. plural_name - синтаксис:
<?xml version="1.0" encoding="utf-8"?> <resources> <plurals name="plural_name"> <item quantity=["zero" | "one" | "two" | "few" | "many" | "other"] >text_string</item> </plurals> </resources>
- элементы:
- пример:
XML-файл сохранен по адресу
res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <plurals name="numberOfSongsAvailable"> <!-- As a developer, you should always supply "one" and "other" strings. Your translators will know which strings are actually needed for their language. Always include %d in "one" because translators will need to use %d for languages where "one" doesn't mean 1 (as explained above). --> <item quantity="one">%d song found.</item> <item quantity="other">%d songs found.</item> </plurals> </resources>
XML-файл сохранен по адресу
res/values-pl/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <plurals name="numberOfSongsAvailable"> <item quantity="one">Znaleziono %d piosenkę.</item> <item quantity="few">Znaleziono %d piosenki.</item> <item quantity="other">Znaleziono %d piosenek.</item> </plurals> </resources>
Данный код приложения извлекает строку во множественном числе из составного объекта с помощью
pluralStringResource():@Composable fun SongCount(count: Int) { Text( text = pluralStringResource( R.plurals.numberOfSongsAvailable, count, count, ) ) }
При использовании функции
pluralStringResource()необходимо дважды передатьcount, если ваша строка содержит форматирование с числом. Например, для строки%d songs found" первый параметрcountвыбирает соответствующую строку во множественном числе, а второй параметрcountвставляется в заполнитель%d. Если ваши строки во множественном числе не содержат форматирования, третий параметр в функциюpluralStringResourceпередавать не нужно.Примечание: Чтобы получить строку во множественном числе вне составной функции, используйте
context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count).
Формат и стиль
Вот несколько важных моментов, которые следует знать о правильном форматировании и оформлении строковых ресурсов.
Обработка специальных символов
Если строка содержит символы, имеющие особое значение в XML, необходимо экранировать эти символы в соответствии со стандартными правилами экранирования XML/HTML. Если вам нужно экранировать символ, имеющий особое значение в Android, следует использовать предшествующую обратную косую черту.
По умолчанию Android сжимает последовательности пробельных символов в один пробел. Этого можно избежать, заключив соответствующую часть строки в двойные кавычки. В этом случае все пробельные символы (включая символы новой строки) сохранятся внутри заключенной в кавычки области. Двойные кавычки также позволяют использовать обычные одинарные кавычки без экранирования.
| Характер | Вырвавшаяся форма(ы) |
|---|---|
| @ | \@ |
| ? | \? |
| Новая линия | \n |
| Вкладка | \t |
| Символ Юникода U+XXXX | \uXXXX |
Одинарная кавычка ( ' ) | Любой из следующих вариантов:
|
Двойная кавычка ( " ) | \"Обратите внимание, что заключение строки в одинарные кавычки не работает. |
Свертывание пробелов и экранирование в Android происходят после того, как ваш ресурсный файл будет проанализирован как XML. Это означает, что <string>      </string> (пробел, пробел знака препинания, пробел Unicode Em) сворачиваются в один пробел ( " " ), поскольку после анализа файла как XML все они являются пробелами Unicode. Чтобы сохранить эти пробелы в исходном виде, вы можете либо заключить их в кавычки ( <string>"      "</string> ), либо использовать экранирование Android ( <string> \u0032 \u8200 \u8195</string> ).
Форматирование строк
Если вам необходимо отформатировать строки, вы можете сделать это, указав аргументы форматирования в строковом ресурсе, как показано в следующем примере ресурса.
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
Данный код приложения форматирует строку внутри составного объекта, передавая аргументы непосредственно в stringResource() :
@Composable fun WelcomeMessage(username: String, mailCount: Int) { Text( text = stringResource( R.string.welcome_messages, username, mailCount, ) ) }
Оформление с использованием HTML-разметки
Вы можете добавить стили к своим строкам с помощью HTML-разметки. Например:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="welcome">Welcome to <b>Android</b>!</string> </resources>
Поддерживаются следующие HTML-элементы:
- Жирным шрифтом:
<b> - Курсив:
<i>,<cite>,<dfn>,<em> - Текст увеличен на 25%:
<big> - Текст уменьшен на 20%:
<small> - Настройка свойств шрифта:
<font face="font_family" color="hex_color">. Примеры возможных семейств шрифтов:monospace,serifиsans_serif. - Настройка моноширинного семейства шрифтов:
<tt> - Зачеркнутые строки:
<s>,<strike>,<del> - Подчеркнуть:
<u> - Верхний индекс:
<sup> - Нижний индекс:
<sub> - Пункты списка:
<ul>,<li> - Разрывы строк:
<br> - Разделение:
<div> - CSS-стиль:
<span style="color|background_color|text-decoration"> - Абзацы:
<p dir="rtl | ltr" style="…">
В некоторых случаях может потребоваться создать стилизованный текстовый ресурс, который также используется в качестве строки форматирования. Обычно это не работает, поскольку методы форматирования, такие как stringResource() , удаляют всю информацию о стиле из строки. Решение этой проблемы заключается в том, чтобы записывать HTML-теги с экранированными сущностями, которые затем восстанавливаются с помощью AnnotatedString.fromHtml() после форматирования. Например:
- Сохраняйте стилизованный текстовый ресурс в виде строки, экранированной HTML-кодом:
<resources> <string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string> </resources>
В эту отформатированную строку добавлен элемент
<b>. Обратите внимание, что открывающая скобка экранирована с помощью HTML-кода<. - Затем отформатируйте строку как обычно, но также вызовите
AnnotatedString.fromHtml()для преобразования HTML-текста в стилизованную строку Compose.
Поскольку функция fromHtml() форматирует все HTML-сущности, обязательно экранируйте все возможные HTML-символы в строках, используемых с форматированным текстом, с помощью TextUtils.htmlEncode() .
import android.text.TextUtils import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.fromHtml @Composable fun WelcomeHtmlMessage(username: String, mailCount: Int) { // Escape the username in case it contains characters like "<" or "&" val escapedUsername = TextUtils.htmlEncode(username) val text = stringResource( R.string.welcome_messages, escapedUsername, mailCount, ) Text( text = AnnotatedString.fromHtml(text) ) }
Оформление с помощью AnnotatedString
AnnotatedString — это текстовый объект Compose, который можно стилизовать с помощью таких свойств, как цвет и толщина шрифта. Создавайте стилизованный текст программно, используя buildAnnotatedString и withStyle .
Данный код приложения создает один текстовый элемент со смешанными стилями:
@Composable fun StyledGreeting() { val styled = buildAnnotatedString { append("Welcome to ") withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { append("Android") } append("!") } Text(text = styled) }
Для изменения цвета, размера шрифта и оформления текста используйте SpanStyle . Для применения стилей на уровне абзаца (например, выравнивания или высоты строки) используйте ParagraphStyle :
@Composable fun RichText() { val text = buildAnnotatedString { withStyle(ParagraphStyle(lineHeight = 24.sp, textAlign = TextAlign.Center)) { withStyle(SpanStyle(color = Color.Gray)) { append("Hello, ") } withStyle( SpanStyle( fontWeight = FontWeight.Bold, color = Color.Red, ) ) { append("world") } append("!") } } Text(text = text) }
Для одноязычных приложений или статического текста в Compose рекомендуется создавать AnnotatedString напрямую. Однако для стилизованного текста, требующего локализации, см. подход с использованием XML <annotation> , подробно описанный в следующем разделе.
Оформление переведенных строк с помощью аннотаций
Для строк, требующих пользовательского оформления и перевода, определите тег <annotation> в strings.xml каждой локали. Переводчики сохранят аннотацию независимо от того, где она находится в предложении. Прочитайте строку с помощью context.resources.getText() , пройдите по её Annotation блокам и преобразуйте результат в AnnotatedString :
@Composable fun AnnotatedTitle() { val context = LocalContext.current val source = context.resources.getText(R.string.title) as SpannedString val text = buildAnnotatedString { append(source.toString()) source.getSpans(0, source.length, Annotation::class.java) .forEach { annotation -> if (annotation.key == "font" && annotation.value == "title_emphasis") { addStyle( SpanStyle( fontFamily = FontFamily( Font(R.font.permanent_marker) ) ), source.getSpanStart(annotation), source.getSpanEnd(annotation), ) } } } Text(text = text) }
Тег <annotation> в вашем XML-файле остаётся неизменным. Изменяется только код извлечения. Переводчики по-прежнему перемещают тег, чтобы он переносил правильное слово на каждом языке.
Дополнительные ресурсы
Для получения дополнительной информации о строковых ресурсах см. следующие дополнительные материалы: