LibrarySites.Banner

Fallback Series Post 2: How to Install and Configure Alex Shyba's Partial Language Fallback Module

As I mentioned in my first post in this blog series, the basis of this is Alex Shyba's Partial Language Fallback Module.  Note that there are two different approaches in this location, you want to download Alex's Partial Language Fallback module.

Like other shared source modules, it's smart to keep the source code somewhere so you can switch the references to specific versions of Sitecore.Client, Sitecore.Kernel, etc.  That way you can build it for your specific site's Sitecore version and avoid conflicts.

Not only is the code provided in the zip, but you can find the package that needs to be installed in /data/packages/.

The package contains the following files:

  • Sitecore.SharedSource.PartialLanguageFallback.config, which will go into App_Config/Include and contains patches, references and configurations needed for fallback to work.  The config file in the package is out-of-date.  You should copy it from the source code within Sitecore.SharedSource.PartialLanguageFallback\App_Config\Include folder and overwrite the one in your project that the package installed.
  • Sitecore.SharedSource.PartialLanguageFallback.dll, which will go into the bin.  Obviously this will be what you replace if you need to recompile the source code for a specific version of Sitecore.  You should initially compile the Sitecore.SharedSource.PartialLanguageFallback project to get the dll to use, since the dll in the package appears to be out-of-date as well (fallback didn't work until I did this).
  • You can take this opportunity to add a 6.6 folder to the references folder, copy your 6.6 Kernel and Client dlls into there, and then update the references of the partial language fallback project.

The package will install the following Sitecore items:

  • In core: Do Not Enable Fallback and Enable Fallback ribbon commands for the content editor
  • In master: Fallback Language droplink field for the System Language template
  • In master: Enable Fallback If Configured checkbox field for the basic Field template

This module is called PARTIAL for a reason.  It enables the developer who is setting up the templates to specify on a field by field basis whether it should fallback.  Because it could become rather tedious to have to go to every field and select the checkbox for fallback, Alex has provided the Enable and Do Not Enable ribbon buttons. 

  • These buttons can be found in the Configure tab of the ribbon, in the Fallback section, and you have to select an Item (folder or template) first in order for that section to show up:

fallback

  • By clicking one of these buttons while on a particular item, the logic will recursively loop down through the children of the item and if is a field, it will check or uncheck the Enable Fallback if Configured checkbox.
  • To see if it is checked, you must click on the actual FIELD item

    fallback

  • Don't forget to publish your templates after you enable the fallback checkbox!

Note that in my experience, I haven't found a reason to NOT check this checkbox for all of my templates' fields.  So I make sure to periodically click on an item and click the Enable button so that it cascades down through all the templates and fields.  That is one of the few drawbacks, not knowing if you may have missed a checkbox.  It can lead to some frustration when you don't know why a value isn't falling back, only to find out the field wasn't checked. 

WARNING: do not get clever and go to the standard values of the field template and check the checkbox so that all fields fall back.  I tried this and had some seriously negative results as apparently lots of system fields were falling back that probably shouldn't have been.

Once you have installed the package into your Sitecore solution, make sure to get the config file from the source code, compile a fresh dll, and copy both into you project overriding what came over with the package, as those are out-of-date. 

Open up the Sitecore.SharedSource.PartialLanguageFallback.config file.  I will explain here, to the best of my abilities, what the different configurations and settings mean.

<databases>

         <!-- Custom GetItemCommand in order to support the "Enforcing of Version Presence" functionality -->

         <database id="master" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">

            <Engines.DataEngine.Commands.GetItemPrototype>

               <obj type="Sitecore.SharedSource.PartialLanguageFallback.DataEngine.GetItemCommand, Sitecore.SharedSource.PartialLanguageFallback" />

            </Engines.DataEngine.Commands.GetItemPrototype>

         </database>

         <database id="web" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">

            <Engines.DataEngine.Commands.GetItemPrototype>

               <obj type="Sitecore.SharedSource.PartialLanguageFallback.DataEngine.GetItemCommand, Sitecore.SharedSource.PartialLanguageFallback" />

            </Engines.DataEngine.Commands.GetItemPrototype>

         </database>

      </databases>

There are two similar entries here, one for each database (master and web), that adds a DataEngine Command.  This is executed when the GetItem command is run.  The code will make sure items that don't have a language version for the current context language won't be returned.  This will only be applied if the enforceVersionPresence attribute of the site is set to true AND the item's template (or base template) is in the Fallback.EnforceVersionPresenceTemplates setting.   I will get into this more in my next blog series entry.

WARNING: We may have found some issues with TDS and/or programmatically inserting into Sitecore when these database configurations are included.  You might need to consider commenting these out if you see issues.

 <pipelines>

         <renderContentEditor>

            <processor type="Sitecore.Shell.Applications.ContentEditor.Pipelines.RenderContentEditor.RenderSkinedContentEditor, Sitecore.Client">

               <patch:attribute name="type">Sitecore.SharedSource.PartialLanguageFallback.Pipelines.RenderContentEditor.CustomRenderSkinedContentEditor,Sitecore.SharedSource.PartialLanguageFallback</patch:attribute>

            </processor>

         </renderContentEditor>

      </pipelines>

This is to customize the look of the content editor so it is clearer that item values are falling back.  I've peeked around in this code and it should theoretically display 'fallback' next to a field, similarly to how it displays 'standard value', but my experiences have shown this to sometimes not work.

fallback

I've found that if there are competing modules that want to override the content editor skin or functionality in the content editor, it will cause problems. 

NOTE: Selecting the Standard Fields checkbox in the View tab of the ribbon will also mess with this because it is a different content editor renderer. 

fallback

It will cause the fallback field note to not display and instead give you a generic 'standard value' message.

fallback

But at least you can take that to mean it is falling back instead of being overridden.

<standardValues>

         <providers>

            <add name="sitecore">

               <patch:attribute name="type">Sitecore.SharedSource.PartialLanguageFallback.Providers.FallbackLanguageProvider,Sitecore.SharedSource.PartialLanguageFallback</patch:attribute>

               <!-- Pipe separated list of the databases that support the fallback

               example: master|web

          -->

               <SupportedDatabases>master|web</SupportedDatabases>

            </add>

         </providers>

      </standardValues>

This the key to it all.  This is where the Sitecore standard values provider is overridden by the FallbackLanguageProvider, which will take the necessary steps to check for values in the fallback languages.  You want to make sure all of your databases are included in here.  If you leave out master, it won't show the values falling back when you are in the content editor viewing the 'master' database.  And the same goes for when you are in web mode.  I don't see a reason to not include a database.  Although if you have a CM/CD production environment, you will have to have a slightly different version of the config file that doesn't reference master. 

<sites>

         <site name="shell">

            <patch:attribute name="enableFallback">true</patch:attribute>

         </site>

         <site name="website">

            <patch:attribute name="enableFallback">true</patch:attribute>

            <!--<patch:attribute name="enforceVersionPresence">true</patch:attribute>-->

         </site>

 

         <!-- When setting up "enforceVersionPresence" feature for the website above

           make sure to uncomment the following for "publisher" site as well

      -->

         <!--<site name="publisher">

        <patch:attribute name="enforceVersionPresence">true</patch:attribute>

      </site>-->

      </sites>

You want to add all of your site nodes in here.  You will need to set enableFallback to ‘true’ if you want to enable language fallback on your site.  If you want to enforce version presence, set enforceVersionPresence to true as well.  If you don't set enforceVersionPresence to true, then if an item does NOT have a specific language version, it will load the item anyway when the page is viewed in the context of that language (as long as it’s set to fall back to another with content).  There are pros and cons to this which I will discuss in my next blog post.

You MUST leave the 'shell' site set to enableFallback = true.  Otherwise fallback won't work correctly in the content editor.

And apparently if using enforceVersionPresence as how Alex has implemented it here, you should also uncomment the publisher site so the enforceVersionPresence = true.  I had problems when this was set to true (performance issues when publishing) and left this commented out.  I haven't had any negative repercussions by not including it.

<!--

            If enabled, the 'enable fallback' checkbox on the field definition item will be looked up

            in the SAME language version as the context language.

            If set to 'true', then when 'en-CA' tries to fallback to 'en', the checkbox field will be retrieved

            from the field definition item in 'en-CA', thus such version should exist.

            This feature enables you to have different fallback settings for the same field in different content languages

            If 'false', then the setting will be looked up from Fallback.MasterLanguage ('en' by default)

            Default value: false

         -->

         <setting name="Fallback.VaryFallbackSettingsPerLanguage" value="false" />

As the comments explain, you COULD allow whether a field is enabled to fall back to vary on a language by language basis.  If you set this to true, it means that you will have to create language versions of all your templates as well.  That way, when viewing the site through a particular language context, it will check the same language version of the item's template to see if the field should fallback before retrieving the value from the fallback language.

Personally, I've found no need for this granular level of configuration.  It creates a lot more overhead, especially if you have a lot of languages.  I prefer to only have a single version of my templates: en, and that's it.

 <!--

            Pipe separated list of feild IDs that will be ignored during the fallback process

            Example: {GUID}|{GUID}

            Default value: empty

         -->

         <setting name="Fallback.IgnoredFields" value="{C8F93AFE-BFD4-4E8F-9C61-152559854661}|{4C346442-E859-4EFD-89B2-44AEDF467D21}|{7EAD6FD6-6CF1-4ACA-AC6B-B200E7BAFE88}|{86FE4F77-4D9A-4EC3-9ED9-263D03BD1965}" />

As the comments explain, you can add fields that should be ignored during fallback.  I'm not entirely sure why this is necessary if you have to enable fields to fallback with the checkbox.  I've found no reason to modify this setting and have left it as is.

<!--

            Whether to process language fallback for the system fields that start with "__"

            Default value: false

         -->

         <setting name="Fallback.ProcessSystemFields" value="false" />

As the comments explain, it will process system fields if set to true.  I'm not sure if this means you wouldn't have to check the enable fallback checkbox for those fields or if this is another setting that would be ignoring that checkbox.  Either way, I've left this set to false, I haven't found reason to fallback values from these fields.

<!--

            Pipe separated list of template GUIDs that support "Enforcing of Version Presence" functionality

            Default value: empty

         -->

         <setting name="Fallback.EnforceVersionPresenceTemplates" value="" />

If you have set that a site should enforceVersionPresence = true, then you should include all templates' GUIDs that should do so here, delimited by a pipe.  You can include a Base Template GUID as well.  So you could create an Enforce Language Version template and set it as a base template for all templates that should enforce a language version and just include that one GUID here.

Something you'll need to consider is what templates do you truly want to enforce versioning on.  It could be that on all pages and callouts you do, but on all media, you don't.  In that case, you wouldn't include any media template GUIDs here.

In my experience, I've found that if I need to enforce versioning, then I might want it to be on all http requests.  In a later post I discuss an enhancement that will run a check for version presence during the httpRequest pipeline and where you could tweak that code to remove the check against the EnforceVersionPresenceTemplates setting. 

<setting name="Fallback.CacheSize" value="10MB" />

Anyone familiar with Sitecore caches will know that you want it to be able to cache values from the database.  Make sure the CacheSize value is big enough to handle your content.  Alex clears this cache upon certain actions.  I haven't found a reason yet to change the default value.

<!--

            Registered Sitecore language to be used for enforcing language fallback, i.e. 'master' language

            It is VERY important NOT to have this language to fallback to any other language on the item definition

 

            The value could be different depending on a locale. For US, that would be 'en' or 'en-US' for example

            If 'enforcing from master language' feature is enabled, this language will be used as a source language.

 

            Default value: en

         -->

         <setting name="Fallback.MasterLanguage" value="en" />

You want this MasterLanguage setting to stay 'en' or whatever the main language that Sitecore is viewed through.  I think I tried changing this once for a client who wanted to use en-GB as their default language.  Ultimately I convinced them to go back to 'en' since we saw some really weird results in the content editor.  I can't speak for those in countries where English is not the main language, but I would recommend always having 'en' be your content editor language, the master language here, and the global language that everything falls back to, even if you won't have 'en' be a language that is viewed explicitly from the front-end of the site.

<commands>

         <command name="flp:setupfallback" type="Sitecore.SharedSource.PartialLanguageFallback.Commands.SetupFallbackCommand,Sitecore.SharedSource.PartialLanguageFallback" />

      </commands>

This final configuration is the command that sets up the Enable Fallback and Do Not Enable Fallback ribbon buttons that check and uncheck the field item checkbox.

I have extended the Sitecore.SharedSource.PartialLanguageFallback.config file to add enhancements and fixes and will address each of those in the rest of the blog series.

Once you have this configured, you will want to test that it is working properly.

  • Make sure that the site node you are using has enableFallback set to true in the config file
  • Add a second language to Sitecore if you have not already done so.  Set this language to fall back to 'en'
fallback

WARNING: If you decide to change which language a particular language falls back to, you may not immediately see a difference when you click on a content item that would be falling back.  There is caching involved.  You might have to go to the /sitecore/admin/cache.aspx and clear your Sitecore cache, and then go back to the content item.  It should show fallback correctly at that point.

  • Click on one of your templates and then click the Enable Fallback button in the ribbon
  • Double check the checkbox has been checked by expanding to the field level in the content tree and then click on the field.
fallback

o    Validate fallback in content editor

  • Go up to the content tree and add a content item instance of that template, make sure you are doing so in the 'en' language
  • Add some content to the fields
  • Click on the language button in the upper right portion of the content editor and select the new language
  • You will see a prompt that no version exists for the current language

 

fallback

Click the link to create the language version

  • It will then display the full content window and the fields should be pre-filled with the values from the original fallback language
  • It should say either 'fallback' or 'standard values' next to the field names
fallback

Switch back to the original language ('en').

  • Change the value of a field
  • Switch back to the new language, see how the value is automatically updated
  • Override one of the fields on the new language, see how the 'fallback'/'standard value' note is no longer displayed
    • § TIP: If you are also viewing 'Standard Fields', it will show 'standard value', if you have 'Standard Field' in the view tab unchecked, it will show 'fallback value'

fallback

Switch back to the original language and modify that same field

  • Switch back to the new language and see how the field is still the value that was overridden
  • While in the new language, select the Versions tab in the ribbon and then click the 'Reset fields' button
fallback

Select the checkbox for the field that was overridden and click OK

fallback

See how the field is now falling back again to the original

fallback

NOTE, you MUST reset in order to have the field falling back again.  If you simply delete the value out of the field and save, all you are doing is overriding the original with a blank value, which is a valid scenario.  You must set it back to null with the Reset button if you want it to fall back again.

o    Validate fallback in front-end

  • Publish your templates so that it pushes all fields that have their Enable Fallback checkbox checked
  • Publish the item, but only in the 'en' language, not the new language
  • Go to the page in the front-end, might be easiest to test by going to the page using the parameter method for setting language:
    • fallbackdemo/?sc_lang=en
  • And verify your content is there
  • Go to the page for a language that is set to fall back to 'en'
    • fallbackdemo/?sc_lang=en-us
    • You'll see that the page loads AND it is falling back (even though you haven't yet published that version to web)
    • This is assuming that enforceLanguagePresence is false, otherwise it would redirect to a 404 page
  • Go to the page for a language that is NOT set to fall back to anything and you haven't yet added a version in that language
    • fallbackdemo/?sc_lang=de-de
    • You'll see that the page loads, but with no content
    • This is assuming that enforceLanguagePresence is false, otherwise it would redirect to a 404 page
      • Set the language (de-de) to fallback to 'en' and publish the language
      • Refresh the front end page for the new language, see that the content is now there
  • Change the value in the ORIGINAL language of one of the fields that are falling back (value not set yet in new version)
  • Publish the original version only ('en')
  • Check the front-end page in both the original and new languages (eg: 'en' and 'en-us')
    • You'll see that the update is in both.  No need to publish again in the new language, just in the original, as long as you aren't changing values directly in the new language.
  • Override the value in the new language
  • Publish in the new language, it will show up there
    • You only need to publish in the new language if you make specific changes to it, whether it be to reset a field or override a field.
  • Change enforceVersionPresence to 'true' in the Sitecore.SharedSource.PartialLanguageFallback.config site node
  • Remove the version of the item in en-US and publish the 'en-us' version
  • Try going to the page again in the frontend, it will throw an error

