();
+ for (const attrId of Object.keys(mine ?? {})) {
+ const a = ATTRIBUTES.find((x) => x.id === attrId);
+ if (!a) continue;
+ let key = "";
+ for (const seg of attrSegs(a)) {
+ key += `/${seg}`;
+ keys.add(key);
+ }
+ }
+ return keys;
+ }, [mine]);
const attr = ATTRIBUTES.find((a) => a.id === selected);
const language = attr?.language;
+ const inherited = useMemo(() => (attr ? resolvedAttribute(id, attr.id, customs) : {}), [id, attr, customs]);
const vars = useMemo(
() => ({ ...previewVars(id, mine, customs, language), ...fontWeightVars(weight, boldFontWeight) }) as CSSProperties,
[id, mine, customs, language, weight, boldFontWeight],
);
+ const baseVars = useMemo(
+ () => ({ ...previewVars(id, mine, customs), ...fontWeightVars(weight, boldFontWeight) }) as CSSProperties,
+ [id, mine, customs, weight, boldFontWeight],
+ );
const update = (attrId: string, v: TextAttributesOverride | undefined) => {
const next: Overrides = { ...(overrides ?? {}) };
const forScheme = { ...(next[id] ?? {}) };
@@ -299,6 +1063,7 @@ function ColorSchemePage() {
setOverrides(next);
};
const schemes = listSchemes(customs);
+ const sample = SAMPLES[scopes[0] ?? ""] ?? SAMPLES["Language Defaults"]!;
const schemeName = schemes.find((s) => s.id === id)?.name ?? id;
const options: SelectOption[] = [
{ value: "theme-default", label: "Theme default" },
@@ -436,57 +1201,120 @@ function ColorSchemePage() {
{scheme === "theme-default" && (
{tx`Follows the IDE theme: currently ${schemeName}.`}
)}
-
-
-
- aria-label="Color scheme attributes"
- roots={TREE}
- getKey={(n) => n.key}
- getLabel={(n) => n.label}
- getChildren={(n) => n.children}
- isExpandable={(n) => !!n.children}
- defaultExpanded={["/Language Defaults", "/General", "/General/Code"]}
- multiSelect={false}
- selected={new Set([selected])}
- onSelectionChange={(_s, lead) => lead?.attr && setSelected(lead.attr.id)}
- getColor={(n) => (n.attr && mine?.[n.attr.id] ? "var(--accent)" : undefined)}
- speedSearch
- />
-
- {attr ? (
-
update(attr.id, v)}
- />
- ) : (
-
- )}
-
-
- {SAMPLE.map((line, i) => (
-
-
{i + 1}
-
- {line.map(([text, attrId], j) => (
- setSelected(attrId) : undefined}
- >
- {text}
-
- ))}
-
+ {landing ? (
+
+ ) : (
+ <>
+
+
+
+ aria-label="Color scheme attributes"
+ roots={roots}
+ getKey={(n) => n.key}
+ getLabel={(n) => n.label}
+ getChildren={(n) => n.children}
+ isExpandable={(n) => !!n.children?.length}
+ expanded={expanded}
+ onExpandedChange={setExpanded}
+ handleRef={treeRef}
+ multiSelect={false}
+ selected={new Set([selected])}
+ onSelectionChange={(_s, lead) => lead?.attr && setSelected(lead.attr.id)}
+ renderNode={(n) => (
+
+ {n.label}
+
+ )}
+ speedSearch
+ />
+
+ {attr ? (
+
+
update(attr.id, v)}
+ />
+
+ ) : (
+
+ )}
- ))}
-
+
+ {sample.code.map((line, i) => (
+
+ {i + 1}
+
+ {line.map(([text, attrId], j) => {
+ const attr = attrId !== undefined ? A(attrId) : undefined;
+ const inPage = attr !== undefined && ids.has(attrId!);
+ return (
+ {
+ if (inPage) reveal(attrId!);
+ else {
+ crossPageReveal = attrId!;
+ selectPage(attrPageId(attr));
+ }
+ }
+ : undefined
+ }
+ >
+ {text}
+
+ );
+ })}
+
+
+ ))}
+
+ >
+ )}
);
}
+const LANGUAGES = [...new Set(ATTRIBUTES.map((a) => a.path[0]!))].filter(
+ (s) => !["General", "Debugger", "Language Defaults"].includes(s),
+);
+
+/** Sub-pages linked from the Color Scheme landing page, in sidebar order. */
+const SCHEME_SUBPAGES = [
+ { id: "editor.colorScheme.general", title: "General" },
+ { id: "editor.colorScheme.language-defaults", title: "Language Defaults" },
+ { id: "editor.colorScheme.debugger", title: "Debugger" },
+ ...LANGUAGES.map((l) => ({ id: `editor.colorScheme.${l.toLowerCase()}`, title: l })),
+];
+
+/** The scope chooser, import/export buttons and preview are identical on every sub-page. */
+function colorSchemeSection(scopes: readonly string[]) {
+ return {
+ items: [
+ {
+ t: "custom" as const,
+ label: "Scheme",
+ keywords: ATTRIBUTES.filter((a) => scopes.includes(a.path[0]!)).map((a) => a.name),
+ component: () => ,
+ },
+ ],
+ };
+}
+
export const COLOR_SCHEME_PAGE = editorPage({
id: "editor.colorScheme",
title: "Color Scheme",
@@ -500,27 +1328,76 @@ export const COLOR_SCHEME_PAGE = editorPage({
"background",
"bold",
"italic",
- "rainbow",
...SCHEMES.map((s) => s.name),
],
sections: [
- { items: [{ t: "custom", label: "Scheme", keywords: ATTRIBUTES.map((a) => a.name), component: ColorSchemePage }] },
{
- title: "Language Defaults",
items: [
{
- t: "check",
- key: "editor.semanticHighlighting",
- label: "Semantic highlighting",
- hint: "Local variables and parameters get a colour derived from their name (needs a language server).",
- },
- {
- t: "check",
- key: "editor.rainbowBrackets",
- label: "Rainbow brackets",
- hint: "Color (), [] and {} by nesting depth; unmatched brackets use the error color.",
+ t: "custom" as const,
+ label: "Scheme",
+ keywords: SCHEMES.map((s) => s.name),
+ component: () => ,
},
],
},
],
});
+
+/** JetBrains layout: scopes and languages live in the settings tree under Color Scheme, one page each. */
+export const COLOR_SCHEME_PAGES: PageSpec[] = [
+ COLOR_SCHEME_PAGE,
+ editorPage({
+ id: "editor.colorScheme.general",
+ title: "General",
+ order: 1,
+ projectScope: false,
+ keywords: ATTRIBUTES.filter((a) => a.path[0] === "General").map((a) => a.name),
+ sections: [colorSchemeSection(["General"])],
+ }),
+ editorPage({
+ id: "editor.colorScheme.language-defaults",
+ title: "Language Defaults",
+ order: 2,
+ projectScope: false,
+ keywords: ["semantic highlighting", "rainbow"],
+ sections: [
+ colorSchemeSection(["Language Defaults"]),
+ {
+ title: "Language Defaults",
+ items: [
+ {
+ t: "check",
+ key: "editor.semanticHighlighting",
+ label: "Semantic highlighting",
+ hint: "Local variables and parameters get a colour derived from their name (needs a language server).",
+ },
+ {
+ t: "check",
+ key: "editor.rainbowBrackets",
+ label: "Rainbow brackets",
+ hint: "Color (), [] and {} by nesting depth; unmatched brackets use the error color.",
+ },
+ ],
+ },
+ ],
+ }),
+ editorPage({
+ id: "editor.colorScheme.debugger",
+ title: "Debugger",
+ order: 3,
+ projectScope: false,
+ keywords: ["breakpoint", "inline values"],
+ sections: [colorSchemeSection(["Debugger"])],
+ }),
+ ...LANGUAGES.map((language, i) =>
+ editorPage({
+ id: `editor.colorScheme.${language.toLowerCase()}`,
+ title: language,
+ order: 4 + i,
+ projectScope: false,
+ keywords: ATTRIBUTES.filter((a) => a.path[0] === language).map((a) => a.name),
+ sections: [colorSchemeSection([language])],
+ }),
+ ),
+];
diff --git a/src/features/settings/pages/editor/index.ts b/src/features/settings/pages/editor/index.ts
index 0b4b51e1b..5d4390e67 100644
--- a/src/features/settings/pages/editor/index.ts
+++ b/src/features/settings/pages/editor/index.ts
@@ -2,7 +2,7 @@
import type { PageSpec } from "../spec";
import { GENERAL_PAGES } from "./general";
import { FONT_PAGE } from "./font";
-import { COLOR_SCHEME_PAGE } from "./colorScheme";
+import { COLOR_SCHEME_PAGES } from "./colorScheme";
import { CODE_STYLE_PAGES } from "./codeStyle";
import { INSPECTIONS_PAGE } from "./inspections";
import { NATURAL_LANGUAGES_PAGE, SPELLING_PAGE } from "./spelling";
@@ -12,7 +12,7 @@ export { codeStyleLanguagePages } from "./codeStyle";
export const EDITOR_PAGES: PageSpec[] = [
...GENERAL_PAGES,
FONT_PAGE,
- COLOR_SCHEME_PAGE,
+ ...COLOR_SCHEME_PAGES,
...CODE_STYLE_PAGES,
INSPECTIONS_PAGE,
NATURAL_LANGUAGES_PAGE,
diff --git a/src/platform/colorScheme.test.ts b/src/platform/colorScheme.test.ts
index 267b9bad7..39d1f506d 100644
--- a/src/platform/colorScheme.test.ts
+++ b/src/platform/colorScheme.test.ts
@@ -1,6 +1,13 @@
import { readFileSync } from "node:fs";
import { beforeAll, describe, expect, it } from "vitest";
-import { _setSchemeSource, schemeAfterThemeChange, schemeCss, schemeTokens } from "./colorScheme";
+import {
+ CLEAR_COLOR,
+ _setSchemeSource,
+ resolvedAttribute,
+ schemeAfterThemeChange,
+ schemeCss,
+ schemeTokens,
+} from "./colorScheme";
import { fontWeightVars, validateEditorExtras } from "./editorSettings";
import type { Settings } from "./ipc";
import { useProject } from "./project";
@@ -37,6 +44,35 @@ describe("color schemes", () => {
expect(imported).toMatch(/\.cm-editor\[data-language="PHP"\] \{\n {2}--syn-variable: #48d8ee !important;/);
});
+ it("resolves scheme attribute state and editor defaults", () => {
+ expect(resolvedAttribute("light", "lineComment")).toMatchObject({
+ foreground: "#8c8c8c",
+ italic: true,
+ });
+ expect(resolvedAttribute("dark", "lineComment")).toMatchObject({
+ foreground: "#7a7e85",
+ italic: false,
+ });
+ expect(resolvedAttribute("dark", "mdHeading")).toMatchObject({ bold: true });
+
+ const customs = {
+ "custom-test": {
+ name: "Test",
+ parent: "dark" as const,
+ attributes: {
+ todo: { foreground: "#139839", background: "#101010", bold: true, italic: false, effect: "wave" as const },
+ },
+ },
+ };
+ expect(resolvedAttribute("custom-test", "todo", customs)).toMatchObject({
+ foreground: "#139839",
+ background: "#101010",
+ bold: true,
+ italic: false,
+ effect: "wave",
+ });
+ });
+
it("emits scheme and override declarations", () => {
const root = document.documentElement;
root.dataset.theme = "light";
@@ -49,6 +85,8 @@ describe("color schemes", () => {
expect(over).toContain("--syn-keyword-bold: var(--fw-code-bold, 700) !important");
const regular = schemeCss("theme-default", { light: { keyword: { bold: false } } }, root);
expect(regular).toContain("--syn-keyword-bold: var(--fw-code, 400) !important");
+ const cleared = schemeCss("theme-default", { light: { keyword: { background: CLEAR_COLOR } } }, root);
+ expect(cleared).toContain("--syn-keyword-bg: transparent !important");
const upright = schemeCss("theme-default", { light: { staticSymbol: { italic: false } } }, root);
expect(upright).toContain("--syn-static-italic: normal !important");
const pythonItalic = schemeCss("theme-default", { light: { pyStaticSymbol: { italic: true } } }, root);
diff --git a/src/platform/colorScheme.ts b/src/platform/colorScheme.ts
index d201cb357..99cfbb20e 100644
--- a/src/platform/colorScheme.ts
+++ b/src/platform/colorScheme.ts
@@ -31,17 +31,26 @@ export interface AttributeDef {
token?: string;
/** A semantic modifier whose only configurable attribute is italic. */
italicOnly?: boolean;
+ defaultBold?: boolean;
defaultItalic?: boolean;
+ defaultEffect?: TextAttributesOverride["effect"];
/** CodeMirror language name; unset attributes are language defaults. */
language?: string;
}
-const syn = (id: string, name: string, path: string[], token: string): AttributeDef => ({
+const syn = (
+ id: string,
+ name: string,
+ path: string[],
+ token: string,
+ defaults: Pick = {},
+): AttributeDef => ({
id,
name,
path,
token,
fg: `--syn-${token}`,
+ ...defaults,
});
const LD = "Language Defaults";
@@ -116,7 +125,7 @@ const BASE_ATTRIBUTES: readonly AttributeDef[] = [
syn("identifier", "Identifiers › Local variable", [LD], "variable"),
syn("parameter", "Identifiers › Parameter", [LD], "param"),
syn("globalVariable", "Identifiers › Global variable", [LD], "global"),
- syn("constant", "Identifiers › Constant", [LD], "constant"),
+ syn("constant", "Identifiers › Constant", [LD], "constant", { defaultItalic: true }),
syn("field", "Identifiers › Instance field", [LD], "property"),
{ id: "staticSymbol", name: "Identifiers › Static symbol", path: [LD], token: "static", italicOnly: true },
syn("functionDeclaration", "Identifiers › Function declaration", [LD], "function"),
@@ -127,7 +136,7 @@ const BASE_ATTRIBUTES: readonly AttributeDef[] = [
syn("string", "String › String text", [LD], "string"),
syn("escape", "String › Valid escape sequence", [LD], "escape"),
syn("lineComment", "Comments › Line comment", [LD], "comment"),
- syn("docComment", "Comments › Doc comment", [LD], "doc-comment"),
+ syn("docComment", "Comments › Doc comment", [LD], "doc-comment", { defaultItalic: true }),
syn("metadata", "Metadata", [LD], "decorator"),
syn("operator", "Braces and Operators", [LD], "punct"),
syn("markupTag", "Markup › Tag", [LD], "tag"),
@@ -156,7 +165,7 @@ const BASE_ATTRIBUTES: readonly AttributeDef[] = [
defaultItalic: false,
},
syn("pyKeywordArg", "Keyword argument", ["Python"], "keyword-arg"),
- syn("pyDocstring", "Docstring", ["Python"], "docstring"),
+ syn("pyDocstring", "Docstring", ["Python"], "docstring", { defaultItalic: true }),
syn("pyBuiltin", "Built-in name", ["Python"], "python-builtin"),
syn("pyDecorator", "Decorator", ["Python"], "annotation"),
syn("pyLocalVariable", "Local variable", ["Python"], "python-local-variable"),
@@ -166,9 +175,9 @@ const BASE_ATTRIBUTES: readonly AttributeDef[] = [
syn("pyConstant", "Constant", ["Python"], "python-constant"),
syn("pyProperty", "Property", ["Python"], "python-property"),
syn("pyTypeParameter", "Type parameter", ["Python"], "python-type-parameter"),
- syn("mdHeading", "Heading", ["Markdown"], "markup-heading"),
+ syn("mdHeading", "Heading", ["Markdown"], "markup-heading", { defaultBold: true }),
syn("mdCode", "Code span", ["Markdown"], "markup-code"),
- syn("mdLink", "Link", ["Markdown"], "link"),
+ syn("mdLink", "Link", ["Markdown"], "link", { defaultEffect: "underline" }),
syn("regexp", "Regular expression", ["RegExp"], "regexp"),
];
@@ -341,6 +350,11 @@ const EFFECT_CSS: Record string> = {
none: () => "none",
};
+/** Explicitly removes a scheme colour; unlike an unset field, this must survive as an override. */
+export const CLEAR_COLOR = "transparent";
+
+const setOrCleared = (value: string | undefined) => isHexColor(value) || value === CLEAR_COLOR;
+
/** Declarations for the overrides of one scheme. */
export function overrideDeclarations(
overrides: Record | undefined,
@@ -352,10 +366,10 @@ export function overrideDeclarations(
if (attr.language !== language) continue;
const o = overrides[attr.id];
if (!o) continue;
- if (isHexColor(o.foreground) && attr.fg) out.push([attr.fg, o.foreground]);
- if (isHexColor(o.background) && attr.bg) out.push([attr.bg, o.background]);
- if (isHexColor(o.effectColor) && attr.effect) out.push([attr.effect, o.effectColor]);
- if (attr.effect && isHexColor(o.effectColor)) {
+ if (setOrCleared(o.foreground) && attr.fg) out.push([attr.fg, o.foreground]);
+ if (setOrCleared(o.background) && attr.bg) out.push([attr.bg, o.background]);
+ if (setOrCleared(o.effectColor) && attr.effect) out.push([attr.effect, o.effectColor]);
+ if (attr.effect && setOrCleared(o.effectColor)) {
if (attr.id === "error") out.push(["--editor-error-decoration", `underline wavy ${o.effectColor}`]);
if (attr.id === "warning") out.push(["--editor-warning-decoration", `underline wavy ${o.effectColor}`]);
}
@@ -366,11 +380,11 @@ export function overrideDeclarations(
out.push([`--syn-${t}-italic`, o.italic ? "italic" : "normal"]);
if (t === "comment") out.push(["--syn-comment-style", o.italic ? "italic" : "normal"]);
}
- if (isHexColor(o.background)) out.push([`--syn-${t}-bg`, o.background]);
+ if (setOrCleared(o.background)) out.push([`--syn-${t}-bg`, o.background]);
if (o.effect)
out.push([
`--syn-${t}-effect`,
- EFFECT_CSS[o.effect]?.(isHexColor(o.effectColor) ? o.effectColor : "currentColor") ?? "none",
+ EFFECT_CSS[o.effect]?.(setOrCleared(o.effectColor) ? o.effectColor! : "currentColor") ?? "none",
]);
}
}
@@ -418,6 +432,74 @@ export function resolvedSchemeTokens(id: string, customs: CustomColorSchemes = {
return tokens;
}
+const hexIn = (value: string | undefined): string | undefined =>
+ value?.match(/#(?:[0-9a-f]{3}|[0-9a-f]{6})\b/i)?.[0]?.toLowerCase();
+
+const effectFromCss = (value: string | undefined): TextAttributesOverride["effect"] => {
+ if (!value) return undefined;
+ if (/line-through/i.test(value)) return "strikeout";
+ if (/wavy/i.test(value)) return "wave";
+ if (/underline/i.test(value)) return "underline";
+ if (/none/i.test(value)) return "none";
+ return undefined;
+};
+
+const boldFromCss = (value: string | undefined): boolean | undefined => {
+ if (!value) return undefined;
+ if (/bold|[6-9]00/i.test(value)) return true;
+ if (/normal|[1-5]00/i.test(value)) return false;
+ return undefined;
+};
+
+const italicFromCss = (value: string | undefined): boolean | undefined => {
+ if (!value) return undefined;
+ if (/italic|oblique/i.test(value)) return true;
+ if (/normal/i.test(value)) return false;
+ return undefined;
+};
+
+/**
+ * The attributes an editor shows for a scheme before user overrides: imported
+ * values where the scheme sets them, otherwise the theme token and the editor's
+ * built-in defaults.
+ */
+export function resolvedAttribute(
+ id: string,
+ attrId: string,
+ customs: CustomColorSchemes = {},
+): TextAttributesOverride {
+ const attr = ATTRIBUTES.find((a) => a.id === attrId);
+ if (!attr) return {};
+ const custom = customSchemes(customs)[id];
+ const own = custom?.attributes[attr.id];
+ const vars = resolvedSchemeTokens(id, customs);
+ if (attr.language)
+ for (const [key, value] of overrideDeclarations(custom?.attributes, attr.language)) vars.set(key, value);
+
+ const token = attr.token;
+ const foreground = attr.fg ? vars.get(attr.fg) : undefined;
+ const background = attr.bg ? vars.get(attr.bg) : token ? vars.get(`--syn-${token}-bg`) : undefined;
+ const effectCss = attr.effect ? vars.get(attr.effect) : token ? vars.get(`--syn-${token}-effect`) : undefined;
+ const effect = own?.effect ?? effectFromCss(effectCss) ?? attr.defaultEffect;
+ const out: TextAttributesOverride = {};
+ if (isHexColor(foreground)) out.foreground = foreground.toLowerCase();
+ if (isHexColor(background)) out.background = background.toLowerCase();
+ if (own?.effectColor && isHexColor(own.effectColor)) out.effectColor = own.effectColor.toLowerCase();
+ else {
+ const effectColor = hexIn(effectCss);
+ if (effectColor) out.effectColor = effectColor;
+ }
+ if (token) {
+ if (!attr.italicOnly)
+ out.bold = own?.bold ?? boldFromCss(vars.get(`--syn-${token}-bold`)) ?? attr.defaultBold ?? false;
+ const italicCss =
+ vars.get(`--syn-${token}-italic`) ?? (token === "comment" ? vars.get("--syn-comment-style") : undefined);
+ out.italic = own?.italic ?? italicFromCss(italicCss) ?? attr.defaultItalic ?? false;
+ } else if (effect) out.effect = effect;
+ if (token && effect) out.effect = effect;
+ return out;
+}
+
const SAFE = /^[^;{}<>]*$/;
/** Stylesheet text for the chosen scheme and its overrides ("" when the theme's own is used unchanged). */
diff --git a/src/platform/locales/text/es.json b/src/platform/locales/text/es.json
index ec1d5d607..990b2a494 100644
--- a/src/platform/locales/text/es.json
+++ b/src/platform/locales/text/es.json
@@ -2340,7 +2340,6 @@
"UI font size": "Tamaño de fuente de la interfaz",
"Uninstalled {name}": "Se desinstaló {name}",
"URL:": "URL:",
- "Unchecked values are inherited from the scheme.": "Los valores desmarcados se heredan del esquema.",
"Uncommitted changes are stashed before the update and restored afterwards.": "Los cambios sin confirmar se guardan en el stash antes de la actualización y se restauran después.",
"Underline": "Subrayado",
"Underscored": "Subrayado simple",
diff --git a/src/platform/locales/text/fr.json b/src/platform/locales/text/fr.json
index 1a6f1fdbc..323f185f5 100644
--- a/src/platform/locales/text/fr.json
+++ b/src/platform/locales/text/fr.json
@@ -2237,7 +2237,6 @@
"UI font size": "Taille de police de l'interface",
"Uninstalled {name}": "{name} désinstallé",
"URL:": "URL :",
- "Unchecked values are inherited from the scheme.": "Les valeurs non cochées sont héritées du schéma.",
"Uncommitted changes are stashed before the update and restored afterwards.": "Les modifications non validées sont remisées avant la mise à jour et restaurées ensuite.",
"Underline": "Souligné",
"Underscored": "Souligné d'un trait",
diff --git a/src/platform/locales/text/ko.json b/src/platform/locales/text/ko.json
index 847280f0e..2ee95ca92 100644
--- a/src/platform/locales/text/ko.json
+++ b/src/platform/locales/text/ko.json
@@ -2396,7 +2396,6 @@
"UI font": "UI 글꼴",
"UI font size": "UI 글꼴 크기",
"Uninstalled {name}": "{name} 제거됨",
- "Unchecked values are inherited from the scheme.": "선택 해제된 값은 구성표에서 상속됩니다.",
"Uncommitted changes are stashed before the update and restored afterwards.": "커밋되지 않은 변경 사항은 업데이트 전에 스태시되었다가 이후에 복원됩니다.",
"Underline": "밑줄",
"Underscored": "밑줄 표시",
diff --git a/src/platform/locales/text/pl.json b/src/platform/locales/text/pl.json
index dff586ba7..baca72a8c 100644
--- a/src/platform/locales/text/pl.json
+++ b/src/platform/locales/text/pl.json
@@ -2319,7 +2319,6 @@
"UI font size": "Rozmiar czcionki interfejsu użytkownika",
"Uninstalled {name}": "Odinstalowano {name}",
"URL:": "Adres URL:",
- "Unchecked values are inherited from the scheme.": "Niezaznaczone wartości są dziedziczone ze schematu.",
"Uncommitted changes are stashed before the update and restored afterwards.": "Niezatwierdzone zmiany są odkładane do schowka przed aktualizacją i przywracane po jej zakończeniu.",
"Underline": "Podkreślenie",
"Underscored": "Podkreślony równo",
diff --git a/src/platform/locales/text/pt.json b/src/platform/locales/text/pt.json
index 81f418cfb..0431c0c77 100644
--- a/src/platform/locales/text/pt.json
+++ b/src/platform/locales/text/pt.json
@@ -2320,7 +2320,6 @@
"UI font size": "Tamanho da fonte da interface",
"Uninstalled {name}": "{name} desinstalado",
"URL:": "URL:",
- "Unchecked values are inherited from the scheme.": "Os valores desmarcados são herdados do esquema.",
"Uncommitted changes are stashed before the update and restored afterwards.": "As alterações não commitadas são guardadas em stash antes da atualização e restauradas depois.",
"Underline": "Sublinhado",
"Underscored": "Sublinhado simples",
diff --git a/src/platform/locales/text/zh.json b/src/platform/locales/text/zh.json
index 9232f653b..8bfd3df9d 100644
--- a/src/platform/locales/text/zh.json
+++ b/src/platform/locales/text/zh.json
@@ -516,6 +516,7 @@
"Collapse Unchanged Fragments": "折叠未更改的片段",
"Color Scheme": "配色方案",
"Color scheme attributes": "配色方案属性",
+ "Color scheme pages": "配色方案页面",
"Color scheme preview": "配色方案预览",
"Color theme": "颜色主题",
"Column": "列",
@@ -2425,7 +2426,7 @@
"UI font size": "UI 字体大小",
"Uninstalled {name}": "已卸载 {name}",
"URL:": "URL:",
- "Unchecked values are inherited from the scheme.": "未勾选的值继承自方案。",
+ "The controls show the scheme's actual appearance; changes override it.": "控件显示方案的实际外观;修改即覆盖方案。",
"Uncommitted changes are stashed before the update and restored afterwards.": "更新前会储藏未提交的更改,并在之后恢复。",
"Underline": "下划线",
"Underscored": "下划线",