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
Commit deabe3b
Browse filesBrowse the repository at this point in the historyBrowse files
fix(settings): settings copy is written in all eleven platform languages, zh-TW reads Traditional, and sms/test answers in the caller's language (#30630) (#30734)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9D9ZFYWnf6P6tsGrp2D14eMY)_Fixes#30630
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:设置里 7 张"按调用者语言写"的文案表(IP 白名单拒存、登录方式下限、两处 MFA
拒存与开启提示、邮件实时投递状态与测试邮件答复、默认币种锁定、"已不再提供")补齐平台 11
种语言;"发送测试短信"改为按调用者语言答复;设置服务自带的"重置"结果与"未注册处理程序"也按语言答复。
- 为什么改:这些表只有 4 种(邮件只有 2
种)语言,法语、德语、韩语等用户看到英文;繁体中文(zh-TW)用户被回成简体;测试短信从不读语言,永远英文。
- 风险与回滚:只改文案与选语言的查表,不改任何判定、错误码或接口;英文原句逐字不变。回滚即撤本 PR。
-
先看:`packages/services/service-sms/src/sms-plugin.ts`(测试短信接上语言);`packages/services/service-settings/src/settings-service.ts`
的 `runAction`
两处内置答复;`packages/plugins/plugin-auth/src/settings-copy-locale.test.ts`(逐表
11 语言 pin)。
- 两分钟验证:`pnpm --filter @objectstack/service-sms exec vitest run
src/sms-test-recipient.pin.test.ts`,预期全绿,其中 zh-TW 的测试短信答复以「測試簡訊已傳送至」开头。
- 需要你做的:无,席位落地。
## What changes
Every module-local settings copy table (sentences composed per request,
which the console's translation bundle cannot carry) now has one entry
per language on the platform locale table (`PLATFORM_LOCALES`: `en`,
`zh-Hans`, `zh-Hant`, `es`, `ar`, `fr`, `pt-BR`, `ru`, `de`, `ja`,
`ko`). The four languages the tables served first keep their codes
(`zh-CN`, `ja-JP`, `es-ES`); the rest use the table's tags, the shape
`storage/test` uses (PR #30627). Translations are real text in every
language, with no English fill.
The seven tables the card names, measured on `origin/main` (`grep` for
the four-locale key sets and for `resolveLocale` callers in the three
packages):
| Package | Table | Before |
| --- | --- | --- |
| `plugin-auth` | `allowed-ip-ranges.ts` save refusal (now exported as
`ALLOWED_IP_RANGES_REFUSAL_COPY` for its pin) | 4 |
| `plugin-auth` | `sign-in-method-floor.ts` `SIGN_IN_FLOOR_COPY` | 4 |
| `plugin-auth` | `mfa-required-enrollment-predicate.ts`
`MFA_REQUIRED_ENROLLMENT_COPY` | 4 |
| `plugin-auth` | `organization-mfa-enrollment-guard.ts` refusal + save
notice (two tables, one lookup) | 4 |
| `plugin-email` | `live-transport-status.ts` `MAIL_DELIVERY_COPY` | 2
(`en`, `zh-CN`) |
| `service-settings` | `localization-currency-lock.ts`
`CURRENCY_LOCK_COPY` | 4 |
| `service-settings` | `localization-locale-options.ts`
`NOT_OFFERED_COPY` | 4 |
The lookup stays core's `resolveLocale`. #30538 is closed and its fix
landed: `resolveLocale` is now `resolveLocaleAmong`, which reads a code
through the platform table's read aliases before the base-language and
variant steps. So with a `zh-Hant` key present, `zh-TW` / `zh-HK` /
`zh-MO` reach it and never `zh-CN`; `pt` reaches `pt-BR`; a code naming
no table language answers `undefined`, which every table serves in
English. No per-table copy of the reader was added.
- **`sms/test`** (`service-sms`): the handler now reads the action
input's `locale` (the route passes `Accept-Language`, else `?locale`)
and writes every answer from a new eleven-language table,
`sms-test-copy.ts`: the five recipient refusals, missing credential,
transport build failure, log-only warning, sent, and failed. A
provider's or the engine's own error text passes through verbatim,
behind a lead-in outside English. The English sentences are
byte-identical to before.
- **The two built-in settings answers** (`service-settings`,
`SettingsService.runAction`): the built-in `reset` result and "No
handler registered for action ..." are written from a new
eleven-language table, `settings-action-copy.ts`, in `display.locale`.
English unchanged.
- One type per package names the eleven keys (`settings-copy-locale.ts`
in `plugin-auth` and `service-settings`, `MailDeliveryCopyLocale`,
`SmsTestCopyLocale`), so a table missing a language fails `tsc`. Arabic
and Russian counts (MFA grace days, currency usage, reset count) use
their plural forms.
## Why
A Setup caller in French, German, Korean, Arabic, Russian, Brazilian
Portuguese or Traditional Chinese read these sentences in English (or,
for `zh-TW`, in Simplified Chinese), and `sms/test` ignored the caller's
language entirely. The eleven-language rule (ruling F of #29349) holds
every surface to the platform table.
## Tests
- New pins, one per table, each asserting: exactly one entry per
platform table language; every field present and non-empty in every
entry and different from English (no fill); each table tag and each
stored alias (`zh-TW`, `zh-HK`, `zh-CN`, `zh`, `ja-JP`, `es-ES`, `pt`,
`en-US`, `fr-CA`, `de-AT`) served its own language; `zh-TW` never served
the Simplified entry; an off-table code (`xx`, `sw-KE`) and no code
served English.
- `plugin-auth/src/settings-copy-locale.test.ts` (5 tables), plus
Russian/Arabic plural cells.
- `plugin-email/src/live-transport-status.pin.test.ts` (new top-level
`describe` in the existing harness).
- `service-settings/src/settings-copy-locale.test.ts` (currency lock,
not-offered, built-in action answers).
- `service-sms/src/sms-test-copy.test.ts`, including the English
sentences pinned byte-identical.
- Served doors: `service-sms/src/sms-test-recipient.pin.test.ts` drives
the real settings route with an `Accept-Language` header:
`zh-TW,zh;q=0.9` answers "測試簡訊已傳送至 …,經由 twilio(id=SM_test)。"; `fr`,
`de-DE`, `ko` refusals are in those languages and send nothing; no
header and `sw-KE` stay English.
`service-settings/src/settings-service.test.ts` pins the reset result in
`zh-TW` and `ru` and the no-handler refusal in `de-DE`, English for none
/ `sw-KE`.
- Updated pins that encoded the four-language state: the currency-lock
coverage pin (was "exactly the bundle's four locales") and its `fr-FR`
row (was English); the email control (`fr-FR` was English, now `sw-KE`);
the `mfa_required` and organization-MFA unknown-locale cells (`fr-FR` →
`sw-KE`, `fr-FR` now French, `zh-TW` added); the organization notice's
"1 is a digit in every language" cell accepts Arabic's word form for one
day ("يوم واحد").
## Acceptance notes
- **Overlap with open PR #30448** (`allowed-ip-ranges.ts`): it rewrites
the `recovery` sentence in the four languages it had. This PR translates
the current one-step recovery into the seven new languages. Whichever
lands second owes the four-step recovery in all eleven; a text conflict
on the `es-ES` hunk is possible.
- **`zh-Hant-TW` / `zh-Hans-CN` are not read through the table** by the
shared resolver: `resolveLocaleAmong`'s table step looks the whole code
up, misses, and the variant step returns the first `zh*` key, `zh-CN`. A
caller whose display language is `zh-Hant-TW` therefore still reads
Simplified here and in every other bundle the resolver serves. The
resolver lives in `packages/spec` (outside this card's file surface);
reported to the seat, not fixed here.
- Labels the copy names on screen ("Send test SMS", "Setup →
Authentication", the mail provider "None (log only)") come from the
settings translation bundle, which ships four languages (#30512's
surface). In the seven new languages the copy describes those controls
instead of quoting a label the console does not show in that language.
- The SMS body sent to the phone (`ObjectStack SMS test message.`) is
unchanged: it is the message, not the answer.
## Verification
Head `b1014f4d` (`a54649c1` the fix, `c3f79fc1` a merge of `origin/main`
at `badf24df`, then two test-only commits). Readings under
`scripts/pm/os-verify-lock.sh` on a shared box.
<details><summary>Repro on origin/main (base 4bf9a2d)</summary>
With the nine edited sources restored to the base (`git restore
--source=4bf9a2d7`, tests from this branch), restored afterwards with
`git checkout HEAD -- packages` and `git diff HEAD` empty:
- `signInFloorCopy('zh-TW')` is the `zh-CN` entry (Simplified);
`signInFloorCopy('fr')` is English; the table's keys are
`en,zh-CN,ja-JP,es-ES`.
- `sms/test` through the served route with `Accept-Language:
zh-TW,zh;q=0.9` answered `Sent test SMS to +8613*******01 via twilio
(id=SM_test).`
- The new pins on the base: plugin-auth 22 failed / 27, service-sms 4
failed (served door), service-settings 8 failed / 156, plugin-email 4
failed / 21.
</details>
<details><summary>Ablations (scripts/ablation-replace.mjs, anchor 1 → 0,
restored to the HEAD blob, git diff HEAD empty; tests import
src/)</summary>
| Ablated | Red |
| --- | --- |
| `sign-in-method-floor.ts`: the lookup reads only the four old keys
(`resolveLocale(locale, ['en','zh-CN','ja-JP','es-ES'])`) | 2 of 26 in
`settings-copy-locale.test.ts` (tags/aliases served their own language;
zh-TW never Simplified) |
| `sms-plugin.ts`: the handler ignores the input locale
(`smsTestCopy(undefined)`) | 4 of 16 in `sms-test-recipient.pin.test.ts`
(zh-TW sent, fr / de-DE / ko refusals) |
</details>
<details><summary>Suites and typecheck</summary>
After the merge of `origin/main`: closure build of the four packages
(`pnpm --filter 'PKG^...' … build`) exit 0, then per package typecheck
(with `check:test-typecheck`) and `pnpm --filter PKG test`:
- `@objectstack/plugin-auth`: typecheck exit 0; Test Files 228 passed
(228), Tests 4088 passed, 10 skipped (4098).
- `@objectstack/plugin-email`: typecheck exit 0; Test Files 48 passed
(48), Tests 805 passed (805).
- `@objectstack/service-settings`: typecheck exit 0; Test Files 70
passed (70), Tests 1195 passed (1195).
- `@objectstack/service-sms`: on `b1014f4d` typecheck exit 0
(`check:test-typecheck: OK`); Test Files 9 passed (9), Tests 119 passed
(119).
</details>
<details><summary>Gates</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 63 commands on `b1014f4d`; each run
with its exit code recorded before any pipe. `--ran`: 63 derived, 62
run, 1 NOT-MEASURED, 0 UNRUN. NOT MEASURED: `pnpm
check:dual-build-cjs-loads` (exit 3, PREREQUISITE NOT MET: it needs a
whole-workspace build; CI runs it). `check:test-source-alias` first went
red on the new `sms/test` copy pin (it read `@objectstack/spec/system`
from the build); fixed by the anchored source alias in
`service-sms/vitest.config.ts`, then exit 0. Every other command exited
0. `pnpm lint` exit 0.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4d1JeXeWGVzxc12FsUx)_
<!-- signed: domain:server#5 · os-elon-musk ·
session_016WV4d1JeXeWGVzxc12FsUx -->
---------
Co-authored-by: Claude <noreply@anthropic.com>
fix(settings): settings refusals, live statements and action answers are written in every platform language, and `zh-TW` reads Traditional Chinese
9
+
10
+
Clause-②: no
11
+
Metadata-protocol: none
12
+
13
+
-**Every module-local settings copy table carries the eleven platform languages** (the platform locale table: English, Simplified and Traditional Chinese, Spanish, Arabic, French, Brazilian Portuguese, Russian, German, Japanese, Korean). Before, they carried four (Setup → Email's live statement two), so a caller in any other language read English. Covered: the allowed-IP-ranges save refusal, the sign-in method floor refusals, the `auth.mfa_required` refusal and the organization MFA refusal and save notice (`@objectstack/plugin-auth`); Setup → Email's live-transport statement and "Send test email" answers (`@objectstack/plugin-email`); the default-currency lock and the "no longer offered" locale option (`@objectstack/service-settings`).
14
+
-**`zh-TW`, `zh-HK` and `zh-MO` callers read Traditional Chinese.** Each table looks the caller's code up with core's `resolveLocale`, which reads it through the platform locale table's read aliases; a code naming no language on the table is answered in English, as before.
15
+
-**"Send test SMS" (`sms/test`, `@objectstack/service-sms`) answers in the caller's language** (`Accept-Language`, else `?locale`), like the mail and storage connection tests. It read no locale before and answered English in every console language. A provider's own error text still passes through verbatim.
16
+
-**The two answers `SettingsService.runAction` writes itself** (the built-in `reset` result and the refusal for an action with no registered handler) are written in the caller's language. With no locale, or one off the platform table, every sentence is the English one callers read before.
0 commit comments