Language Tools

Intro

SCORE 1.4 introduced a Language Tools feature that supports copying content from one language version to another as well as creating empty language versions for solutions that use field-level language fallback. The feature is available in both Content Editor and Page Editor:

Overview

Copy Language supports two modes:

  • Create Empty Language Versions. This mode will only create new version of the item in the selected target language(s) if no version exists. New version will not be created if there's a version already in the target language. No content will be copied into the newly created version.

    Standard Values will be inherited (and tokens resolved) provided that the template's __Standard values item has a version in the target language. This is important to understand and we have a feature on SCORE roadmap that will help default to the standard values in the primary language version, see  SCORE-311 - Getting issue details... STATUS

  • Ensure Language Versions and Copy Content. This will create item versions in the target language(s) as needed and will copy content from the current language (this is the language currently selected in your Content or Page Editor and this is the content you were looking at in the item when you opened the Copy Language dialog).

    Copy Langauge only copies non-shared field values that the item itself has in the current language. Standard values and default values will not be copied. The expectations is that defaults will come from the template's standard values - please see the note above about the language versions of __Standard values item.

    If the item version in the target language already has a non null value ((warning) an empty string - if the field is not set to Reset is not considered a null value) it won't be overwritten.

In order to use the tool in either of the two modes the Sitecore instance has to have multiple (more than one) content language:

If you only have a single language you will see the following warning in the Copy Language dialog:

If the item doesn't have a version in the current language the only option available will be to Create Empty Versions:

  

If the instance is configured to have multiple content languages and the item has a version in the current language the default option is to Ensure Versions and Copy Content and the current language is excluded from the selection of target languages.

Options

Both modes support:

  • Working with multiple target languages at the same time. 
  • Processing descendants of the current items (Include Subitems). This option is OFF by default. If you turn this option ON all subitems will be processed recursively.
  • Processing datasources referenced from the items (Include Datasources). This option is ON by default. All datasource items as references by the components on the pages (page local, site shared, multi site shared, and other content items) will be included

Security

Versions are created and content copied with security disabled. The editor / user, however, needs to have Read access to the item for which the Copy Language is executed (the starting point). The item cannot be in a read only state either. If either of the two conditions are not met Copy Language will be disabled:

Performance

The Copy Language Tool works in two steps in both execution mode:

  • Collecting Items to process according to the selected options
  • Processing the items according to the selected mode

Step 1: Prepare

This is usually a very fast stage unless you are processing a really large content subtree:

Step 2: Process

This may take a while depending on how large if the collected set of items. 10,000 items, for example, will take a few minutes to run. 

Copy Language does not disable events so all event handlers (including default ones) attached to item:versionAdded (both modes, only if new version was created) and  item:saving and item:saved (copy content mode if the version in the target version was modified) will be called. It's not designed to be blazing fast as running large content trees through the Copy Language utility is not something we expect to be a daily routine (unlike publishing, for example)

Item Buckets

Copy Language will work through bucketed item's (subitems that are bucketed and datasources that are in an item bucket) just fine. Bucketed items are technically still just items with a folder structure automatically created for you by Sitecore.

Pipelines

Copy Language is very extensible and customizable via pipeline extensions. It's broken down into three new pipelines

score.copyLanguage.collect

<score.copyLanguage.collect>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.AddDescendants, Score.Custom"/>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.AddDatasources, Score.Custom"/>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.DeduplicateQueue, Score.Custom"/>
</score.copyLanguage.collect>

You would customize this pipeline to remove items that inherit from certain data templates, for example. An example of such customization might look like this code snippet (illustration purpose only):

public class FilterQueue
{
    public virtual void Process(CopyLanguagePipelineArgs args)
    {
        Assert.IsNotNull(args, "args");
        if (args.Queue.Count == 0)
        {
            return;
        }
 
        var templateId = new ID("{...GUID...}");

        args.Queue = args.Queue
            .Where(el => !el.IsDerived(templateId))
            .ToList();
    }
}

score.copyLanguage.execute

<score.copyLanguage.execute>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.Execute, Score.Custom"/>
</score.copyLanguage.execute>

The Execute processor will iterate over a collected queue of items and perform required actions. We don't expect that this pipeline be customized but you can do certain before and after actions if required (e.g. emitting an event). Paralleling out the processing of the queue will require modifications to the arguments class (and potentially the dialog code-behind) to properly handle multi threaded progress updates. The SCORE development team might implement a parallel version in the future.

score.copyLanguage.process

<score.copyLanguage.process>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.EnsureVersions, Score.Custom"/>
    <processor type="Score.Custom.Pipelines.Globalization.CopyLanguage.CopyContent, Score.Custom"/>
</score.copyLanguage.process>

This pipeline is called for every item in the queue. You would customize it to perform additional actions on every item as it flows through the copy language pipeline.

API

The Copy Language UI dialog runs it in the background using Sitecore's JobManager facility. You can kick off these jobs or run the steps synchronously by using Score.Custom.Pipelines.Globalization.CopyLanguageJobRunner:

Asynchronous

var args = new CopyLanguagePipelineArgs()
{
    // ...
};
var handlerCollect = CopyLanguageJobRunner.Collect(args);
// ...
// Make sure you pass in the same args as Execute expects a full Queue
var handlerExecute = CopyLanguageJobRunner.Execute(args)

Synchronous

var args = new CopyLanguagePipelineArgs()
{
    // ...
};

new CopyLanguageJobRunner.Worker().DoCollect(args);
new CopyLanguageJobRunner.Worker().DoExecute(args);