Tridion Language Switcher

language-switcherSDL Tridion is known for its superior capabilities when it comes to managing multi-lingual websites, and such websites typically have a some kind of a switch to allow switching between languages.  In this article I’ll attempt to explain the concept of setting the Publication Context and how to use Tridion’s Dynamic Linking to allow us not only switch from a site in one language to another, but to do it for any given page on the site.

Language switchers come in all shapes and sizes, from the most basic hyperlinks to dropdowns to fancy maps.  Some sites may even detect your IP and automatically send the user to the most apporiate local website.

There are a number of approaches to implement such functionality.  One way is to implement a redirect (or a direct hyperlink) which always sends the user to the homepage on the target language site.  This is fairly straight forward.  If we’re on the .com site and the user selects “Canada” as the country, we send him to the .ca website… Boring.

What isn’t boring is maintaining the page that the user is currently on while giving the options to view it another language/locale. Some may say, “what’s the big deal? Just switch the language fragment part of the URL and redirect”.  This might work for a minute, but could get us into trouble down the road.  Let’s explore this for a minute.

For instance, in Tridion we typically specify the Publication URL property on the Publication as follows:

publication_url

When we publish pages this will yield URLs in this format:

http://www.johnwinterhascooties.com/en-ca/index.jsp
http://www.johnwinterhascooties.com/en-ca/about-us/index.jsp
… and etc.

So when we want to switch to a different locale, we might be tempted to do some string manipulation on the URL and do a redirect.  For example, to switch from Canadian English to French, we could do something like this:

String urlEn = request.getRequestURL().toString();
String urlFr = url.replace("/en-ca/", "/fr-ca/");
response.redirect(urlFr);

If we have domain-level configurations to have a country-specific domain (e.g: http://www.johnwinterhascooties.ca/index.jsp or http://www.johnwinterhascooties.ca/about-us/index.jsp) then our logic will need to take care of swapping the domains.

What if the page at the same relative URL isn’t available in the target language?

What if you have a requirement where URLs need to be translated or localized?

In such cases our url manipulation approach simply won’t do.  The good news is that to solve the problem we can (and should) leverage:

  1. The Tridion Blueprint
  2. Tridion’s Dynamic Linking

This will help ensure that we always get the true URL if it is available, and easily let us treat the scenario when the local URL isn’t available.

At a high level, all we need to do is implement the following steps:

  1. Leverage the power of Blueprinting – local websites should inherit from a default Website Master Publication in our Tridion Blueprint (the classic Blueprint). 
  2. Make your page templates render the TCM ID of each page.  E.g.: add this scriptlet at the top of each of your DWT page templates to set the TCM ID into Request-level scope:
  3. Get the context to our target language publication from our app’s config file.
  4. Switch the context publication of the TCMURI in the request.
  5. Retrieve the dynamic Page Link URL within that context.

Now, let’s dive into the details.

1. Leverage the power of Blueprinting

Local websites should inherit from a default Website Master Publication in our Tridion Blueprint.  This way pages are created only once in the default language and all the loacal websites simply inherit them and serve localized content.  Here is a classic Tridion Blueprint diagram.

classic-blueprint

2. Make your page templates render the TCM ID of each page

First thing we need to know is the page that we’re on with respect to Tridion.  So what we need is the page’s TCM ID.  To make this available on the Content Delivery side, we simply bake it into our pages at publish time by having our Page Templates render it.

All we need to do is throw a basic scriptlet near the top of each Page Template’s DWT (or whatever CM-side layout rendering mechanism you use).

<%
    // this is java, but .NET should be pretty much the same (mind the namespace)
// Also note the @@Page.ID@@. This is Tridion DWT syntax to inject the Page ID within a DWT TBB.     com.tridion.util.TCMURI pageID = 
            new com.tridion.util.TCMURI("@@Page.ID@@"); 
    request.setAttribute("pageID", pageID);
%>

Now our request object has the page ID so we know where we are in the context of Tridion.  The next step is to get the ID of the target language publication.

3. Get the context to our target language publication

If you study the Tridion Content Delivery API, you’ll notice that many constructors take the publication ID as a parameter.  This is to set the context in which you’ll be operating in. We need to maintain the mapping of each publication name to its ID in a configuration file. If Java then we normally use a Properties file.  If .NET, then web.configs are often most appropriate.

A typical config (Java Properties) file might look like this:

PUB_ID_EN_CA = 1;
PUB_ID_EN_US = 2;
PUB_ID_FR_FR = 3;
PUB_ID_IT = 4;
... and so on.

4. Switch the context publication of the TCMURI in the request

So now we have the TCM URI of our current page.  We also have the publication ID of the language publication that we want to switch to.  We can now simply switch the context:

//Repeat the following for each language your site supports
// You may want to fetch all properties that begin with common prefix.  
// I'll leave that up to you to implement.

 //todo: use a Constants file for the PUB_ID_* variables.
int targetLanguagePubID = Integer.parseInt(myProperties.getProperty("PUB_ID_FR_FR"));
TCMURI currentPageTcmUri = (TCMURI)request.getAttribute("PageID");

//create the TCM URI object for the page in the language we want to switch to.
TCMURI targetPageTcmUri = new TCMURI(targetLanguagePubID,
currentPageTcmUri.getItemId(),
currentPageTcmUri.getItemType(),
currentPageTcmUri.getVersion());

Now we are almost ready to get the link.

5. Retrieve the dynamic Page Link URL within that context

PageLink pageLink = new PageLink(targetPageTcmUri.getPublicationId());
Link link = pageLink.getLink(targetPageTcmUri.getItemId());
String targetLanguageUrl = link.getURL();

Presto!  Of course you will need to add some logic to handle nulls, i.e. if the link.getUrl() doesn’t resolve, i.e. if the page in the target language is not available/not published.  This should be fairly straight forward.  Either don’t render the link or send the user to the target language’s home page.

Happy coding!

4 thoughts on “Tridion Language Switcher

  1. Nice usage there Nick. Is there anything to consider regarding blueprinting? e.g. best suited to a blueprinting structure where all child language sites inherit pages from a common parent publication.
    I’d imagine this must be the case in order for the page TCM ids to match.

  2. Good stuff – this is the best application of cross-publication linking I have seen. Its worth pointing out that all of your sites should be using the same storage configuration, so that the linking info is available across all different sites.
    Its also perhaps a good idea to only resolve the links when needed, as if you have 23 languages and the language selector on each page you are doing a 23 link resolutions each page render, just on the off chance that someone wants to switch language…

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>