Dictionary service in Sitecore NextJS


Multi-market and multi-language capabilities is important in the Enterprise and have always been a very strong capability in Sitecore CMS. This have been formalized a bit since the introduction of Sitecore Experience Accelerator (SXA) and Sitecore Javascript Services (JSS) to support headless development.

We now have a dedicated place and templates for Dictionary items in the Sitecore site structure, and it is backend with a dedicated Dictionary Api1 in the Headless Services and an implementation in the @sitecore/jss npm packages

Sitecore CMS Site structure with Dictionary item

When to use Dictionary service

I see implementations where I find that the dictionary is used way too much. Don’t get it wrong, the dictionary is the right place for small texts/labels that are used across the site and allows easy and central editing and translating those texts.

However, when adding a text in a component, please make the consideration if the text is really “generic” and should be translated with a dictionary item or if we create a better website experience by have a more specific text. Eg. when creating a list of items (carousel, list, etc.) we create a better experience for all users, improve SEO and accessibility by have a specific “click here to see all news” instead of a generic “See all” dictionary label.

It might be that you can help the editors by having a generic fallback text as a dictionary item, but allow the editor to override with a specific text in the specific location.

NextJS implementation

When implementing you headless site in NextJS, there are implementation to support this. In @sitecore-jss/sitecore-jss-nextjs there is a dictionary service implementation for both REST and GraphQL and the head template has DictionaryServiceFactory implementation.

Implementation of Dictionary Service Factory, from the foundation head template

This dictionary service is used in the PageProps factory implementation (actually a plugin) to set the page property called dictionary with all of those dictionary values.

Hereby you can actually use any NextJS localization library you want to get the translations. Again there is a full implementation in the head template by using next-localization and initialized in _app.tsx so in any component you can get a label by using this library, eg.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { useI18n } from 'next-localization';

export const SearchList = (props: SearchListProps): JSX.Element => {
  const { t } = useI18n();
  const [keyphrase, setKeyphrase] = useState('');
  const title =
    keyphrase.trim() !== ''
      ? t('search-result-for', { query: keyphrase })
      : props.fields?.Title?.value?.toString();
}

When to specify

Ok, we prefer to use the GraphQL service. I was struggling on one of our solutions that we had to specify the rootItemId in dictionary-service-factory.ts.

By looking a bit to the logs I can see that the dictionary service is making this request to find the site root:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
query AppRootQuery($jssAppTemplateId: String! = "061cba1554744b918a0617903b102b82", $siteName: String!, $language: String!) {
  layout(site: $siteName, routePath: "/", language: $language) {
    homePage: item {
      id
      rootItem: ancestors(includeTemplateIDs: [$jssAppTemplateId]) {
        id
      }
    }
  }
}

This means that it is very important that the template of your headless site is inheriting from this specific template, which is /sitecore/templates/Foundation/JavaScript Services/App.

We had our site template generated and placed in /sitecore/templates/Project/<tenant>/Headless Site, which is fine, but it didn’t inherit the App!

Base templates of tenant specific Headless Site template

So adding this base template and now we can remove the rootItemId and fully support multi sites.