LibrarySites.Banner

Fallback Series Post 10: Additional Miscellaneous Topics for Multilingual and Language Fallback Implementation

We've come to the final post in my blog series on Language Fallback and using Alex Shyba's Partial Language Fallback Module


In my previous posts, I've gone over strategy for multilingual sites with language fallback, instructions on how to install and configure the Partial Language Fallback Module, using the module to Enforce Language Version Presence and when to do so, customizations that can be made involving that Enforcement, using fallback with the Sitecore Dictionary, using fallback with Advanced Database Crawler, defaulting language version creation for fallback, the Language Migration Tool, and the Language Fallback Report Tool.

 

Now I'd like to discuss a few other things to consider during implementation, including references to other blogs and tools that will definitely aid you in finishing your multilingual and multi-cultural solution.

 

                     i.LinkManager attributes for languageEmbedding and useDisplayName:

<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" lowercaseUrls="true" shortenUrls="true" useDisplayName="true" />

 

  • This LinkManager setting is in the web.config, but may be patched and overridden in other config files, you'll want to make sure you update these attributes in the config that is ultimately used by Sitecore.
  • The languageEmbedding attribute, when set to 'always', will embed the current language into the url when outputting any links to items in the site, between the hostname and the path, eg: www.yoursite.com/en-us/about-us
  • A simple strategy is that if your site is multilingual and you do not have custom hostnames for each language (eg: www.yoursite.de), then set the languageEmbedding attribute to 'always'.  Otherwise set it to 'never'.  'asNeeded' is also an option, but can has unexpected results.
    • NOTE, a limitation to this setting is if you set it for one site in your instance, it is set for all.  That can be a problem if you have a second site that is not multilingual and you don't want the language showing up in the url.  A custom workaround to this is to create a LinkProvider that will check a languageEmbedding property in the Site node.  There is an example of this in my demo.

<linkManager>

      <patch:attribute name="defaultProvider">custom</patch:attribute>

      <providers>

        <clear />

        <add name="custom"

             type="Verndale.SharedSource.SitecoreProviders.CustomLinkProvider, Verndale.SharedSource"

             addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always"

             languageLocation="filePath" lowercaseUrls="true" shortenUrls="true" useDisplayName="true" />

      </providers>

    </linkManager>

  • In the CustomLinkProvider class, it checks to see if a languageEmbedding site attribute is set using the method CheckOverrideLanguageEmbedding in LanguageHelper.cs,  before using the global default one in the LinkManager configuration.  I have to give Aaron Paul credit for this idea.
    • The useDisplayName attribute tells Sitecore to use the Display Name field when rendering the link to the item, instead of the Name field.  You can change this Display Name within different language versions.  This way you can translate the page name into different languages so that the url isn't outputting English words if you are viewing the site through Spanish, for example. If you don’t set Display Name at all, then LinkManager will use Name.
    • The strategy here is based on client preference, is it important to their multilingual users to have the urls translated as well?
  1. Sitecore Setting Media.UploadAsVersionableByDefault

<!--  MEDIA - UPLOAD AS VERSIONABLE AS DEFAULT

            This setting controls if uploaded media is versionable by default or not.

      -->

 <setting name="Media.UploadAsVersionableByDefault" value="false" />

 

  • By default, Media items are not versionable and the above setting is set to false in the web.config.  If you upload an image in one language, it will persist across all language versions.
  • If you change this to true, then versioning will apply and you would have to set the media item into all language versions, or enable fallback, but if enforce version presence is turned on, you'll have to make sure all language versions at least exist.
    • § NOTE: To enable fallback on versioned media items, please remember to go to the /sitecore/templates/system/media/versioned folder and for each template that has fields, click the Enable Fallback ribbon command so that the fields will fallback.
    • I would recommend setting this to true, if you plan on using fallback on your site.
    • The obvious benefit to doing this is you can create a different media item version for every language version of a logo (for example).  You can have the single logo, and just attach different images to each language version.  It could keep the media library a little cleaner, depending on how your content authors are hoping to organize the media library.
    • WARNING 1: caching of images and other media that is done by browsers could prevent different versions in languages from being shown if a user is switching back and forth between languages.
    • This is because, by default, language is not embedded into media urls and so switching between languages would point at the same media url, which many browsers would cache.
    • You could override and extend the GetMediaUrl of the MediaProvider so that it takes the languageEmbedding attribute into consideration.  This method is not only accessible programmatically, but the sc:Image and rich text fields use it to output the media urls.  The demo project implements this and sets the CustomMediaProvider in the Fallback.config file.

<mediaLibrary>

      <mediaProvider>

            <patch:attribute name="type">Verndale.SharedSource.SitecoreProviders.CustomMediaProvider, Verndale.SharedSource</patch:attribute>

      </mediaProvider>

</mediaLibrary>

    • A different way to handle this need would be to have different media items entirely for different languages and then just override the language version of the item that is using the media to reference different media items.
  • WARNING 2: if you are making this update for a site that already has media items added to it, then those media items were probably added as 'Unversioned' media templates

