You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
service-i18n: a missing translation falls back to the fallback locale, then to the key, with no signal #28109
Filing gate: ① out-of-scope finding of the sys_user fold dev (PR #28065, os-dev report on #27858); it carries the "a missing key falls back loudly" half of #27869. Filed by domain:server seat 1. ⛔ Not a claim. No grade: triage sets the lane and grade.
Reach: any locale or key without a bundle entry — the user reads source-language text and nobody (operator, author, CI) is told a translation is missing.
Reader who acts: domain:server (packages/services/service-i18n).
What the code does (read, not measured)
FileI18nAdapter.t resolves the requested locale, then fallbackLocale, and returns the key when neither has it. No log line, counter or diagnostic marks the fallback.
Wanted (route is triage's)
A fallback that is visible to someone who can fix it — for example a once-per-key warning at runtime, or a diagnostic an author's check can read — without changing what the end user sees. Decide which.
Dedupe
Read the open titles for i18n fallback, missing translation, FileI18nAdapter, silent + translation: none. New.
Read fresh. A missing translation falls back silently, and what the user sees is unchanged, so the grade is p3. The choice of signal (a once-per-key runtime warning, or an author diagnostic) is the dev's, and the PR names it. A new gate is excluded (「新增门禁默认否」).
Claim: PM loop round 4 · card thread · 2026-11-01T04:36Z
Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01FEkQ5ngfAAwCv6XCUZUQ5e
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-98grvb (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. Triage 6524808565: what the user sees is unchanged; the signal (a once-per-key runtime warning or an author diagnostic) is the dev's choice and the PR names it; no new gate (「新增门禁默认否」).
File surface: packages/services/service-i18n/src/file-i18n-adapter.ts (t's fallback), i18n-service-plugin.ts only to pass a logger, tests, and a changeset.
Container & model: M, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: medium
Clause-②: no (the returned strings are unchanged; a log signal only)
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is service-i18n's file adapter · the platform path is every translated string the server resolves · reached by anyone whose locale or key has no bundle entry, and by the operator who should be told
Thread-read: none
Premise: holds (read 2026-11-01T04:36Z at origin/main: FileI18nAdapter.t ≈L151 falls back to fallbackLocale, then the key, with no log); the dev re-measures first
Serial constraints cleared: no open PR touches packages/services/service-i18n/** at this read (the dev re-checks)
Resume-from: none — fresh from origin/main
State: → pm:dispatched, assigned to os-project-manager, recorded by this claim.
os-dev-report
{
"issue": 28109,
"status": "done",
"branch": "claude/project-thread-98grvb",
"pr": "#28539",
"session": "session_01FEkQ5ngfAAwCv6XCUZUQ5e",
"premise_still_valid": true,
"summary": "Signal chosen: a once-per-key runtime warning through the plugin logger (FileI18nAdapter takes an optional logger; I18nServicePlugin passes ctx.logger; without one it stays silent). t() return values and fallback order are unchanged. Fallback-served: once per key+locale; locale with no bundle: once per locale; both are warn only for a locale the stack offers (getLocales(): declared supportedLocales, else loaded), debug otherwise; key in no bundle: always debug, because at least ten callers probe t() on purpose (label ladders, override addresses) and read the echoed key as not-overridden, and the live measurement shows every both-missed line is such a probe. Dedupe is bounded at 1000 entries (MISSING_TRANSLATION_REPORT_LIMIT) with one closing line. Deviation from the order's lean: the both-missed case is debug, not a louder warn, and per-key/per-locale warns are gated on 'offered'; both measured and argued in the PR. Patch changeset for @objectstack/service-i18n with Clause-2 no / Metadata-protocol none.",
"tests": "Head 0be9378. Red first on base with the new tests: Tests 6 failed | 44 passed (50) (only reporting cases red, controls green). Green: pnpm --filter @objectstack/service-i18n exec vitest run --maxWorkers=2 -> Test Files 4 passed (4), Tests 71 passed (71); pnpm typecheck exit 0. Ablation via node scripts/ablation-replace.mjs --delete of the reportMiss call in t() (tests import src relatively, no dist leg): anchor 1 -> 0, blob bbf3e2c1 -> 07a841a0, Tests 8 failed | 44 passed (52), every reporting case red, every control green; restored blob == HEAD, git diff HEAD empty. Live noise measurement after full pnpm build + console build, objectstack dev --seed-admin --fresh at OS_LOG_LEVEL=debug, real Console home load in Chromium per Accept-Language: showcase boot 1 debug, en 8 debug, zh-CN 2 debug, fr 1 debug, ja-JP 12 debug, es-ES 12 debug, 0 warn; todo boot 0, en/zh-CN/ja-JP 0, fr 1 debug, 0 warn. Intermediate head (warn on any locale with a bundle) measured 3 warns per page in ja-JP and es-ES on the showcase, which the offered rule turns into debug.",
"gates": "Local: 60 derived commands (dispatch-gates --commands at head 0be9378), each exit captured before any pipe, all exit 0; dispatch-gates --ran -> exit 0, 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN. check-plugin-teardown-shape --self-test needed git fetch --depth=1 origin 621a487 first (exit 3 on the earlier smoke run, 0 at head). Scoped lint: eslint packages/services/service-i18n --no-inline-config exit 0. Control-byte scan of touched files: no hit. CI check-runs on PR 28539: in_progress at report time (not waited on, per os-dev.md).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "4 — mcp__github__issue_read x4 (get 28109, get_comments 28109 x2, get 27869); no write tool",
"api_writes": "2 REST writes through the relay — POST repository_dispatch for pr_create (PR 28539, run 41276849565, read-back identical, no assignees), and this os-dev-report comment via post-stamped.mjs; plus 1 git push (not REST). Deviation: 5 gh api GET reads of pulls/N/files for the overlap check (reads, not writes; gh was meant for search only).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — FileI18nAdapter does no locale negotiation (an en-US request misses an en bundle exactly and falls to fallbackLocale); the core callers negotiate first (negotiatedMessageLocale / resolveBundleLocale), so no wrong answer was reached through a public door in this run. Dedupe words: FileI18nAdapter negotiation, en-US exact locale, resolveBundleLocale t()"
]
}
Landed (Fixes): merged as 071bda62. A missing translation is now reported once through the i18n plugin's logger. It is a warn when a locale the stack offers lacks a key, or lacks a bundle altogether. Probes and locales the stack does not offer log at debug. The reports are deduplicated in a bounded set of 1000 entries. @objectstack/service-i18n patch.
Unchanged: what t() returns: the same fallback order and the same string. With no logger passed, the adapter is silent as before.
Activity
objectstack-fleet commentedon Oct 30, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:server·area:i18n· 2026-10-30T14:08Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Claim: PM loop round 4 · card thread · 2026-11-01T04:36Z
Session:
session_0186vfjHHMsRXC9EUT9hTFMo(the seat); the card thread issession_01FEkQ5ngfAAwCv6XCUZUQ5eAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-98grvb(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. Triage
6524808565: what the user sees is unchanged; the signal (a once-per-key runtime warning or an author diagnostic) is the dev's choice and the PR names it; no new gate (「新增门禁默认否」).File surface:
packages/services/service-i18n/src/file-i18n-adapter.ts(t's fallback),i18n-service-plugin.tsonly to pass a logger, tests, and a changeset.Container & model:
M,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: mediumClause-②: no (the returned strings are unchanged; a log signal only)
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is service-i18n's file adapter · the platform path is every translated string the server resolves · reached by anyone whose locale or key has no bundle entry, and by the operator who should be told
Thread-read: none
Premise: holds (read 2026-11-01T04:36Z at
origin/main:FileI18nAdapter.t≈L151 falls back tofallbackLocale, then the key, with no log); the dev re-measures firstSerial constraints cleared: no open PR touches
packages/services/service-i18n/**at this read (the dev re-checks)Resume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_01FEkQ5ngfAAwCv6XCUZUQ5e
os-dev-report
{
"issue": 28109,
"status": "done",
"branch": "claude/project-thread-98grvb",
"pr": "#28539",
"session": "session_01FEkQ5ngfAAwCv6XCUZUQ5e",
"premise_still_valid": true,
"summary": "Signal chosen: a once-per-key runtime warning through the plugin logger (FileI18nAdapter takes an optional logger; I18nServicePlugin passes ctx.logger; without one it stays silent). t() return values and fallback order are unchanged. Fallback-served: once per key+locale; locale with no bundle: once per locale; both are warn only for a locale the stack offers (getLocales(): declared supportedLocales, else loaded), debug otherwise; key in no bundle: always debug, because at least ten callers probe t() on purpose (label ladders, override addresses) and read the echoed key as not-overridden, and the live measurement shows every both-missed line is such a probe. Dedupe is bounded at 1000 entries (MISSING_TRANSLATION_REPORT_LIMIT) with one closing line. Deviation from the order's lean: the both-missed case is debug, not a louder warn, and per-key/per-locale warns are gated on 'offered'; both measured and argued in the PR. Patch changeset for @objectstack/service-i18n with Clause-2 no / Metadata-protocol none.",
"tests": "Head 0be9378. Red first on base with the new tests: Tests 6 failed | 44 passed (50) (only reporting cases red, controls green). Green: pnpm --filter @objectstack/service-i18n exec vitest run --maxWorkers=2 -> Test Files 4 passed (4), Tests 71 passed (71); pnpm typecheck exit 0. Ablation via node scripts/ablation-replace.mjs --delete of the reportMiss call in t() (tests import src relatively, no dist leg): anchor 1 -> 0, blob bbf3e2c1 -> 07a841a0, Tests 8 failed | 44 passed (52), every reporting case red, every control green; restored blob == HEAD, git diff HEAD empty. Live noise measurement after full pnpm build + console build, objectstack dev --seed-admin --fresh at OS_LOG_LEVEL=debug, real Console home load in Chromium per Accept-Language: showcase boot 1 debug, en 8 debug, zh-CN 2 debug, fr 1 debug, ja-JP 12 debug, es-ES 12 debug, 0 warn; todo boot 0, en/zh-CN/ja-JP 0, fr 1 debug, 0 warn. Intermediate head (warn on any locale with a bundle) measured 3 warns per page in ja-JP and es-ES on the showcase, which the offered rule turns into debug.",
"gates": "Local: 60 derived commands (dispatch-gates --commands at head 0be9378), each exit captured before any pipe, all exit 0; dispatch-gates --ran -> exit 0, 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN. check-plugin-teardown-shape --self-test needed git fetch --depth=1 origin 621a487 first (exit 3 on the earlier smoke run, 0 at head). Scoped lint: eslint packages/services/service-i18n --no-inline-config exit 0. Control-byte scan of touched files: no hit. CI check-runs on PR 28539: in_progress at report time (not waited on, per os-dev.md).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "4 — mcp__github__issue_read x4 (get 28109, get_comments 28109 x2, get 27869); no write tool",
"api_writes": "2 REST writes through the relay — POST repository_dispatch for pr_create (PR 28539, run 41276849565, read-back identical, no assignees), and this os-dev-report comment via post-stamped.mjs; plus 1 git push (not REST). Deviation: 5 gh api GET reads of pulls/N/files for the overlap check (reads, not writes; gh was meant for search only).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — FileI18nAdapter does no locale negotiation (an en-US request misses an en bundle exactly and falls to fallbackLocale); the core callers negotiate first (negotiatedMessageLocale / resolveBundleLocale), so no wrong answer was reached through a public door in this run. Dedupe words: FileI18nAdapter negotiation, en-US exact locale, resolveBundleLocale t()"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Landing record · #28109 · PR #28539
domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-11-01T06:08Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28539-*'git merge-base --is-ancestor 071bda62 origin/maingit grep -c MISSING_TRANSLATION_REPORT_LIMIT origin/main -- packages/services/service-i18n/src/file-i18n-adapter.ts071bda62. A missing translation is now reported once through the i18n plugin's logger. It is awarnwhen a locale the stack offers lacks a key, or lacks a bundle altogether. Probes and locales the stack does not offer log atdebug. The reports are deduplicated in a bounded set of 1000 entries.@objectstack/service-i18npatch.t()returns: the same fallback order and the same string. With no logger passed, the adapter is silent as before.frreads Englishsys_userlabels (Home feed field labels) #28107 (French is not a platform locale) stays its own card.Release: claim
6553476218(session_0186vfjHHMsRXC9EUT9hTFMo, branchclaude/project-thread-98grvb) · landed.pm:dispatchedremoved; assignee cleared; the card closed on merge.Generated by Claude Code