At this point, your site is ready to roll with Language Fallback.  There are additional steps that must be taken to make sure the Dictionary and Advanced Database Crawler work correctly.  There are also some things to consider when deciding if the presence of a language version should be enforced.  Additionally, having to add language versions for content just so it can fall back, especially when you start to add more languages to your site, could become tedious.  There are some customizations you can add to make this more automated.  And what about knowing what items are missing language versions?  A simple tool could really help with that.  All of this and more will be addressed in the rest of this blog series.

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


  • Hi Elizabeth  Thanks for this great and very detailed article.  Regarding this sentence:  Although if you have a CM/CD production environment, you will have to have a slightly different version of the config file that doesn't reference master.   Can you provide the Config / Transformation for the CD environment?  In my MasterToWeb.config I have this included, but it seem not work:      <databases>       <!-- Remove Master DB (Configuration Document) -->       <database id="master">         <patch:delete />       </database>  Any idea?  Thanks again  

  • Here is my SwitchMasterToWeb (note I have two publishing targets in production, web and liveweb):  <!-- START: Addition to Sitecore SwitchMasterToWeb.config - update supported databases to be just web in Sitecore.SharedSource.PartialLanguageFallback -->     <standardValues>       <providers>         <add name="sitecore">           <patch:attribute name="type">Sitecore.SharedSource.PartialLanguageFallback.Providers.FallbackLanguageProvider,Sitecore.SharedSource.PartialLanguageFallback</patch:attribute>           <!-- Pipe separated list of the databases that support the fallback                 example: master|web                 ** REMOVE master IF ON A CD ENVIRONMENT! and add liveweb           -->           <SupportedDatabases>web|liveweb</SupportedDatabases>         </add>       </providers>     </standardValues>     <!-- END: Addition to Sitecore SwitchMasterToWeb.config - update supported databases to be just web in Sitecore.SharedSource.PartialLanguageFallback -->  I'm not using the custom GetItemCommand to EnforceVersionPresence at this time and have that part commented out in my fallback.config and instead I use the custom method I describe in my Custom Enforce Version Presence post...