Resource string

Resource string menyediakan string teks untuk aplikasi Anda dengan pemformatan dan penataan gaya teks opsional. Ada tiga jenis resource yang bisa menyediakan string untuk aplikasi Anda:

String
Resource XML yang menyediakan string tunggal.
String Array
Resource XML yang menyediakan array string.
String Jumlah (Jamak)
Resource XML yang membawa string berbeda untuk pluralisasi.

Semua string mampu menerapkan beberapa argumen markup penataan gaya dan pemformatan. Untuk informasi tentang string penataan gaya dan pemformatan, lihat bagian tentang Pemformatan dan Penataan Gaya.

String

String tunggal yang dapat direferensikan dari kode aplikasi (seperti fungsi composable) atau dari file resource lainnya.

lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer. name elemen <string> digunakan sebagai ID resource.
jenis data resource yang dihimpun:
Pointer resource ke String.
referensi resource:
Di Kotlin: R.string.string_name
Dalam XML: @string/string_name
sintaksis:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
elemen:
<resources>
Wajib. Elemen ini harus menjadi node root.

Tidak ada atribut.

<string>
Sebuah string, yang bisa berisi tag penataan gaya. Ketahuilah bahwa Anda harus mengurung tanda apostrof dan tanda petik. Untuk informasi selengkapnya tentang cara menata gaya dan memformat string Anda dengan benar, lihat Memformat dan Menata Gaya, di bawah ini.

atribut:

name
String. Nama untuk string. Nama ini digunakan sebagai ID resource.
contoh:
File XML yang disimpan di res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

Kode aplikasi ini mengambil string dari dalam composable dengan stringResource():

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

Catatan: Untuk mengambil string di luar fungsi composable, gunakan context.getString(R.string.hello).

Anda juga dapat mereferensikan resource string dari file XML lain, seperti AndroidManifest.xml:
<activity
    android:name=".MainActivity"
    android:label="@string/hello" />

Array string

Array string yang bisa direferensikan dari aplikasi.

lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer. name elemen <string-array> digunakan sebagai ID resource.
jenis data resource yang dihimpun:
Pointer resource ke array String.
referensi resource:
Di Kotlin: R.array.string_array_name
Dalam XML: @[package:]array/string_array_name
sintaksis:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="string_array_name">
        <item
            >text_string</item>
    </string-array>
</resources>
elemen:
<resources>
Wajib. Elemen ini harus menjadi node root.

Tidak ada atribut.

<string-array>
Mendefinisikan array string. Berisi satu atau beberapa elemen <item>.

atribut:

name
String. Nama untuk array. Nama ini akan digunakan sebagai ID resource untuk mereferensikan array.
<item>
Sebuah string, yang bisa berisi tag penataan gaya. Nilainya dapat berupa referensi ke resource string lainnya. Harus berupa turunan dari elemen <string-array>. Ketahuilah bahwa Anda harus mengurung tanda apostrof dan tanda petik. Lihat Memformat dan Menata Gaya di bawah ini, untuk informasi tentang cara menata gaya dan memformat string Anda dengan benar.

Tidak ada atribut.

contoh:
File XML yang disimpan di 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>

Kode aplikasi ini mengambil array string dari dalam composable dengan stringArrayResource():

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

Catatan: Untuk mengambil array string di luar fungsi composable, gunakan context.resources.getStringArray(R.array.planets_array).

String jumlah (jamak)

Bahasa yang berbeda memiliki aturan yang berbeda pula untuk kesepakatan gramatikal pada jumlah. Dalam bahasa Inggris, misalnya, jumlah 1 adalah kasus khusus. Kita menulis "1 buku", tetapi untuk jumlah lain kita akan menulis "n buku". Perbedaan antara tunggal dan jamak sudah sangat umum, tetapi bahasa lain membuat perbedaan yang lebih tipis. Set lengkap yang didukung Android adalah zero, one, two, few, many, dan other.