Fallback

  • When this attribute is changed to true, going forward, media items will be added as 'Versioned' media templates.
  • So now you need to determine if and how you can change the media that is already in the system from 'unversioned' to 'versioned' and what repercussions that may have.

                  iii.Determining Sitecore Context Language

                                       ·      A few years ago, John West wrote a blog post about overriding Sitecore's logic for figuring out the context language through which the user is viewing the site.

https://www.sitecore.com/Community/Technical-Blogs/John-West-Sitecore-Blog/Posts/2010/11/Overriding-Sitecores-Logic-to-Determine-the-Context-Language.aspx

  • The gist is that out-of-the-box, Sitecore considers the following logic for determining context, in priority of this order:
  1. The sc_lang query string parameter. (results in session cookie)
  2. The language prefix in the path in the requested URL. (results in session cookie)
  3. The language cookie associated with the context site.
  4. The default language associated with the context logical site.
  5. The DefaultLanguage setting specified in web.config.
  • John's solution describes how to add a custom processor after the ItemResolver.  The Fallback parts are probably unnecessary now considering the Partial Language Fallback Module, but SetCulture and PersistLanguage could be very helpful.
  • You may want to add additional checks like:
  • Consider the browser language preference
  • Default another language if missing (not so necessary with Fallback enabled)
  • Load from a persistent cookie
  • Check authenticated user's preference saved to profile
    • And you may want to add in custom code to set CurrentCulture (for dates, currency and such) based on language of the site, rather than operating system settings.  There is an example of this in my demo.
    • Add another patch in the Fallback.config file's httpRequestBegin pipeline:

<!-- Custom pipeline processor that will set the .net culture based on the current sitecore context language -->

        <processor patch:after="*[@type='Verndale.SharedSource.SitecoreProcessors.ItemLanguageValidation, Verndale.SharedSource']" type="Verndale.SharedSource.SitecoreProcessors.CultureResolver, Verndale.SharedSource" />     

     

  • And then in the CultureResolver code, set the .NET culture based on the Context Language:

System.Threading.Thread.CurrentThread.CurrentUICulture =

                        new System.Globalization.CultureInfo(Sitecore.Context.Language.Name);

System.Threading.Thread.CurrentThread.CurrentCulture =                         System.Globalization.CultureInfo.CreateSpecificCulture(Sitecore.Context.Language.Name);

 

                 iv.Other Cultural Considerations

                                       ·      As mentioned above, the current culture through which .NET is displaying things such as date is important to consider.  You could set it in a processor during httpBeginRequest pipeline.  Or you could set it at the time the user selects the language or when language is loaded from a cookie.  Regardless, you would set it with the above code.

                                       ·      If you don't set it at this global level, you would have to pass in a CultureInfo object for the specific language whenever you are working with something that could differ based on culture (string methods, date methods, currency methods, etc).

System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo(Sitecore.Context.Language.Name));
DateTime dt = DateTime.Parse(date, ci);

And

System.Globalization.CultureInfo CultureInfo ci = new CultureInfo(Sitecore.Context.Language.Name));
amount.ToString("C", ci);

 

                   v.Unsharing the Layout fields

                                       ·      By default, the Layout fields, such as Renderings, are 'Shared' fields.  This means that whatever it is set to in any language or version number is shared across all languages, and presentation cannot be changed based on language version.  You can use conditional rendering and personalization to change out datasources of sublayouts on the page and change visibility of the sublayouts, but otherwise, you are pretty much committed to having the same presentation across languages.

                                       ·      Although I personally have not done this before, you can un-share the Layout fields.  Jan Hebnes discusses doing so for a project here and it is worth reading when considering this strategy:

                                       ·      https://www.sitecore.com/Community/Best-Practice-Blogs/Jan-Hebnes/Posts/2012/09/Unsharing-the-Layout-field-in-Sitecore.aspx

                                       ·      There are pros and cons to doing this and extra customization work that you must put in place.  I have also read that some unexpected results can occur when using fallback with these fields, so be forewarned!

 

                 vi.Conditional Rendering and Personalization by Language

                                       ·      A simpler, less intrusive alternative to unsharing the Layout fields is to setup some rules that can be used in conditional rendering.

                                       ·      First, add a Rule in the Personalization section of the Marketing Center.

Fallback

  • There several filters you can choose from, including 'where the item language compares to value'.

Fallback

  • And many result actions:

Fallback

  • Once the rule is setup, you should make sure that the personalization section is turned on within Controls by going to the sitecore icon and choosing Application Options.
  • Fallback
  • Switch to the View tab and select the 'Show the Personalization Section' in Control properties

Fallback

  • Then when you are  setting the control properties of a sublayout, you will be able select the rule:

Fallback

  • Sitecore will apply the rule upon rendering.

                vii.Security For Languages

                                       ·      There is most likely going to be a need for different content authors to have different access writes to different languages.  It could be that an author in Germany will need to be able to go in and view/translate only the German version of all the pages.  For this reason, Sitecore has two additional permissions that can be set when you are on a language item (in /sitecore/system/languages): Language Read and Language Write.  You could create a German Editor Role that only has access to the German language.  Give that role to anyone who will be editing German content only.

 

