CtrlK
BlogDocsLog inGet started
Tessl Logo

orchardcore-localization

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.

75

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

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

GoalLayer
Translate a label/message in code or a viewUI localization (S/T/H) + PO file
Pluralize ("1 item" / "{0} items")S.Plural(...) + PO msgid_plural
Translate a blog post into FrenchContent localization (LocalizationPart)
Add a supported language / set defaultLocalization 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

LocalizerConventionWhere
IStringLocalizer<T>field Sdrivers, services, controllers
IViewLocalizerproperty TRazor views (already on RazorPage)
IHtmlLocalizer<T>field Hwhen 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

SymbolTypeOutput
SIStringLocalizer<T>plain string
TIViewLocalizerencoded view string
HIHtmlLocalizer<T>HTML-safe string

Content localization APIs

MemberPurpose
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

ProviderPicks culture from
ContentRequestCultureProviderthe localized content route (added first)
AdminCookieCultureProvideradmin_culture_* cookie, admin paths only
cookie / querystring / Accept-LanguageASP.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
Repository
OrchardCMS/OrchardCore
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.