Smart String
Smart String は、SmartFormat ライブラリの修正版です。
Smart String は、動的文字列を生成する際に使用できる String.Format の強力な代替です。Smart String を使用した場合、データ駆動型テンプレートに、適切な複数形化、性に基づく活用、リスト、条件に基づく言語理論を含めることができます。名前付きプレースホルダーを用いることで、より直観的に、よりエラーが発生しにくい形で変数を導入することができ、翻訳者に追加的な文脈を提供する上で役立ちます。
ローカライズされた文字列を Smart としてマークするには、Table Editor ウィンドウ内で Smart フィールドを選択してください。
Localized String エディターの Smart フィールドでも文字列を Smart としてマークできます。
エディタースクリプトを使用してフィールドを Smart としてマークするには、フィールドに IsSmart プロパティを追加し、それを true に設定してください。
// Get the collection.
var collection = LocalizationEditorSettings.GetStringTableCollection("My Strings");
// Get the English table.
var englishTable = collection.GetTable("en") as StringTable;
// Get the Entry we want to mark as Smart.
var entry = englishTable.GetEntry("My Entry");
entry.IsSmart = true;
#if UNITY_EDITOR
// If we are in the Editor then we need to mark the table dirty so the changes are saved.
EditorUtility.SetDirty(englishTable);
#endif
はじめに
Smart String は、リテラルテキストと書式項目 (プレースホルダーとも呼ばれます) で構成されます。プレースホルダーは、String.Format プレースホルダーと同様に、{placeholder} ブロック内にカプセル化されます。
プレースホルダーは以下を含む複数の要素から構成することができます。
- Selector (セレクター)
- Formatter Name (フォーマッター名)
- Formatter Options (フォーマッターオプション)
- Format (書式)
下の画像は、Smart String の一例の構造を示したものです。
下の図はプレースホルダーの書式設定のステップを示したものです。まず、ソースデータが選択されるまでソースが評価され、その後でフォーマッターが適用されます。
Selector
Selector (セレクター) はプレースホルダーからオブジェクトを抽出します。これは多くの場合、引数あるいは外部のソース (例えば Persistent Variables ソース など) から値を抽出することを意味します。ソースがセレクターを評価し、その後 フォーマッター がオブジェクトの書式設定を行います。
例えば、渡された引数がゲームオブジェクトに添付されたオブジェクトへの参照である場合、Reflection ソースは、ゲームオブジェクトの名前を次の Smart String で抽出できます。
The name of the GameObject is {gameObject.name}.
複数のソースを 1 つの書式項目に使用することができます。
例: The name of the GameObject is {1:gameObject.name}
Smart String はまず Default ソースを使用してインデックス 1 の引数を抽出し、その後Reflection ソースが、抽出された値を処理します。
ノート: 引数インデックスが指定されていない場合は、常にインデックス 0 の引数が使用されます。
ソースは、最初の項目から順に、ソースがセレクターを処理できるようになるまで評価されます。ソースの順序によって結果の文字列が変わります。
例えば、以下のディクショナリインスタンスが Smart String The value is {Count}
の引数として使用された場合:
var localizedString = new LocalizedString("My Table", "My Table Entry");
var dict = new Dictionary<string, string> { { "Count", "Hello World" } };
localizedString.Arguments = new object[] { dict };
Reflection ソースが Dictionary ソースの前にある場合、出力は
The value is 1
となりますが、Dictionary が最初にある場合は出力は The value is Hello World
になります。
ソースの順序を考慮し、他のソースと競合する可能性のある名前付きプレースホルダーの使用を避けることが重要です。
セレクターの構文は C# の 挿入文字列 に似ています。セレクターを使用してデータの各サブセットをフィルタリングし、ドット表記を使用して目的のオブジェクトに到達できます。 以下の例では、スライダーと値は両方ともセレクターです。スライダーセレクターは、インデックス 0 の Smart String に渡される引数を評価します。次に、値セレクターが前のセレクターの結果を評価します。
ノート: インデックス値が含まれていない場合は、インデックス 0 の引数がデフォルトで使用されます。
例えば、文字列を UI Slider 参照と共に使用してスライダーの現在の値を抽出し、それをソース値として使用することもできます。
{slider.value}: この例では、slider Local Variable は UI Slider (1) を参照します。Persistent Variables Source がこの値を抽出します。
{slider.value}: スライダーが取得されると、値のプレースホルダーがスライダーの値 (2) を返します。Reflection ソース がこの値を抽出します。
複数の引数
String.Format と同様に、複数のデータソースをパラメーターとして使用できます。インデックス付きプレースホルダーを使用して、インデックス 0 にない任意の値を使用できます。
var localizedString = new LocalizedString("My Table", "My Table Entry");
var dict1 = new Dictionary<string, string>() { { "Name", "John" } };
var dict2 = new Dictionary<string, string>() { { "City", "Washington" } };
localizedString.Arguments = new object[] { dict1, dict2 };
Debug.Log("The value is: " + localizedString.GetLocalizedString());
例えば、localizedString
は、同じ "First dictionary: John, second dictionary: Washington" という文字列を結果として得るために、以下の形式を取ることができます。
ドット表記 | First dictionary: {0.Name}, second dictionary: {1.City} |
ネストされたスコープ | First dictionary: {0:{Name}}, second dictionary: {1:{City}} |
インデックスの指定がない場合は、デフォルトで項目 0 が使用されます。 | First dictionary: {Name}, second dictionary: {1.City} |
スクリプトを表記せずに複数の引数を定義したい場合は、Persistent Variables ソース を参照してください。
ネストとスコープ
Smart String をネストすることで繰り返しを避けることができます。例: {User.Address:{Street}, {City}, {State} {Zip}}
ネスティング (ネスト化) は一般的に Conditional、Plural、List で使用されます。 以下は、Person クラスのインスタンスを引数として使用した場合の例です。
public class Address
{
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string FullName { get; set; }
public string Name => FirstName + " " + LastName;
public DateTime Birthday { get; set; }
public int Age
{
get
{
if (Birthday.Month < DateTime.Now.Month || (Birthday.Month == DateTime.Now.Month && Birthday.Day <= DateTime.Now.Day))
{
return DateTime.Now.Year - Birthday.Year;
}
else
{
return DateTime.Now.Year - 1 - Birthday.Year;
}
}
}
public Address Address { get; set; }
public List<Person> Friends { get; set; }
public int NumberOfFriends => this.Friends.Count;
public Person Spouse { get; set; }
}
ネスティングなし: {User.Name} ({User.Age}) {User.Address.City} {User.Address.State}
ネスティングあり: {User:{Name} ({Age})} {User.Address:{City} {State}}
ここでは、Name と Age は User スコープ内にあり、City と State は User.Address スコープ内にあります。
ネストされたスコープ内で、外部スコープにアクセスできます。例えば、{User.Address:{User.Name} {City} {State}}
という文字列内で、ルートスコープ内にある {User.Name}
は、ネストされた User.Address スコープ内からアクセス可能です。
スコープ内の現在の値を使用するには、空のプレースホルダー {} を使用してください。
Formatter
Formatter (フォーマッター) は、セレクターが返したオブジェクトを文字列に変換します。 フォーマッターは、日付や時刻、リスト、複数形の書式設定だけでなく、条件付きロジックの適用にも使用できます。
特定のフォーマッターを使用するには、フォーマッター名を指定します。名前を指定しなかった場合は、指定された引数とデータの文脈に基づいてフォーマッターが選択されます。 例えば、Plural フォーマッターには 3 つの名前 ("plural"、"p"、"") が含まれています。これは、Plural フォーマッターは "plural" または "p" の名前で明示的に使用でき、名前が指定されていない場合は暗黙的に試行されることを意味します。
明示的使用 | I have {0:plural:1 Apple|{} Apples} |
明示的使用 | I have {0:p:1 Apple|{} Apples} |
暗黙的使用 | I have {0:1 Apple|{} Apples} |
暗黙的フォーマッターはリストの先頭にある最初の項目から下に向かって順に評価されます。フォーマッターの順序によって結果の文字列が変わります。
ほとんどの場合は、明示的フォーマッターの使用が推奨されます (明示的フォーマッターは他のフォーマッターとの競合を回避するため)。ただし、同じ文字列が異なるデータによって駆動される場合、異なるソースとフォーマッターが使用されます。これには暗黙的フォーマッターが必要になります。
FormatterBase クラスから継承して カスタムフォーマッター を作成することもできます。
一部のフォーマッターには、丸括弧内に追加的なオプションの提供が必要です。例えば、{0:choose(1,2,3):one|two|three}
内で提供されているオプションは 1,2,3 です。Choose フォーマッターはこれらを使用して、1、2、3 のどのリテラルテキストを使用するかを決定します。
ローカライズ済み書式設定の
Smart String は、その属するテーブルのロケールを使用して、ローカライズ済み書式設定 (通貨記号、数値の書式設定、日付、時刻など) を適用します。
ロケールの書式設定に関する情報は Locale の Inspector で確認できます。