Page tree
Skip to end of metadata
Go to start of metadata

A language switcher link is a common feature on multi-language sites. At present Magnolia CMS does not come with an out-of-the box solution. There are however a number of approaches that you can take to implementing this feature:

  • Create a new component containing a sub-component with a link list.
  • Implement a code based and static solution, which is the approach that we look at here.

This tutorial should be read in conjunction with: http://documentation.magnolia-cms.com/technical-guide/i18n.html

See also

Error rendering macro 'jira'

Unable to locate Jira server for this macro. It may be due to Application Link configuration.

This tutorial provides step-by-step instructions on how to create a language switching link

  • using the tempting function in Admin Central, and by 
  • adding the required code to the script.

Code based (static) solution

The simplest way to create a language switcher is to repeat the following procedure per language required:

  1. Go to Templating Kit/Templates/templating-kit/pages/global/metaNavigation 
  2. Open the script.
  3. After the list close tag (</ul>) insert the following:
[#assign localizedLinks=model.localizedLinks!]
[#list localizedLinks?keys as lang]
  <li><a href="${localizedLinks[lang]}">${lang}</a></li>
[/#list]
  1. skip
  2. skip
  3. skip
  4. Select the Enable template checkbox and save.

Magnolia CMS 4.4

If you are working with Magnolia CMS 4.4, add the following methods to templates/component/model:

public Map<String, String> getLocalizedLinks() {
        final STKTemplateModel pageModel = (STKTemplateModel) getRoot();
        final Site site = pageModel.getSite();
        final I18nContentSupport i18n = site.getI18n();

        final Content currentPage = pageModel.getContent();
        if (i18n.isEnabled() &amp;&amp; i18n.getLocales().size() > 1) {
            Map<String, String> map = new HashMap<String, String>();
            for (Locale locale : i18n.getLocales()) {
                String uri = createURI(i18n, currentPage, locale);
                String label = StringUtils.capitalize(locale.getDisplayName(locale));
                map.put(label, uri);
            }

            return map;
        } else {
            return Collections.emptyMap();
        }
    }

    protected String createURI(I18nContentSupport i18nContentSupport, Content currentPage, Locale locale) {
        // we are going to change the context language, this is ugly but is safe
        // as only the current Thread is modified
        final Locale currentLocale = i18nContentSupport.getLocale();
        String uri = null;
        try {
            // this is going to set the local in the aggregation state and hence
            // wont change the i18nSupport object itself
            i18nContentSupport.setLocale(locale);
            uri = LinkUtil.createAbsoluteLink(currentPage);
        }
        // make sure that we always reset to the original locale
        finally {
            i18nContentSupport.setLocale(currentLocale);
        }
        return uri;
    }

Magnolia CMS 4.5

If you are using Magnolia CMS 4.5, add the the following methods to templates/component/model:

public Map<String, String> getLocalizedLinks() throws RepositoryException {
        final STKPageModel pageModel = (STKPageModel) getRoot();
        final Site site = pageModel.getSite();
        final I18nContentSupport i18n = site.getI18n();

        final String ident = pageModel.getContent().getJCRNode().getIdentifier();
        if (i18n.isEnabled() &amp;&amp; i18n.getLocales().size() > 1) {
            Map<String, String> map = new HashMap<String, String>();
            for (Locale locale : i18n.getLocales()) {
                String uri = createURI(i18n, ident, locale);
                String label = locale.getLanguage(); // full name of the language StringUtils.capitalize(locale.getDisplayName(locale));
                map.put(label, uri);
            }

            return map;
        } else {
             return Collections.emptyMap();
        }
    }

    protected String createURI(I18nContentSupport i18nContentSupport, String ident, Locale locale) {
        // we are going to change the context language, this is ugly but is safe
        // as only the current Thread is modified
        final Locale currentLocale = i18nContentSupport.getLocale();
        String uri = null;	
        try {
            // this is going to set the local in the aggregation state and hence
            // wont change the i18nSupport object itself
            i18nContentSupport.setLocale(locale);
            uri = LinkUtil.createAbsoluteLink(RepositoryConstants.WEBSITE, ident);
        } catch (RepositoryException e) {
			e.printStackTrace();
		}
        // make sure that we always reset to the original locale
        finally {
            i18nContentSupport.setLocale(currentLocale);
        }
        return uri;
    }
  • No labels

2 Comments

  1. Should be also the system local be set?

    ...
    uri = LinkUtil.createAbsoluteLink(currentPage);

    //Setting the system language
    MgnlContext.getAggregationState().setLocale(locale);
    ....

    When using ${i18n['some.key']} it will use the systems fallbackLocal because its not i18n content support.
    The fallbackLocal in the site definition is only relevant for the content support.
    I had in a project, that when the system local was not set to the same as the local used for the content support, if fell back to 'en' from the system fallbackLocal. But the project only providing de and fr messages files -> unresolved static messages.

  2. Hello,

    Is there a current example for Magnolia 5.4?
    Would it be possible to design a language switcher a bit more involve that the one at:
    https://documentation.magnolia-cms.com/display/DOCS/cmsfn
    Mainly to display the full name of the locale.

    Thanks.