Fallback

 

              viii.Translating Content and Tools to help

                                       ·      The whole point of a multilingual site is to have content in other languages.  Content authors could supply their English content to a professional translating service, receive back the content and then manually enter it.  They could have translators on staff who log into sitecore and update the content.  But there are also some tools that integrate seamlessly into Sitecore to aid with this.

      • Clay Tablet

                                                                           ·            https://www.sitecore.com/Partners/Technology-Partners/Clay-Tablet.aspx

                                                                           ·            Per the above link: "You can select one item or all your content and send it out to any translation provider or technology (like Google Translate) instantly. More importantly, translated content is automatically returned into the correct locations in Sitecore, saving more time."

                                                                           ·            This is the Sitecore recommended solution and was co-developed with Sitecore.  It is not free, however. 

                                                                           ·            We recently integrated a client with this and it went well.

                                                                           ·            My colleague Julie Moynihan had this to say about it: Clay tablet is a Sitecore integrated module that provides the ability to send items to an external system/ vendor for translation.  Translation can be batched and multiple types of translation (machine, human) or multiple vendors.  The items are placed into a workflow and sent through the Clay tablet system to the translation vendor.  Clay tablet works with the translation vendor regarding integration with their software.  Items are then returned through Sitecore and placed back into workflow.

      • Item Translator: Sitecore Marketplace Module

                                                                           ·            http://marketplace.sitecore.net/en/Modules/Item_Translator.aspx

                                                                           ·            I haven't used this myself, however it seems pretty cool.  It leverages the Google translate functionality.  The content author will click a button and it will translate the content.  Granted, Google translate is not perfect, but it could be a good starting point (and it's free).

 

                 ix.Custom Language Registration

                                       ·      My coworker Summit Phadke recommended that I include the following information since he had to implement this for one of our clients as well.

                                       ·      When you add a new language to Sitecore, in /sitcore/system/language, it allows you to either choose from a pre-defined language culture, or you can enter your own.  If you decide to enter your own, you can specify the code for Language and optionally a code for Culture

                                       ·      At this point you decide you want a language specifically for German in the United State, so you enter 'de' and 'US' in the language and Culture code fields.

      • Or maybe you want to make up a culture that represents a region, eg: 're' for the language, meaning region, and 'Asia' for the culture.

                                       ·      You submit and are presented with a message telling you that it is not a valid option

Fallback

  • The problem is that Sitecore is limited to using what the .NET framework already has registered on the server/computer you are running the site on.
  • Therefore, you must register the new custom language on the server/computer first.
  • WARNING: This will need to be done on ALL servers that this application will ever live on, and must be considered when deciding if you indeed want to use a custom language/culture.  Will you want to do that or even be able to do that?
  • ADDITIONALLY, if you use custom cultures, you will need to tweak any code that you may have written to set the culture within the application (see Other Cultural Considerations above).  .NET won't know how to format text, currency, dates, etc if the culture is custom, so you'll need to figure out a way to default it to something else.
    • If you decide this is something you want to do, then there is a Sitecore Marketplace tool for this:
    • It contains an exe file (and the source code) for a windows app
    • You run the exe file and it will open the app:
    • You can pick from pre-defined languages or set everything custom, including Names, ISO, Region Info, and Currency Info
    • Finally click Register
    • You also have the option to Unregister
    • Fallback

 

 

This brings me to the end of my blog series on Partial Language Fallback in conjunction with multilingual strategy in Sitecore websites.  I hope that after reading through all the posts, you have a comprehensive understanding of how Alex Shyba's Partial Language Fallback Module should be installed and configured, what to consider when deciding to enforce language version presence, and additional updates to ensure fallback works with the dictionary and Advanced Database Crawler.  And now at your disposal are several tools to make it easier to work with multilingual sites using fallback, including the Language Migration Tool and Language Fallback Report Tool.

 

Link to Resources:

https://github.com/Verndale-Corp/Sitecore-Misc-Multilingual

https://github.com/Verndale-Corp/Sitecore-Fallback-FullDemo

 

  • Hi Elizabeth,  first of all, thank you for this very helpful post. But in my opinion, one detail is missing in a multilingual solution. Above you described two important config changes: languageEmbedding="always" and useDisplayName="true" With these attributes, we are able to create language specific url's like <host>/en-us/company or <host>/es-es/empresa With Alex Shyba's FallbackProvider, it is possible to render pages with no content, if they have a fallback to a language with content, e.g. /en-ca has a fallback to /en-us. Now, the attribute "useDisplayNames" will not be used, because en-ca has no value in "__DisplayName"-field and the fallback of en-us is not used. This ends up in different urls for /en-ca and /en-us.  I hope, you understand my explanations. Do you have any idea, how to solve this issue?  Thanks in advance and best regards Fabian

  • To be honest, we don't often use the Display Name, so although I would have thought theoretically it should function as expected, I can't speak to the specific issue.  For sure if we run into an answer, I will post it here.