This documentation applies to Omni for Umbraco 17 and 18. Both version lines have the same functionality and configuration. Choose the package version for your Umbraco site.
Choose the smallest safe extension
Omni extends support at the persisted-value boundary. Choose an approach based on what the editor actually stores—not how it renders in the backoffice.
Map simple values in configuration
Use PlainText only when the editor stores text directly. Use RichText only when it stores HTML compatible with Umbraco's rich-text parser.
{
"DiploTranslatorOmni": {
"ContentTranslation": {
"PropertyEditorMappings": [
{ "EditorAlias": "Acme.Headline", "Adapter": "PlainText" },
{ "EditorAlias": "Acme.FormattedIntroduction", "Adapter": "RichText" }
]
}
}
}Only PlainText and RichText are accepted. Unknown mappings, complex JSON and unsafe values remain unsupported.
Implement a code adapter for complex values
For structured persisted values, implement IContentTranslationPropertyEditorAdapter. An adapter identifies the editors it handles, extracts stable text-unit IDs, patches only those units into a cloned value and validates that protected structure remains unchanged.
using Diplo.Translator.Omni.Services;
public sealed class CalloutTranslationAdapter
: IContentTranslationPropertyEditorAdapter
{
public bool CanHandle(ContentTranslationEditorAdapterContext context)
=> context.EditorAlias == "Acme.Callout";
public ContentTranslationEditorExtraction Extract(
ContentTranslationEditorAdapterContext context,
string sourceValue) { /* return stable text units */ }
public ContentTranslationEditorPatch Patch(
ContentTranslationEditorAdapterContext context,
string sourceValue,
IReadOnlyDictionary<string, string> translations,
IReadOnlyCollection<ContentTranslationEditorUnit> units)
{ /* patch a clone of the persisted value */ }
public ContentTranslationEditorValidation Validate(
ContentTranslationEditorAdapterContext context,
string originalValue,
string patchedValue)
{ /* verify protected structure is unchanged */ }
}The outline shows the contract; production implementations must parse defensively and return extraction, patch and validation failures rather than accepting uncertain output.
Register the adapter
Register the implementation from an Umbraco composer:
using Diplo.Translator.Omni;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
public sealed class TranslationComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
=> builder.AddContentTranslationEditorAdapter<CalloutTranslationAdapter>();
}Safety behaviour
- Configuration mappings do not override built-in handling. Code adapters may disambiguate a specific editor UI using
Umbraco.Plain.String; match bothEditorAliasandPropertyEditorUiAliasso unrelated string editors are unaffected. Omni's recognised Ph Heading handling takes precedence. - Adapter exceptions and validation failures fail closed.
- Duplicate or unknown unit IDs and null patch results are rejected.
- Use stable unit IDs so Omni can track source changes reliably.
- Adapters registered through the helper are singletons. Keep them thread-safe and do not retain per-request state or scoped services.
The interface and value types are in Diplo.Translator.Omni.Services. The registration helper is in Diplo.Translator.Omni. The outline is illustrative and requires real method bodies before it will compile.