mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-07 01:54:24 +08:00
feat(i18n): implement internationalization framework and update UI components for language support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { ArrowUp, LoaderCircle, Square } from "lucide-react";
|
||||
import { Button } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { ModelPicker } from "@/components/model-picker";
|
||||
import { defaultConfig, resolveModelForCapability, useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
|
||||
@@ -30,6 +31,7 @@ type CanvasNodePromptPanelProps = {
|
||||
};
|
||||
|
||||
export function CanvasNodePromptPanel({ node, isRunning, onPromptChange, onConfigChange, onGenerate, onStop, mentionReferences = [], onImageSettingsOpenChange, modeOverride }: CanvasNodePromptPanelProps) {
|
||||
const { t } = useTranslation();
|
||||
const globalConfig = useEffectiveConfig();
|
||||
const openConfigDialog = useConfigStore((state) => state.openConfigDialog);
|
||||
const theme = canvasThemes[useThemeStore((state) => state.theme)];
|
||||
@@ -73,7 +75,7 @@ export function CanvasNodePromptPanel({ node, isRunning, onPromptChange, onConfi
|
||||
onSubmit={submit}
|
||||
className="thin-scrollbar h-40 w-full cursor-text resize-none rounded-xl px-3 py-2 text-sm leading-5 outline-none"
|
||||
style={{ background: "transparent", color: theme.node.text }}
|
||||
placeholder={promptPlaceholder(mode, hasImageContent, hasTextContent)}
|
||||
placeholder={t(`canvas.promptPanel.${mode === "image" && hasImageContent ? "editImage" : mode === "text" && hasTextContent ? "editText" : mode}`)}
|
||||
/>
|
||||
|
||||
<div className="mt-2 flex min-w-0 items-center justify-between gap-2">
|
||||
@@ -114,14 +116,14 @@ export function CanvasNodePromptPanel({ node, isRunning, onPromptChange, onConfi
|
||||
danger={isRunning}
|
||||
disabled={!isRunning && !prompt.trim()}
|
||||
onClick={() => (isRunning ? onStop(node.id) : submit())}
|
||||
aria-label={isRunning ? "停止生成" : "生成"}
|
||||
aria-label={t(isRunning ? "canvas.promptPanel.stopGeneration" : "canvas.promptPanel.generate")}
|
||||
>
|
||||
<span className="flex items-center gap-1.5">
|
||||
{isRunning ? (
|
||||
<>
|
||||
<LoaderCircle className="size-4 animate-spin" />
|
||||
<Square className="size-3.5 fill-current" />
|
||||
<span className="text-xs font-medium">停止</span>
|
||||
<span className="text-xs font-medium">{t("canvas.promptPanel.stop")}</span>
|
||||
</>
|
||||
) : (
|
||||
<ArrowUp className="size-4" />
|
||||
@@ -157,13 +159,6 @@ function buildNodeConfig(globalConfig: AiConfig, node: CanvasNodeData, mode: Can
|
||||
};
|
||||
}
|
||||
|
||||
function promptPlaceholder(mode: CanvasNodeGenerationMode, hasImageContent: boolean, hasTextContent: boolean) {
|
||||
if (mode === "video") return "描述要生成的视频内容";
|
||||
if (mode === "audio") return "描述要生成的音频内容";
|
||||
if (mode === "image") return hasImageContent ? "请输入你想要把这张图修改成什么" : "描述要生成的图片内容";
|
||||
return hasTextContent ? "请输入你想要将本段文本修改成什么" : "请输入你想要生成的文本内容";
|
||||
}
|
||||
|
||||
function videoConfigPatch(key: keyof AiConfig, value: string) {
|
||||
if (key === "videoSeconds") return { seconds: value };
|
||||
if (key === "videoGenerateAudio") return { generateAudio: value };
|
||||
|
||||
Reference in New Issue
Block a user