Repository navigation
feat(i18n): spec 019 foundation: language packs, checker, problem+json, dashboard runtime - #668
ValgulNecron wants to merge 39 commits into
Conversation
… and i18n-check Spec 019 T001-T004, T007-T019: new Go module i18n/ (go.work, GO_MODULES, CI matrices, dependabot, coverage gate 90), ICU MessageFormat subset parser/formatter with CLDR plurals, pack load/validate/completeness, embedded catalog with regional -> base -> en fallback, the i18n-check CLI and one seeded defective fixture per finding code. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Spec 019 T005, T006 (web), T024-T033: react-intl provider with language resolution, storage and no-flash boot snippet; locale-aware formatting helpers replacing hard-coded en-US; problem+json parsing in APIError with err.body kept as the English detail; extract/compile/manifest scripts; formatjs ESLint rules on migrated paths. No visible UI change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Spec 019 T006 (api/operator), T020-T023: api/internal/messages registry (server.* ids with translator notes), httperr.Message and WriteMessage, RFC 9457 problem details only when Accept lists application/problem+json with q > 0 (plain-text bodies stay byte-identical), 5xx never echo error text or args, messages-export command and make i18n-sync writing the server.* entries into i18n/locales/en/app.json. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Spec 019 T034, T048: the web job builds the language manifest, runs i18n-check (extraction drift, server-message drift, before/after completeness in the job summary) and self-tests the checker on the seeded defective packs; make check-i18n joins make lint. i18n-check now creates the manifest's directory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…tions golangci-lint (gosec G703, staticcheck QF1001) on the new i18n module. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
eslint formatjs/enforce-description on src/lib/i18n/serverMessage.ts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
CI Report - 2ec9b39run 38323667797 - attempt 1 1 failed - 29 passed - 0 skipped - 97m44s elapsed Failing
Coverage
Changed
Slowest jobs
e2e buckets run
|
|
Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
…guage Spec 019 T036, T038-T041, T093: migration 016 adds user_preferences.language; PUT /users/me/language (listed languages only, server.i18n.unknown_language); language in GET /users/me/preferences; unauthenticated GET /auth/locale exposing only defaultLanguage; admin config section i18n validated against the listed languages (server.i18n.unlisted_language). E2E for /auth/locale in the api-auth bucket. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
…ider Spec 019 T042, T046, T047: Users.setLanguage and Auth.locale endpoints, AppI18nProvider reading the cached /users/me language and /auth/locale default, and the 0% fixture language behind VITE_I18N_FIXTURES=1. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> GameServerStatus gains conditionArgs (map of condition type to the values interpolated into its English message), set after each status pass and cleared when the reason carries no values. The condition-ids generator writes condition.<type>.<reason> English entries into the reference pack and has a -check mode for drift. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Sinks take an optional language (validated against the listed languages). Titles, details and test text come from notify.* catalog entries in the sink language, then the instance default, then English. Webhook payloads add language, title and text and keep every existing field. English output is unchanged. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Every 4xx http.Error in handlers, auth, ws and rbac now goes through httperr.WriteMessage (registry id) or httperr.WriteCode (generic id). Plain-text bodies stay byte-identical; 5xx stays http.Error. Unauthenticated login and OIDC paths only use server.auth.invalid_credentials or generic ids. make i18n-sync also syncs notify.* and condition.* ids, and i18n-check covers notify.* drift. Adds the problem+json E2E and ticks the 019 US5 backend tasks. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> i18n-check gains --valid-out, which writes each pack's usable entries. The compile script and the web image use it, so a broken translation shows the English text instead (FR-018). Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
valgul approved this expectation change on the spec 019 decision card. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> New i18n/modlocale derives module ids from module.yaml and template.yaml with reversible ~0/~1 escaping. gp-module gains i18n extract and i18n stamp, validate checks locales/*.json, and package adds one OCI layer per language and includes locales/ in --output tarballs. i18n-check --module checks en.json drift and validates translations. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Every module source (OCI, directory, git, HTTP, upload) carries locales/*.json. The Module reconciler validates them against the template's ids and writes valid entries to <template>-locales in the operator namespace. GameTemplate status gains conditions; LocalesValid reports WriteFailed, LocalesTooLarge (naming oversized languages) or InvalidEntries, and the Warning event fires only when problems change. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GET /modules/{name}/locales/{tag} returns the module's messages for the
tag, its base language, or {} (also for a malformed tag). Uploads may
include locales. Records valgul's US6 rulings as OD-005..OD-014.
Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Each locale file was capped at 900 KiB but a bundle could carry any number of them. Languages past the 4 MiB budget are reported as oversized (LocalesTooLarge), the same as an oversized file. Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> valgul ruled on OD-007 (report in validate), OD-009 (WriteFailed ranks first) and OD-013 (i18n-check --module --stamp stays an error). Signed-off-by: Claude <noreply@anthropic.com>
The locale check needs GameplanePanel/Gameplane#668 on master; running it last keeps the build.sh and validate.py tests visible meanwhile. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
Design for T043, T072 and T094 of spec 019, with exports. - Personal settings: a Language card is the first card of Theme & Appearance (also on the Warnings variant), plus a mobile screen. - Login and share pages: a compact picker in the top-right corner of the card on every state, and a screen with its menu open. It shows language names only. - Notifications: a Language select on each sink row and a new screen for the Add sink form, which the design did not have. - Admin settings: a Language card with the Default language field. Records the placement rulings as OD-015 to OD-017 and ticks the three design tasks. loginCard (J14ME) is unchanged: Pencil cannot insert a child into it, so the login screens use a wrapper component (see assets/design-export/MANIFEST.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com>
PR #668 conflicted with master, so no CI run started. Four conflicts, one hunk each, resolved by keeping both sides: - Makefile: lint runs check-i18n and check-coverage-gaps. - api/go.mod: golang.org/x/sys v0.49.0 from master; golang.org/x/text stays a direct requirement. - web/package.json and web/package-lock.json: the @formatjs dev dependencies from the branch, @playwright/test ^1.64.0 from master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com>
|
Cause: this PR's Generated by Claude Code |
…lgul) The dashboard asks for the instance default language on every page load. Without a mock route the request reached the dev proxy and returned 502, which failed the console-error checks in serverDetail.spec.ts and settingsSubTabs.spec.ts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
…approved by valgul) --module now checks en.json against the ids the template derives (OD Q4), so the fixture template declares spec.displayName and the packs use the derived id template.displayName. Both cases and exit codes are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
hadolint DL3062 flags go run without a version; building the local package and running the binary does the same work. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
…ad-awjqv0 Signed-off-by: Claude <noreply@anthropic.com>
Codegen drift gate (make tidy) expects the tidied i18n/go.sum. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
|
This isn't caused by this PR: it doesn't touch that file, and master 2155568 has the same mismatch. #672 and #674 each flipped a gap against the same old summary line. No fix exists yet. I've asked the spec 013 thread, which owns the file, to fix it on master. I'll merge master here once the fix lands. Generated by Claude Code |
golangci-lint: errcheck on the i18n command's output writes, gosec G602 on the --output value read, and G703 on the stamp write. Translations are now written through an os.Root on the locales directory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
gosec G703 on the condition-ids generator's write of app.json. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
|
The test races the capabilities query. It asserts the Completed row's download button is enabled right after the list renders, but A fix already exists on #677 (a8ffe53, which wraps the assertion in Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
- gp-module: locale archive fixture includes the required README.md - api/db: theme migration test applies the remaining migrations before reading preferences (016 adds language) - api/handlers: TestValidateI18n checks the canonical JSON; the locales test path-escapes its invalid tag so the request reaches the handler - e2e: close the locales response body; drop two unused ct assignments Each change approved by valgul on its decision card. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
misspell flags the French "Exemple" as a typo of "Example". The fixture pair becomes Template/Modèle; the test still compares message ids only. Approved by valgul. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Claude <noreply@anthropic.com>
|
The cause is in this PR. The new Fixing it means editing the new test. This repo needs explicit sign-off for test edits, and one option (a different IP) was declined. The fix is waiting on a decision in the project thread. Generated by Claude Code |
Before: Gameplane has no translation system. Dashboard text, API errors and notifications are English-only, and dates and numbers are hard-coded to
en-US.After: Gameplane has one shared catalog and its checks, still behind an English-only catalog. A new
i18n/Go module holds the language packs, an ICU MessageFormat formatter, a pack validator and thei18n-checkCI tool. The API returns RFC 9457 problem details with amessageIdonly to clients that ask forapplication/problem+json. The dashboard has a react-intl runtime: language resolution, a no-flash<html lang>boot snippet and locale-aware formatting. Nothing visible changes in English, and plain-text API error bodies stay byte-identical.This is the foundation (Phases 1–2) of spec 019, tasks T001–T034 plus T048. The pickers and the per-story work come in later PRs.
How
i18n/:icu(parser for the ICU subset, CLDR plurals viagolang.org/x/text),pack(load, validate with the finding codes from contracts/check-tool.md, completeness, 80% listing rule),catalog(embedded packs, regional → base → English fallback, invalid translations dropped),cmd/i18n-checkand one seeded defective fixture per finding code (SC-007). Coverage gate 90; the module is added to go.work, GO_MODULES, the CI matrices and dependabot.api/internal/messagesregistry (server.*ids with translator notes).httperr.MessageandWriteMessage. Content negotiation parsesAcceptq-values, and wildcards never select problem details. 5xx responses never echo error text or args.make i18n-syncwrites the registry intoi18n/locales/en/app.json.src/lib/i18n/(provider, resolution order FR-004, storage, format helpers, server-message mapping).APIErrorparses problem bodies but keepserr.bodyas the English detail, so existing callers are unchanged. New scriptsi18n:extract,i18n:compileandi18n:manifest. TheformatjsESLint rules are scoped to migrated paths. The Dockerfile builds the language manifest in a Go stage.webjob builds the manifest and runsi18n-check, which checks extraction drift and server-message drift and writes before/after completeness to the job summary. It also self-tests the checker on the fixtures.make check-i18njoinsmake lint.Spec notes
--registry <file>was added toi18n-checkfor the two server flags, and contracts/check-tool.md is updated to match.go:embedlives in the rooti18npackage because embed paths cannot use...Only compile checks and the generators were run locally (
go build,tsc --noEmit,npm run build,make i18n-sync). Tests and lint run here in CI.🤖 Generated with Claude Code
Generated by Claude Code