Back to the blog
  • May 10, 2022
  • 7 MIN
Category Tech
Internationalize SPAs 1200x628
Internationalizing Template Labels In SPAs

Internationalizing Template Labels In SPAs

Internationalization is a key feature when looking for a headless CMS that must handle more than one language version of a website. In the majority of projects, we can distinguish between two groups of translatable text:

  • Editorial content makes for the majority of translatable text. It is the main content on your website created to appeal to and educate your target audience.

  • Template labels are text that is displayed to visitors but it is not editorial content and cannot be changed by content authors. Examples of labels are page breadcrumb labels such as “You are here” and static button text in specific components such as “Login” or “Logout”.

Internationalizing editorial content for headless consumption in Magnolia is very easy. I covered this topic under “Localized content” in my blog Headless Magnolia: The Delivery Endpoint API.

But what about translating template labels in headless Magnolia? In this blog post, I will show you one possible solution using a content app to store translations. Think of it as a digital vocabulary book.

New Content Type

Magnolia Content Types define the content model in Magnolia. Content authors can edit this content in content apps. So, let’s create a Content Type and a content app.

Start by creating a new Magnolia Light Module directory “i18n-lm”.

Once our new Light Module is in place, define a new Content Type “i18n”.

File: /i18n-lm/contentTypes/i18n.yaml

  datasource:  workspace: i18n  autoCreate: true model:  properties:    - name: name      required: true    - name: value      i18n: true  

We will store the data in a new workspace called “i18n”. The content model will have two properties:

  • name - the name of the property. Let’s make this required.

  • value - translation text. This property has to have internationalization (i18n) enabled.

Once you created the new Content Type, let Magnolia create a Content App called “i18n” for it.

File: /i18n-lm/apps/i18n-app.yaml

  !content-type:i18n name: i18n-app label: i18n icon: icon-forums-app subApps:  browser:    workbench:      contentViews:        tree:          columns: !override            name:              $type: jcrTitleColumn              expandRatio: 1            value:              expandRatio: 1            activationStatus:              $type: jcrStatusColumn              width: 200  

You should now see the new app in Magnolia:


Adding Translations

You can now add translations.

I recommend you create a folder first and add translations inside the folder. That way you can group translations by pages.


When adding content in the app you can see the language switcher in the bottom-left corner.


The languages you see in this list are taken from the default (fallback) language settings in your site definition.

Fetching Data

To fetch the correct translations you can use the Magnolia Delivery API. Create its endpoint first:

File: /i18n-lm/restEndpoints/delivery/i18n.yaml

  workspace: i18n bypassWorkspaceAcls: true limit: 1000 depth: 10 nodeTypes:  - mgnl:folder childNodeTypes:  - mgnl:content  

You can now fetch translations in the default locale via /.rest/delivery/i18n/my-page:

  {  "@name": "my-page",  "@path": "/my-page",  "@id": "100ceaa5-3ee4-47d7-9b8d-621423ef45fd",  "@nodeType": "mgnl:folder",  "name": "my-page",  "foo": {    "@name": "foo",    "@path": "/my-page/foo",    "@id": "135c4be1-3358-4d9b-a566-4a7c40a92261",    "@nodeType": "mgnl:content",    "value": "Hey",    "name": "foo",    "@nodes": []  },  "bar": {    "@name": "bar",    "@path": "/my-page/bar",    "@id": "e85104ac-188a-4a5a-bed8-42abb60ab9ee",    "@nodeType": "mgnl:content",    "value": "Bye",    "name": "bar",    "@nodes": []  },  "@nodes": [    "foo",    "bar"  ] }  

If you want translations in another language, use the URL parameter lang, for example, “de” for German:


You can use your translations in your app, for example, as an object:

  const i18n = response['@nodes'].reduce((acc, item) => {  acc[item] = response[item].value;  return acc; }, {});  

If you need a specific translation you can simply reference the key:


Auto-translating Labels

We can speed up the global rollout through automatically translating all data in the content app using the DeepL Translator from the Magnolia Marketplace.

Once the module is installed, you have to add a new action to your app:

File: /i18n-lm/apps/i18n-app.yaml

  !content-type:i18n name: i18n-app label: i18n icon: icon-forums-app subApps:  browser:    workbench:      contentViews:        tree:          columns: !override            name:              $type: jcrTitleColumn              expandRatio: 1            value:              expandRatio: 1            activationStatus:              $type: jcrStatusColumn              width: 200    actionbar:      sections:        folder:          groups:            activationActions:              items:                publishRecursive: {}            i18n:              items:                addToTranslationBatch: {}        item:          groups:            activationActions:              items:                publishRecursive: {}            i18n:              items:                addToTranslationBatch: {}    actions:      # Publishes the selected node and its children to the public instance      publishRecursive:        icon: icon-publish-incl-sub        $type: jcrCommandAction        command: publish        asynchronous: true        params:          recursive: true        availability:          writePermissionRequired: true          rules:            isDeletedRule:              $type: jcrIsDeletedRule              negate: true            publishableRule:              $type: jcrPublishableRule      # DeepL Translator module action      addToTranslationBatch:        label: Add to translation batch        dialogName: content-translation-support-ext-core:addToTranslationBatch        icon: icon-add-folder        class:$Definition        availability:          writePermissionRequired: true          access:            roles:              superuser: superuser          nodeTypes:            folder: mgnl:folder            content: mgnl:content          rules:            notDeleted:              $type: jcrIsDeletedRule              negate: true          multiple: true          root: false  

Git Repo

By creating a simple Content Type and content app you can enable your content authors to manage the translation of labels. If you want to implement this solution yourself, you can find the code examples on Git.

About the Author

Bartosz Staryga Front-End Solution Architect at Magnolia

Bartosz is an expert in headless content management and front-end development at Magnolia. He designs and develops new Magnolia features and supports customers with their headless implementations from content types to APIs to integrations. Bartosz enjoys building new things and seeing them in action. He is also a trainer for Magnolia’s Headless training.

Read more