Recursos de string

Um recurso de string fornece strings de texto para seu aplicativo com estilo e formatação de texto opcionais. Existem três tipos de recursos que podem fornecer strings ao seu aplicativo:

String
Recurso XML que fornece uma só string.
Matriz de strings
Recurso XML que fornece uma matriz de strings.
Strings de quantidade (plurais)
Recurso XML que contém diferentes strings para pluralização.

Todas as strings podem aplicar algumas marcações de estilo e argumentos de formatação. Para saber mais sobre estilos e formatação de strings, consulte a seção sobre Formatação e estilo.

String

É uma string única que pode ser referenciada do código do aplicativo (como uma função combinável) ou de outros arquivos de recursos.

localização do arquivo:
res/values/filename.xml
O nome do arquivo é arbitrário. O name do elemento <string> é usado como o ID do recurso.
tipo de dados do recurso compilado:
Ponteiro do recurso para um String.
referência de recurso:
Em Kotlin: R.string.string_name
Em XML: @string/string_name
Sintaxe:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
elementos:
<resources>
Obrigatório. Precisa ser o nó raiz.

Nenhum atributo.

<string>
É uma string que pode conter tags de estilo. Você precisa executar o escape de apóstrofos e aspas. Para saber mais sobre como ajustar corretamente o estilo e a formatação das strings, consulte Formatação e estilo abaixo.

atributos:

name
String. É o nome da string. Esse nome é usado como o ID do recurso.
exemplo:
Arquivo XML salvo em res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

Este código do aplicativo extrai uma string de dentro de um elemento combinável com stringResource():

@Composable
fun Greeting() {
    Text(text = stringResource(R.string.hello))
}

Observação:para extrair uma string fora de uma função combinável, use context.getString(R.string.hello).

Você também pode referenciar recursos de string de outros arquivos XML, como AndroidManifest.xml:
<activity
    android:name=".MainActivity"
    android:label="@string/hello" />

Matriz de strings

É a matriz de strings que pode ser referenciada pelo aplicativo.

localização do arquivo:
res/values/filename.xml
O nome do arquivo é arbitrário. O name do elemento <string-array> é usado como o ID do recurso.
tipo de dados do recurso compilado:
Ponteiro de recurso para uma matriz de Strings.
referência de recurso:
Em Kotlin: R.array.string_array_name
Em XML: @[package:]array/string_array_name
Sintaxe:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="string_array_name">
        <item
            >text_string</item>
    </string-array>
</resources>
elementos:
<resources>
Obrigatório. Precisa ser o nó raiz.

Nenhum atributo.

<string-array>
Define uma matriz de strings. Contém um ou mais elementos <item>.

atributos:

name
String. Um nome para a matriz. O nome do arquivo é usado como o ID do recurso para referenciar a matriz.
<item>
É uma string que pode conter tags de estilo. O valor pode ser uma referência a outro recurso de string. Precisa ser um filho de um elemento <string-array>. Você precisa executar o escape de apóstrofos e aspas. Para saber mais sobre o ajuste correto do estilo e da formatação de strings, consulte Formatação e estilo abaixo.

Nenhum atributo.

exemplo:
Arquivo XML salvo em 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>

Este código do aplicativo extrai uma matriz de strings de dentro de um elemento combinável com stringArrayResource():

@Composable
fun PlanetList() {
    val planets: Array =
        stringArrayResource(R.array.planets_array)
    // Render the array, e.g. inside a LazyColumn.
}

Observação:para recuperar uma matriz de strings fora de uma função combinável, use context.resources.getStringArray(R.array.planets_array).

Strings de quantidade (plurais)

Diferentes idiomas têm diferentes regras de concordância gramatical de quantidade. Em inglês, por exemplo, a quantidade 1 é um caso especial. Escrevemos "1 book" (1 livro), mas, para qualquer outra quantidade, "n books" (n livros). Essa distinção entre singular e plural é muito comum, mas outros idiomas fazem distinções mais precisas. O conjunto completo permitido pelo Android é zero, one, two, few, many e other.

As regras para decidir qual caso usar para determinado idioma e quantidade podem ser muito complexas. Por isso, o Android fornece métodos como pluralStringResource() para selecionar o recurso apropriado para você.

Apesar de serem historicamente conhecidas como "strings de quantidade" (ainda chamadas assim na API), elas precisam ser usadas somente para plurais. Seria um erro usar strings de quantidade para implementar algo como a "Caixa de entrada" do Gmail em vez de "Caixa de entrada (12)" quando houver mensagens não lidas, por exemplo. Pode parecer conveniente usar strings de quantidade em vez de uma instrução if, mas é importante observar que alguns idiomas (como o chinês) não fazem essas distinções gramaticais. Por isso, você sempre vai receber a string other.

