Skip to content

i18n: @objectstack/core's exported resolveLocale is a verbatim second copy of @objectstack/spec's resolveBundleLocale — one rule, two places to edit #16085

Description

@claude

Observation

@objectstack/core ships a second, behaviourally identical copy of the locale-negotiation rule that @objectstack/spec owns.

Measured on origin/main at merge base 31403453d:

  • packages/spec/src/system/i18n-resolver.ts exports resolveBundleLocale(bundle, requested) — the rule the platform treats as authoritative. Four steps: exact match, case-insensitive match, base-language match, variant expansion. pickData calls it, and every document translator goes through pickData; packages/spec/src/system/validation-message.ts and packages/spec/src/system/operation-message.ts both call it directly for their built-in catalogs.
  • packages/core/src/fallbacks/memory-i18n.ts exports resolveLocale(requestedLocale, availableLocales) — the same four steps, in the same order, with the same comments naming the same examples (zh-cn to zh-CN, zh-CN to zh, zh to zh-CN). It is list-shaped where the spec one is record-shaped; that is the whole difference.

Why it is filed as an observation, not a defect

The two produce the same answer for every input this repo can construct, so nothing is wrong today. It is a maintenance hazard, not a live bug:

Where

  • packages/core/src/fallbacks/memory-i18n.tsresolveLocale, and its two call sites in resolveTranslations.
  • packages/spec/src/system/i18n-resolver.tsresolveBundleLocale, the rule it duplicates.

Suggested shape, if it is taken

Have resolveLocale delegate to resolveBundleLocale rather than re-derive the steps, or retire it in favour of a call to the spec rule. Either way the check to keep is that the two never diverge; a delegating one-liner makes divergence impossible rather than merely unlikely.

Found while implementing #15757, which routes the write path's validation-message bridge through resolveBundleLocale so that path stops being a second negotiation rule of its own. This is the third copy that card's premise implies, spotted on the way; it is out of that card's scope and is not changed by it.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions