Skip to main content


Workflow Engine supports localization out of the box. Localization constants are stored in the Localization section, they can be accessed by clicking on a corresponding button in the Designer's toolbar.

The localization constants have the following properties which might be modified:

  • ObjectName - the object current name for localization;
  • Type - the type of name that is being translated: State, Command, Parameter, Comment and others;
  • IsDefault - this translation will be used if the appropriate culture is not found;
  • Culture - Language Culture Name - culture name in format: languagecode2-country/regioncode2; for example, en-US, ar-AA, etc;
  • Value - localized actual value of name.

The localization culture can be explicitly set in GetAvailableCommands and GetAvailableStateToSet methods. If it is not specified, the current culture CultureInfo.CurrentCulture is used.

Assigning a localized name to an object called "Name" in the following way: if there is a translation with the specified culture explicitly , then it is used; if there is not, but there is a localization constant with the "IsDefault" = true attribute, then it is used. Otherwise, "Name" is used as the localized name.


In the ObjectName field for a translation of the type Comment, it is recommended to use it, but separated by : comment key for identification purposes, such as: [object type]:[object name]:[nested object name].

Examples: The ObjectName of the localized comment for the 'Approve' command will be Command:Approve, for the 'Count' parameter of the 'Approve' command will be Command:Approve:Count.


The recommended way for obtaining the localized names is used in the Localizer property via indexer.

string stateName = "State1";
string localizedName = Localizer[stateName, LocalizeType.State, CultureInfo.CurrentCulture];

It has the following signature:

/// <summary> Get the localized name in specific culture from bound sources. </summary>
/// <param name="name">System name. See <see cref="Translation.Name"/></param>
/// <param name="type">Localize type of name</param>
/// <param name="culture">Desired culture. If null then used <see cref="CultureInfo.CurrentCulture"/></param>
/// <returns>Localized name if exists, else input <paramref name="name"/></returns>
public string this[string name, LocalizeType type, CultureInfo? culture = null];

And is an alias for the GetLocalizedName method.

Localizer is accessed in the instance WorkflowRuntime, ProcessInstance and ProcessDefinition (scheme) with different initial sources to search a value:

  • WorkflowRuntime - search only in ExternalLocalization;
  • ProcessInstance - search in localization of scheme and ExternalLocalization of runtime owner;
  • ProcessDefinition - search only in own localization;

Binds can be used for extend of range. It needs source of localization:

string localizedName1 = Localizer.FromProcess(processId)[stateName, LocalizeType.State, CultureInfo.CurrentCulture];
string localizedName2 = Localizer.FromScheme(schemeName)[stateName, LocalizeType.State, CultureInfo.CurrentCulture];
string localizedName3 = Localizer.FromScheme(schemeId)[stateName, LocalizeType.State, CultureInfo.CurrentCulture];
string localizedName4 = Localizer.FromRuntime(runtime)[stateName, LocalizeType.State, CultureInfo.CurrentCulture];

Or multi binds for some sources:

string localizer = Localizer
string localizedStateName = localizer[stateName, LocalizeType.State];
string localizedCommandName = localizer[stateName, LocalizeType.Command];

Additional methods

The instances WorkflowRuntime, ProcessInstance and ProcessDefinition contain some additional methods (aliases for localizer property) in order get the localized name.


The object WorkflowRuntime has additional methods to obtain the localized object name. Considering states:

string localizedStateName = WorkflowInit.Runtime.GetLocalizedStateName(processId, stateName);
string localizedStateName = WorkflowInit.Runtime.GetLocalizedStateNameBySchemeCode(schemeCode, stateName);
string localizedStateName = WorkflowInit.Runtime.GetLocalizedStateNameBySchemeId(schemeId, stateName);

In case of commands:

string localizedCommandName = WorkflowInit.Runtime.GetLocalizedCommandName(processId, stateName);
string localizedCommandName = WorkflowInit.Runtime.GetLocalizedCommandNameBySchemeId(schemeId, stateName);


Saved in the designer localization, it can be accessed directly by the Localized property in the instance ProcessDefinition.

Additional methods for getting the localized name:

var name = "ObjectName";
var culture = CultureInfo.CurrentCulture;

var stateName = scheme.GetLocalizedStateName(name, culture);
var commandName = scheme.GetLocalizedCommandName(name, culture);
var conditionName = scheme.GetLocalizedConditionName(name, culture);

Process instance

The instance ProcessInstance contains methods similar to ProcessDefinition, but engages the external localization if it exists.

var stateName = process.GetLocalizedStateName(name, culture);
var commandName = process.GetLocalizedCommandName(name, culture);
var conditionName = process.GetLocalizedConditionName(name, culture);


Additional localization can be connected by implementing the interface ILocalizationProvider and configuring WorkflowRuntime.

Then, the predefined toggle button to see these translations, must appear in the localization section of designer.

Signature of this provider:

public interface ILocalizationProvider
/// <summary>
/// Get the localized string.
/// </summary>
/// <param name="name">System name</param>
/// <param name="type">Localize type of name</param>
/// <param name="culture">Culture</param>
/// <returns>Localized string if exists, else null</returns>
public Translation? Get(string name, LocalizeType type, CultureInfo culture);

/// <summary>
/// Get all localized strings for specific scheme. Used in the designer with predefined mark.
/// </summary>
/// <param name="schemeCode"> Scheme code</param>
/// <returns></returns>
public List<Translation> GetAll(string schemeCode);

WorkflowEngine provides the Localization class that is the simplest way to add translations. It is the implementation of ILocalizationProvider and List<Translation>:

//In WorlflowInit.cs

using OptimaJet.Workflow.Core.Model;


.WithLocalizationProvider(new Localization
new ("SimpleWF", "SimpleWF_en-US", LocalizeType.Scheme, "en-US"),
new ("State", "State_en-US", LocalizeType.State, "en-US", true)

An example of custom implementation and provider plug in:

public class LocalizationProvider : ILocalizationProvider
private Localization Localization { get; }

public LocalizationProvider()
Localization = new Localization
new("PredefinedAction", "PredefinedAction_en-US", LocalizeType.Action, "en-US"),
new("Command", "PredefinedCommand_en-US", LocalizeType.Command, "en-US", true)

public Translation? Get(string name, LocalizeType type, CultureInfo culture)
return Localization.Get(name, type, culture);

public List<Translation> GetAll(string schemeCode) => Localization.GetAll(schemeCode);

Afterward, WorkflowRuntime can be configured on initial step:

_runtime.WithLocalizationProvider(new LocalizationProvider());