Feat: 增加语言过滤功能,临时性不显示对应语言
This commit is contained in:
parent
83e826e034
commit
2ae98780de
|
|
@ -35,7 +35,7 @@ export async function requestTranslations({
|
|||
const keysJson = JSON.stringify(items.map((it) => it.key));
|
||||
const instruction = [
|
||||
"你是一个专业的翻译助手。",
|
||||
`请将多条原文同时翻译为这些目标语言:${targetList},注意英语的首字母务必是大写。`,
|
||||
`请使用当地人的习惯用语,将多条原文同时翻译为这些目标语言:${targetList},注意英语的首字母务必是大写。`,
|
||||
"翻译偏好:",
|
||||
prompt,
|
||||
"严格要求:",
|
||||
|
|
|
|||
|
|
@ -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<Set<string>>(new Set());
|
||||
const [visibleLangs, setVisibleLangs] = useState<Set<string>>(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() {
|
|||
/>
|
||||
</th>
|
||||
<th style={{ width: 300 }} className="text-left px-3 py-2">翻译条目名称</th>
|
||||
{languages.map((lang) => (
|
||||
{displayedLanguages.map((lang) => (
|
||||
<th key={lang} style={{ width: 200 }} className="text-left px-3 py-2">{lang}</th>
|
||||
))}
|
||||
<th style={{ width: 60 }} className="sticky right-0 text-left px-3 py-2 bg-muted">操作</th>
|
||||
</tr>
|
||||
), [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}
|
||||
</button>
|
||||
</td>
|
||||
{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() {
|
|||
</td>
|
||||
</>
|
||||
);
|
||||
}, [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() {
|
|||
</Button>
|
||||
</form>
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" title="过滤显示的语言列">
|
||||
<Filter />
|
||||
语言过滤
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="w-48">
|
||||
<DropdownMenuItem onClick={() => setVisibleLangs(new Set(languages))}>
|
||||
全部显示
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
{languages.map((lang) => {
|
||||
const checked = visibleLangs.has(lang);
|
||||
return (
|
||||
<DropdownMenuCheckboxItem
|
||||
key={lang}
|
||||
onSelect={(e) => 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}
|
||||
</DropdownMenuCheckboxItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={selected.size === 0 || selected.size > MAX_AI_ITEMS}
|
||||
|
|
|
|||
Loading…
Reference in New Issue