feat: add source/target language selectors to edit glossary dialog
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m24s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m24s
Users can now change the language pair when editing a glossary: - EditGlossaryDialog has source/target language dropdowns - Default target_language changed from 'en' to 'multi' in create dialog - onSave passes source_language and target_language to the backend - Backend PATCH endpoint already supports updating these fields Also fixes: - CreateGlossaryDialog defaults to 'multi' instead of 'en' - SUPPORTED_LANGUAGES now includes 'multi' option for target Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -292,7 +292,7 @@ export function CreateGlossaryDialog({
|
||||
const [name, setName] = useState('');
|
||||
const [nameAutoFilled, setNameAutoFilled] = useState(false);
|
||||
const [sourceLanguage, setSourceLanguage] = useState('fr');
|
||||
const [targetLanguage, setTargetLanguage] = useState('en');
|
||||
const [targetLanguage, setTargetLanguage] = useState('multi');
|
||||
const [terms, setTerms] = useState<GlossaryTermInput[]>([{ source: '', target: '' }]);
|
||||
const [fileTerms, setFileTerms] = useState<GlossaryTermInput[]>([]);
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<GlossaryTemplate | null>(null);
|
||||
@@ -305,7 +305,7 @@ export function CreateGlossaryDialog({
|
||||
setName('');
|
||||
setNameAutoFilled(false);
|
||||
setSourceLanguage('fr');
|
||||
setTargetLanguage('en');
|
||||
setTargetLanguage('multi');
|
||||
setTerms([{ source: '', target: '' }]);
|
||||
setFileTerms([]);
|
||||
setSelectedTemplate(null);
|
||||
|
||||
@@ -17,13 +17,13 @@ import { TermEditor } from './TermEditor';
|
||||
import { exportGlossaryToCsv, parseCsvToTerms } from './csvUtils';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
import type { Glossary, GlossaryTermInput } from './types';
|
||||
import { MAX_TERMS_PER_GLOSSARY } from './types';
|
||||
import { MAX_TERMS_PER_GLOSSARY, SUPPORTED_LANGUAGES } from './types';
|
||||
|
||||
interface EditGlossaryDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
glossary: Glossary | null;
|
||||
onSave: (id: string, data: { name: string; terms: GlossaryTermInput[] }) => Promise<void>;
|
||||
onSave: (id: string, data: { name: string; source_language: string; target_language: string; terms: GlossaryTermInput[] }) => Promise<void>;
|
||||
isSaving: boolean;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ export function EditGlossaryDialog({
|
||||
isSaving,
|
||||
}: EditGlossaryDialogProps) {
|
||||
const [name, setName] = useState('');
|
||||
const [sourceLanguage, setSourceLanguage] = useState('fr');
|
||||
const [targetLanguage, setTargetLanguage] = useState('multi');
|
||||
const [terms, setTerms] = useState<GlossaryTermInput[]>([]);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -42,6 +44,8 @@ export function EditGlossaryDialog({
|
||||
|
||||
if (glossary && !isInitialized.current) {
|
||||
setName(glossary.name);
|
||||
setSourceLanguage(glossary.source_language || 'fr');
|
||||
setTargetLanguage(glossary.target_language || 'multi');
|
||||
setTerms(glossary.terms.map(t => ({ source: t.source, target: t.target })));
|
||||
isInitialized.current = true;
|
||||
}
|
||||
@@ -57,9 +61,11 @@ export function EditGlossaryDialog({
|
||||
|
||||
await onSave(glossary.id, {
|
||||
name: name.trim(),
|
||||
source_language: sourceLanguage,
|
||||
target_language: targetLanguage,
|
||||
terms: validTerms,
|
||||
});
|
||||
}, [glossary, name, terms, onSave]);
|
||||
}, [glossary, name, sourceLanguage, targetLanguage, terms, onSave]);
|
||||
|
||||
const handleExport = useCallback(() => {
|
||||
if (!glossary) return;
|
||||
@@ -154,6 +160,36 @@ export function EditGlossaryDialog({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1">
|
||||
<Label className="text-xs text-muted-foreground mb-1 block">Langue source</Label>
|
||||
<select
|
||||
value={sourceLanguage}
|
||||
onChange={e => setSourceLanguage(e.target.value)}
|
||||
disabled={isSaving}
|
||||
className="w-full h-9 rounded-md border border-input bg-background px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
||||
>
|
||||
{SUPPORTED_LANGUAGES.filter(l => l.code !== 'multi').map(l => (
|
||||
<option key={l.code} value={l.code}>{l.flag} {l.label}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="pt-5 text-muted-foreground font-bold">→</div>
|
||||
<div className="flex-1">
|
||||
<Label className="text-xs text-muted-foreground mb-1 block">Langue cible</Label>
|
||||
<select
|
||||
value={targetLanguage}
|
||||
onChange={e => setTargetLanguage(e.target.value)}
|
||||
disabled={isSaving}
|
||||
className="w-full h-9 rounded-md border border-input bg-background px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
|
||||
>
|
||||
{SUPPORTED_LANGUAGES.map(l => (
|
||||
<option key={l.code} value={l.code}>{l.flag} {l.label}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Terms ({validTermsCount} valid)</Label>
|
||||
<TermEditor
|
||||
|
||||
@@ -185,7 +185,7 @@ export default function GlossariesPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveGlossary = async (id: string, data: { name: string; terms: GlossaryTermInput[] }) => {
|
||||
const handleSaveGlossary = async (id: string, data: { name: string; source_language: string; target_language: string; terms: GlossaryTermInput[] }) => {
|
||||
try {
|
||||
await updateGlossary(id, data);
|
||||
setEditDialogOpen(false);
|
||||
|
||||
Reference in New Issue
Block a user