A seleção da string é feita exclusivamente com base na necessidade gramatical. Em inglês, uma string para zero é ignorada mesmo que a quantidade seja 0, porque 0 não é gramaticalmente diferente de 2 ou de qualquer outro número, exceto 1 ("zero books", "one book", "two books" e assim por diante). Por outro lado, em coreano apenas a string other é usada.

Não se engane pelo fato de que, por exemplo, two parece ser aplicável somente para a quantidade 2: um idioma pode exigir que 2, 12, 102 (e assim por diante) sejam tratados da mesma forma, mas de forma diferente de outras quantidades. Converse com um tradutor para identificar quais são as distinções obrigatórias de cada idioma.

Se a mensagem não tiver um número de quantidade, provavelmente não é uma boa opção para um plural. Por exemplo, em lituano, a forma singular é usada para 1 e 101. Portanto, "1 livro" é traduzido como "1 knyga", e "101 livros" é traduzido como "101 knyga". Já "um livro" é "knyga" e "vários livros" é "daug knygų". Se uma mensagem no plural em inglês contiver "a book" (singular) e "many books" (plural) sem o número real, ela poderá ser traduzida como "knyga" (um livro)/"daug knygų" (muitos livros), mas, com as regras do lituano, ela vai mostrar "knyga" (um livro), quando o número for 101.

Geralmente, é possível evitar strings de quantidade usando formulações de quantidade neutra, como "Livros: 1". Isso vai facilitar seu trabalho e o dos tradutores, caso seja um estilo compatível com seu aplicativo.

Na API 24 ou versões mais recentes, é possível usar a classe ICU MessageFormat, que é muito mais eficiente.

localização do arquivo:
res/values/filename.xml
O nome do arquivo é arbitrário. O name do elemento <plurals> é usado como o ID do recurso.
referência de recurso:
Em Kotlin: R.plurals.plural_name
Sintaxe:
<?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>
elementos:
<resources>
Obrigatório. Precisa ser o nó raiz.

Nenhum atributo.

<plurals>
Uma coleção que fornece uma string de acordo com a quantidade de um item. Contém um ou mais elementos <item>.

atributos:

name
String. É o nome do par de strings. Esse nome é usado como o ID do recurso.
<item>
Indica se uma string é plural ou singular. O valor pode ser uma referência a outro recurso de string. Precisa ser um filho de um elemento <plurals>. Você precisa executar o escape de apóstrofos e aspas. Para saber mais sobre o ajuste correto do estilo e da formatação das suas strings, consulte Formatação e estilo abaixo.

atributos:

quantity
Palavra-chave. É o valor que indica quando é preciso usar a string. Valores válidos, com exemplos entre parênteses:
ValorDescrição
zeroIndica se o idioma exige tratamento especial para o número 0 (como em árabe).
oneIndica se o idioma exige tratamento especial para números como 1 (como em inglês e na maioria dos idiomas). Em russo, qualquer número terminado em 1, mas não em 11, se encontra nessa classe.
twoIndica se o idioma exige tratamento especial para números como 2 (como 2 em galês ou 102 em esloveno).
fewIndica se o idioma exige tratamento especial para números "pequenos" (como 2, 3 e 4 em tcheco ou números terminados em 2, 3 ou 4, mas não 12, 13 ou 14, em polonês).
manyQuando o idioma exige tratamento especial para números "grandes", como números que terminam de 11 a 99 em maltês.
otherIndica se o idioma não exige tratamento especial na quantidade em questão (como com todos os números em chinês ou 42 em inglês).
exemplo:

Arquivo XML salvo em 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>

Arquivo XML salvo em 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>

Este código do aplicativo extrai uma string plural de dentro de um elemento combinável com pluralStringResource():

@Composable
fun SongCount(count: Int) {
    Text(
        text = pluralStringResource(
            R.plurals.numberOfSongsAvailable,
            count,
            count,
        )
    )
}

Ao usar a função pluralStringResource(), você precisa transmitir o count duas vezes se a string tiver formatação com um número. Por exemplo, para a string %d songs found, o primeiro parâmetro count seleciona a string plural apropriada, e o segundo parâmetro count é inserido no marcador %d. Se as strings de plural não tiverem formatação de string, você não vai precisar transmitir o terceiro parâmetro para pluralStringResource.

Observação:para recuperar uma string no plural fora de uma função combinável, use context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count).

Formato e estilo

Apresentamos abaixo alguns itens importantes sobre como definir a formatação e o estilo dos seus recursos de string.

Processar caracteres especiais

Quando uma string contém caracteres que têm uso especial em XML, é necessário que eles tenham um escape de acordo com as regras padrão de XML/HTML. Se você precisar de escape para um caractere que tenha um significado especial no Android, use uma barra invertida no início.

Por padrão, o Android procura sequências de caracteres de espaço em branco e as transforma em um único espaço. Para evitar isso, coloque a parte relevante da string entre aspas duplas. Nesse caso, todos os caracteres de espaço em branco (incluindo novas linhas) serão preservados dentro da região entre aspas. Aspas duplas também permitem o uso de aspas simples sem escape comuns.

