mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-15 08:08:18 +00:00
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
44 lines
1.8 KiB
TypeScript
44 lines
1.8 KiB
TypeScript
/**
|
||
* File › File Properties › Make File Read-only / Writable (IDEA's "Toggle
|
||
* Read-only Attribute", also the status bar lock): asks, then flips the
|
||
* file's writable bit and the open document's editability.
|
||
*/
|
||
import { call, commands, isTauri } from "@/platform/ipc";
|
||
import { basename } from "@/platform/project";
|
||
import { notifications } from "@/workbench/contributions";
|
||
import { confirm } from "@/workbench/messages";
|
||
import type { DocModel } from "./model/document";
|
||
import { tx } from "@/platform/i18n";
|
||
|
||
export function readOnlyQuestion(name: string, readOnly: boolean) {
|
||
return readOnly
|
||
? { title: "Make File Writable", message: tx`'${name}' is read-only. Make it writable?`, confirm: "Make Writable" }
|
||
: { title: "Make File Read-only", message: tx`Make '${name}' read-only?`, confirm: "Make Read-only" };
|
||
}
|
||
|
||
/** Applies the toggle without asking. Returns the new read-only state, or null on failure. */
|
||
export async function setFileWritable(model: DocModel, writable: boolean): Promise<boolean | null> {
|
||
try {
|
||
const readOnly = isTauri() ? await call(commands.fsSetWritable(model.path, writable)) : !writable;
|
||
model.setReadOnly(readOnly);
|
||
return readOnly;
|
||
} catch (e) {
|
||
notifications().notify({
|
||
level: "error",
|
||
title: `Cannot make ${basename(model.path)} ${writable ? "writable" : "read-only"}`,
|
||
body: e instanceof Error ? e.message : String(e),
|
||
});
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function toggleReadOnly(model: DocModel) {
|
||
if (model.virtual) return;
|
||
const meta = model.getMeta();
|
||
if (meta.banner === "binary" || meta.banner === "tooLarge") return;
|
||
const q = readOnlyQuestion(basename(model.path), meta.readOnly);
|
||
void confirm({ title: q.title, message: q.message, ok: q.confirm }).then(
|
||
(ok) => ok && void setFileWritable(model, meta.readOnly),
|
||
);
|
||
}
|