diff --git a/src/lib/ai.ts b/src/lib/ai.ts index 3735b49..536cadb 100644 --- a/src/lib/ai.ts +++ b/src/lib/ai.ts @@ -35,7 +35,7 @@ export async function requestTranslations({ const keysJson = JSON.stringify(items.map((it) => it.key)); const instruction = [ "你是一个专业的翻译助手。", - `请将多条原文同时翻译为这些目标语言:${targetList},注意英语的首字母务必是大写。`, + `请使用当地人的习惯用语,将多条原文同时翻译为这些目标语言:${targetList},注意英语的首字母务必是大写。`, "翻译偏好:", prompt, "严格要求:", diff --git a/src/pages/editor.tsx b/src/pages/editor.tsx index eb0100e..fa1f6c5 100644 --- a/src/pages/editor.tsx +++ b/src/pages/editor.tsx @@ -17,7 +17,7 @@ import { updateProject, deleteProjectDeep, } from "@/lib/db"; -import { ArrowBigDownDash, ArrowBigUpDash, ArrowLeft, Brackets, CaseSensitive, Languages, LocateFixed, MoreVertical, PencilLine, Trash2 } from "lucide-react"; +import { ArrowBigDownDash, ArrowBigUpDash, ArrowLeft, Brackets, CaseSensitive, Filter, Languages, LocateFixed, MoreVertical, PencilLine, Trash2 } from "lucide-react"; import { useTranslationInlineEdit } from "@/hooks/biz/use-translation-inline-edit"; import { flattenEntries, type FlatEntry, insertEntrySibling, removeEntryAtPath, renameEntryAtPath } from "@/lib/i18n-structure"; import { ImportLanguageModal } from "@/components/biz/import-language-modal"; @@ -31,6 +31,7 @@ import { DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, + DropdownMenuCheckboxItem, DropdownMenuSeparator, } from "@/components/ui/dropdown-menu"; import { useClipboard } from "@/hooks/use-clipboard"; @@ -59,6 +60,7 @@ export default function Editor() { const [aiBulkOpen, setAiBulkOpen] = useState(false); const [settingsOpen, setSettingsOpen] = useState(false); const [selected, setSelected] = useState>(new Set()); + const [visibleLangs, setVisibleLangs] = useState>(new Set()); const { copy } = useClipboard(); @@ -139,7 +141,14 @@ export default function Editor() { onError: (m) => setPageError(m), }); - const tableWidth = useMemo(() => (languages.length * 200) + 36 + 60 + 300, [languages.length]); + // 同步可见语言集合 + useEffect(() => { + setVisibleLangs(new Set(languages)); + }, [languages]); + + const displayedLanguages = useMemo(() => languages.filter((l) => visibleLangs.has(l)), [languages, visibleLangs]); + + const tableWidth = useMemo(() => (displayedLanguages.length * 200) + 36 + 60 + 300, [displayedLanguages.length]); function computeSuggestedLanguages(pathsInput: string[]): string[] { if (languages.length === 0 || pathsInput.length === 0) return []; @@ -204,12 +213,12 @@ export default function Editor() { /> 翻译条目名称 - {languages.map((lang) => ( + {displayedLanguages.map((lang) => ( {lang} ))} 操作 - ), [languages, allSelected, entries]); + ), [displayedLanguages, allSelected, entries]); const renderItemContent = useCallback((_idx: number, entry: FlatEntry) => { const handleCopy = () => { @@ -236,7 +245,7 @@ export default function Editor() { {entry.path} - {languages.map((lang) => { + {displayedLanguages.map((lang) => { const isEditing = inline.isEditingCell(entry.path, lang); const isSaving = inline.isSavingCell(entry.path, lang); const displayValue = inline.getDisplayValue(entry.path, lang); @@ -324,7 +333,7 @@ export default function Editor() { ); - }, [languages, inline, projectId, structure, setStructure, setValuesByLang, copy, selected]); + }, [displayedLanguages, inline, projectId, structure, setStructure, setValuesByLang, copy, selected]); useEffect(() => { if (!projectId || languages.length === 0) return; @@ -414,6 +423,39 @@ export default function Editor() {
+ + + + + + setVisibleLangs(new Set(languages))}> + 全部显示 + + + {languages.map((lang) => { + const checked = visibleLangs.has(lang); + return ( + e.preventDefault()} + checked={checked} + onCheckedChange={(v) => { + setVisibleLangs((prev) => { + const next = new Set(prev); + if (v) next.add(lang); else next.delete(lang); + return next; + }); + }} + > + {lang} + + ); + })} + +