Risorse stringa

Una risorsa stringa fornisce stringhe di testo per la tua applicazione con stile e formattazione del testo facoltativi. Esistono tre tipi di risorse che possono fornire stringhe alla tua applicazione:

String
Risorsa XML che fornisce una singola stringa.
String Array
Risorsa XML che fornisce un array di stringhe.
Stringhe di quantità (plurali)
Risorsa XML che contiene stringhe diverse per la pluralizzazione.

Tutte le stringhe sono in grado di applicare alcuni argomenti di formattazione e markup di stile. Per informazioni sulla formattazione e sullo stile delle stringhe, consulta la sezione Formattazione e stile.

Stringa

Una singola stringa a cui è possibile fare riferimento dal codice dell'applicazione (ad esempio una funzione componibile) o da altri file di risorse.

posizione del file:
res/values/filename.xml
Il nome file è arbitrario. L'<string> dell'elemento name viene utilizzato come ID risorsa.
tipo di dati della risorsa compilata:
Puntatore alla risorsa String.
resource reference:
In Kotlin: R.string.string_name
In XML: @string/string_name
sintassi:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
elementi:
<resources>
Obbligatorio. Deve essere il nodo principale.

Nessun attributo.

<string>
Una stringa che può includere tag di stile. Tieni presente che devi usare il carattere di escape per gli apostrofi e le virgolette. Per ulteriori informazioni su come applicare correttamente lo stile e la formattazione alle stringhe, consulta la sezione Formattazione e stile di seguito.

attributi:

name
Stringa. Un nome per la stringa. Questo nome viene utilizzato come ID risorsa.
esempio:
File XML salvato in res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

Questo codice dell'applicazione recupera una stringa dall'interno di un elemento componibile con stringResource():

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

Nota:per recuperare una stringa al di fuori di una funzione componibile, utilizza context.getString(R.string.hello).

Puoi anche fare riferimento alle risorse stringa di altri file XML, ad esempio AndroidManifest.xml:
<activity
    android:name=".MainActivity"
    android:label="@string/hello" />

Array di stringhe

Un array di stringhe a cui è possibile fare riferimento dall'applicazione.

posizione del file:
res/values/filename.xml
Il nome file è arbitrario. L'<string-array> dell'elemento name viene utilizzato come ID risorsa.
tipo di dati della risorsa compilata:
Puntatore di risorse a un array di String.
resource reference:
In Kotlin: R.array.string_array_name
In XML: @[package:]array/string_array_name
sintassi:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="string_array_name">
        <item
            >text_string</item>
    </string-array>
</resources>
elementi:
<resources>
Obbligatorio. Deve essere il nodo principale.

Nessun attributo.

<string-array>
Definisce un array di stringhe. Contiene uno o più elementi <item>.

attributi:

name
Stringa. Un nome per l'array. Questo nome viene utilizzato come ID risorsa per fare riferimento all'array.
<item>
Una stringa che può includere tag di stile. Il valore può essere un riferimento a un'altra risorsa stringa. Deve essere un elemento secondario di un elemento <string-array>. Tieni presente che devi usare il carattere di escape per gli apostrofi e le virgolette. Per informazioni su come formattare e applicare correttamente lo stile alle stringhe, consulta la sezione Formattazione e stile di seguito.

Nessun attributo.

esempio:
File XML salvato in 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>

Questo codice dell'applicazione recupera un array di stringhe dall'interno di un elemento componibile con stringArrayResource():

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

Nota:per recuperare un array di stringhe al di fuori di una funzione componibile, utilizza context.resources.getStringArray(R.array.planets_array).

Stringhe di quantità (plurali)

Lingue diverse hanno regole diverse per la concordanza grammaticale con la quantità. In inglese, ad esempio, la quantità 1 è un caso speciale. Scriviamo "1 libro", ma per qualsiasi altra quantità scriveremmo "n libri". Questa distinzione tra singolare e plurale è molto comune, ma altre lingue fanno distinzioni più sottili. Il set completo supportato da Android è zero, one, two, few, many e other.

Le regole per decidere quale caso utilizzare per una determinata lingua e quantità possono essere molto complesse, quindi Android ti fornisce metodi come pluralStringResource() per selezionare la risorsa appropriata.

