Skip to content

Extract configurable-operation translations out of core .ts files into lingui catalogs #4820

Description

@BibiSebi

Background

PR #4806 added Czech (LanguageCode.cs) translations for configurable operations. To do so it had to edit ~20 core source files (ShippingCalculator, ShippingEligibilityChecker, all promotion actions/conditions, entity duplicators, payment/fulfillment handlers, collection filters) and append a { languageCode, value } entry to every inline LocalizedString[] array.

// packages/core/src/config/shipping-method/default-shipping-calculator.ts
description: [
    { languageCode: LanguageCode.en, value: 'Default Flat-Rate Shipping Calculator' },
    { languageCode: LanguageCode.cs, value: 'Výchozí kalkulátor dopravy s pevnou sazbou' }, // ← added
],

Problem

Inline LocalizedString[] arrays mean every new locale linearly bloats every config file. The translation content (a translator's concern) is interleaved with operation logic (a developer's concern), in the wrong file type, with no tooling. This pattern doesn't scale past a couple of languages and diverges from how the rest of the packages handle i18n (lingui .po catalogs — e.g. packages/dashboard/src/i18n/locales/cs.po).

Proposed approach

Extract configurable-operation labels/descriptions out of the .ts source into dedicated locale catalogs, keep LanguageCode.en inline as the source/default, and use lingui (consistent with the dashboard & other packages). At build time, copy/merge the compiled catalogs into the dashboard.

Sketch:

  • Source .ts keeps only the English default (or a stable message key).
  • Translations live in per-locale catalog files owned by translators, not developers.
  • A build step compiles + copies catalogs into the dashboard bundle.
  • Server resolves LocalizedString for a given languageCode from the catalog rather than from the inline array.

Open questions / decisions

  • Key strategy — derive translation keys from operation code + arg name (e.g. default-shipping-calculator.args.rate.label), or use the English string as the msgid (lingui default)?
  • Backwards compatibility — third-party plugins still ship inline LocalizedString[]. The resolver must fall back to inline arrays so existing plugins keep working.
  • Server vs dashboard — these labels are consumed both server-side (Admin API responses) and in the dashboard UI. Where does resolution happen, and how do catalogs reach both?
  • Build wiring — exact mechanism for the "copy to dashboard at build" step.

Scope

  • Define catalog format + key strategy
  • Resolver with fallback to inline LocalizedString[] (no breaking change for plugins)
  • Build step to compile/copy catalogs into dashboard
  • Migrate core configurable operations off inline arrays
  • Re-apply fix(dashboard,i18n): improve Czech translations #4806 Czech translations in the new structure
  • Docs for plugin authors on the new translation workflow

Related to #4806.

Metadata

Metadata

Assignees

Labels

No labels
No labels
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions