Un recurso de cadenas proporciona cadenas de texto para tu aplicación con formato y estilo de texto opcionales. Existen tres tipos de recursos que pueden proporcionar strings para tu aplicación:
- String
- Recurso XML que proporciona una sola cadena.
- Array de cadenas
- Recurso XML que proporciona un array de cadenas.
- Strings de cantidad (plurales)
- Recurso XML que conlleva diferentes strings para brindar pluralización.
Todas las cadenas pueden aplicar algunos argumentos de formato y marcado de estilo. Para obtener información sobre las cadenas de formato y estilo, consulta la sección sobre Formato y estilo.
String
Una sola cadena a la que se puede hacer referencia desde el código de la aplicación (por ejemplo, una función de componibilidad) o desde otros archivos de recursos.
- ubicación del archivo:
res/values/filename.xml
El nombre del archivo es arbitrario. Elnamedel elemento de<string>se usa como ID del recurso.- tipo de datos de recursos compilados:
- Puntero de recursos a un
String. - referencia del recurso:
-
En Kotlin:
R.string.string_name
En XML:@string/string_name - sintaxis:
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="string_name" >text_string</string> </resources>
- elementos:
- ejemplo:
- Archivo en formato XML guardado en
res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello!</string> </resources>
Este código de la aplicación recupera una cadena desde el interior de un elemento componible con
stringResource():@Composable fun Greeting() { Text(text = stringResource(R.string.hello)) }
Nota: Para recuperar una cadena fuera de una función de componibilidad, usa
También puedes hacer referencia a recursos de cadenas desde otros archivos XML, como tucontext.getString(R.string.hello).AndroidManifest.xml:<activity android:name=".MainActivity" android:label="@string/hello" />
Matriz de string
Array de cadenas al cual se puede hacer referencia desde la aplicación.
- ubicación del archivo:
res/values/filename.xml
El nombre del archivo es arbitrario. Elnamedel elemento de<string-array>se usa como ID del recurso.- tipo de datos de recursos compilados:
- Puntero de recurso para un elemento de array de
Strings. - referencia del recurso:
-
En Kotlin:
R.array.string_array_name
En XML:@[package:]array/string_array_name - sintaxis:
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="string_array_name"> <item >text_string</item> </string-array> </resources>
- elementos:
- ejemplo:
- Archivo en formato XML guardado en
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 de la aplicación recupera un array de cadenas desde el interior de un elemento componible con
stringArrayResource():@Composable fun PlanetList() { val planets: Array
= stringArrayResource(R.array.planets_array) // Render the array, e.g. inside a LazyColumn. } Nota: Para recuperar un array de cadenas fuera de una función de componibilidad, usa
context.resources.getStringArray(R.array.planets_array).
Strings de cantidad (plurales)
Los diferentes idiomas tienen distintas reglas de concordancia gramatical con la cantidad. En inglés, por ejemplo, la cantidad 1 es un caso especial. Escribimos "1 libro", pero, para las demás cantidades, se debe escribir "n libros". Esta distinción entre singular y plural es muy común; sin embargo, en otros idiomas, se hacen distinciones más detalladas. El conjunto completo compatible con Android es zero, one, two, few, many y other.
Las reglas para decidir el caso que se usará para un idioma y una cantidad determinados pueden ser muy complejas, por lo cual Android te proporciona métodos como pluralStringResource() para seleccionar el recurso adecuado para ti.
Si bien históricamente se llamaron "cadenas de cantidad" (y aún se llaman así en la API), las cadenas de cantidad solo deben usarse para los plurales. Sería un error usar cadenas de cantidad para implementar algo como "Recibidos" de Gmail en comparación con "Recibidos (12)" cuando existen mensajes no leídos, por ejemplo. Podría parecer conveniente usar cadenas de cantidad en lugar de una instrucción if, pero es importante tener en cuenta que, en algunos idiomas (como el chino), no se hacen estas distinciones gramaticales en absoluto, por lo que siempre obtendrás la cadena other.
La selección de la cadena que se debe usar se realiza únicamente según la necesidad gramatical. En inglés, una cadena para zero se ignora incluso si la cantidad es 0, ya que 0 no es gramaticalmente diferente de 2, o cualquier otro número, excepto 1 ("zero books", "one book", "two books", y así sucesivamente). En cambio, en coreano, solo se usa la cadena other.
No te confundas por el hecho de que, por ejemplo, two suena como si solo pudiera aplicarse a la cantidad 2: un idioma puede requerir que 2, 12, 102 (y así sucesivamente) se traten de manera similar, pero de forma diferente de otras cantidades. Confía en tu traductor para conocer las distinciones de su idioma.
Si tu mensaje no contiene el número de cantidad, es probable que no sea un buen candidato para un plural. Por ejemplo, en lituano, la forma singular se usa para los números 1 y 101, por lo que "1 libro" se traduce como "1 knyga" y "101 libros" como "101 knyga". Mientras que "un libro" es "knyga", "muchos libros" es "daug knygų". Si un mensaje en inglés en plural contiene "un libro" (singular) y "muchos libros" (plural) sin el número real, se puede traducir como "knyga" (un libro) o "daug knygų" (muchos libros), pero con las reglas del lituano, se mostrará "knyga" (un solo libro) cuando el número sea 101.
En ocasiones, es posible evitar las cadenas de cantidad usando fórmulas de cantidad neutra, por ejemplo, "Libros: 1". Esto hará más fáciles las cosas para ti y tus traductores si se trata de un estilo aceptable para tu aplicación.
En el nivel de API 24 y versiones posteriores, puedes usar la clase MessageFormat de ICU mucho más potente en su lugar.
- ubicación del archivo:
res/values/filename.xml
El nombre del archivo es arbitrario. Elnamedel elemento de<plurals>se usa como ID del recurso.- referencia del recurso:
-
En Kotlin:
R.plurals.plural_name - sintaxis:
-
<?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:
- ejemplo:
Archivo en formato XML guardado en
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>
Archivo en formato XML guardado en
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 de la aplicación recupera una cadena plural desde un elemento componible con
pluralStringResource():@Composable fun SongCount(count: Int) { Text( text = pluralStringResource( R.plurals.numberOfSongsAvailable, count, count, ) ) }
Cuando se usa la función
pluralStringResource(), debes pasarcountdos veces si tu cadena incluye formato de cadena con un número. Por ejemplo, para la string%d songs found, el primer parámetro decountselecciona el plural adecuado, y el segundo parámetro decountse inserta en el marcador de posición%d. Si tus strings de plural no incluyen formato de string, no es necesario que pases el tercer parámetro apluralStringResource.Nota: Para recuperar una cadena plural fuera de una función de componibilidad, usa
context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count).
Formato y estilo
A continuación, se mencionan algunos puntos importantes que debes conocer sobre cómo dar formato y estilo adecuadamente a tus recursos de cadenas.
Caracteres especiales
Cuando una cadena contiene caracteres que tienen un uso especial en XML, debes escapar los caracteres de acuerdo con las reglas de escape estándar de XML/HTML. Si necesitas escapar un carácter que tiene un significado especial en Android, debes usar antes una barra inversa.
De forma predeterminada, Android contraerá secuencias de caracteres de espacios en blanco en un solo espacio. Para evitar esto, encierra la parte relevante de la cadena entre comillas dobles. En este caso, todos los caracteres de espacios en blanco (incluidas las nuevas líneas) se conservarán dentro de la región entrecomillada. Las comillas dobles también te permitirán usar comillas simples regulares sin escapar.
| Carácter | Formas de escape |
|---|---|
| @ | \@ |
| ? | \? |
| Nueva línea | \n |
| Tab | \t |
| carácter Unicode U+XXXX | \uXXXX |
Comilla simple (') |
Cualquiera de los siguientes:
|
Comillas dobles (") |
\"
Ten en cuenta que encerrar la string entre comillas simples no funciona. |
La contracción del espacio en blanco y el escape de Android ocurren después de que se analiza tu archivo de recursos como XML. Esto significa que <string>      </string> (espacio, espacio de puntuación, espacio largo de Unicode) se contraen a un solo espacio (" "), ya que son todos espacios de Unicode después de que se analiza el archivo como XML.
Para conservar esos espacios como están, puedes entrecomillarlos (<string>"      "</string>) o usar el escape de Android (<string> \u0032 \u8200 \u8195</string>).
Cómo dar formato a las strings
Si necesitas dar formato a tus cadenas, puedes hacerlo disponiendo tus argumentos de formato en el recurso de cadenas, tal como se demuestra en el siguiente recurso de ejemplo.
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
Este código de la aplicación formatea la cadena desde un elemento componible pasando argumentos directamente a stringResource():
@Composable fun WelcomeMessage(username: String, mailCount: Int) { Text( text = stringResource( R.string.welcome_messages, username, mailCount, ) ) }
Cómo dar estilo con el lenguaje de marcado HTML
Puedes agregar estilo a tus strings con el lenguaje de marcado HTML. Por ejemplo:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="welcome">Welcome to <b>Android</b>!</string> </resources>
Se admiten los siguientes elementos HTML:
- Negrita:
<b> - Cursiva:
<i>,<cite>,<dfn>,<em> - Texto 25% más grande:
<big> - Texto 20% más pequeño:
<small> - Configurar propiedades de la fuente:
<font face="font_family" color="hex_color">. Algunas familias de fuentes posibles sonmonospace,serifysans_serif. - Configurar una familia de fuentes monoespacio:
<tt> - Tachado:
<s>,<strike>,<del> - Subrayado:
<u> - Superíndice:
<sup> - Subíndice:
<sub> - Viñetas:
<ul>y<li> - Saltos de línea:
<br> - División:
<div> - Estilo de CSS:
<span style="color|background_color|text-decoration"> - Párrafos:
<p dir="rtl | ltr" style="…">
En algunos casos, es posible que desees crear un recurso de texto con estilo que también se use como una cadena de formato. Generalmente, esto no funciona porque los métodos de formato, como stringResource(), quitan toda la información de estilo de la cadena.
La solución temporal para esto es escribir las etiquetas HTML con entidades escapadas, que se recuperan después con AnnotatedString.fromHtml() una vez que se lleva a cabo el formato. Por ejemplo:
- Almacena tu recurso de texto con estilo como una string escapada con HTML:
<resources> <string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string> </resources>
En esta string con formato, se agrega un elemento
<b>. Ten en cuenta que el corchete de apertura está con escape HTML mediante la anotación<. - Luego, da formato a la cadena como siempre, pero también llama a
AnnotatedString.fromHtml()para convertir el texto HTML en una cadena de Compose con estilo.
Debido a que fromHtml() da formato a todas las entidades HTML, asegúrate de escapar todos los caracteres HTML posibles en las cadenas que usas con el texto con formato, mediante 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) ) }
Cómo dar estilo con AnnotatedString
Un AnnotatedString es un objeto de texto de Compose al que puedes dar estilo con propiedades como el color y el grosor de la fuente. Crea texto con estilo de forma programática con buildAnnotatedString y withStyle.
Este código de la aplicación crea un solo elemento de texto con estilos mixtos:
@Composable fun StyledGreeting() { val styled = buildAnnotatedString { append("Welcome to ") withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { append("Android") } append("!") } Text(text = styled) }
Para aplicar color, tamaño de fuente y decoración de texto, usa SpanStyle. Para aplicar un diseño a nivel del párrafo (como la alineación o la altura de la línea), usa 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) }
Compilar el AnnotatedString directamente es el enfoque recomendado para las apps en un solo idioma o el texto estático en Compose. Sin embargo, para el texto con estilo que requiere localización, consulta el enfoque de <annotation> en XML que se detalla en la siguiente sección.
Cómo dar estilo a cadenas traducidas con anotaciones
Para las cadenas que necesitan un diseño y una traducción personalizados, define la etiqueta <annotation> en el strings.xml de cada configuración regional. Los traductores conservan la anotación, independientemente de dónde se ubique en la oración. Lee la cadena con context.resources.getText(), recorre sus intervalos de Annotation y convierte el resultado en un 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) }
La etiqueta <annotation> en tu archivo XML no se modificará. Solo difiere el código de recuperación. Los traductores aún mueven la etiqueta para envolver la palabra correcta en cada idioma.
Recursos adicionales
Para obtener más información sobre los recursos de cadena, consulta los siguientes recursos adicionales: