orchardcore-localization

star 8.1k

Localizes OrchardCore apps — UI strings (IStringLocalizer/IViewLocalizer S, T, H), PO files and pluralization, content translation (LocalizationPart, culture picker), and supported-culture configuration. Use when the user needs to translate strings, add a culture, set up PO files, or make content items multilingual.

OrchardCMS By OrchardCMS schedule Updated 6/8/2026

name: orchardcore-localization description: Localizes OrchardCore apps — UI strings (IStringLocalizer/IViewLocalizer S, T, H), PO files and pluralization, content translation (LocalizationPart, culture picker), and supported-culture configuration. Use when the user needs to translate strings, add a culture, set up PO files, or make content items multilingual.

OrchardCore Localization

This skill guides you through OrchardCore localization following project conventions.

Three layers, often confused:

  • UI/code localization — translate hard-coded strings in C#/Razor/Liquid via IStringLocalizer (S), IViewLocalizer (T), IHtmlLocalizer (H). Translations live in PO files.
  • Content localization — translate content items across cultures via LocalizationPart and the OrchardCore.ContentLocalization module.
  • Culture configuration — which cultures the site supports and how the request culture is chosen.

Decide which layer

Goal Layer
Translate a label/message in code or a view UI localization (S/T/H) + PO file
Pluralize ("1 item" / "{0} items") S.Plural(...) + PO msgid_plural
Translate a blog post into French Content localization (LocalizationPart)
Add a supported language / set default Localization settings (LocalizationSettings)
Translate data-driven values (e.g. taxonomy terms) Data Localization (DataLocalization module)

Workflow A: localize UI strings

Step 1: Inject the right localizer

Localizer Convention Where
IStringLocalizer<T> field S drivers, services, controllers
IViewLocalizer property T Razor views (already on RazorPage)
IHtmlLocalizer<T> field H when the translation contains HTML
public sealed class AliasPartDisplayDriver : ContentPartDisplayDriver<AliasPart>
{
    internal readonly IStringLocalizer S;

    public AliasPartDisplayDriver(IStringLocalizer<AliasPartDisplayDriver> localizer)
        => S = localizer;
}

In Razor: @T["Welcome to Orchard Core"]. In a class: S["A value is required for {0}.", name].

Step 2: Pluralize when counting

S.Plural(count, "{0} book", "{0} books");
// IHtmlLocalizer: H.Plural(count, "{0} book", "{0} books")

Step 3: Provide PO translations

PO files are discovered (in order) from each module's Localization/, a global /Localization, the tenant's App_Data/Sites/{tenant}/Localization, and culture folders. A PO entry:

msgctxt "OrchardCore.Admin.Views.AdminDashboard"
msgid "Welcome to Orchard Core"
msgstr "Bienvenue sur Orchard Core"

msgctxt = {Namespace}.{Class} (services) or {Namespace}.{ViewPath} (views). Plurals:

msgctxt "OrchardCore.AdminMenu.Views.Menu.List"
msgid "1 item"
msgid_plural "{0} items"
msgstr[0] "{0} élément"
msgstr[1] "{0} éléments"

See references/localization.md for the full PO discovery order and headers.

Workflow B: localize content

Step 1: Enable the feature, attach the part

Enable OrchardCore.ContentLocalization (Content Localization). Attach LocalizationPart to the content type (admin or recipe). It carries:

public class LocalizationPart : ContentPart, ILocalizable
{
    public string LocalizationSet { get; set; } // links all translations
    public string Culture { get; set; }         // this version's culture
}

On create, the part handler generates a unique LocalizationSet and sets the default culture automatically.

Step 2: Translate

From the editor's Localization, "Translate" creates a sibling content item sharing the same LocalizationSet with a different Culture. Programmatically:

var translated = await _contentLocalizationManager.LocalizeAsync(contentItem, "fr-FR");

Step 3: Surface translations / culture picker

IContentLocalizationManager fetches across a set:

await _contentLocalizationManager.GetContentItemAsync(localizationSet, "fr");
await _contentLocalizationManager.GetItemsForSetAsync(localizationSet);

Liquid: {{ Model.ContentItem.Content.LocalizationPart.LocalizationSet | localization_set: "en" }}. The Content Culture Picker feature adds a front-end language switcher and a ContentRequestCultureProvider that derives the culture from the localized route.

Workflow C: configure cultures

Recipe settings step:

{
  "name": "settings",
  "LocalizationSettings": {
    "DefaultCulture": "en-US",
    "SupportedCultures": [ "en-US", "fr-FR", "es-ES" ],
    "FallBackToParentCulture": true
  }
}

The Localization module reads these at startup and calls app.UseRequestLocalization(...) with the configured default + supported cultures.

Quick Reference

Localizers

Symbol Type Output
S IStringLocalizer<T> plain string
T IViewLocalizer encoded view string
H IHtmlLocalizer<T> HTML-safe string

Content localization APIs

Member Purpose
IContentLocalizationManager.LocalizeAsync(item, culture) create a translation
.GetContentItemAsync(set, culture) one translation
.GetItemsForSetAsync(set) all translations
.GetItemsForSetsAsync(sets, culture) batch
ILocalizationService.GetDefaultCultureAsync() / GetSupportedCulturesAsync() culture config

Request culture providers

Provider Picks culture from
ContentRequestCultureProvider the localized content route (added first)
AdminCookieCultureProvider admin_culture_* cookie, admin paths only
cookie / querystring / Accept-Language ASP.NET Core defaults

Liquid filters

localization_set: "fr" — translated item; switch_culture_url — culture-switch URL.

Gotchas

  • msgctxt must exactly match the namespace+class (or namespace+view path). Wrong context → string stays untranslated.
  • IStringLocalizer<T> context comes from T's type — inject the localizer typed to the class that owns the strings.
  • LocalizationSet links translations; never share one set across unrelated items, and don't overwrite it.
  • Add a culture to SupportedCultures before content can be translated into it.
  • DataAnnotations need AddDataAnnotationsPortableObjectLocalization() (the Localization module registers it).

References

  • references/localization.md — PO discovery order, contexts, plural forms, content localization internals, startup wiring
  • src/docs/reference/modules/Localize/README.md (repo)
  • src/docs/reference/modules/ContentLocalization/README.md (repo)
  • src/docs/reference/modules/DataLocalization/README.md (repo)
  • AGENTS.md (repo root) — build commands
Install via CLI
npx skills add https://github.com/OrchardCMS/OrchardCore --skill orchardcore-localization
Repository Details
star Stars 8,092
call_split Forks 2,573
navigation Branch main
article Path SKILL.md
More from Creator