Tailwind Logo

Adjusting the sxastarter sample for use on multilingual sites - Part 1-2 Navigation Part 2

XM CloudHeadless SXA

Published: 2024-09-13

In the last issue, we introduced the procedure for linking URLs that are displayed in the Navigation component, using URLs that include locales. In fact, we will look at a few more issues related to navigation when you have data in multiple languages.

As a menu for each language

If an item does not always have data for all languages, querying Sitecore for data will behave as follows

  • If the item is only in Japanese, $name, which is the Standard Value of the item, is returned as the Display name.
  • For English-only items, the item's Display name is returned.

First, a tree with English and Japanese data is prepared as a base.

xmcaddlanguage03.png

In contrast, we will provide English-only items and Japanese-only items. The following are English-only items.

xmcaddlanguage04.png

Next, prepare a Japanese-only item under Global Menu 3.

xmcaddlanguage05.png

What would the display look like if the Navigation component were placed in this state? First of all, if you display it in English, it will look like this.

xmcaddlanguage06.png

Switching to Japanese, the following is displayed.

xmcaddlanguage07.png

Checking data using Postman

This time we will use Postman to see how the data is returned. This time we will use the ID of the Home item to retrieve the two items below it.

GraphQL
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
                    }
                }
            }
        }
    }
}

The above query is designed to retrieve English content. For example, for items in Sub Menu 1-1, the following results are returned

JSON
{
   "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"
    }
}

On the other hand, the following data is returned when the Japanese Menu is queried in English.

JSON
{
   "Id": "c1b7a744-b502-4b7a-81d6-f668cc4ad640",
    "Styles": [
        "level2",
        "item0",
        "odd",
        "first",
        "last"
    ],
    "Href": "/Global-Menu-3/Japanese-Menu",
    "Querystring": "",
    "NavigationTitle": {
        "value": "$name",
        "editable": "$name"
    }
}

The $name defined as the Standard Value of the item is returned, even though the item is not owned by the user. Therefore, the $name menu will be displayed in the English navigation for Japanese-only items.

Now let's switch to ja-JP and try to retrieve the data.

JSON
{
    "Id": "7b4cc476-bdec-4313-980f-13aa693df651",
    "Styles": [
        "level1",
        "item3",
        "even",
        "last"
    ],
    "Href": "/English-Menu",
    "Querystring": "",
    "DisplayName": "English Menu"
}

The English information of the item is retrieved from the item's English menu. This allows the English Menu to be displayed in the Japanese menu.

Solution

If you go to check the code of the Navigation component, you will see that the function to get the name of the item is defined as follows

TypeScript
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;
};

This code displays the item's text as NavigationTitle if it has one, the page's Title if it has one, and DisplayName otherwise. This ensures that the item will be displayed in the menu even if settings are missing.

This time, rewrite NavigationTile to display if it is valid, but not if NavigationTitle does not contain a value or is set to $name.

This process is a function of NavigationList, and the following line should be added before return.

TypeScript
  if (!props.fields.NavigationTitle) {
    return null;
  }

  if (props.fields.NavigationTitle.value === '$name') {
    return null;
  }

As a result, $name is no longer displayed for English menus first.

xmcaddlanguage08.png

The English Menu is no longer displayed when Japanese is displayed.

xmcaddlanguage09.png

Summary

The standard Navigation component has been modified and rewritten to display only when there is a NavigationTitle that has it as a language. This allows the menu to automatically display each item as a tree of content, with English-only and Japanese-only items.

Tags