文字列リソースは、アプリにテキスト文字列と、オプションのテキストのスタイルやフォーマットを提供します。アプリに文字列を提供できるリソースには、次の 3 つのタイプがあります。
- String
- 単一の文字列を提供する XML リソース。
- 文字列配列
- 文字列配列を提供する XML リソース。
- 数量文字列(複数形)
- 複数形を表すさまざまな文字列を保有する XML リソース。
どの文字列にも、スタイル設定のマークアップと書式設定引数を適用できます。文字列のスタイル設定と書式設定については、 書式設定とスタイル設定をご覧ください。
String
アプリコード(コンポーズ可能な関数など)や他のリソース ファイルから参照できる単一の文字列。
- ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<string>要素のnameをリソース ID として使用します。- コンパイルされるリソースのデータ型:
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>
- 要素:
- 例:
res/values/strings.xmlに保存された 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)) }
注: コンポーズ可能な関数の外部で文字列を取得するには、
文字列リソースは、context.getString(R.string.hello)を使用します。AndroidManifest.xmlなどの他の XML ファイルから参照することもできます。<activity android:name=".MainActivity" android:label="@string/hello" />
文字列配列
アプリから参照可能な文字列の配列。
- ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<string-array>要素のnameをリソース ID として使用します。- コンパイルされるリソースのデータ型:
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>
- 要素:
- 例:
res/values/strings.xmlに保存された 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 の場合は「1 book」と記述しますが、その他の数量については「n books」と記述します。このような単数形と複数形の区別は一般的なものですが、さらに細かく区別する言語もあります。Android でサポートされている区分は、zero、one、two、few、many、other です。
特定の言語および数量にどの区分が当てはまるかを決定するルールは非常に複雑になる可能性があるため、Android では `pluralStringResource()` などのメソッドによって、適切なリソースが選択されるようになっています。pluralStringResource()
数量文字列は慣例的に、また API では現在も「数量」文字列と呼ばれていますが、実際には複数形の処理にのみ使用します。 たとえば、Gmail の「受信トレイ」を、未読メッセージがある場合に「受信トレイ (12)」などと表示するための実装に数量文字列を使用するのは間違いです。if ステートメントの代わりに数量文字列を使用する方が便利にも見えますが、一部の言語(中国語など)では単複の文法的な区別が行われないため、常に other 文字列が取得されます。
使用する文字列は、文法上の必要性 のみに基づいて選択されます。英語における 0 は、2 やその他 1 を除く数字と文法的な違いはないため(「zero books」、「one book」、「two books」となる)、数量が 0 であっても zero の文字列は無視されます。これに対して韓国語では、other という文字列だけが使用されます。
また、two は数量 2 のみに適用されるように思えますが、言語によっては、2、12、102 などが同じルールで扱われ、その他の数量とは区別される場合があります。各言語でどのような区別が求められるかは、翻訳者が判断することになります。
メッセージに数値が含まれていない場合、複数形の使用には適さない可能性があります。たとえば、リトアニア語では単数形が 1 と 101 の両方に使用されるため、「1 book」は「1 knyga」、「101 books」は「101 knyga」に翻訳されます。一方、「a book」は「knyga」で、「many books」は「daug knygų」になります。英語の複数形のメッセージに「a book」(単数形)と「many books」(複数形)が含まれていて、数字がない場合は、「knyga」(a book)/「daug knygų」(many books)と翻訳しますが、リトアニア語の文法では、101 という数値があった場合でも、1 冊の本を表す「knyga」と記載されます。
多くの場合、「Books: 1」のような数量に依存しない形式にすることで、数量文字列を回避できます。このスタイルをアプリで使用できれば、その後のアプリの管理や、翻訳時の負担が軽減されます。
API 24 以降では、さらに強力な ICU MessageFormat
クラスを使用できます。
- ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<plurals>要素のnameをリソース ID として使用します。- リソースの参照:
-
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>
- 要素:
- 例:
res/values/strings.xmlに保存された 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>
res/values-pl/strings.xmlに保存された 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を 2 回渡す必要があります。たとえば、%d songs foundという文字列の場合、最初のcountパラメータが適切な複数形の文字列を選択し、 2 つ目のcountパラメータが%dプレースホルダに挿入されます。複数形の文字列に文字列形式が含まれていない場合、3 つ目のパラメータをpluralStringResourceに渡す必要はありません。注: コンポーズ可能な関数の外部で複数形の文字列を取得するには、
context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count)を使用します。
書式とスタイル
ここでは、文字列リソースの書式とスタイルを適切に設定する方法について説明します。
特殊文字の処理
XML で特別な意味を持つ文字が文字列に含まれている場合は、それらの文字を XML/HTML の標準のエスケープ ルールに従ってエスケープする必要があります。Android で特別な意味を持つ文字をエスケープする必要がある場合は、該当する文字の前にバックスラッシュを置きます。
Android ではデフォルトで、連続する空白文字が 1 つのスペースに短縮されます。これを回避するには、文字列の該当する部分を二重引用符で囲みます。それにより、引用符で囲んだ部分の空白文字(改行を含む)が保持されます。この二重引用符により、エスケープされない標準の単一引用符を使用することも可能になります。
| 文字 | エスケープ書式 |
|---|---|
| @ | \@ |
| ? | \? |
| 改行 | \n |
| Tab | \t |
| U+XXXX Unicode 文字 | \uXXXX |
単一引用符(') |
次のいずれか:
|
二重引用符(") |
\"
文字列を単一引用符で囲んでも機能しません。 |
空白の短縮と Android のエスケープは、リソース ファイルが XML として解析された後に行われます。つまり、<string>      </string>
(スペース、句読点スペース、Unicode Em スペース)は、ファイルが XML として解析されるとすべて Unicode のスペースになるため、すべてが 1 つのスペース
(" ")に短縮されます。
それらのスペースを保持するには、スペースを引用符で囲む
(<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) }
context.getText(R.string.your_string)AnnotatedString を直接作成する方法は、単一言語のアプリや Compose の静的テキストにおすすめです。ただし、ローカライズが必要なスタイル付きのテキストについては、次のセクションで説明する XML <annotation> の方法をご覧ください。
アノテーションを使用した翻訳済み文字列のスタイル設定
カスタム スタイル設定と翻訳の両方が必要な文字列の場合は、各ロケールの strings.xml で
<annotation> タグを定義します。翻訳者は、文中のどこに配置されるかに関係なく、アノテーションを保持します。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) }
XML の <annotation> タグは変更されません。取得コードのみが異なります。翻訳者は、各言語で正しい単語を囲むようにタグを移動します。
参考情報
文字列リソースについて詳しくは、次のリソースをご覧ください。