OrchardCMS/OrchardCore · error · InvalidOperationException

Cannot localize an unsupported culture

Error message

Cannot localize an unsupported culture

What it means

DefaultContentLocalizationManager.LocalizeAsync validates the requested target culture against the site's configured supported cultures (ILocalizationService.GetSupportedCulturesAsync) using a case-insensitive comparison. If the culture is not supported it throws InvalidOperationException, because localization cannot proceed without a culture the site can serve.

Solutions

  1. Add the target culture in admin Settings > Localization before localizing.
  2. Pass a culture exactly as listed by ILocalizationService.GetSupportedCulturesAsync (case-insensitive).
  3. Validate the culture with the supported-cultures list in your own code before calling LocalizeAsync.
  4. Fall back to a supported parent culture (e.g. 'fr' instead of 'fr-CA') if the regional variant is absent.

Example fix

// before
await _contentLocalizationManager.LocalizeAsync(item, "fr-CA"); // throws if not supported
// after
var supported = await _localizationService.GetSupportedCulturesAsync();
var culture = supported.FirstOrDefault(c => c.StartsWith("fr", StringComparison.OrdinalIgnoreCase)) ?? throw new InvalidOperationException("Add a French culture first");
await _contentLocalizationManager.LocalizeAsync(item, culture);
Defensive patterns

Strategy: validation

Validate before calling

var supported = await _localizationService.GetSupportedCulturesAsync();
if (!supported.Any(c => string.Equals(c, targetCulture, StringComparison.OrdinalIgnoreCase)))
    throw new ArgumentException($"Culture '{targetCulture}' is not enabled for this site.", nameof(targetCulture));

Type guard

static bool IsSupportedCulture(IEnumerable<string> supported, string culture) => supported.Any(c => string.Equals(c, culture, StringComparison.OrdinalIgnoreCase));

Try / catch

try { var localized = await _contentLocalizationManager.LocalizeAsync(item, culture); }
catch (InvalidOperationException ex) when (ex.Message == "Cannot localize an unsupported culture")
{
    logger.LogWarning("Culture {Culture} not enabled; falling back to source item", culture);
    localized = item;
}

Prevention

When it happens

Trigger: Calling IContentLocalizationManager.LocalizeAsync(content, targetCulture) with a culture string that is not enabled under Settings > Localization (e.g. 'fr-FR' when only 'en-US' and 'de' are configured), or with a misspelled culture code.

Common situations: Programmatic translation workflows passing cultures that were never added to the site; cultures removed from settings after custom code was written; regional variants ('pt-BR' vs 'pt') not configured.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/4ab28683af20afef. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.ContentLocalization/DefaultContentLocalizationManager.cs:71

    }

    public async Task<IEnumerable<ContentItem>> GetItemsForSetAsync(string localizationSet)
    {
        return await _session.Query<ContentItem, LocalizedContentItemIndex>(i => (i.Published || i.Latest) && i.LocalizationSet == localizationSet).ListAsync();
    }

    public async Task<IEnumerable<ContentItem>> GetItemsForSetsAsync(IEnumerable<string> localizationSets, string culture)
    {
        var invariantCulture = culture.ToLowerInvariant();
        return await _session.Query<ContentItem, LocalizedContentItemIndex>(i => (i.Published || i.Latest) && i.LocalizationSet.IsIn(localizationSets) && i.Culture == invariantCulture).ListAsync();
    }

    public async Task<ContentItem> LocalizeAsync(ContentItem content, string targetCulture)
    {
        var supportedCultures = await _localizationService.GetSupportedCulturesAsync();
        if (!supportedCultures.Any(c => string.Equals(c, targetCulture, StringComparison.OrdinalIgnoreCase)))
        {
            throw new InvalidOperationException("Cannot localize an unsupported culture");
        }

        var localizationPart = content.GetOrCreate<LocalizationPart>();
        if (string.IsNullOrEmpty(localizationPart.LocalizationSet))
        {
            // If the source content item is not yet localized, define its defaults.
            localizationPart.LocalizationSet = _iidGenerator.GenerateUniqueId();
            localizationPart.Culture = await _localizationService.GetDefaultCultureAsync();
            await _session.SaveAsync(content);
        }
        else
        {
            var existingContent = await GetContentItemAsync(localizationPart.LocalizationSet, targetCulture);

            if (existingContent != null)
            {
                // Already localized.
                return existingContent;

View on GitHub (pinned to 4306c0717f)