Aturan untuk memutuskan kasus mana yang akan digunakan untuk bahasa dan jumlah yang diberikan boleh jadi akan sangat kompleks, jadi Android menyediakan beberapa metode seperti pluralStringResource() untuk memilih resource yang sesuai untuk Anda.

Meskipun secara historis disebut "string jumlah" (dan tetap disebut demikian di API), string jumlah hanya boleh digunakan untuk jamak. Akan salah jika menggunakan string jumlah untuk mengimplementasikan sesuatu seperti "Kotak Masuk" Gmail dan "Kotak Masuk (12)" saat ada pesan yang belum dibaca. Sepertinya mungkin praktis menggunakan string jumlah sebagai ganti pernyataan if, tetapi perlu diperhatikan bahwa beberapa bahasa (seperti bahasa China) tidak membuat perbedaan gramatikal ini sama sekali, jadi Anda akan selalu mendapatkan string other.

Pemilihan string yang akan digunakan dilakukan semata-mata berdasarkan keperluan gramatikal. Dalam bahasa Inggris, string untuk zero diabaikan meskipun jumlahnya 0, karena 0 secara gramatikal tidak berbeda dengan 2, atau angka lain kecuali 1 ("zero books", "one book", "two books", dan seterusnya). Sebaliknya, dalam bahasa Korea hanya string other yang pernah digunakan.

Jangan salah paham dengan fakta bahwa, misalnya, two seolah hanya bisa diterapkan pada jumlah 2: suatu bahasa mungkin mengharuskan 2, 12, 102 (dan seterusnya) semua diperlakukan seperti satu sama lain, tetapi secara berbeda untuk jumlah lainnya. Percayakan pada penerjemah Anda untuk mengetahui perbedaan sesungguhnya dalam bahasa masing-masing.

Jika pesan Anda tidak berisi jumlah, itu mungkin bukan kandidat yang baik untuk jamak. Misalnya, dalam bahasa Lituania, bentuk tunggal digunakan untuk 1 dan 101, sehingga "1 buku" diterjemahkan sebagai "1 knyga", dan "101 buku" diterjemahkan sebagai "101 knyga". Sementara itu, "buku" adalah "knyga" dan "banyak buku" adalah "daug knygų". Jika pesan jamak dalam bahasa Inggris berisi "a book" (tunggal) dan "many books" (jamak) tanpa angka sebenarnya, pesan tersebut dapat diterjemahkan sebagai "knyga" (satu buku)/"daug knygų" (banyak buku), tetapi dengan aturan bahasa Lituania, pesan tersebut akan menampilkan "knyga" (satu buku), jika angkanya adalah 101.

Sering kali, string jumlah dapat dihindari dengan menggunakan formulasi netral jumlah seperti "Buku: 1". Hal ini membuat urusan Anda dan penerjemah Anda jadi lebih mudah, jika ini adalah gaya yang bisa diterima untuk aplikasi Anda.

Di API 24+, Anda dapat menggunakan class MessageFormat ICU yang jauh lebih canggih.

lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer. name elemen <plurals> digunakan sebagai ID resource.
referensi resource:
Di Kotlin: R.plurals.plural_name
sintaksis:
<?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>
elemen:
<resources>
Wajib. Elemen ini harus menjadi node root.

Tidak ada atribut.

<plurals>
Kumpulan string, yang menjadi tempat menyediakan satu string, bergantung pada jumlah sesuatu. Berisi satu atau beberapa elemen <item>.

atribut:

name
String. Nama untuk pasangan string. Nama ini digunakan sebagai ID resource.
<item>
String jamak atau tunggal. Nilainya dapat berupa referensi ke resource string lainnya. Harus berupa turunan dari elemen <plurals>. Ketahuilah bahwa Anda harus mengurung tanda apostrof dan tanda petik. Lihat Memformat dan Menata Gaya di bawah ini, untuk informasi tentang cara menata gaya dan memformat string Anda dengan benar.

atribut:

