Repository navigation
Commit 4bd7215
fix(lint): the translation-reference rules judge a locale pack's picklists face (#24474)
Fixes #23566
Clause-②: no
## What changed
`packages/lint/src/validate-translation-references.ts` now reads a
locale pack's `picklists` face. Until now nothing read it, so a wrong
key passed `os lint --strict` and was dropped silently at runtime. Two
rules already covered the same mistakes elsewhere, and this change
extends both of them to the new face. No rule id is added, and each
finding carries the severity of its field-level twin (the triage ruling:
"the two existing rules … extend to the picklist face, at their
field-level twins' severity. No new rule id."):
| key | verdict | severity |
|---|---|---|
| `picklists.NAME` naming a list that no package in the stack declares |
`translation-target-unknown`, with "Did you mean" from the declared list
names; fix line: "Match the key to a picklist's `name`, or drop it." |
error (same as the field orphan) |
| `picklists.NAME.options.KEY` where KEY is not a value of that list |
`translation-option-key-unknown`, with the field twin's two arms: a key
spelled as the DISPLAY LABEL is told the value to rename it to, and any
other key gets the nearest declared value | warning (same as a field
option key) |
**What a key resolves against.** The rule uses the same set the runtime
uses. `lookupPicklistOption` (`@objectstack/spec/system`) is called with
the list's name and each served option's value read as text. For a
picklist-bound field, the served options are the list's own `options`
plus every `picklistExtensions` entry for it
(`PicklistServedFieldSchema`). So the universe is the declaration's
options together with the options every extension adds. Lists and
extensions are read from the stack in hand and from every
`packages[].manifest` body. Both keys have the `concat` disposition,
which places them inside the ADR-0130 D4 assembled body, the same
reasoning the other sibling-package folds use. When both the stack and a
sibling declare a list, the declaration being judged keeps the slot (the
dashboards' decision). Extensions are a union.
**What is not judged.** If the stack only *extends* a list and no
package of the stack declares it, the `picklists.NAME` subtree is
skipped wholly. The owner's options cannot be seen from here. This is
rung 2b of the object ladder (`objectExtensions`) applied to a list.
`os explain translation-target-unknown` and `os explain
translation-option-key-unknown` (`rule-explanations.ts`) now name the
face, and the module header documents it.
## Deviation from the field twin (one, deliberate)
The field twin's option-key fix line ends with "Declared values: …". The
picklist fix line does not. It stays one line of at most 200 characters,
the shape #22161 settled on, and the verdict's "Did you mean" names the
nearest value. The field twin's hint is unchanged.
## Tests (at head `d237990699`, after merging `origin/main`
`26501ae24f`)
- New describe block `the picklist face (#23566)` in
`validate-translation-references.test.ts`, one pin per leg:
- Leg A: `….picklists.salutation.options.mister`,
`translation-option-key-unknown`, warning. The test asserts the same
rule and severity on the field twin.
- Leg B: `….picklists.not_a_list`, `translation-target-unknown`, error.
The near-miss `salutaton` gets `Did you mean "salutation"?`. The test
asserts the field twin's orphan severity.
- Also covered: the display-label arm; a lit control; a value an
extension adds (accepted) next to one nobody adds (refused); a list and
an extension that live in a sibling package; and the extended-only skip.
- The new message and fix arms are added to the #22161 one-line-verdict
and one-line-fix rosters and to the `os explain` fact pins.
- `pnpm --filter @objectstack/lint test`: 145 files and 6871 tests
passed, lock VERDICT command-exit 0. `pnpm --filter @objectstack/lint
typecheck`: VERDICT command-exit 0.
- `pnpm --filter @objectstack/spec test:repo`: 69 files and 1134 tests
passed, VERDICT command-exit 0.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 64 commands, and I ran all of them.
Reconciled with `--ran` (each line `CMD :: exit N`): 62 exit 0 and 2 NOT
MEASURED. `check:dual-build-cjs-loads` and `check:lean-entry-closure`
exited 3 with PREREQUISITE NOT MET, because they need a whole-workspace
`pnpm build` that I did not run locally. CI builds the full tree for
them.
- Consumer sweep: no example in this repository declares or translates
`picklists` (`git grep -n picklists -- examples` returns 0 hits), so no
shipped stack starts failing. HotCRM keeps its local guard until this
ships (see the card's consumer note).
## Acceptance notes
- `content/docs/protocol/kernel/i18n-standard.mdx`: the table of
resolvable keys has no `picklists.{list}` /
`picklists.{list}.options.{value}` rows. The file is outside this card's
claimed surface, so it is left for a docs follow-up. Carrier: none
named.
- Boundary: suppose a field references a list (`picklist: NAME`) owned
by a dependency outside the artifact. A `picklists.NAME` translation key
for that list is reported as `translation-target-unknown`. This matches
the object twin's verdict for an object contributed by another installed
package. It does not match the CLI's `picklist-reference-unverified`
notice for the reference itself.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 01fafde commit 4bd7215
4 files changed
Lines changed: 323 additions & 7 deletions
File tree
- .changeset
- packages/lint/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3188 | 3188 | | |
3189 | 3189 | | |
3190 | 3190 | | |
3191 | | - | |
| 3191 | + | |
| 3192 | + | |
3192 | 3193 | | |
3193 | 3194 | | |
3194 | 3195 | | |
| |||
3202 | 3203 | | |
3203 | 3204 | | |
3204 | 3205 | | |
3205 | | - | |
3206 | | - | |
| 3206 | + | |
| 3207 | + | |
| 3208 | + | |
3207 | 3209 | | |
3208 | 3210 | | |
3209 | 3211 | | |
| |||
3222 | 3224 | | |
3223 | 3225 | | |
3224 | 3226 | | |
3225 | | - | |
| 3227 | + | |
3226 | 3228 | | |
3227 | 3229 | | |
3228 | | - | |
3229 | | - | |
| 3230 | + | |
| 3231 | + | |
| 3232 | + | |
3230 | 3233 | | |
3231 | 3234 | | |
3232 | 3235 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3738 | 3738 | | |
3739 | 3739 | | |
3740 | 3740 | | |
| 3741 | + | |
| 3742 | + | |
| 3743 | + | |
| 3744 | + | |
| 3745 | + | |
| 3746 | + | |
| 3747 | + | |
| 3748 | + | |
| 3749 | + | |
| 3750 | + | |
| 3751 | + | |
| 3752 | + | |
| 3753 | + | |
| 3754 | + | |
| 3755 | + | |
| 3756 | + | |
| 3757 | + | |
| 3758 | + | |
| 3759 | + | |
| 3760 | + | |
| 3761 | + | |
| 3762 | + | |
| 3763 | + | |
| 3764 | + | |
| 3765 | + | |
| 3766 | + | |
| 3767 | + | |
| 3768 | + | |
| 3769 | + | |
| 3770 | + | |
| 3771 | + | |
| 3772 | + | |
| 3773 | + | |
| 3774 | + | |
| 3775 | + | |
| 3776 | + | |
| 3777 | + | |
| 3778 | + | |
| 3779 | + | |
| 3780 | + | |
| 3781 | + | |
| 3782 | + | |
| 3783 | + | |
| 3784 | + | |
| 3785 | + | |
| 3786 | + | |
| 3787 | + | |
| 3788 | + | |
| 3789 | + | |
| 3790 | + | |
| 3791 | + | |
| 3792 | + | |
| 3793 | + | |
| 3794 | + | |
| 3795 | + | |
| 3796 | + | |
| 3797 | + | |
| 3798 | + | |
| 3799 | + | |
| 3800 | + | |
| 3801 | + | |
| 3802 | + | |
| 3803 | + | |
| 3804 | + | |
| 3805 | + | |
| 3806 | + | |
| 3807 | + | |
| 3808 | + | |
| 3809 | + | |
| 3810 | + | |
| 3811 | + | |
| 3812 | + | |
| 3813 | + | |
| 3814 | + | |
| 3815 | + | |
| 3816 | + | |
| 3817 | + | |
| 3818 | + | |
| 3819 | + | |
| 3820 | + | |
| 3821 | + | |
| 3822 | + | |
| 3823 | + | |
| 3824 | + | |
| 3825 | + | |
| 3826 | + | |
| 3827 | + | |
| 3828 | + | |
| 3829 | + | |
| 3830 | + | |
| 3831 | + | |
| 3832 | + | |
| 3833 | + | |
| 3834 | + | |
| 3835 | + | |
| 3836 | + | |
| 3837 | + | |
| 3838 | + | |
| 3839 | + | |
| 3840 | + | |
| 3841 | + | |
| 3842 | + | |
| 3843 | + | |
| 3844 | + | |
| 3845 | + | |
| 3846 | + | |
| 3847 | + | |
| 3848 | + | |
| 3849 | + | |
| 3850 | + | |
| 3851 | + | |
| 3852 | + | |
| 3853 | + | |
| 3854 | + | |
| 3855 | + | |
| 3856 | + | |
| 3857 | + | |
| 3858 | + | |
| 3859 | + | |
| 3860 | + | |
| 3861 | + | |
| 3862 | + | |
| 3863 | + | |
| 3864 | + | |
| 3865 | + | |
| 3866 | + | |
| 3867 | + | |
| 3868 | + | |
| 3869 | + | |
| 3870 | + | |
| 3871 | + | |
| 3872 | + | |
| 3873 | + | |
| 3874 | + | |
| 3875 | + | |
| 3876 | + | |
| 3877 | + | |
3741 | 3878 | | |
3742 | 3879 | | |
3743 | 3880 | | |
| |||
3776 | 3913 | | |
3777 | 3914 | | |
3778 | 3915 | | |
| 3916 | + | |
3779 | 3917 | | |
3780 | 3918 | | |
3781 | 3919 | | |
| |||
3785 | 3923 | | |
3786 | 3924 | | |
3787 | 3925 | | |
| 3926 | + | |
3788 | 3927 | | |
3789 | 3928 | | |
3790 | 3929 | | |
| |||
3861 | 4000 | | |
3862 | 4001 | | |
3863 | 4002 | | |
| 4003 | + | |
| 4004 | + | |
3864 | 4005 | | |
3865 | 4006 | | |
3866 | 4007 | | |
3867 | 4008 | | |
3868 | 4009 | | |
3869 | 4010 | | |
3870 | 4011 | | |
| 4012 | + | |
3871 | 4013 | | |
3872 | 4014 | | |
3873 | 4015 | | |
| |||
3922 | 4064 | | |
3923 | 4065 | | |
3924 | 4066 | | |
| 4067 | + | |
3925 | 4068 | | |
3926 | 4069 | | |
3927 | 4070 | | |
| |||
0 commit comments