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:

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:

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:

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);