This is post 4 of 5 in a series titled Patterns for navigation controls
- Patterns for navigation controls - Basics
- Patterns for navigation controls - Breadcrumbs
- Patterns for navigation controls - Varied styles
- Patterns for navigation controls - Language versions
- Patterns for navigation controls - Language trees
I was going to stop at three posts on simple patterns for navigation (Parts one,two and three are here) – but earlier this week I realised I'd not covered an important topic in navigation for Sitecore-based websites: How you can navigate between different language versions of your sites and pages. So this week, I'll start looking at language navigation.
There are two common patterns for how you might structure your content in Sitecore if you have a multi-lingual site. Depending on what sort of content you're dealing with, you might choose to:
(Technically, there's also a third option, where you have multiple content trees which may also have multiple languages – but that's just a combination of the two ideas I'll present)
The core navigation controls for these sites work in exactly the same way as the ideas I've presented in previous posts. But if you have multiple languages, then you need some code to display links to let the users swap between languages. And you need slightly different code for these two scenarios. So this week I'll look at the first of these:
To achieve this we need to provide a set of links for the different language versions of the context page. There is a
Languages
property on each Sitecore
Item
which gives you a list of the languages themselves, but this doesn't give you the content for the different versions. Also an
Item
can have zero versions in a language - so we need to filter the data to make sure we don't show a link to an unpublished or missing language version.
The code for this is fairly simple. Starting with some very basic mark-up:
<asp:Repeater runat="server" ID="languageRepeater"> <HeaderTemplate><ul></HeaderTemplate> <ItemTemplate> <li> <asp:HyperLink runat="server" id="languageLink" /> </li> </ItemTemplate> <FooterTemplate></ul></FooterTemplate> </asp:Repeater>
And adding some code-behind:
protected void Page_Load(object sender, EventArgs e) { languageRepeater.DataSource = Sitecore.Context.Item.Languages; languageRepeater.ItemDataBound += languageRepeater_ItemDataBound; languageRepeater.DataBind(); } private void languageRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { if(e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item) { var languageLink = e.Item.FindControl("languageLink") as HyperLink; var language = e.Item.DataItem as Language; var options = new Sitecore.Links.UrlOptions{ LanguageEmbedding=Sitecore.Links.LanguageEmbedding.Always, Language = language }; var itm = Sitecore.Context.Database.GetItem(Sitecore.Context.Item.ID, language); if(itm.Versions.Count > 0) { languageLink.Text = itm.DisplayName; languageLink.NavigateUrl = Sitecore.Links.LinkManager.GetItemUrl(itm, options); } else { e.Item.Visible = false; } } }
The data source for our repeater is the list of
Languages
that Sitecore has recorded for the current page. When each of those languages gets processed we need to find the right data to display.
For each language, having grabbed references to the link we plan to display and to the language that the repeater has passed us, we construct a
UrlOptions
object. This is used to customise the generation of links to our page in a minute: we need to ensure that the language data we're processing is added to the URL.
Then the code reloads the context item in our current language. This ensures we have the data for the correct language version of the item for processing. With this loaded, we test to see if the number of versions the
Item
object holds is greater than zero. If there are none then we don't want to show a link to this language – the appropriate data hasn't been created or published. In this case we hide the repeater item from view. But if we do have a version then we can bind the
DisplayName
and the url (generated with our options) to our link.
DisplayName
is a good choice for what to display because it's a field you can translate – but you might choose to use another field if you have specific "navigation title" data in your site's schema.
If we create an item which has these versions:
Then the result of running this code is to generate: (Please excuse my Google Translated page titles – chances are they make no sense if you speak Japanese or German – sorry...)
Note that the "English UK" language which is present in the Languages drop-down is not shown in the navigation data – since it has no version to display.
Hovering over or clicking those links will reveal a URL in the format:
http://test/ja-JP/NavigationPage
By passing the language data to the
LinkManager
when generating the URL, the data describing which language to show has been included in the URL. This is not the only way that language data can be inserted into the URL however. It can also be added to the
sc_lang
querystring parameter if preferred - though that seems less useful from an SEO perspective to me.
Note that the url is using the
Name
of the item by default - which is not a translated value. Hence the Japanese link has an English page name in it. It is possible to translate the URLs themselves by enabling the configuration property for "use display names in URLs".
So with the basic logic described here you can create a component that matches the look and feel of your site.
Next week, I'll look at an approach to navigation between separate content trees for languages.
↑ Back to top