Caractere Formas de escape
@ \@
? \?
Nova linha \n
Tab \t
Caractere Unicode U+XXXX \uXXXX
Aspas simples (')

Uma destas opções:

  • \'
  • Coloque toda a string entre aspas duplas ("This'll work", por exemplo).
Aspas duplas (") \"

Não é possível inserir a string entre aspas simples.

A redução dos espaços em branco e o escape de Android acontecem depois que o arquivo de recurso é analisado como XML. Isso significa que <string> &#32; &#8200; &#8195;</string> (espaço, espaço da pontuação, espaço Unicode Em) são reduzidos em um único espaço (" "), porque todos são espaços Unicode após a análise do arquivo como um XML. Para preservar esses espaços como estão, você pode os colocar entre aspas (<string>" &#32; &#8200; &#8195;"</string>) ou usar o escape do Android (<string> \u0032 \u8200 \u8195</string>).

Como formatar strings

Se você precisar formatar suas strings, é possível colocar os argumentos de formato no recurso de string, conforme demonstrado no exemplo a seguir.

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

Este código do aplicativo formata a string de dentro de um elemento combinável transmitindo argumentos diretamente para stringResource():

@Composable
fun WelcomeMessage(username: String, mailCount: Int) {
    Text(
        text = stringResource(
            R.string.welcome_messages,
            username,
            mailCount,
        )
    )
}

Aplicar estilo com marcação HTML

Você pode adicionar estilo às suas strings com marcações HTML. Por exemplo:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="welcome">Welcome to <b>Android</b>!</string>
</resources>

Os elementos HTML abaixo podem ser usados:

  • Negrito: <b>
  • Itálico: <i>, <cite>, <dfn>, <em>
  • Texto 25% maior: <big>
  • Texto 20% menor: <small>
  • Definição das propriedades da fonte: <font face="font_family" color="hex_color">. Exemplos de possíveis famílias de fontes incluem monospace, serif e sans_serif.
  • Definir uma família de fontes monoespaçadas: <tt>
  • Tachado: <s>, <strike>, <del>
  • Sublinhado: <u>
  • Sobrescrito: <sup>
  • Subscrito: <sub>
  • Tópicos: <ul>, <li>
  • Quebras de linha: <br>
  • Divisão: <div>
  • Estilo CSS: <span style="color|background_color|text-decoration">
  • Parágrafos: <p dir="rtl | ltr" style="…">

Em alguns casos, você pode criar um recurso de texto com estilo que também é usado como uma string de formatação. Normalmente, isso não funciona porque os métodos de formatação, como stringResource(), tiram todas as informações de estilo da string. A solução para esse problema é criar tags HTML com entidades com escape, que são então extraídas com AnnotatedString.fromHtml(), após a realização da formatação. Exemplo:

  1. Armazene seu recurso de texto com estilo como uma string HTML com escape:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>

    Nessa string formatada, é adicionado um elemento <b>. O colchete de abertura tem escape HTML usando a notação &lt;.

  2. Em seguida, formate a string normalmente, mas também chame AnnotatedString.fromHtml() para converter o texto HTML em uma string estilizada do Compose.

Como fromHtml() formata todas as entidades HTML, não esqueça de usar TextUtils.htmlEncode() para executar o escape de qualquer caractere HTML possível nas strings usadas com o texto formatado.

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

Criar um estilo com AnnotatedString

Um AnnotatedString é um objeto de texto do Compose que pode receber estilo com propriedades como cor e peso da fonte. Crie texto estilizado de forma programática usando buildAnnotatedString e withStyle.

Este código do aplicativo cria um único elemento do texto com estilos mistos:

@Composable
fun StyledGreeting() {
    val styled = buildAnnotatedString {
        append("Welcome to ")
        withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
            append("Android")
        }
        append("!")
    }
    Text(text = styled)
}

Para aplicar cor, tamanho da fonte e decoração de texto, use SpanStyle. Para aplicar estilos no nível do parágrafo (como alinhamento ou altura da linha), use 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)
}

Criar o AnnotatedString diretamente é a abordagem recomendada para apps de um único idioma ou texto estático no Compose. No entanto, para texto estilizado que exige localização, consulte a abordagem XML <annotation> detalhada na próxima seção.

Estilizar strings traduzidas com anotações

Para strings que precisam de estilização e tradução personalizadas, defina a tag <annotation> no strings.xml de cada localidade. Os tradutores preservam a anotação, não importa onde ela esteja na frase. Leia a string com context.resources.getText(), percorra os intervalos Annotation e converta o resultado em um 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)
}

A tag <annotation> no seu XML não muda. Apenas o código de recuperação é diferente. Os tradutores ainda movem a tag para envolver a palavra correta em cada idioma.

Outros recursos

Para mais informações sobre recursos de string, consulte os seguintes recursos adicionais:

Documentação

Visualiza conteúdo