quantity
Kata kunci. Sebuah nilai yang menunjukkan kapan string ini harus digunakan. Nilai yang valid, dengan contoh yang belum selengkapnya dalam tanda kurung:
NilaiDeskripsi
zeroBila suatu bahasa memerlukan perlakuan khusus atas bilangan 0 (seperti dalam bahasa Arab).
oneBila suatu bahasa memerlukan perlakuan khusus atas bilangan seperti satu (sebagaimana dengan bilangan 1 dalam bahasa Inggris dan kebanyakan bahasa lainnya; dalam bahasa Rusia, bilangan yang diakhiri dengan 1 namun bukan diakhiri dengan 11 ada dalam class ini).
twoBila suatu bahasa memerlukan perlakuan khusus atas bilangan seperti dua (sebagaimana dengan 2 dalam bahasa Welsh, atau 102 dalam bahasa Slovenia).
fewBila suatu bahasa memerlukan perlakuan khusus atas bilangan "kecil" (sebagaimana dengan 2, 3, dan 4 dalam bahasa Ceko; atau bilangan yang berakhiran 2, 3, atau 4 namun bukan 12, 13, atau 14 dalam bahasa Polandia).
manyJika bahasanya memerlukan perlakuan khusus atas bilangan "besar" (sebagaimana dengan bilangan yang berakhiran 11-99 dalam bahasa Malta).
otherBila suatu bahasa tidak memerlukan perlakuan khusus atas kuantitas yang diberikan (sebagaimana dengan semua bilangan dalam bahasa Cina, atau 42 dalam bahasa Inggris).
contoh:

File XML yang disimpan di 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 yang disimpan di 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>

Kode aplikasi ini mengambil string jamak dari dalam composable dengan pluralStringResource():

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

Saat menggunakan fungsi pluralStringResource(), Anda perlu meneruskan count dua kali jika string berisi pemformatan string dengan angka. Misalnya, untuk string %d songs found, parameter count pertama akan memilih string jamak yang sesuai dan parameter count kedua akan dimasukkan ke dalam placeholder %d. Jika string jamak Anda tidak berisi pemformatan string, Anda tidak perlu meneruskan parameter ketiga ke pluralStringResource.

Catatan: Untuk mengambil string jamak di luar fungsi composable, gunakan context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count).

Format dan gaya

Inilah beberapa hal penting yang harus Anda ketahui tentang cara yang benar untuk memformat dan menata gaya resource string.

Menangani karakter khusus

Jika string berisi karakter yang memiliki penggunaan khusus dalam XML, Anda harus meng-escape karakter sesuai dengan aturan escaping XML/HTML standar. Jika Anda perlu meng-escape karakter yang memiliki arti khusus di Android, Anda harus menggunakan garis miring terbalik sebelumnya.

Secara default, Android akan menciutkan urutan karakter spasi kosong menjadi satu spasi. Anda dapat menghindari hal ini dengan mengapit bagian string yang relevan dalam tanda kutip ganda. Dalam hal ini, semua karakter spasi kosong (termasuk baris baru) akan dipertahankan dalam region yang dikutip. Tanda kutip ganda juga akan memungkinkan Anda menggunakan tanda kutip tunggal tanpa konversi reguler.

