HsuehYi opened a new issue, #75063:
URL: https://github.com/apache/airflow/issues/75063
### What happened and how to reproduce it?
`breeze ui check-translation-completeness --add-missing` / `--remove-unused`
rewrites each locale file with its keys sorted by `natural_sort_key()`
(`dev/breeze/src/airflow_breeze/commands/ui_commands.py`), which compares
case-insensitively. The repo enforces a different order for the same files:
`jsonc/sort-keys` with `natural: true`
(`airflow-core/src/airflow/ui/rules/jsonc.js`), applied by the
`ts-compile-lint-ui` pre-commit hook. eslint-plugin-jsonc (3.4.2 here)
implements that rule with `natural-compare`, which is case-sensitive —
uppercase letters sort before lowercase ones.
Both write helpers sort the whole file, not just the added/removed keys, so
any locale file that gets rewritten (it has to have missing or unused keys to
be touched at all) can be re-ordered as a side effect. For case-dependent keys
the resulting order violates the repo's own ESLint rule, and the pre-commit
hook flips those keys back — pure churn for contributors.
Observed while updating the zh-TW locale (#75061): the command reordered 4
pre-existing key pairs and the `Compile / format / lint UI` hook reverted all
of them:
| keys | order written by breeze | order required by ESLint |
| --- | --- | --- |
| `logLevel` / `logicalDate` | `logicalDate`, `logLevel` | `logLevel`,
`logicalDate` |
| `selectLanguage` / `selected` | `selected`, `selectLanguage` |
`selectLanguage`, `selected` |
| `sortMultiColumnHint` / `sortedAscending` | `sortedAscending`,
`sortMultiColumnHint` | `sortMultiColumnHint`, `sortedAscending` |
| `modeTooltip` / `modes` | `modes`, `modeTooltip` | `modeTooltip`, `modes` |
Minimal check of the ESLint side (from `airflow-core/src/airflow/ui`):
```console
$ cat public/i18n/locales/en/scratch.json # order as written by the breeze
command
{
"logicalDate": "Logical Date",
"logLevel": "Log Level"
}
$ pnpm exec eslint public/i18n/locales/en/scratch.json
2:3 error Expected object keys to be in natural ascending order.
'logicalDate' should be after 'logLevel' jsonc/sort-keys
✖ 1 problem (1 error, 0 warnings)
```
`pnpm exec eslint --fix` rewrites the file with `"logLevel"` first.
Tool side, with the committed `natural_sort_key`:
```pycon
>>> from airflow_breeze.commands.ui_commands import natural_sort_key
>>> sorted(["logLevel", "logicalDate"], key=natural_sort_key)
['logicalDate', 'logLevel']
>>> sorted(["selectLanguage", "selected"], key=natural_sort_key)
['selected', 'selectLanguage']
```
### What you think should happen instead?
The command should write keys in the order the repo enforces, so that using
it never produces an order ESLint rejects. Options:
1. Align `natural_sort_key()` with the comparator the rule actually uses:
port the character mapping of `natural-compare` (case-sensitive — digits before
letters, `A-Z` before `a-z`, same punctuation mapping) and update
`TestNaturalSorting.test_natural_sort_matches_eslint` accordingly. The current
docstring says the key "mimics JavaScript's `localeCompare` with `numeric:
true`" — eslint-plugin-jsonc does not use `localeCompare`; it depends on
`natural-compare`.
2. Or run the UI ESLint fix step on the rewritten files (e.g. invoke the
existing `ts-compile-lint-ui` hook, or `pnpm eslint --fix`, from the command).
That was the plan agreed in #58487 when it was closed ("convert
`check_translation_completeness` into a breeze command and run prek run eslint
as part of it") — the conversion landed (#58637), but the command writes its
own order and never invokes ESLint.
For completeness, the rule also supports `caseSensitive: false`; enabling it
would make ESLint accept the current tool order, but every existing locale file
would then have to be re-sorted, so aligning the command is likely the cheaper
fix.
### Anything else?
- Related history: #58487 reported this churn for the previous script and
was closed assuming the new breeze command would run ESLint. The conversion to
a breeze command (#58637) introduced the current comparator, but ESLint is
still not invoked — this issue tracks what remains.
- `TestNaturalSorting.test_natural_sort_matches_eslint` currently locks in
the wrong expectation: it asserts `Zebra` sorts last, while `natural-compare`
sorts `Z` (mapped to 101) before `a` (mapped to 102), i.e. `Zebra` first —
ESLint reports "Expected object keys to be in natural ascending order. 'apple'
should be after 'Zebra'". The test needs to be updated together with the
comparator.
---
Drafted-by: OpenCode; reviewed by @HsuehYi before posting
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]