前回は Navigation コンポーネントで表示をする URL に関して、ロケールを入れた URL を利用してリンクを張る手順を紹介しました。実は多言語でデータを持っているときのナビゲーションに関して、もう少し課題を見ていきます。
各言語ごとのメニューとして
アイテムが常にすべての言語に対してデータを持っていない場合、Sitecore にデータを問い合わせをした場合、以下のような動作をします。
- 日本語のみのアイテムの場合、Display name としてアイテムの Standard Value となる $name が返ってくる
- 英語のみのアイテムの場合、そのアイテムの Display name が返ってくる
まずベースとして、英語と日本語のデータが設定されているツリーを用意します。
これに対して、英語のみのアイテム、日本語のみのアイテムを用意します。以下が英語のみのアイテムです。
続いて Global Menu 3 の下に日本語のみのアイテムを用意します。
この状態で Navigation コンポーネントを配置するとどのような表示になるでしょうか?まず英語で表示をさせると以下のようになります。
続いて日本語に切り替えてると、以下のようになります。
Postman を利用してデータの確認
今回は Postman を利用してデータがどのように返ってきているのかを確認します。今回は Home アイテムの ID を利用して、そのアイテムの2つ下のアイテムを取得していきます。
query Item {
item(language: "en", path: "{819432C0-EFF5-4D0D-82E4-50CD4782F948}") {
displayName
id
name
path
rendered
version
children(hasLayout: true) {
total
results {
displayName
hasChildren
id
name
path
rendered
version
children(hasLayout: true) {
total
results {
displayName
hasChildren
id
name
path
rendered
version
}
}
}
}
}
}
上記の問い合わせは英語のコンテンツを取得するようにしています。例えば、Sub Menu 1-1 のアイテムの場合、以下のような結果が返ってきています。
{
"Id": "376ed8b8-5e97-4390-8d1f-319fb4671a3e",
"Styles": [
"level2",
"item0",
"odd",
"first"
],
"Href": "/Global-Menu-1/Sub-Menu-1-1",
"Querystring": "",
"NavigationTitle": {
"value": "Sub Menu 1-1",
"editable": "Sub Menu 1-1"
}
}
これに対して、Japanese Menu に関しては英語で問い合わせをすると以下のデータが返ってきます。
{
"Id": "c1b7a744-b502-4b7a-81d6-f668cc4ad640",
"Styles": [
"level2",
"item0",
"odd",
"first",
"last"
],
"Href": "/Global-Menu-3/Japanese-Menu",
"Querystring": "",
"NavigationTitle": {
"value": "$name",
"editable": "$name"
}
}
アイテムとして持っていない状況ですが、アイテムの Standard Value として定義されている $name が返ってくる形となっています。このため、日本語のみのアイテムに対して、英語のナビゲーションには $name のメニューが表示される形です。
今度は ja-JP に切り替えてデータを取得してみます。
{
"Id": "7b4cc476-bdec-4313-980f-13aa693df651",
"Styles": [
"level1",
"item3",
"even",
"last"
],
"Href": "/English-Menu",
"Querystring": "",
"DisplayName": "English Menu"
}
アイテムの英語の情報を取得する形となっています。これにより日本語のメニューでは English Menu が表示されるようになっています。
解決方法
Navigation コンポーネントのコードを確認しにいくと、アイテムの名前を取得するための関数が以下のように定義されています。
const getNavigationText = function (props: NavigationProps): JSX.Element | string {
let text;
if (props.fields.NavigationTitle) {
text = <Text field={props.fields.NavigationTitle} />;
} else if (props.fields.Title) {
text = <Text field={props.fields.Title} />;
} else {
text = props.fields.DisplayName;
}
return text;
};
このコードは、アイテムの text として NavigationTitle があればその値を、ページの Title があればその項目を、それ以外は DisplayName を表示するようにしています。これにより設定が不足している場合でもアイテムがメニューに表示されるようになります。
今回は NavigationTile が有効であれば表示する、ただし NavigationTitle に値が含まれていない、もしくは $name になっている場合は表示しない、という形に書き換えます。
この処理は NavigationList の関数で、return の前に以下の行を追加してください。
if (!props.fields.NavigationTitle) {
return null;
}
if (props.fields.NavigationTitle.value === '$name') {
return null;
}
結果として、まず英語のメニューに対して $name が表示されないようになりました。
続いて日本語の表示の時に English Menu が表示されない形となりました。
まとめ
標準の Navigation コンポーネントを変更して、言語として持っている NavigationTitle があるときのみ表示するように書き換えました。これにより、コンテンツのツリーとして英語のみ、日本語のみという形でアイテムを持ってそれぞれメニューを自動的に表示することが可能となります。