Karakter Bentuk yang di-escape
@ \@
? \?
Baris baru \n
Tab \t
Karakter Unicode U+XXXX \uXXXX
Tanda petik tunggal (')

Salah satu dari berikut:

  • \'
  • Sertakan seluruh string dalam tanda petik ganda (misalnya "This'll work")
Tanda kutip ganda (") \"

Perlu diperhatikan bahwa mengelilingi string dengan tanda kutip tunggal tidak berfungsi.

Spasi kosong diciutkan dan escaping Android terjadi setelah file resource Anda diurai sebagai XML. Artinya, <string> &#32; &#8200; &#8195;</string> (spasi, spasi tanda baca, spasi Unicode Em) semuanya diciutkan ke satu spasi (" "), karena semuanya merupakan spasi Unicode setelah file diuraikan sebagai XML. Untuk mempertahankan ruang tersebut apa adanya, Anda dapat mengutipnya (<string>" &#32; &#8200; &#8195;"</string>) atau menggunakan escape Android (<string> \u0032 \u8200 \u8195</string>).

Memformat string

Jika perlu memformat string, Anda dapat melakukannya dengan menempatkan argumen format dalam resource string, seperti yang ditunjukkan oleh resource contoh berikut.

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

Kode aplikasi ini memformat string dari dalam composable dengan meneruskan argumen langsung ke stringResource():

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

Menata gaya dengan markup HTML

Anda bisa menambahkan penataan gaya ke string dengan markup HTML. Misalnya:

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

Elemen HTML berikut didukung:

  • Tebal: <b>
  • Miring: <i>, <cite>, <dfn>, <em>
  • Teks 25% lebih besar: <big>
  • 20% teks lebih kecil: <small>
  • Menetapkan properti font: <font face="font_family" color="hex_color">. Contoh kemungkinan jenis font meliputi monospace, serif, dan sans_serif.
  • Menyetel jenis font monospace: <tt>
  • Coret: <s>, <strike>, <del>
  • Garis bawah: <u>
  • Superskrip: <sup>
  • Subskrip: <sub>
  • Poin butir: <ul>, <li>
  • Jeda baris: <br>
  • Divisi: <div>
  • Gaya CSS: <span style="color|background_color|text-decoration">
  • Paragraf: <p dir="rtl | ltr" style="…">

Dalam beberapa kasus, Anda mungkin ingin membuat resource teks bergaya yang juga digunakan sebagai string format. Biasanya, hal ini tidak akan berhasil karena metode pemformatan, seperti stringResource(), akan menghapus semua informasi gaya dari string. Solusinya adalah menuliskan tag HTML dengan entitas yang dikurung, yang kemudian dipulihkan dengan AnnotatedString.fromHtml(), setelah pemformatan dilakukan. Contoh:

  1. Simpan resource teks bergaya sebagai string yang dikurung dengan HTML:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>

    Dalam string yang diformat ini, elemen <b> telah ditambahkan. Perhatikan bahwa kurung buka adalah HTML yang di-escape, dengan menggunakan notasi &lt;.

  2. Kemudian format string tersebut seperti biasa, namun panggil juga AnnotatedString.fromHtml() untuk mengonversi teks HTML menjadi string Compose yang diberi gaya.

Karena fromHtml() memformat semua entity HTML, pastikan untuk meng-escape semua karakter HTML yang memungkinkan dalam string yang Anda gunakan bersama teks berformat, menggunakan 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)
    )
}

Menata gaya dengan AnnotatedString

AnnotatedString adalah objek teks Compose yang dapat Anda beri gaya dengan properti seperti warna dan ketebalan font. Buat teks bergaya secara terprogram menggunakan buildAnnotatedString dan withStyle.

Kode aplikasi ini membuat satu elemen teks dengan gaya campuran:

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

Untuk menerapkan warna, ukuran font, dan dekorasi teks, gunakan SpanStyle. Untuk menerapkan gaya tingkat paragraf (seperti perataan atau tinggi baris), gunakan 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)
}

Membangun AnnotatedString secara langsung adalah pendekatan yang direkomendasikan untuk aplikasi satu bahasa atau teks statis di Compose. Namun, untuk teks bergaya yang memerlukan pelokalan, lihat pendekatan <annotation> XML yang dijelaskan di bagian berikutnya.

Menata gaya string yang diterjemahkan dengan anotasi

Untuk string yang memerlukan gaya dan terjemahan kustom, tentukan tag <annotation> di strings.xml setiap lokalitas. Penerjemah mempertahankan anotasi, di mana pun posisinya dalam kalimat. Baca string dengan context.resources.getText(), telusuri rentang Annotation-nya, dan konversi hasilnya menjadi 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)
}

Tag <annotation> di XML Anda tidak berubah. Hanya kode pengambilan yang berbeda. Penerjemah tetap memindahkan tag untuk membungkus kata yang benar dalam setiap bahasa.

Referensi lainnya

Untuk mengetahui informasi selengkapnya tentang resource string, lihat referensi tambahan berikut:

Dokumentasi

Melihat konten