Join us on the livestream at Android Dev Summit on 7-8 November 2018, starting at 10AM PDT!

文字列リソース

文字列リソースは、アプリケーションのテキスト文字列に対して、テキストのスタイルや書式を任意で設定します。 アプリケーションに文字列を提供できるリソースは 3 種類あります。

文字列
1 つの文字列を提供する XML リソース。
文字列配列
文字列配列を提供する XML リソース。
数量文字列(複数形)
さまざまな複数形の文字列を扱う XML リソース。

すべての文字列は、スタイル設定のマークアップや書式設定の引数を適用可能です。文字列のスタイル設定と形式指定の詳細は、書式設定とスタイル設定のセクションをご覧ください。

文字列

アプリケーションから、または他のリソース ファイル(XML レイアウトなど)から参照できる、1 つの文字列。

注: 文字列は、name 属性(XML ファイルの名前ではありません)で提供された値を使って参照される、単純なリソースです。 そのため、文字列リソースと他の単純なリソースを、1 つの XML ファイル内の 1 つの <resources> 要素の中で組み合わせることが可能です。

ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<string> 要素の name はリソース ID として使用されます。
コンパイルずみのリソース データタイプ:
String に対するリソース ポインタ
リソース リファレンス:
Java の場合:R.string.string_name
XML の場合:@string/string_name
構文:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
エレメント:
<resources>
必須ルート要素でなければなりません。

属性はありません。

<string>
スタイル設定タグを含むことが可能な文字列。アポストロフィや引用符をエスケープする必要があることに注意してください。 文字列のスタイルや書式を正しく設定する方法の詳細は、下の書式設定とスタイル設定をご覧ください。

属性:

name
文字列文字列の名前になります。この名前はリソース ID として使用されます。
例:
res/values/strings.xml に保存された XML ファイル:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

このレイアウト XML は文字列をビューに適用します。

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />

このアプリケーション コードは文字列を取得します。

String string = getString(R.string.hello);

getString(int)getText(int) のどちらかを使って文字列を取得できます。getText(int) は文字列に適用されたリッチテキストのスタイルを保持します。

文字列配列

アプリケーションから参照可能な文字列配列。

注: 文字列配列は、name 属性(XML ファイルの名前ではありません)で提供された値を使って参照される、単純なリソースです。 そのため、文字列配列リソースと他の単純なリソースを、1 つの XML ファイル内の 1 つの <resources> 要素の中で組み合わせることが可能です。

ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<string-array> 要素の name はリソース ID として使用されます。
コンパイルずみのリソース データタイプ:
String 配列へのリソース ポインタ。
リソース リファレンス:
Java の場合:R.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>
エレメント:
<resources>
必須ルート要素でなければなりません。

属性はありません。

<string-array>
文字列の配列を定義します。一つ以上の <item> エレメントを含んでいます。

属性:

name
文字列配列の名前。この名前は、配列を参照するためのリソース ID として使用されます。
<item>
スタイル設定タグを含むことが可能な文字列。この値は、別の文字列リソースからの参照が可能です。 <string-array> エレメントに従属しなければなりません。アポストロフィや引用符をエスケープする必要があることに注意してください。 文字列のスタイルや書式を正しく設定する方法については、下の書式設定とスタイル設定をご覧ください。

属性はありません。

例:
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>

このアプリケーション コードは文字列配列を取得します。

Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);

数量文字列(複数形)

言語が異なると、数量と文法を一致させるためのルールも異なります。たとえば、英語では、1 という数は特別なケースです。 1 冊の本は「1 book」と書きますが、その他の数の場合は「n books」と書きます。 この単数形と複数形の違いはごく一般的なものですが、もっと微妙な違いのある言語も存在します。 Android でサポートされているフル セットは、zeroonetwofewmanyother です。

特定の言語と数量で使用すべきケースを判断するためのルールは、非常に複雑になりかねないので、Android では getQuantityString() という、適切なリソースを選択するためのメソッドが用意されています。

以前から「数量文字列」と呼ばれていますが(API 内でもそう呼ばれています)、数量文字列は複数形にのみ使用します。 たとえば、Gmail の「Inbox」と、未読メッセージがある場合の「Inbox (12)」のような違いを実装するために数量文字列を使うのは誤りです。 if 文の代わりに数量文字列を使うのは便利に思えるかもしれませんが、一部の言語(中国語など)ではそうした文法上の区別をしないため、常に other 文字列を使うという点に注意が必要です。

