Skip to content

feat(sdk): per-locale module tag labels (TagLabels), mirroring NameLabels#134

Merged
I-am-nothing merged 1 commit into
mainfrom
feat/tag-labels-i18n
Jul 3, 2026
Merged

feat(sdk): per-locale module tag labels (TagLabels), mirroring NameLabels#134
I-am-nothing merged 1 commit into
mainfrom
feat/tag-labels-i18n

Conversation

@I-am-nothing

Copy link
Copy Markdown
Contributor

Problem

The module card (module-info-dialog header + the /modules grid tile) renders a module's TAGS ("Auth") in English regardless of locale. The manifest's defaults.Tags is a raw []string with no per-locale map at all — unlike defaults.NameLabels (per-locale display name, module.name catalog key) and descriptionLabels (added earlier this session), which the web already resolves by locale.

Change (SDK only)

Add ManifestDefaults.TagLabels map[string][]string (locale → localized tag LIST, JSON key tagLabels, omitempty) alongside the existing raw TagsTags stays the default/fallback, mirroring how Name stays the fallback for NameLabels.

Resolution mirrors NameLabels: read the module's i18n catalog at manifest build. New i18n.LookupList(key, sep) is the list counterpart of i18n.Lookup — like Lookup it does not fall back to the raw key, so a locale with no translation is omitted and the web falls back to raw Tags.

Authoring convention (wire shape for the web agent)

Message catalogs are string-valued (flatten() ignores JSON array leaves), so the author packs each locale's tag list into a single comma-separated catalog value under the key module.tags:

// i18n/en-US.json      // i18n/zh-TW.json
"module": {             "module": {
  "name": "OAuth Core",   "name": "使用者核心",
  "tags": "Auth"          "tags": "驗證"
}                       }

The manifest splits on "," and space-trims each tag → tagLabels: { "en-US": ["Auth"], "zh-TW": ["驗證"] }. Multiple tags: "Auth, Payments"["Auth","Payments"].

No api-platform change — the map flows through verbatim as JSONB, the same path NameLabels / descriptionLabels already use.

Tests

  • i18n.LookupList: splits/trims/drops-empties; missing key → empty map (no raw-key fallback).
  • Manifest end-to-end: a module registering module.name + module.tags surfaces nameLabels + tagLabels per-locale; a module with neither leaves both absent (raw Name/Tags fallback).

go build ./... + go vet ./... + go test ./... all green.

Consumer (separate, uncommitted)

ms-app-modules/oauth-core authors module.tags (en-US Auth, zh-TW 驗證) in its catalog — no main.go change needed since tags resolve from the catalog like NameLabels. Verified it compiles against this branch via a temp GOWORK.

Rollout note: the runner's mounted SDK (app-module-sdk-wt-lambda-shim) must include this commit before oauth-core rebuilds — the main session handles that.

🤖 Generated with Claude Code

…bels

The module card (info-dialog header + grid tile) renders the raw
Config.Tags list, so a module's badges stay English regardless of locale.
NameLabels already carries a per-locale display name (module.name catalog
key), but Tags had no per-locale map at all.

Add ManifestDefaults.TagLabels (map[string][]string, locale -> tag LIST,
JSON "tagLabels", omitempty) ALONGSIDE the raw Tags fallback. It resolves
from the module's i18n catalog key "module.tags" whose per-locale value
packs the list into one comma-separated string (message catalogs are
string-valued, so a JSON array leaf can't be used) -- new i18n.LookupList
splits on the delimiter and trims each tag. A locale with no translation
is omitted, so the web falls back to raw Tags exactly as it falls back to
Name for NameLabels. No api-platform change: the map flows through as
JSONB verbatim, the same path DescriptionLabels/NameLabels already use.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@I-am-nothing I-am-nothing merged commit 6f1a34f into main Jul 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant