Quickly Create New Language Versions on your Sitecore CMS

10 April 2012
Przemek Taront
Frink_Cognifide_2016_HeaderImages_0117

This post concerns Sitecore 6.5.0 (rev. 111123).

Add new version command in the ribbon On every website that supports multiple languages, there is this moment in the lifecycle where you have finished entering content in the primary language/ target market and are about to begin translating the content into other languages. And you go through this painful process: switch to a new language, add a new version and populate all non-shared fields with localized content. There is the so called translate mode that would display two language versions side-by-side, but it is unfortunately, not available while editing in the on-page mode. Of course, it would be much easier if you could create a new version with all fields already pre-populated with content copied from the main language. Then, clearly you would be able to translate your content in-place, either in the content editor or in page editor.

Is there anything else you would like to add to this wish list? I believe your page has probably got references to some other items as well, such as: * media library files, * links to other items, * datasources of presentation components, etc.

Instead of navigating to each referenced item individually and creating a new version for it, how about we leave this job to a new command presented in this blog post?

Implementation

Our new command runs internally in a pipeline, receiving three arguments:
1 - ID of the item,
2 - source language and
3 - target language.

The algorithm builds a set of items referenced by the current item. It iterates over all renderings found in the presentation field and adds all datasources to the set.
private HashSet LinkSet;
protected void Run(ClientPipelineArgs args)
{
  string id = args.Parameters["id"];
  Language sourceLang = Language.Parse(args.Parameters["sourceLang"]);
  Language targetLang = Language.Parse(args.Parameters["targetLang"]);
  LinkSet = new HashSet();

  Item item = Context.ContentDatabase.GetItem(id, targetLang);
  if (item == null)	return;
  if (Context.IsAdministrator || (item.Access.CanWrite()
      && (item.Locking.CanLock() || item.Locking.HasLock())))
  {
    if (SheerResponse.CheckModified())
    {
      AddAllReferences(item);
      LayoutField layoutField = item.Fields[FieldIDs.LayoutField];
      LayoutDefinition layout = LayoutDefinition.Parse(layoutField.Value);
      foreach (DeviceDefinition device in layout.Devices)
      {
        foreach (RenderingDefinition rendering in device.Renderings)
        {
          string path = rendering.Datasource ?? string.Empty;
          Item datasource = Context.ContentDatabase.GetItem(path, targetLang);
          if (datasource == null) continue;
          AddAllReferences(datasource);
        }
      }
      foreach (ID linkId in LinkSet)
      {
        CopyVersion(linkId, sourceLang, targetLang);
      }
	}
  }
}
For every item found, the AddAllReferences method is called. It goes over all fields of the item looking for links to items that can be added to the set.
private void AddAllReferences(Item item)
{
  if (LinkSet.Add(item.ID))
  {
    foreach (ItemLink itemLink in item.Links.GetValidLinks(false))
    {
      Item reference = itemLink.GetTargetItem();
      if (reference.Paths.IsContentItem || reference.Paths.IsMediaItem)
      {
        LinkSet.Add(reference.ID);
      }
    }
  }
}
Eventually, for every item from the set, a new version is created in the target language if it does not exist. Then all non-shared fields are copied from the source langauge version.
private void CopyVersion(ID id, Language sourceLang, Language targetLang)
{
  Item source = Context.ContentDatabase.GetItem(id, sourceLang);
  Item target = Context.ContentDatabase.GetItem(id, targetLang);
  if (source == null || target == null || target.Versions.Count > 0) return;

  target.Versions.AddVersion();
  target.Editing.BeginEdit();
  foreach (Field field in source.Fields)
  {
    if (!field.Shared)
    {
      target[field.Name] = source[field.Name];
    }
  }
  target.Editing.EndEdit();
}
After adding this new command to the ribbon in content editor and to the toolbar in page editor you can test how they work. Copy from another language version command in the ribbon Copy from another language version command in page editor In both cases, you need a language drop down to select the source language. This step as well as the core database settings are out of scope of this blog post. However, you can download the full package and the source code including missing classes using the links below:

Download Quick Language Version Creator source

Download Quick Language Version Creator package

to be used with Installation Wizard from Sitecore Desktop

Feel free to drop me a line below, if you have any feedback. And yes, I'd certainly appreciate your feedback ;-)