使用する文字列の選択は、文法上の「必要性」にのみ基づいて行われます。英語では、zero の文字列は、数量が 0 の場合でも無視されます。0 は、1 以外の、2 やその他の数と文法上の違いはないからです(「zero books」、「one book」、「two books」などと表します)。 反対に韓国語では、other 文字列のみが使われます。

たとえば、two は 2 という数量にのみ適用できるように思えますが、誤解のないようにしてください。ある言語では、2、12、102 などの数はすべて同じように扱い、他の数とは区別する必要があるかもしれないからです。 各言語が実際にどのような区別を必要としているかを知るには、その言語の翻訳担当者に相談してください。

たとえば「Books: 1」のように、数量について中立的な表現を使うことで、数量文字列を使用せずに済む場合が多くあります。 それがアプリケーションと調和したスタイルであれば、デベロッパーや翻訳者の負担は減ります。

注: 複数形の集合は、name 属性(XML ファイルの名前ではありません)で提供された値を使って参照される、単純なリソースです。 そのため、複数形リソースと他の単純なリソースを、1 つの XML ファイル内の 1 つの <resources> 要素の中で組み合わせることが可能です。

ファイルの場所:
res/values/filename.xml
ファイル名は任意です。<plurals> 要素の name はリソース ID として使用されます。
リソース リファレンス:
Java の場合: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>
エレメント:
<resources>
必須ルート要素でなければなりません。

属性はありません。

<plurals>
何かの量に応じて 1 つの文字列が提供されるような文字列の集合。 一つ以上の <item> エレメントを含んでいます。

属性:

name
文字列文字列のペアの名前。この名前はリソース ID として使用されます。
<item>
複数形または単数形の文字列。この値は、別の文字列リソースからの参照が可能です。 <plurals> エレメントに従属しなければなりません。アポストロフィや引用符をエスケープする必要があることに注意してください。 文字列にスタイルや書式を正しく設定する方法については、下の書式設定とスタイル設定をご覧ください。

属性:

quantity
キーワード文字列を使用すべきケースを示す値。有効な値。丸かっこ内の例は網羅的ではありません。
説明
zero0 を特別に取り扱う必要がある場合(アラビア語など)。
one1 などの数を特別に取り扱う必要がある場合(英語や他の多くの言語における 1。ロシア語では、末尾が 1 だが 11 ではない数がこのケースにあたる)。
two2 などの数を特別に取り扱う必要がある場合(ウェールズ語の 2、スロベニア語の 102 など)。
few「小さい」数を特別に取り扱う必要がある場合(チェコ語の 2、3、4 や、ポーランド語の末尾が 2、3、4 だが 12、13、14 ではない数など)。
many「大きい」数を特別に取り扱う必要がある場合(マルタ語の末尾が 11 から 99 の数など)。
other特定の数に特別な取り扱いを必要としない場合(中国語のすべての数、英語の 42 など)
例:
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>

Java コード:

int count = getNumberOfsongsAvailable();
Resources res = getResources();
String songsFound = res.getQuantityString(R.plurals.numberOfSongsAvailable, count, count);

getQuantityString() メソッドを使う場合、文字列に数による文字列書式設定が含まれていれば、count を 2 回渡す必要があります。 たとえば、%d songs found という文字列では、1 回目の count パラメータが適切な複数形の文字列を選び、2 回目の count パラメータが %d プレースホルダに挿入されます。 複数形の文字列に文字列書式設定が含まれていなければ、3 つ目のパラメータを getQuantityString に渡す必要はありません。

書式設定とスタイル設定

ここでは、文字列リソースの書式とスタイルを正しく設定するために理解しておくべき重要な点をいくつか説明します。

アポストロフィと引用符をエスケープする