Sebbene storicamente siano chiamate "stringhe di quantità" (e lo siano ancora nell'API), le stringhe di quantità devono essere utilizzate solo per i plurali. Sarebbe un errore utilizzare le stringhe di quantità per implementare qualcosa come "Posta in arrivo" di Gmail rispetto a "Posta in arrivo (12)" quando ci sono messaggi non letti, ad esempio. Potrebbe sembrare comodo utilizzare stringhe di quantità anziché un'istruzione if, ma è importante notare che alcune lingue (come il cinese) non fanno queste distinzioni grammaticali, quindi otterrai sempre la stringa other.

La selezione della stringa da utilizzare si basa esclusivamente sulla necessità grammaticale. In inglese, una stringa per zero viene ignorata anche se la quantità è 0, perché 0 non è grammaticalmente diverso da 2 o da qualsiasi altro numero tranne 1 ("zero books", "one book", "two books" e così via). Al contrario, in coreano solo la stringa other viene utilizzata.

Non lasciarti ingannare dal fatto che, ad esempio, two sembra applicarsi solo alla quantità 2: una lingua potrebbe richiedere che 2, 12, 102 (e così via) vengano trattati allo stesso modo, ma in modo diverso rispetto ad altre quantità. Affidati al tuo traduttore per sapere quali distinzioni richiede la sua lingua.

Se il messaggio non contiene il numero di quantità, probabilmente non è un buon candidato per un plurale. Ad esempio, in lituano la forma singolare viene utilizzata sia per 1 che per 101, quindi "1 libro" viene tradotto come "1 knyga" e "101 libri" come "101 knyga". Nel frattempo, "un libro" è "knyga" e "molti libri" è "daug knygų". Se un messaggio plurale in inglese contiene "a book" (singolare) e "many books" (plurale) senza il numero effettivo, può essere tradotto come "knyga" (un libro)/"daug knygų" (molti libri), ma con le regole lituane, verrà visualizzato "knyga" (un libro singolo) quando il numero è 101.

Spesso è possibile evitare le stringhe di quantità utilizzando formulazioni neutre rispetto alla quantità, ad esempio "Libri: 1". In questo modo, la tua vita e quella dei tuoi traduttori saranno più semplici, se si tratta di uno stile accettabile per la tua applicazione.

Sulle API 24 e successive puoi utilizzare la classe ICU MessageFormat, molto più potente.

posizione del file:
res/values/filename.xml
Il nome file è arbitrario. L'<plurals> dell'elemento name viene utilizzato come ID risorsa.
resource reference:
In Kotlin: R.plurals.plural_name
sintassi:
<?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>
elementi:
<resources>
Obbligatorio. Deve essere il nodo principale.

Nessun attributo.

<plurals>
Una raccolta di stringhe, di cui una viene fornita in base alla quantità di qualcosa. Contiene uno o più elementi <item>.

attributi:

name
Stringa. Un nome per la coppia di stringhe. Questo nome viene utilizzato come ID risorsa.
<item>
Una stringa al plurale o al singolare. Il valore può essere un riferimento a un'altra risorsa stringa. Deve essere un elemento secondario di un elemento <plurals>. Tieni presente che devi inserire il carattere di escape per apostrofi e virgolette. Per informazioni su come formattare e applicare correttamente lo stile alle stringhe, consulta la sezione Formattazione e Stile di seguito.

attributi:

quantity
Parola chiave. Un valore che indica quando deve essere utilizzata questa stringa. Valori validi, con esempi non esaustivi tra parentesi:
ValoreDescrizione
zeroQuando la lingua richiede un trattamento speciale del numero 0 (come in arabo).
oneQuando la lingua richiede un trattamento speciale dei numeri come uno (come il numero 1 in inglese e nella maggior parte delle altre lingue; in russo, qualsiasi numero che termina con 1 ma non con 11 rientra in questa classe).
twoQuando la lingua richiede un trattamento speciale dei numeri come due (come 2 in gallese o 102 in sloveno).
fewQuando la lingua richiede un trattamento speciale dei numeri "piccoli" (come 2, 3 e 4 in ceco o i numeri che terminano con 2, 3 o 4, ma non 12, 13 o 14 in polacco).
manyQuando la lingua richiede un trattamento speciale dei numeri "grandi" (come per i numeri che terminano con 11-99 in maltese).
otherQuando la lingua non richiede un trattamento speciale della quantità indicata (come per tutti i numeri in cinese o 42 in inglese).
esempio:

File XML salvato in 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>

File XML salvato in 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>

Questo codice dell'applicazione recupera una stringa plurale dall'interno di un composable con pluralStringResource():

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

Quando utilizzi la funzione pluralStringResource(), devi passare count due volte se la stringa include la formattazione della stringa con un numero. Ad esempio, per la stringa %d songs found, il primo parametro count seleziona la stringa plurale appropriata e il secondo parametro count viene inserito nel segnaposto %d. Se le stringhe plurali non includono la formattazione delle stringhe, non devi passare il terzo parametro a pluralStringResource.

Nota:per recuperare una stringa plurale al di fuori di una funzione componibile, utilizza context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count).

Formato e stile

Ecco alcune informazioni importanti su come formattare e stilizzare correttamente le risorse stringa.

Gestire i caratteri speciali

Quando una stringa contiene caratteri con un utilizzo speciale in XML, devi utilizzare il codice di escape per i caratteri in base alle regole standard di escape XML/HTML. Se devi eseguire l'escape di un carattere che ha un significato speciale in Android, devi utilizzare una barra rovesciata precedente.

Per impostazione predefinita, Android comprime le sequenze di caratteri di spazio vuoto in un unico spazio. Per evitare questo problema, racchiudi la parte pertinente della stringa tra virgolette doppie. In questo caso, tutti i caratteri di spazio vuoto (incluse le nuove righe) verranno conservati all'interno della regione tra virgolette. Le virgolette doppie ti consentono di utilizzare anche virgolette singole normali senza caratteri di escape.

