fix(i18n): Translate UI text built from template literals

Template literals such as `Remove data source '${name}'?` reached props and
calls that look text up exactly (dialog messages, labels, aria-labels, menu
items, action titles), so they always showed in English. Some notification
titles also spliced lowercase English words into a sentence.

- `tx` also works as a tag: tx`Remove data source '${name}'?` looks up
  "Remove data source '{name}'?" by its literal parts, fills in the values
  (translated when the catalog has them) and remembers the result, so the
  primitives that pass strings through `tx` translate it again after a locale
  change or once the catalog has loaded (actions registered at startup).
- 269 template literals at exact-lookup sites now use the tag; text that
  spliced words or plural suffixes is written as one sentence per variant
  (safe delete, Docker delete/prune, rebase, conflicts, VCS "No … in
  progress", database copy errors, inspection descriptions, ...).
- zh: 280 new entries; stale and duplicate-shape entries removed.
- textCatalog guard: untagged template literals at exact-lookup sites fail
  (with an allowlist for code-like text), tagged text is checked against the
  catalog by shape, case-changing values and `c ? "a" : "b"` suffixes inside
  translated templates fail, and a catalog may hold one entry per template shape.

Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
l0ng-ai committed 2026-10-27 18:43:53 +08:00
1 джерело 2616e3fe6d
коміт b03983847c
142 files changed
+1032 -363

No files matched your search

+2 -2
Переглянути файл
@@ -21,7 +21,7 @@ import clsx from "clsx";
import { useEditorRegistry } from "@/editor/api";
import { executeAction } from "@/platform/actions";
import { setContext } from "@/platform/context";
import { useTxTemplate } from "@/platform/i18n";
import { tx, useTxTemplate } from "@/platform/i18n";
import { isTauri } from "@/platform/ipc";
import type { RootFolder } from "@/platform/languageSettings";
import { useEffectiveRoots } from "@/platform/projectRoots";
@@ -442,7 +442,7 @@ export function ProjectView() {
setDropTarget(valid ? target.key : null);
setDrag({
paths,
label: paths.length === 1 ? nameOf(paths[0]!) : `${paths.length} items`,
label: paths.length === 1 ? nameOf(paths[0]!) : tx`${paths.length} items`,
x: ev.clientX,
y: ev.clientY,
copy: ev.altKey,