Sitecore makes managing a multi-language/multi-culture site easy:

  1. A site can be managed in any number of cultures (for example, US English).
  2. Every field on a template can be marked as unique to a specific language or shared across all languages.  For example, a company logo would be common to all languages and on the same item a different field can be unique in any language.
  3. Each language has its own version history. 
  4. Items can be pushed through workflow to incorporate the translation process.
  5. When implemented properly, a site will not require software changes to support new languages.

This model makes it easy to tailor your site’s content to a variety of languages and markets.

However, some organizations might not have the resources to translate every page into every language culture, especially if there is no or little difference between culture variations.  For example, the company’s history in English might only have spelling differences in the US, Canadian and UK versions.  And the company history in US, Mexican and Castilian Spanish might be identical across all three.

One might be tempted to just use language, rather than culture, to streamline content management.

But consider a firm with regional management in each market.  Bios for the US managers might be presented in US English and US Spanish.  A completely different list of managers in different languages would be presented in other markets.

This suggests a need for a “base language” for a set of language cultures.  If a culture-specific version is missing (es-MX or es-PR; en-CA or en-UK), the system could return the version from the base culture for that language (es-ES; en-US).  This could even be cascaded to a global base language: if no culture- or language-specific page is available, return US English. 

We can use Sitecore’s extensible API to develop a solution:

1.       A data model for the language hierarchy. 

a.       A simple model is a tree of language culture items (en-US).  A language culture item would have a field for base language culture that is a dropdown to the item’s siblings.  This approach ensures that a culture can only have one base language.

b.      The default language can be stored in a .config file.

2.       A mechanism for generating links to and retrieving a “base language item” when the current language does not have a version. 

3.       A mechanism for generating links to and retrieving a “default language item” when no other version exists.

4.       The feature can only “kick in” when you are not editing and when you are looking at the WEB database.  This protects the integrity of the master database during edits and allows the editor to create a culture-specific version when needed.

One place to implement this logic is in the ItemProvider.  Here is some pseudo-code that shows a lightweight example.  For brevity we are not showing how to lookup the appropriate default language. 

Overall the capability can save your clients time and money in meeting demands for multi-language websites without limiting flexibility.  Revere has used this approach on several sites to support our clients’ global presence by streamlining creation of language versions. 

<!-- DOMAINS -->
< itemManager defaultProvider = "languageReplace">
  < providers >
    < clear />
    < add name = "default" type="Sitecore.Data.Managers.ItemProvider, Sitecore.Kernel"/>
    < add name = "languageReplace" type="MyNamespace.DefaultLanguageItemProvider, MyAssembly"/>
  </ providers >
</ itemManager >
 
 
public class DefaultLanguageItemProvider : ItemProvider
{
    /// Note we recommend putting this in a .config file but for brevity
    /// in the illustration we are hard coding it
    private Language defaultLanguage = Language.Parse("en-US");
 
    /// <summary>
    /// Replace the ItemProvider's GetItem
    /// Our version checks for missing language versions and replaces with a default language.
    /// </summary>
    protected override Item GetItem(ID itemId, Language language, Version version, Database database)
    {
        Assert.ArgumentNotNull(itemId, "itemId");
        Assert.ArgumentNotNull(language, "language");
        Assert.ArgumentNotNull(version, "version");
        Assert.ArgumentNotNull(database, "database");
 
        // get the item as usual
        Item item = base.GetItem(itemId, language, version, database);
 
        // if item isn’t null and we aren't in an editing situation
        if (item != null && (Sitecore.Context.PageMode.IsNormal || Sitecore.Context.PageMode.IsPreview))
        {
            // no versions in this language and context language isn't the default
            if (item.Versions.Count == 0 && language != defaultLanguage)
            {
                // replace with default language
                item = base.GetItem(itemId, defaultLanguage, Version.Latest, database);
            }
        }
        return item;
    }
}