mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-06 09:24:24 +08:00
feat(i18n): enhance language switching and UI consistency across themes and components
This commit is contained in:
@@ -258,6 +258,7 @@ export function AgentSkillsView({ clientId }: { clientId: string }) {
|
||||
</div>
|
||||
),
|
||||
},
|
||||
],
|
||||
onClick: ({ key }) => {
|
||||
if (key === "manual") {
|
||||
setDraft(null);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { ModelPicker } from "@/components/model-picker";
|
||||
import { ChannelEditorDrawer } from "@/components/layout/channel-editor-drawer";
|
||||
import { ConfigPromptSources } from "@/components/layout/config-prompt-sources";
|
||||
import { changeAppLocale, type AppLocale } from "@/i18n";
|
||||
import type { AppLocale } from "@/i18n";
|
||||
import { exportAppConfig, importAppConfig } from "@/services/config-file";
|
||||
import { syncAppDataToWebdav, type AppSyncDomainKey, type AppSyncProgressEvent } from "@/services/app-sync";
|
||||
import { testWebdavConnection, WEBDAV_MANIFEST_FILE_NAME } from "@/services/webdav-sync";
|
||||
@@ -215,17 +215,6 @@ export function AppConfigPanel({ showDoneButton = false, initialTab = "channels"
|
||||
label: t("config.tabs.preferences"),
|
||||
children: (
|
||||
<Form layout="vertical" requiredMark={false}>
|
||||
<div className="mb-2 text-sm font-semibold">{t("config.preferences.interface")}</div>
|
||||
<Form.Item label={t("config.preferences.language")} extra={t("config.preferences.languageDescription")} className="mb-4 max-w-sm">
|
||||
<Select
|
||||
value={locale}
|
||||
options={[
|
||||
{ label: t("locale.zhCN"), value: "zh-CN" },
|
||||
{ label: t("locale.enUS"), value: "en-US" },
|
||||
]}
|
||||
onChange={(value: AppLocale) => void changeAppLocale(value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<div className="mb-2 text-sm font-semibold">{t("config.preferences.defaultModels")}</div>
|
||||
<div className="mb-4 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
{modelGroups.map((group) => (
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { CSSProperties } from "react";
|
||||
import { BookOpen, Keyboard, Puzzle, Settings2 } from "lucide-react";
|
||||
import { BookOpen, Globe2, Keyboard, Puzzle, Settings2 } from "lucide-react";
|
||||
import { Dropdown } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { AnimatedThemeToggler } from "@/components/ui/animated-theme-toggler";
|
||||
import { GitHubLink } from "@/components/layout/github-link";
|
||||
import { VersionReleaseModal } from "@/components/layout/version-release-modal";
|
||||
import { DOCS_URL } from "@/constant/env";
|
||||
import { changeAppLocale, type AppLocale } from "@/i18n";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { canvasThemes } from "@/lib/canvas-theme";
|
||||
import { useConfigStore } from "@/stores/use-config-store";
|
||||
@@ -19,7 +21,7 @@ type UserStatusActionsProps = {
|
||||
};
|
||||
|
||||
export function UserStatusActions({ showConfig = true, variant = "default", onOpenShortcuts, onOpenPlugins }: UserStatusActionsProps) {
|
||||
const { t } = useTranslation();
|
||||
const { i18n, t } = useTranslation();
|
||||
const theme = useThemeStore((state) => state.theme);
|
||||
const setTheme = useThemeStore((state) => state.setTheme);
|
||||
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
|
||||
@@ -45,6 +47,22 @@ export function UserStatusActions({ showConfig = true, variant = "default", onOp
|
||||
<Settings2 className="size-4" />
|
||||
</button>
|
||||
) : null}
|
||||
<Dropdown
|
||||
trigger={["click"]}
|
||||
placement="bottomRight"
|
||||
menu={{
|
||||
selectedKeys: [i18n.resolvedLanguage],
|
||||
items: [
|
||||
{ key: "zh-CN", label: t("locale.zhCN") },
|
||||
{ key: "en-US", label: t("locale.enUS") },
|
||||
],
|
||||
onClick: ({ key }) => void changeAppLocale(key as AppLocale),
|
||||
}}
|
||||
>
|
||||
<button type="button" className={naturalIconClass} style={iconStyle} aria-label={t("topNav.language")} title={t("topNav.language")}>
|
||||
<Globe2 className="size-4" />
|
||||
</button>
|
||||
</Dropdown>
|
||||
<AnimatedThemeToggler theme={theme} onThemeChange={setTheme} className={naturalIconClass} style={iconStyle} aria-label={t(theme === "dark" ? "topNav.lightTheme" : "topNav.darkTheme")} title={t(theme === "dark" ? "topNav.lightTheme" : "topNav.darkTheme")} />
|
||||
<VersionReleaseModal style={versionStyle} />
|
||||
<GitHubLink className={cn("bg-transparent hover:bg-transparent dark:hover:bg-transparent", gitHubClassName)} style={gitHubStyle} />
|
||||
|
||||
@@ -323,6 +323,7 @@ export default {
|
||||
closeAgent: "Close Agent",
|
||||
plugins: "Node plugins",
|
||||
docs: "Documentation",
|
||||
language: "Change language",
|
||||
shortcuts: "Keyboard shortcuts",
|
||||
lightTheme: "Switch to light theme",
|
||||
darkTheme: "Switch to dark theme",
|
||||
|
||||
@@ -323,6 +323,7 @@ export default {
|
||||
closeAgent: "收起 Agent",
|
||||
plugins: "节点插件",
|
||||
docs: "文档",
|
||||
language: "切换语言",
|
||||
shortcuts: "快捷键",
|
||||
lightTheme: "切换到浅色主题",
|
||||
darkTheme: "切换到深色主题",
|
||||
|
||||
+33
-20
@@ -6,11 +6,11 @@ const neutral = {
|
||||
primary: "#171717",
|
||||
primaryHover: "#000000",
|
||||
primaryText: "#ffffff",
|
||||
menuBg: "#f5f5f5",
|
||||
menuText: "#171717",
|
||||
selectActiveBg: "#f5f5f5",
|
||||
selectSelectedBg: "#f0f0f0",
|
||||
selectText: "#171717",
|
||||
elevatedBg: "#ffffff",
|
||||
itemHoverBg: "rgba(23, 23, 23, 0.06)",
|
||||
itemSelectedBg: "rgba(23, 23, 23, 0.1)",
|
||||
itemSelectedHoverBg: "rgba(23, 23, 23, 0.14)",
|
||||
itemText: "#171717",
|
||||
tableSelectedBg: "rgba(17, 17, 17, 0.05)",
|
||||
tableSelectedHoverBg: "rgba(17, 17, 17, 0.08)",
|
||||
},
|
||||
@@ -18,11 +18,11 @@ const neutral = {
|
||||
primary: "#fafafa",
|
||||
primaryHover: "#ffffff",
|
||||
primaryText: "#171717",
|
||||
menuBg: "#262626",
|
||||
menuText: "#fafafa",
|
||||
selectActiveBg: "#262626",
|
||||
selectSelectedBg: "#333333",
|
||||
selectText: "#fafafa",
|
||||
elevatedBg: "#1c1917",
|
||||
itemHoverBg: "rgba(250, 250, 249, 0.08)",
|
||||
itemSelectedBg: "rgba(250, 250, 249, 0.12)",
|
||||
itemSelectedHoverBg: "rgba(250, 250, 249, 0.16)",
|
||||
itemText: "#fafafa",
|
||||
tableSelectedBg: "rgba(255, 255, 255, 0.08)",
|
||||
tableSelectedHoverBg: "rgba(255, 255, 255, 0.12)",
|
||||
},
|
||||
@@ -41,24 +41,37 @@ export function getAntThemeConfig(dark: boolean): ThemeConfig {
|
||||
colorLinkHover: color.primaryHover,
|
||||
colorLinkActive: color.primary,
|
||||
colorTextLightSolid: color.primaryText,
|
||||
colorBgElevated: color.elevatedBg,
|
||||
controlItemBgHover: color.itemHoverBg,
|
||||
controlItemBgActive: color.itemSelectedBg,
|
||||
controlItemBgActiveHover: color.itemSelectedHoverBg,
|
||||
},
|
||||
components: {
|
||||
Button: {
|
||||
primaryShadow: "none",
|
||||
},
|
||||
Dropdown: {
|
||||
colorBgElevated: color.elevatedBg,
|
||||
colorText: color.itemText,
|
||||
controlItemBgHover: color.itemHoverBg,
|
||||
controlItemBgActive: color.itemSelectedBg,
|
||||
controlItemBgActiveHover: color.itemSelectedHoverBg,
|
||||
},
|
||||
Menu: {
|
||||
itemActiveBg: color.menuBg,
|
||||
itemHoverBg: color.menuBg,
|
||||
itemSelectedBg: color.menuBg,
|
||||
itemSelectedColor: color.menuText,
|
||||
darkItemHoverBg: neutral.dark.menuBg,
|
||||
darkItemSelectedBg: neutral.dark.menuBg,
|
||||
darkItemSelectedColor: neutral.dark.menuText,
|
||||
popupBg: color.elevatedBg,
|
||||
itemActiveBg: color.itemSelectedBg,
|
||||
itemHoverBg: color.itemHoverBg,
|
||||
itemSelectedBg: color.itemSelectedBg,
|
||||
itemSelectedColor: color.itemText,
|
||||
darkPopupBg: neutral.dark.elevatedBg,
|
||||
darkItemHoverBg: neutral.dark.itemHoverBg,
|
||||
darkItemSelectedBg: neutral.dark.itemSelectedBg,
|
||||
darkItemSelectedColor: neutral.dark.itemText,
|
||||
},
|
||||
Select: {
|
||||
optionActiveBg: color.selectActiveBg,
|
||||
optionSelectedBg: color.selectSelectedBg,
|
||||
optionSelectedColor: color.selectText,
|
||||
optionActiveBg: color.itemHoverBg,
|
||||
optionSelectedBg: color.itemSelectedBg,
|
||||
optionSelectedColor: color.itemText,
|
||||
},
|
||||
Table: {
|
||||
rowSelectedBg: color.tableSelectedBg,
|
||||
|
||||
Reference in New Issue
Block a user