|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +"@objectstack/client": minor |
| 4 | +--- |
| 5 | + |
| 6 | +fix(spec,client)!: `GetTranslationsRequest` is locale-only — drop the |
| 7 | +`namespace` / `keys` filters no server ever read (#3676) |
| 8 | + |
| 9 | +`GetTranslationsRequestSchema` declared two optional filters, and the endpoint |
| 10 | +description promised one of them ("...for the specified locale and optional |
| 11 | +namespace"). Neither serving surface read either: the dispatcher domain body |
| 12 | +(`runtime/src/domains/i18n.ts`) takes `parts[1]` / `query.locale`, and |
| 13 | +service-i18n (`i18n-service-plugin.ts`) takes `req.params.locale`. Both return |
| 14 | +the locale's whole bundle. The SDK meanwhile put both on the query string, so a |
| 15 | +caller who passed `keys` to shrink the response shrank nothing and got no |
| 16 | +indication the filter was inert — Prime Directive #10's declared ≠ enforced, the |
| 17 | +same shape #1475 trimmed out of the validation-rule types. |
| 18 | + |
| 19 | +Trimmed rather than implemented, on three counts: |
| 20 | + |
| 21 | +- **No consumer.** No call site in this repo or `objectui` passed either field. |
| 22 | + The docs (`content/docs/api/client-sdk.mdx`, `skills/objectstack-i18n/SKILL.md`) |
| 23 | + already documented `getTranslations(locale)` as a full-bundle snapshot, so the |
| 24 | + schema was the outlier, not the docs. The one thing that did exercise them was |
| 25 | + a client test asserting the query string got *built* — it pinned the phantom |
| 26 | + rather than any behaviour, since no server read what it asserted was sent. It |
| 27 | + is replaced here by its inverse: a regression test that the request carries no |
| 28 | + filter query at all. |
| 29 | +- **`keys` could not deliver what it advertises.** `II18nService.getTranslations` |
| 30 | + (`contracts/i18n-service.ts`) takes only `locale`, so a filter could only be a |
| 31 | + post-filter over an already-materialized bundle. `keys` reads as a payload |
| 32 | + optimization; a post-filter saves wire bytes but none of the server work, and |
| 33 | + widening the contract would break every implementer (`memory-i18n`, |
| 34 | + `file-i18n-adapter`) for a capability with no caller. |
| 35 | +- **`keys` has no defined meaning against the current bundle shape.** Under the |
| 36 | + retired flat `o.`-dotted dialect, `keys: ['o.account.label']` was an obvious |
| 37 | + pick. #3778 settled the tree on one nested `TranslationData` shape, where a |
| 38 | + flat `string[]` is neither a path set nor a group set, and a filtered response |
| 39 | + would have to be rebuilt as a sparse nested tree to stay schema-valid. That is |
| 40 | + a design decision, and nothing is waiting on it. |
| 41 | + |
| 42 | +`namespace` is the one that got *easier* — it now lands exactly on |
| 43 | +`TranslationData`'s top-level groups, which is what its own description already |
| 44 | +said ("e.g., objects, apps, messages"). It is still trimmed here: re-adding an |
| 45 | +optional request field is additive and non-breaking the day the Studio's |
| 46 | +per-module views actually need it, whereas shipping an unexercised filter path |
| 47 | +now means dead code with tests to match, and a declared-but-unread field is |
| 48 | +precisely the exemplar the next author copies. |
| 49 | + |
| 50 | +BREAKING: the two schema fields and the `getTranslations(locale, options?)` |
| 51 | +second parameter are removed with no deprecation cycle. Nothing worked through |
| 52 | +them — a passed filter was silently ignored — so there is no behavior to |
| 53 | +protect. Runtime impact is nil (the fields were optional and now strip); TS |
| 54 | +callers passing them fail to compile, which is the intended signal. |
0 commit comments