diff --git a/packages/blocks/package.json b/packages/blocks/package.json index ed7344c..5fdacf5 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -34,12 +34,22 @@ "exports": { "./globals.css": "./src/styles/globals.css", "./appearance": "./src/blocks/appearance/index.ts", + "./appearance/locales": "./src/blocks/appearance/locales/catalogs.ts", + "./appearance/locales/*": "./src/blocks/appearance/locales/*.ts", "./chats": "./src/blocks/chats/index.ts", + "./chats/locales": "./src/blocks/chats/locales/catalogs.ts", + "./chats/locales/*": "./src/blocks/chats/locales/*.ts", "./components/*": "./src/components/*.tsx", "./hooks/*": "./src/hooks/*.ts", "./lib/*": "./src/lib/*.tsx", "./layout": "./src/blocks/layout/index.ts", + "./layout/locales": "./src/blocks/layout/locales/catalogs.ts", + "./layout/locales/*": "./src/blocks/layout/locales/*.ts", "./navigation": "./src/blocks/navigation/index.ts", - "./notifications": "./src/blocks/notifications/index.ts" + "./navigation/locales": "./src/blocks/navigation/locales/catalogs.ts", + "./navigation/locales/*": "./src/blocks/navigation/locales/*.ts", + "./notifications": "./src/blocks/notifications/index.ts", + "./notifications/locales": "./src/blocks/notifications/locales/catalogs.ts", + "./notifications/locales/*": "./src/blocks/notifications/locales/*.ts" } } diff --git a/packages/blocks/src/blocks/appearance/controller.tsx b/packages/blocks/src/blocks/appearance/controller.tsx index 3950108..734fd6b 100644 --- a/packages/blocks/src/blocks/appearance/controller.tsx +++ b/packages/blocks/src/blocks/appearance/controller.tsx @@ -1,5 +1,6 @@ import { useCallback, useState } from "react" import { useHotkey } from "@tanstack/react-hotkeys" +import { useMessage } from "@workspace/i18n" import { useResolvedTheme, useUiState } from "./ui-state" import { Dialog, @@ -15,6 +16,62 @@ import { import { appearanceDialogHandle } from "./dialog" import { CompactPreference, ModePreference } from "./preferences" import { ThemeConfigPanel } from "./theme-config-panel" +import { LocalizedText } from "../../components/localized-text" +import { appearanceMessages } from "./messages" + +interface AppearanceHotkeysProps { + onToggleDialog: VoidFunction + onToggleTheme: VoidFunction +} + +function AppearanceHotkeys({ + onToggleDialog, + onToggleTheme, +}: AppearanceHotkeysProps) { + const appearanceTitle = useMessage(appearanceMessages.appearance) + const appearanceDescription = useMessage( + appearanceMessages.appearanceCommandDescription + ) + const toggleThemeTitle = useMessage(appearanceMessages.toggleTheme) + const toggleThemeDescription = useMessage( + appearanceMessages.toggleThemeDescription + ) + + useHotkey("Mod+,", onToggleDialog, { + ignoreInputs: true, + preventDefault: true, + stopPropagation: false, + meta: { + name: appearanceTitle, + description: appearanceDescription, + }, + }) + + useHotkey("Mod+D", onToggleTheme, { + ignoreInputs: true, + preventDefault: true, + stopPropagation: false, + meta: { + name: toggleThemeTitle, + description: toggleThemeDescription, + }, + }) + + return null +} + +function AppearanceDialogHeader() { + return ( + + + + + + + + + ) +} export function AppearanceController() { const [isOpen, setIsOpen] = useState(false) @@ -33,37 +90,18 @@ export function AppearanceController() { setThemeMode(resolvedTheme === "dark" ? "light" : "dark") }, [resolvedTheme, setThemeMode]) - useHotkey("Mod+,", toggleDialog, { - ignoreInputs: true, - preventDefault: true, - stopPropagation: false, - meta: { - name: "界面外观", - description: "打开主题与布局偏好", - }, - }) - - useHotkey("Mod+D", toggleTheme, { - ignoreInputs: true, - preventDefault: true, - stopPropagation: false, - meta: { - name: "切换主题", - description: "在浅色与深色主题之间切换", - }, - }) - return ( + appearanceDialogHandle.open(null)} /> - - 界面外观 - 主题与布局偏好 - +
@@ -73,13 +111,8 @@ export function AppearanceController() { - +
diff --git a/packages/blocks/src/blocks/appearance/locales/catalogs.test.ts b/packages/blocks/src/blocks/appearance/locales/catalogs.test.ts new file mode 100644 index 0000000..133c8b8 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/catalogs.test.ts @@ -0,0 +1,35 @@ +import { describe, it } from "vitest" + +import { expectCompleteCatalogs } from "../../../i18n/test-catalogs" +import { appearanceMessages, themeColorMessages } from "../messages" +import { appearanceCatalogLocales } from "./catalogs" +import { messages as de } from "./de" +import { messages as en } from "./en" +import { messages as es } from "./es" +import { messages as fr } from "./fr" +import { messages as ja } from "./ja" +import { messages as ko } from "./ko" +import { messages as zhHans } from "./zh-Hans" +import { messages as zhHant } from "./zh-Hant" + +describe("appearance locale catalogs", () => { + it("ship every appearance message in every built-in locale", () => { + expectCompleteCatalogs({ + catalogs: { + de, + en, + es, + fr, + ja, + ko, + "zh-Hans": zhHans, + "zh-Hant": zhHant, + }, + locales: appearanceCatalogLocales, + messageIds: [ + ...Object.values(appearanceMessages), + ...Object.values(themeColorMessages), + ].map((descriptor) => descriptor.id), + }) + }) +}) diff --git a/packages/blocks/src/blocks/appearance/locales/catalogs.ts b/packages/blocks/src/blocks/appearance/locales/catalogs.ts new file mode 100644 index 0000000..cb5250c --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/catalogs.ts @@ -0,0 +1,12 @@ +import type { appearanceMessages, themeColorMessages } from "../messages" +import { + blockCatalogLocales, + type BlockCatalogLocale, + type BlockMessageCatalog, +} from "../../../i18n/catalogs" + +export { blockCatalogLocales as appearanceCatalogLocales } +export type AppearanceCatalogLocale = BlockCatalogLocale +export type AppearanceMessageCatalog = BlockMessageCatalog< + typeof appearanceMessages & typeof themeColorMessages +> diff --git a/packages/blocks/src/blocks/appearance/locales/de.ts b/packages/blocks/src/blocks/appearance/locales/de.ts new file mode 100644 index 0000000..e367991 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/de.ts @@ -0,0 +1,53 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "de" +export const languageTag = "de-DE" + +export const messages = { + "blocks.appearance.active": "Aktiv", + "blocks.appearance.baseColor": "Basisfarbe", + "blocks.appearance.color.amber": "Bernstein", + "blocks.appearance.color.blue": "Blau", + "blocks.appearance.color.cyan": "Cyan", + "blocks.appearance.color.emerald": "Smaragd", + "blocks.appearance.color.fuchsia": "Fuchsia", + "blocks.appearance.color.green": "Grün", + "blocks.appearance.color.indigo": "Indigo", + "blocks.appearance.color.lime": "Limette", + "blocks.appearance.color.mauve": "Malve", + "blocks.appearance.color.mist": "Nebel", + "blocks.appearance.color.neutral": "Neutral", + "blocks.appearance.color.olive": "Oliv", + "blocks.appearance.color.orange": "Orange", + "blocks.appearance.color.pink": "Rosa", + "blocks.appearance.color.purple": "Lila", + "blocks.appearance.color.red": "Rot", + "blocks.appearance.color.rose": "Rose", + "blocks.appearance.color.sky": "Himmelblau", + "blocks.appearance.color.stone": "Stein", + "blocks.appearance.color.taupe": "Taupe", + "blocks.appearance.color.teal": "Blaugrün", + "blocks.appearance.color.violet": "Violett", + "blocks.appearance.color.yellow": "Gelb", + "blocks.appearance.color.zinc": "Zink", + "blocks.appearance.command.description": "Design- und Layout-Einstellungen öffnen", + "blocks.appearance.compact.description": "Eine kompakte Breite für den Hauptinhalt verwenden", + "blocks.appearance.compact.title": "Kompaktes Layout", + "blocks.appearance.description": "Design- und Layout-Einstellungen", + "blocks.appearance.mode.dark": "Dunkel", + "blocks.appearance.mode.dark.description": "Die Oberfläche verwendet immer das dunkle Design", + "blocks.appearance.mode.light": "Hell", + "blocks.appearance.mode.light.description": "Die Oberfläche verwendet immer das helle Design", + "blocks.appearance.mode.system": "System", + "blocks.appearance.mode.system.description": "Das Design der Oberfläche folgt der Systemeinstellung", + "blocks.appearance.mode.title": "Darstellungsmodus", + "blocks.appearance.primaryColor": "Primärfarbe", + "blocks.appearance.theme.dark": "Dunkles Design", + "blocks.appearance.theme.dark.description": "Dieses Design wird im dunklen Systemmodus verwendet", + "blocks.appearance.theme.light": "Helles Design", + "blocks.appearance.theme.light.description": "Dieses Design wird im hellen Systemmodus verwendet", + "blocks.appearance.title": "Darstellung", + "blocks.appearance.toggleTheme": "Design wechseln", + "blocks.appearance.toggleTheme.description": + "Zwischen hellem und dunklem Design wechseln", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/en.ts b/packages/blocks/src/blocks/appearance/locales/en.ts new file mode 100644 index 0000000..68f3ce0 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/en.ts @@ -0,0 +1,25 @@ +import type { MessageDescriptor } from "@workspace/i18n" + +import { appearanceMessages, themeColorMessages } from "../messages.ts" +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "en" +export const languageTag = "en-US" + +function createSourceCatalog( + ...groups: readonly Record[] +): AppearanceMessageCatalog { + return Object.fromEntries( + groups.flatMap((group) => + Object.values(group).map((descriptor) => [ + descriptor.id, + descriptor.message, + ]) + ) + ) as AppearanceMessageCatalog +} + +export const messages = createSourceCatalog( + appearanceMessages, + themeColorMessages +) satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/es.ts b/packages/blocks/src/blocks/appearance/locales/es.ts new file mode 100644 index 0000000..228fb88 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/es.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "es" +export const languageTag = "es-ES" + +export const messages = { + "blocks.appearance.active": "Activo", + "blocks.appearance.baseColor": "Color base", + "blocks.appearance.color.amber": "Ámbar", + "blocks.appearance.color.blue": "Azul", + "blocks.appearance.color.cyan": "Cian", + "blocks.appearance.color.emerald": "Esmeralda", + "blocks.appearance.color.fuchsia": "Fucsia", + "blocks.appearance.color.green": "Verde", + "blocks.appearance.color.indigo": "Índigo", + "blocks.appearance.color.lime": "Lima", + "blocks.appearance.color.mauve": "Malva", + "blocks.appearance.color.mist": "Niebla", + "blocks.appearance.color.neutral": "Neutro", + "blocks.appearance.color.olive": "Oliva", + "blocks.appearance.color.orange": "Naranja", + "blocks.appearance.color.pink": "Rosa", + "blocks.appearance.color.purple": "Morado", + "blocks.appearance.color.red": "Rojo", + "blocks.appearance.color.rose": "Rosa intenso", + "blocks.appearance.color.sky": "Celeste", + "blocks.appearance.color.stone": "Piedra", + "blocks.appearance.color.taupe": "Topo", + "blocks.appearance.color.teal": "Verde azulado", + "blocks.appearance.color.violet": "Violeta", + "blocks.appearance.color.yellow": "Amarillo", + "blocks.appearance.color.zinc": "Zinc", + "blocks.appearance.command.description": "Abrir las preferencias de tema y diseño", + "blocks.appearance.compact.description": "Usar un ancho compacto para el contenido principal", + "blocks.appearance.compact.title": "Diseño compacto", + "blocks.appearance.description": "Preferencias de tema y diseño", + "blocks.appearance.mode.dark": "Oscuro", + "blocks.appearance.mode.dark.description": "La interfaz siempre usará el tema oscuro", + "blocks.appearance.mode.light": "Claro", + "blocks.appearance.mode.light.description": "La interfaz siempre usará el tema claro", + "blocks.appearance.mode.system": "Sistema", + "blocks.appearance.mode.system.description": "El tema de la interfaz seguirá la apariencia del sistema", + "blocks.appearance.mode.title": "Modo de tema", + "blocks.appearance.primaryColor": "Color principal", + "blocks.appearance.theme.dark": "Tema oscuro", + "blocks.appearance.theme.dark.description": "Este tema se usa cuando el sistema está en modo oscuro", + "blocks.appearance.theme.light": "Tema claro", + "blocks.appearance.theme.light.description": "Este tema se usa cuando el sistema está en modo claro", + "blocks.appearance.title": "Apariencia", + "blocks.appearance.toggleTheme": "Cambiar tema", + "blocks.appearance.toggleTheme.description": "Cambiar entre los temas claro y oscuro", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/fr.ts b/packages/blocks/src/blocks/appearance/locales/fr.ts new file mode 100644 index 0000000..0cdb90e --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/fr.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "fr" +export const languageTag = "fr-FR" + +export const messages = { + "blocks.appearance.active": "Actif", + "blocks.appearance.baseColor": "Couleur de base", + "blocks.appearance.color.amber": "Ambre", + "blocks.appearance.color.blue": "Bleu", + "blocks.appearance.color.cyan": "Cyan", + "blocks.appearance.color.emerald": "Émeraude", + "blocks.appearance.color.fuchsia": "Fuchsia", + "blocks.appearance.color.green": "Vert", + "blocks.appearance.color.indigo": "Indigo", + "blocks.appearance.color.lime": "Citron vert", + "blocks.appearance.color.mauve": "Mauve", + "blocks.appearance.color.mist": "Brume", + "blocks.appearance.color.neutral": "Neutre", + "blocks.appearance.color.olive": "Olive", + "blocks.appearance.color.orange": "Orange", + "blocks.appearance.color.pink": "Rose", + "blocks.appearance.color.purple": "Pourpre", + "blocks.appearance.color.red": "Rouge", + "blocks.appearance.color.rose": "Rose soutenu", + "blocks.appearance.color.sky": "Bleu ciel", + "blocks.appearance.color.stone": "Pierre", + "blocks.appearance.color.taupe": "Taupe", + "blocks.appearance.color.teal": "Sarcelle", + "blocks.appearance.color.violet": "Violet", + "blocks.appearance.color.yellow": "Jaune", + "blocks.appearance.color.zinc": "Zinc", + "blocks.appearance.command.description": "Ouvrir les préférences de thème et de mise en page", + "blocks.appearance.compact.description": "Utiliser une largeur compacte pour le contenu principal", + "blocks.appearance.compact.title": "Mise en page compacte", + "blocks.appearance.description": "Préférences de thème et de mise en page", + "blocks.appearance.mode.dark": "Sombre", + "blocks.appearance.mode.dark.description": "L’interface utilisera toujours le thème sombre", + "blocks.appearance.mode.light": "Clair", + "blocks.appearance.mode.light.description": "L’interface utilisera toujours le thème clair", + "blocks.appearance.mode.system": "Système", + "blocks.appearance.mode.system.description": "Le thème de l’interface suivra l’apparence du système", + "blocks.appearance.mode.title": "Mode du thème", + "blocks.appearance.primaryColor": "Couleur principale", + "blocks.appearance.theme.dark": "Thème sombre", + "blocks.appearance.theme.dark.description": "Ce thème est utilisé lorsque le système est en mode sombre", + "blocks.appearance.theme.light": "Thème clair", + "blocks.appearance.theme.light.description": "Ce thème est utilisé lorsque le système est en mode clair", + "blocks.appearance.title": "Apparence", + "blocks.appearance.toggleTheme": "Changer de thème", + "blocks.appearance.toggleTheme.description": "Basculer entre les thèmes clair et sombre", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/ja.ts b/packages/blocks/src/blocks/appearance/locales/ja.ts new file mode 100644 index 0000000..b26ec7f --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/ja.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "ja" +export const languageTag = "ja-JP" + +export const messages = { + "blocks.appearance.active": "使用中", + "blocks.appearance.baseColor": "ベースカラー", + "blocks.appearance.color.amber": "アンバー", + "blocks.appearance.color.blue": "ブルー", + "blocks.appearance.color.cyan": "シアン", + "blocks.appearance.color.emerald": "エメラルド", + "blocks.appearance.color.fuchsia": "フクシア", + "blocks.appearance.color.green": "グリーン", + "blocks.appearance.color.indigo": "インディゴ", + "blocks.appearance.color.lime": "ライム", + "blocks.appearance.color.mauve": "モーブ", + "blocks.appearance.color.mist": "ミスト", + "blocks.appearance.color.neutral": "ニュートラル", + "blocks.appearance.color.olive": "オリーブ", + "blocks.appearance.color.orange": "オレンジ", + "blocks.appearance.color.pink": "ピンク", + "blocks.appearance.color.purple": "パープル", + "blocks.appearance.color.red": "レッド", + "blocks.appearance.color.rose": "ローズ", + "blocks.appearance.color.sky": "スカイ", + "blocks.appearance.color.stone": "ストーン", + "blocks.appearance.color.taupe": "トープ", + "blocks.appearance.color.teal": "ティール", + "blocks.appearance.color.violet": "バイオレット", + "blocks.appearance.color.yellow": "イエロー", + "blocks.appearance.color.zinc": "ジンク", + "blocks.appearance.command.description": "テーマとレイアウト設定を開く", + "blocks.appearance.compact.description": "メインページのコンテンツをコンパクトな幅で表示します", + "blocks.appearance.compact.title": "コンパクトレイアウト", + "blocks.appearance.description": "テーマとレイアウトの設定", + "blocks.appearance.mode.dark": "ダーク", + "blocks.appearance.mode.dark.description": "常にダークテーマを使用します", + "blocks.appearance.mode.light": "ライト", + "blocks.appearance.mode.light.description": "常にライトテーマを使用します", + "blocks.appearance.mode.system": "システム", + "blocks.appearance.mode.system.description": "インターフェースのテーマをシステムの外観に合わせます", + "blocks.appearance.mode.title": "テーマモード", + "blocks.appearance.primaryColor": "プライマリカラー", + "blocks.appearance.theme.dark": "ダークテーマ", + "blocks.appearance.theme.dark.description": "システムがダークモードのときに使用するテーマです", + "blocks.appearance.theme.light": "ライトテーマ", + "blocks.appearance.theme.light.description": "システムがライトモードのときに使用するテーマです", + "blocks.appearance.title": "外観", + "blocks.appearance.toggleTheme": "テーマを切り替える", + "blocks.appearance.toggleTheme.description": "ライトテーマとダークテーマを切り替えます", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/ko.ts b/packages/blocks/src/blocks/appearance/locales/ko.ts new file mode 100644 index 0000000..6604841 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/ko.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "ko" +export const languageTag = "ko-KR" + +export const messages = { + "blocks.appearance.active": "사용 중", + "blocks.appearance.baseColor": "기본 색상", + "blocks.appearance.color.amber": "호박색", + "blocks.appearance.color.blue": "파란색", + "blocks.appearance.color.cyan": "청록색", + "blocks.appearance.color.emerald": "에메랄드", + "blocks.appearance.color.fuchsia": "자홍색", + "blocks.appearance.color.green": "초록색", + "blocks.appearance.color.indigo": "남색", + "blocks.appearance.color.lime": "라임", + "blocks.appearance.color.mauve": "연보라", + "blocks.appearance.color.mist": "안개색", + "blocks.appearance.color.neutral": "중성색", + "blocks.appearance.color.olive": "올리브", + "blocks.appearance.color.orange": "주황색", + "blocks.appearance.color.pink": "분홍색", + "blocks.appearance.color.purple": "보라색", + "blocks.appearance.color.red": "빨간색", + "blocks.appearance.color.rose": "장미색", + "blocks.appearance.color.sky": "하늘색", + "blocks.appearance.color.stone": "돌색", + "blocks.appearance.color.taupe": "회갈색", + "blocks.appearance.color.teal": "틸", + "blocks.appearance.color.violet": "제비꽃색", + "blocks.appearance.color.yellow": "노란색", + "blocks.appearance.color.zinc": "아연색", + "blocks.appearance.command.description": "테마 및 레이아웃 환경설정 열기", + "blocks.appearance.compact.description": "기본 페이지 콘텐츠에 좁은 너비를 사용합니다", + "blocks.appearance.compact.title": "컴팩트 레이아웃", + "blocks.appearance.description": "테마 및 레이아웃 환경설정", + "blocks.appearance.mode.dark": "어둡게", + "blocks.appearance.mode.dark.description": "인터페이스에서 항상 어두운 테마를 사용합니다", + "blocks.appearance.mode.light": "밝게", + "blocks.appearance.mode.light.description": "인터페이스에서 항상 밝은 테마를 사용합니다", + "blocks.appearance.mode.system": "시스템", + "blocks.appearance.mode.system.description": "인터페이스 테마가 시스템 화면 모드를 따릅니다", + "blocks.appearance.mode.title": "테마 모드", + "blocks.appearance.primaryColor": "주요 색상", + "blocks.appearance.theme.dark": "어두운 테마", + "blocks.appearance.theme.dark.description": "시스템이 어두운 모드일 때 사용하는 테마입니다", + "blocks.appearance.theme.light": "밝은 테마", + "blocks.appearance.theme.light.description": "시스템이 밝은 모드일 때 사용하는 테마입니다", + "blocks.appearance.title": "화면 모양", + "blocks.appearance.toggleTheme": "테마 전환", + "blocks.appearance.toggleTheme.description": "밝은 테마와 어두운 테마 사이를 전환합니다", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/zh-Hans.ts b/packages/blocks/src/blocks/appearance/locales/zh-Hans.ts new file mode 100644 index 0000000..b55ec32 --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/zh-Hans.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "zh-Hans" +export const languageTag = "zh-CN" + +export const messages = { + "blocks.appearance.active": "使用中", + "blocks.appearance.baseColor": "基础颜色", + "blocks.appearance.color.amber": "琥珀色", + "blocks.appearance.color.blue": "蓝色", + "blocks.appearance.color.cyan": "青色", + "blocks.appearance.color.emerald": "翠绿色", + "blocks.appearance.color.fuchsia": "紫红色", + "blocks.appearance.color.green": "绿色", + "blocks.appearance.color.indigo": "靛蓝色", + "blocks.appearance.color.lime": "青柠色", + "blocks.appearance.color.mauve": "紫灰", + "blocks.appearance.color.mist": "雾灰", + "blocks.appearance.color.neutral": "中性灰", + "blocks.appearance.color.olive": "橄榄灰", + "blocks.appearance.color.orange": "橙色", + "blocks.appearance.color.pink": "粉色", + "blocks.appearance.color.purple": "紫色", + "blocks.appearance.color.red": "红色", + "blocks.appearance.color.rose": "玫红色", + "blocks.appearance.color.sky": "天蓝色", + "blocks.appearance.color.stone": "石灰", + "blocks.appearance.color.taupe": "灰褐", + "blocks.appearance.color.teal": "蓝绿色", + "blocks.appearance.color.violet": "紫罗兰色", + "blocks.appearance.color.yellow": "黄色", + "blocks.appearance.color.zinc": "锌灰", + "blocks.appearance.command.description": "打开主题与布局偏好", + "blocks.appearance.compact.description": "启用后,页面主内容将使用紧凑宽度", + "blocks.appearance.compact.title": "紧凑布局", + "blocks.appearance.description": "主题与布局偏好", + "blocks.appearance.mode.dark": "深色", + "blocks.appearance.mode.dark.description": "界面将始终使用深色主题", + "blocks.appearance.mode.light": "浅色", + "blocks.appearance.mode.light.description": "界面将始终使用浅色主题", + "blocks.appearance.mode.system": "系统", + "blocks.appearance.mode.system.description": "界面主题将跟随系统外观设置", + "blocks.appearance.mode.title": "主题模式", + "blocks.appearance.primaryColor": "主要颜色", + "blocks.appearance.theme.dark": "深色主题", + "blocks.appearance.theme.dark.description": "当系统设置为深色模式时,将使用此主题", + "blocks.appearance.theme.light": "浅色主题", + "blocks.appearance.theme.light.description": "当系统设置为浅色模式时,将使用此主题", + "blocks.appearance.title": "界面外观", + "blocks.appearance.toggleTheme": "切换主题", + "blocks.appearance.toggleTheme.description": "在浅色与深色主题之间切换", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/locales/zh-Hant.ts b/packages/blocks/src/blocks/appearance/locales/zh-Hant.ts new file mode 100644 index 0000000..2adabfc --- /dev/null +++ b/packages/blocks/src/blocks/appearance/locales/zh-Hant.ts @@ -0,0 +1,52 @@ +import type { AppearanceMessageCatalog } from "./catalogs" + +export const locale = "zh-Hant" +export const languageTag = "zh-TW" + +export const messages = { + "blocks.appearance.active": "使用中", + "blocks.appearance.baseColor": "基礎顏色", + "blocks.appearance.color.amber": "琥珀色", + "blocks.appearance.color.blue": "藍色", + "blocks.appearance.color.cyan": "青色", + "blocks.appearance.color.emerald": "翠綠色", + "blocks.appearance.color.fuchsia": "紫紅色", + "blocks.appearance.color.green": "綠色", + "blocks.appearance.color.indigo": "靛藍色", + "blocks.appearance.color.lime": "萊姆色", + "blocks.appearance.color.mauve": "淡紫色", + "blocks.appearance.color.mist": "霧灰色", + "blocks.appearance.color.neutral": "中性灰", + "blocks.appearance.color.olive": "橄欖色", + "blocks.appearance.color.orange": "橙色", + "blocks.appearance.color.pink": "粉紅色", + "blocks.appearance.color.purple": "紫色", + "blocks.appearance.color.red": "紅色", + "blocks.appearance.color.rose": "玫瑰色", + "blocks.appearance.color.sky": "天藍色", + "blocks.appearance.color.stone": "石灰色", + "blocks.appearance.color.taupe": "灰褐色", + "blocks.appearance.color.teal": "藍綠色", + "blocks.appearance.color.violet": "紫羅蘭色", + "blocks.appearance.color.yellow": "黃色", + "blocks.appearance.color.zinc": "鋅灰色", + "blocks.appearance.command.description": "開啟主題與版面配置偏好", + "blocks.appearance.compact.description": "使用較緊湊的主頁內容寬度", + "blocks.appearance.compact.title": "緊湊版面配置", + "blocks.appearance.description": "主題與版面配置偏好", + "blocks.appearance.mode.dark": "深色", + "blocks.appearance.mode.dark.description": "介面將一律使用深色主題", + "blocks.appearance.mode.light": "淺色", + "blocks.appearance.mode.light.description": "介面將一律使用淺色主題", + "blocks.appearance.mode.system": "系統", + "blocks.appearance.mode.system.description": "介面主題將跟隨系統外觀設定", + "blocks.appearance.mode.title": "主題模式", + "blocks.appearance.primaryColor": "主要顏色", + "blocks.appearance.theme.dark": "深色主題", + "blocks.appearance.theme.dark.description": "系統使用深色模式時套用此主題", + "blocks.appearance.theme.light": "淺色主題", + "blocks.appearance.theme.light.description": "系統使用淺色模式時套用此主題", + "blocks.appearance.title": "介面外觀", + "blocks.appearance.toggleTheme": "切換主題", + "blocks.appearance.toggleTheme.description": "在淺色與深色主題之間切換", +} as const satisfies AppearanceMessageCatalog diff --git a/packages/blocks/src/blocks/appearance/messages.ts b/packages/blocks/src/blocks/appearance/messages.ts new file mode 100644 index 0000000..0e19b7d --- /dev/null +++ b/packages/blocks/src/blocks/appearance/messages.ts @@ -0,0 +1,187 @@ +import type { MessageDescriptor } from "@workspace/i18n" + +export const appearanceMessages = { + active: /* i18n */ { + id: "blocks.appearance.active", + message: "Active", + }, + appearance: /* i18n */ { + id: "blocks.appearance.title", + message: "Appearance", + }, + appearanceCommandDescription: /* i18n */ { + id: "blocks.appearance.command.description", + message: "Open theme and layout preferences", + }, + baseColor: /* i18n */ { + id: "blocks.appearance.baseColor", + message: "Base color", + }, + compactDescription: /* i18n */ { + id: "blocks.appearance.compact.description", + message: "Use a compact width for the main page content", + }, + compactLayout: /* i18n */ { + id: "blocks.appearance.compact.title", + message: "Compact layout", + }, + darkMode: /* i18n */ { + id: "blocks.appearance.mode.dark", + message: "Dark", + }, + darkModeDescription: /* i18n */ { + id: "blocks.appearance.mode.dark.description", + message: "The interface will always use the dark theme", + }, + darkTheme: /* i18n */ { + id: "blocks.appearance.theme.dark", + message: "Dark theme", + }, + darkThemeDescription: /* i18n */ { + id: "blocks.appearance.theme.dark.description", + message: "This theme is used when the system is in dark mode", + }, + followSystem: /* i18n */ { + id: "blocks.appearance.mode.system", + message: "System", + }, + followSystemDescription: /* i18n */ { + id: "blocks.appearance.mode.system.description", + message: "The interface theme will follow the system appearance", + }, + lightMode: /* i18n */ { + id: "blocks.appearance.mode.light", + message: "Light", + }, + lightModeDescription: /* i18n */ { + id: "blocks.appearance.mode.light.description", + message: "The interface will always use the light theme", + }, + lightTheme: /* i18n */ { + id: "blocks.appearance.theme.light", + message: "Light theme", + }, + lightThemeDescription: /* i18n */ { + id: "blocks.appearance.theme.light.description", + message: "This theme is used when the system is in light mode", + }, + primaryColor: /* i18n */ { + id: "blocks.appearance.primaryColor", + message: "Primary color", + }, + themeAndLayoutPreferences: /* i18n */ { + id: "blocks.appearance.description", + message: "Theme and layout preferences", + }, + themeMode: /* i18n */ { + id: "blocks.appearance.mode.title", + message: "Theme mode", + }, + toggleTheme: /* i18n */ { + id: "blocks.appearance.toggleTheme", + message: "Toggle theme", + }, + toggleThemeDescription: /* i18n */ { + id: "blocks.appearance.toggleTheme.description", + message: "Switch between light and dark themes", + }, +} as const satisfies Record + +export const themeColorMessages = { + amber: /* i18n */ { + id: "blocks.appearance.color.amber", + message: "Amber", + }, + blue: /* i18n */ { + id: "blocks.appearance.color.blue", + message: "Blue", + }, + cyan: /* i18n */ { + id: "blocks.appearance.color.cyan", + message: "Cyan", + }, + emerald: /* i18n */ { + id: "blocks.appearance.color.emerald", + message: "Emerald", + }, + fuchsia: /* i18n */ { + id: "blocks.appearance.color.fuchsia", + message: "Fuchsia", + }, + green: /* i18n */ { + id: "blocks.appearance.color.green", + message: "Green", + }, + indigo: /* i18n */ { + id: "blocks.appearance.color.indigo", + message: "Indigo", + }, + lime: /* i18n */ { + id: "blocks.appearance.color.lime", + message: "Lime", + }, + mauve: /* i18n */ { + id: "blocks.appearance.color.mauve", + message: "Mauve", + }, + mist: /* i18n */ { + id: "blocks.appearance.color.mist", + message: "Mist", + }, + neutral: /* i18n */ { + id: "blocks.appearance.color.neutral", + message: "Neutral", + }, + olive: /* i18n */ { + id: "blocks.appearance.color.olive", + message: "Olive", + }, + orange: /* i18n */ { + id: "blocks.appearance.color.orange", + message: "Orange", + }, + pink: /* i18n */ { + id: "blocks.appearance.color.pink", + message: "Pink", + }, + purple: /* i18n */ { + id: "blocks.appearance.color.purple", + message: "Purple", + }, + red: /* i18n */ { + id: "blocks.appearance.color.red", + message: "Red", + }, + rose: /* i18n */ { + id: "blocks.appearance.color.rose", + message: "Rose", + }, + sky: /* i18n */ { + id: "blocks.appearance.color.sky", + message: "Sky", + }, + stone: /* i18n */ { + id: "blocks.appearance.color.stone", + message: "Stone", + }, + taupe: /* i18n */ { + id: "blocks.appearance.color.taupe", + message: "Taupe", + }, + teal: /* i18n */ { + id: "blocks.appearance.color.teal", + message: "Teal", + }, + violet: /* i18n */ { + id: "blocks.appearance.color.violet", + message: "Violet", + }, + yellow: /* i18n */ { + id: "blocks.appearance.color.yellow", + message: "Yellow", + }, + zinc: /* i18n */ { + id: "blocks.appearance.color.zinc", + message: "Zinc", + }, +} as const satisfies Record diff --git a/packages/blocks/src/blocks/appearance/preferences.tsx b/packages/blocks/src/blocks/appearance/preferences.tsx index 46c263b..d63b1b7 100644 --- a/packages/blocks/src/blocks/appearance/preferences.tsx +++ b/packages/blocks/src/blocks/appearance/preferences.tsx @@ -1,4 +1,5 @@ import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react" +import { useMessage } from "@workspace/i18n" import { Select, SelectContent, @@ -10,12 +11,8 @@ import { Switch } from "@workspace/ui/components/switch" import type { ThemeMode } from "./state" import { useUiState } from "./ui-state" - -const modeItems: ReadonlyArray<{ label: string; value: ThemeMode }> = [ - { label: "使用浅色", value: "light" }, - { label: "使用深色", value: "dark" }, - { label: "跟随系统", value: "system" }, -] +import { LocalizedText } from "../../components/localized-text" +import { appearanceMessages } from "./messages" function ModeIcon({ mode }: { mode: ThemeMode | null }) { if (mode === "light") return @@ -25,15 +22,29 @@ function ModeIcon({ mode }: { mode: ThemeMode | null }) { export function ModePreference() { const [themeMode, setThemeMode] = useUiState("theme-mode") + const lightLabel = useMessage(appearanceMessages.lightMode) + const darkLabel = useMessage(appearanceMessages.darkMode) + const systemLabel = useMessage(appearanceMessages.followSystem) + const lightDescription = useMessage(appearanceMessages.lightModeDescription) + const darkDescription = useMessage(appearanceMessages.darkModeDescription) + const systemDescription = useMessage( + appearanceMessages.followSystemDescription + ) + const title = useMessage(appearanceMessages.themeMode) + const modeItems: ReadonlyArray<{ label: string; value: ThemeMode }> = [ + { label: lightLabel, value: "light" }, + { label: darkLabel, value: "dark" }, + { label: systemLabel, value: "system" }, + ] const description = { - light: "界面将始终使用浅色主题", - dark: "界面将始终使用深色主题", - system: "界面主题将跟随系统外观设置", + light: lightDescription, + dark: darkDescription, + system: systemDescription, }[themeMode] return (
-

主题模式

+

{title}

{description}