fix: edit dialog remaps terms when target language changes
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s
When the user changes the target language dropdown in the edit dialog, terms now remap to show the language-specific translation from the translations dict. E.g. changing to Spanish shows 'servidor' instead of 'server'. Falls back to default English if no translation exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useCallback, useRef } from 'react';
|
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -27,6 +27,13 @@ interface EditGlossaryDialogProps {
|
|||||||
isSaving: boolean;
|
isSaving: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get the display target for a term based on the selected target language */
|
||||||
|
function getDisplayTarget(term: { target: string; translations?: Record<string, string> }, lang: string): string {
|
||||||
|
if (lang === 'multi' || lang === 'en') return term.target;
|
||||||
|
const translations = term.translations || {};
|
||||||
|
return translations[lang] || term.target;
|
||||||
|
}
|
||||||
|
|
||||||
export function EditGlossaryDialog({
|
export function EditGlossaryDialog({
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
@@ -39,14 +46,19 @@ export function EditGlossaryDialog({
|
|||||||
const [targetLanguage, setTargetLanguage] = useState('multi');
|
const [targetLanguage, setTargetLanguage] = useState('multi');
|
||||||
const [terms, setTerms] = useState<GlossaryTermInput[]>([]);
|
const [terms, setTerms] = useState<GlossaryTermInput[]>([]);
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const isInitialized = useRef(false);
|
const isInitialized = useRef(false);
|
||||||
|
|
||||||
|
// Initialize when glossary changes
|
||||||
if (glossary && !isInitialized.current) {
|
if (glossary && !isInitialized.current) {
|
||||||
setName(glossary.name);
|
setName(glossary.name);
|
||||||
setSourceLanguage(glossary.source_language || 'fr');
|
setSourceLanguage(glossary.source_language || 'fr');
|
||||||
setTargetLanguage(glossary.target_language || 'multi');
|
setTargetLanguage(glossary.target_language || 'multi');
|
||||||
setTerms(glossary.terms.map(t => ({ source: t.source, target: t.target })));
|
// Store terms with full translations data
|
||||||
|
setTerms(glossary.terms.map(t => ({
|
||||||
|
source: t.source,
|
||||||
|
target: t.target,
|
||||||
|
translations: t.translations || {},
|
||||||
|
})));
|
||||||
isInitialized.current = true;
|
isInitialized.current = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +66,28 @@ export function EditGlossaryDialog({
|
|||||||
isInitialized.current = false;
|
isInitialized.current = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When target language changes, remap displayed targets from translations dict
|
||||||
|
const handleTargetLanguageChange = useCallback((newLang: string) => {
|
||||||
|
setTargetLanguage(newLang);
|
||||||
|
// Don't remap if multi or en — those use the default target field
|
||||||
|
if (newLang === 'multi' || newLang === 'en') return;
|
||||||
|
setTerms(prev => prev.map(t => {
|
||||||
|
const translations = (t as any).translations || {};
|
||||||
|
const langTarget = translations[newLang];
|
||||||
|
if (langTarget) {
|
||||||
|
// Show the language-specific translation as the target
|
||||||
|
return { source: t.source, target: langTarget, translations };
|
||||||
|
}
|
||||||
|
// No translation for this language — keep the default English target
|
||||||
|
return t;
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSave = useCallback(async () => {
|
const handleSave = useCallback(async () => {
|
||||||
if (!glossary || !name.trim()) return;
|
if (!glossary || !name.trim()) return;
|
||||||
|
|
||||||
const validTerms = terms.filter(t => t.source.trim() && t.target.trim());
|
const validTerms = terms.filter(t => t.source.trim() && t.target.trim());
|
||||||
|
|
||||||
await onSave(glossary.id, {
|
await onSave(glossary.id, {
|
||||||
name: name.trim(),
|
name: name.trim(),
|
||||||
source_language: sourceLanguage,
|
source_language: sourceLanguage,
|
||||||
@@ -69,7 +98,7 @@ export function EditGlossaryDialog({
|
|||||||
|
|
||||||
const handleExport = useCallback(() => {
|
const handleExport = useCallback(() => {
|
||||||
if (!glossary) return;
|
if (!glossary) return;
|
||||||
|
|
||||||
const glossaryWithCurrentTerms: Glossary = {
|
const glossaryWithCurrentTerms: Glossary = {
|
||||||
...glossary,
|
...glossary,
|
||||||
name,
|
name,
|
||||||
@@ -77,11 +106,11 @@ export function EditGlossaryDialog({
|
|||||||
id: `temp-${i}`,
|
id: `temp-${i}`,
|
||||||
source: t.source,
|
source: t.source,
|
||||||
target: t.target,
|
target: t.target,
|
||||||
translations: t.translations || {},
|
translations: (t as any).translations || {},
|
||||||
created_at: null,
|
created_at: null,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
exportGlossaryToCsv(glossaryWithCurrentTerms);
|
exportGlossaryToCsv(glossaryWithCurrentTerms);
|
||||||
}, [glossary, name, terms]);
|
}, [glossary, name, terms]);
|
||||||
|
|
||||||
@@ -132,7 +161,7 @@ export function EditGlossaryDialog({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
|
|
||||||
e.target.value = '';
|
e.target.value = '';
|
||||||
}, [toast]);
|
}, [toast]);
|
||||||
|
|
||||||
@@ -144,7 +173,7 @@ export function EditGlossaryDialog({
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Edit Glossary</DialogTitle>
|
<DialogTitle>Edit Glossary</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Update the glossary name and term pairs.
|
Update the glossary name, language pair, and terms.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
@@ -179,7 +208,7 @@ export function EditGlossaryDialog({
|
|||||||
<Label className="text-xs text-muted-foreground mb-1 block">Langue cible</Label>
|
<Label className="text-xs text-muted-foreground mb-1 block">Langue cible</Label>
|
||||||
<select
|
<select
|
||||||
value={targetLanguage}
|
value={targetLanguage}
|
||||||
onChange={e => setTargetLanguage(e.target.value)}
|
onChange={e => handleTargetLanguageChange(e.target.value)}
|
||||||
disabled={isSaving}
|
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"
|
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"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user