文字列にアポストロフィ(')がある場合は、それをバックスラッシュ(\')でエスケープするか、文字列を二重引用符("")で囲む必要があります。 たとえば、以下は有効な文字列と無効な文字列の例です。

<string name="good_example">This\'ll work</string>
<string name="good_example_2">"This'll also work"</string>
<string name="bad_example">This doesn't work</string>
    <!-- Causes a compile error -->

文字列に二重引用符がある場合は、それをエスケープする必要があります(\")。 文字列を単一引用符で囲んでも「無効」です。

<string name="good_example">This is a \"good string\".</string>
<string name="bad_example">This is a "bad string".</string>
    <!-- Quotes are stripped; displays as: This is a bad string. -->
<string name="bad_example_2">'This is another "bad string".'</string>
    <!-- Causes a compile error -->

文字列の書式を設定する

String.format(String, Object...) を使用して文字列の書式を設定する必要がある場合は、書式引数を文字列リソースに格納します。 たとえば、次のようなリソースがあるとします。

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

この例では、書式文字列には 2 つの引数があります。%1$s は文字列、%2$d は小数です。 このように、アプリケーションから引数で文字列の書式設定をすることが可能です。

Resources res = getResources();
String text = String.format(res.getString(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> テキストを斜体にします。
  • <u> テキストにアンダーラインを引きます。

書式文字列としても使用する、スタイル設定済みテキスト リソースを作成したい場合があるかもしれません。 通常、これはうまくいきません。String.format(String, Object...) メソッドが文字列からすべてのスタイル情報を取り除くからです。 この回避策は、エスケープされたエンティティを使って HTML タグを書くことです。そうすると、書式設定が行われた後に、fromHtml(String) によって復元されます。 次に例を示します。

  1. スタイル設定をしたテキスト リソースを HTML のエスケープ処理をした文字列として格納します。
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    この書式設定済みの文字列には、<b> 要素が追加されています。左かっこは、&lt; 記号を使って HTML をエスケープしていることに注意してください。

  2. 次に、通常の方法で文字列の書式を設定しますが、さらに fromHtml(String) を呼び出して、HTML テキストをスタイル設定済みのテキストに変換します。
    Resources res = getResources();
    String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
    CharSequence styledText = Html.fromHtml(text);
    

fromHtml(String) メソッドでは、すべての HTML エンティティの書式を設定します。そのため、htmlEncode(String) を使用して、書式設定済みのテキストで使用している文字列中の HTML 文字をできる限りエスケープするようにします。 たとえば、文字列の引数を、「<」や「&」のような文字を含む String.format() に渡そうとする場合には、書式を設定する前にそうした文字をエスケープする必要があります。そうすると、書式設定済みの文字列が fromHtml(String) によって渡されたときに、その文字は本来書かれていたとおりに表示されます。 次に例を示します。

String escapedUsername = TextUtil.htmlEncode(username);

Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), escapedUsername, mailCount);
CharSequence styledText = Html.fromHtml(text);

Spannable でスタイル設定をする

Spannable は、色やフォント ウェイトといった書体プロパティでスタイルを設定できるテキスト オブジェクトです。 SpannableStringBuilder を使ってテキストを作成してから、android.text.style パッケージで定義されたスタイルをテキストに適用します。

以下のヘルパー メソッドを使うと、Spannable テキストを作成する処理の大部分を構成できます。

/**
 * Returns a CharSequence that concatenates the specified array of CharSequence
 * objects and then applies a list of zero or more tags to the entire range.
 *
 * @param content an array of character sequences to apply a style to
 * @param tags the styled span objects to apply to the content
 *        such as android.text.style.StyleSpan
 *
 */
private static CharSequence apply(CharSequence[] content, Object... tags) {
    SpannableStringBuilder text = new SpannableStringBuilder();
    openTags(text, tags);
    for (CharSequence item : content) {
        text.append(item);
    }
    closeTags(text, tags);
    return text;
}

/**
 * Iterates over an array of tags and applies them to the beginning of the specified
 * Spannable object so that future text appended to the text will have the styling
 * applied to it. Do not call this method directly.
 */
private static void openTags(Spannable text, Object[] tags) {
    for (Object tag : tags) {
        text.setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK);
    }
}

/**
 * "Closes" the specified tags on a Spannable by updating the spans to be
 * endpoint-exclusive so that future text appended to the end will not take
 * on the same styling. Do not call this method directly.
 */
private static void closeTags(Spannable text, Object[] tags) {
    int len = text.length();
    for (Object tag : tags) {
        if (len > 0) {
            text.setSpan(tag, 0, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            text.removeSpan(tag);
        }
    }
}

以下の bolditaliccolor のメソッドでは、ヘルパー メソッドを呼び出して、android.text.style パッケージで設定されたスタイルを適用する方法を示しています。 別の種類のテキスト スタイル設定を行う場合にも、同じメソッドを作成できます。

/**
 * Returns a CharSequence that applies boldface to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence bold(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.BOLD));
}

/**
 * Returns a CharSequence that applies italics to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence italic(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.ITALIC));
}

/**
 * Returns a CharSequence that applies a foreground color to the
 * concatenation of the specified CharSequence objects.
 */
public static CharSequence color(int color, CharSequence... content) {
    return apply(content, new ForegroundColorSpan(color));
}

以下の例では、こうしたメソッドを連結させて、個々の単語に異なる種類のスタイルを適用した文字列の作成方法を示しています。

// Create an italic "hello, " a red "world",
// and bold the entire sequence.
CharSequence text = bold(italic(res.getString(R.string.hello)),
    color(Color.RED, res.getString(R.string.world)));