Carattere Form(s) escaped
@ \@
? \?
Nuova riga \n
Tab \t
Carattere Unicode U+XXXX \uXXXX
Virgoletta singola (')

Uno dei seguenti:

  • \'
  • Racchiudi l'intera stringa tra virgolette doppie (ad esempio "This'll work")
Virgolette doppie (") \"

Tieni presente che racchiudere la stringa tra virgolette singole non funziona.

La compressione degli spazi bianchi e l'escape di Android vengono eseguiti dopo l'analisi del file di risorse come XML. Ciò significa che <string> &#32; &#8200; &#8195;</string> (spazio, spazio di punteggiatura, spazio Unicode Em) si riducono a un unico spazio (" "), perché sono tutti spazi Unicode dopo l'analisi del file come XML. Per preservare questi spazi così come sono, puoi racchiuderli tra virgolette (<string>" &#32; &#8200; &#8195;"</string>) o utilizzare l'escape di Android (<string> \u0032 \u8200 \u8195</string>).

Stringhe di formattazione

Se devi formattare le stringhe, puoi farlo inserendo gli argomenti di formattazione nella risorsa stringa, come mostrato nell'esempio di risorsa seguente.

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

Questo codice dell'applicazione formatta la stringa dall'interno di un elemento componibile passando gli argomenti direttamente a stringResource():

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

Applicare stili con il markup HTML

Puoi aggiungere uno stile alle stringhe con il markup HTML. Ad esempio:

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

Sono supportati i seguenti elementi HTML:

  • Grassetto: <b>
  • Corsivo: <i>, <cite>, <dfn>, <em>
  • Testo più grande del 25%: <big>
  • Testo più piccolo del 20%: <small>
  • Impostazione delle proprietà del carattere: <font face="font_family" color="hex_color">. Esempi di possibili famiglie di caratteri includono monospace, serif e sans_serif.
  • Impostazione di una famiglia di caratteri monospazio: <tt>
  • Barrato: <s>, <strike>, <del>
  • Sottolineato: <u>
  • Apice: <sup>
  • Pedice: <sub>
  • Elenco puntato: <ul>, <li>
  • Interruzioni di riga: <br>
  • Divisione: <div>
  • Stile CSS: <span style="color|background_color|text-decoration">
  • Paragrafi: <p dir="rtl | ltr" style="…">

In alcuni casi, potresti voler creare una risorsa di testo con stile che venga utilizzata anche come stringa di formato. Normalmente, questo non funziona perché i metodi di formattazione, come stringResource(), rimuovono tutte le informazioni di stile dalla stringa. La soluzione alternativa consiste nello scrivere i tag HTML con entità di escape, che vengono poi recuperate con AnnotatedString.fromHtml(), dopo la formattazione. Ad esempio:

  1. Memorizza la risorsa di testo con stile come stringa con escape HTML:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>

    In questa stringa formattata viene aggiunto un elemento <b>. Nota che la parentesi aperta è codificata in HTML utilizzando la notazione &lt;.

  2. Quindi, formatta la stringa come di consueto, ma chiama anche AnnotatedString.fromHtml() per convertire il testo HTML in una stringa di composizione con stile.

Poiché fromHtml() formatta tutte le entità HTML, assicurati di eseguire l'escape di tutti i possibili caratteri HTML nelle stringhe che utilizzi con il testo formattato, utilizzando 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)
    )
}

Stile con AnnotatedString

Un AnnotatedString è un oggetto di testo di Compose che puoi stilizzare con proprietà come colore e spessore del carattere. Crea testo con stile a livello di programmazione utilizzando buildAnnotatedString e withStyle.

Questo codice dell'applicazione crea un singolo elemento di testo con stili misti:

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

Per applicare colore, dimensione del carattere e decorazione del testo, utilizza SpanStyle. Per applicare uno stile a livello di paragrafo (ad esempio allineamento o altezza riga), utilizza 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)
}

La creazione di AnnotatedString direttamente è l'approccio consigliato per app in una sola lingua o testo statico in Compose. Tuttavia, per il testo formattato che richiede la localizzazione, consulta l'approccio XML <annotation> descritto nella sezione successiva.

Applicare stili alle stringhe tradotte con annotazioni

Per le stringhe che richiedono uno stile personalizzato e la traduzione, definisci il tag <annotation> nel file strings.xml di ogni impostazione internazionale. I traduttori mantengono l'annotazione indipendentemente dalla sua posizione nella frase. Leggi la stringa con context.resources.getText(), percorri gli intervalli Annotation e converti il risultato in 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)
}

Il tag <annotation> nel tuo XML è invariato. Solo il codice di recupero è diverso. I traduttori spostano comunque il tag per racchiudere la parola corretta in ogni lingua.

Risorse aggiuntive

Per saperne di più sulle risorse stringa, consulta le seguenti risorse aggiuntive:

Documentazione

Visualizza contenuti