Localization
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
.
Localizer
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 inExternalLocalization
;ProcessInstance
- search in localization of scheme andExternalLocalization
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
.FromProcess(processId1)
.FromProcess(processId2);
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.
Runtime
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);
Scheme
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);
ILocalizationProvider
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());