fix(translate): ajout des cles de traduction manquantes et re-positionnement intelligent du bouton de traduction
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m41s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m41s
This commit is contained in:
@@ -184,7 +184,7 @@ export default function TranslatePage() {
|
||||
const qualityLabel = useMemo(() => getQualityLabel(t, config.provider), [t, config.provider]);
|
||||
|
||||
return (
|
||||
<div className="min-h-full p-6 lg:p-8 dark:bg-[#0a0a0a] selection:bg-brand-accent/10">
|
||||
<div className="min-h-full p-6 pb-24 lg:pb-8 lg:p-8 dark:bg-[#0a0a0a] selection:bg-brand-accent/10">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
|
||||
{/* ── HEADER (Landing Page Style) ───────────────────────── */}
|
||||
@@ -296,6 +296,44 @@ export default function TranslatePage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── Desktop Submit Button & Actions (shown when not processing/complete) ── */}
|
||||
{(showUpload || showConfiguring) && (
|
||||
<div className="hidden lg:block editorial-card p-6 bg-white dark:bg-[#141414] border-none shadow-editorial space-y-4">
|
||||
<button
|
||||
disabled={!config.isConfigValid || submit.isSubmitting || !upload.file}
|
||||
onClick={handleTranslate}
|
||||
className={cn(
|
||||
'w-full py-4 text-[10px] font-bold uppercase tracking-[0.25em] flex items-center justify-center gap-2 rounded-2xl transition-all shadow-sm active:scale-98',
|
||||
config.isConfigValid && upload.file && !submit.isSubmitting
|
||||
? 'bg-brand-dark text-white hover:bg-brand-accent dark:bg-brand-accent dark:text-brand-dark hover:shadow-xl cursor-pointer'
|
||||
: 'bg-brand-muted/70 text-brand-dark/25 dark:bg-white/5 dark:text-white/20 cursor-not-allowed border border-black/[0.03] dark:border-white/[0.03]'
|
||||
)}
|
||||
>
|
||||
{submit.isSubmitting ? (
|
||||
<><Loader2 className="size-4 animate-spin" /> {t('dashboard.translate.actions.uploading') || 'Soumission...'}</>
|
||||
) : (
|
||||
<>Lancer la traduction <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{!upload.file && (
|
||||
<p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 font-bold uppercase tracking-widest">{t('dashboard.translate.noFile') || 'Veuillez charger un fichier'}</p>
|
||||
)}
|
||||
{upload.file && !config.targetLang && (
|
||||
<p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 font-bold uppercase tracking-widest">{t('dashboard.translate.noTargetLang') || 'Veuillez choisir une langue cible'}</p>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between text-[7.5px] font-bold uppercase tracking-[0.15em] text-brand-dark/30 dark:text-white/30 border-t border-black/5 dark:border-white/5 pt-4">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<ShieldCheck size={12} /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<Clock size={12} /> {t('landing.translate.filesDeleted') || 'Fichiers supprimés post-traitement'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── PROCESSING STATE: Rich progress ───────────────── */}
|
||||
{showProcessing && (
|
||||
<div className="editorial-card p-12 h-full border-none shadow-editorial bg-white dark:bg-[#141414] space-y-12">
|
||||
@@ -570,41 +608,6 @@ export default function TranslatePage() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── TRANSLATE BUTTON — fixed at bottom, never scrolls away ── */}
|
||||
<div className="shrink-0 p-6 pt-4 bg-white dark:bg-[#141414] border-t border-black/5 dark:border-white/5">
|
||||
<button
|
||||
disabled={!config.isConfigValid || submit.isSubmitting || !upload.file}
|
||||
onClick={handleTranslate}
|
||||
className={cn(
|
||||
'w-full py-4 text-[10px] font-bold uppercase tracking-[0.2em] flex items-center justify-center gap-2 rounded-2xl transition-all shadow-sm active:scale-98',
|
||||
config.isConfigValid && upload.file && !submit.isSubmitting
|
||||
? 'bg-brand-dark text-white hover:bg-brand-accent dark:bg-brand-accent dark:text-brand-dark hover:shadow-xl cursor-pointer'
|
||||
: 'bg-brand-muted/70 text-brand-dark/25 dark:bg-white/5 dark:text-white/20 cursor-not-allowed border border-black/[0.03] dark:border-white/[0.03]'
|
||||
)}
|
||||
>
|
||||
{submit.isSubmitting ? (
|
||||
<><Loader2 className="size-4 animate-spin" /> Soumission...</>
|
||||
) : (
|
||||
<>Lancer la traduction <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
|
||||
)}
|
||||
</button>
|
||||
{!upload.file && (
|
||||
<p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 mt-2.5 font-bold uppercase tracking-widest">↑ Veuillez charger un fichier pour commencer</p>
|
||||
)}
|
||||
{upload.file && !config.targetLang && (
|
||||
<p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 mt-2.5 font-bold uppercase tracking-widest">↑ Veuillez choisir une langue cible</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 flex justify-between px-6 pb-5 pt-1 text-[7.5px] font-bold uppercase tracking-[0.15em] text-brand-dark/30 dark:text-white/30">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<ShieldCheck size={12} /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<Clock size={12} /> {t('landing.translate.filesDeleted') || 'Fichiers supprimés post-traitement'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -747,6 +750,28 @@ export default function TranslatePage() {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Mobile Sticky Action Bar (visible on mobile, hidden on lg) */}
|
||||
{(showUpload || showConfiguring) && (
|
||||
<div className="block lg:hidden fixed bottom-0 left-0 right-0 z-40 p-4 bg-white/90 dark:bg-[#141414]/90 backdrop-blur-md border-t border-black/5 dark:border-white/5 shadow-lg">
|
||||
<button
|
||||
disabled={!config.isConfigValid || submit.isSubmitting || !upload.file}
|
||||
onClick={handleTranslate}
|
||||
className={cn(
|
||||
'w-full py-4 text-[10px] font-bold uppercase tracking-[0.2em] flex items-center justify-center gap-2 rounded-xl transition-all active:scale-98',
|
||||
config.isConfigValid && upload.file && !submit.isSubmitting
|
||||
? 'bg-brand-dark text-white hover:bg-brand-accent dark:bg-brand-accent dark:text-brand-dark cursor-pointer'
|
||||
: 'bg-brand-muted/70 text-brand-dark/25 dark:bg-white/5 dark:text-white/20 cursor-not-allowed'
|
||||
)}
|
||||
>
|
||||
{submit.isSubmitting ? (
|
||||
<><Loader2 className="size-4 animate-spin" /> {t('dashboard.translate.actions.uploading') || 'Soumission...'}</>
|
||||
) : (
|
||||
<>Lancer la traduction <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -195,6 +195,11 @@ const messages: Record<Locale, Record<string, string>> = {
|
||||
"dashboard.translate.provider.upgrade": "Upgrade to Pro",
|
||||
"dashboard.translate.provider.upgradeSuffix":
|
||||
"to unlock AI translation",
|
||||
"dashboard.translate.provider.tabStandard": "Standard",
|
||||
"dashboard.translate.provider.tabLLM": "AI Multi-Models",
|
||||
"translate.glossary.selectGlossary": "Select a glossary...",
|
||||
"dashboard.translate.translateImages": "Translate images",
|
||||
"dashboard.translate.translateImagesDesc": "Extract and translate text inside images (vision required)",
|
||||
"dashboard.translate.trust.zeroRetention": "Zero retention",
|
||||
"dashboard.translate.trust.deletedAfter":
|
||||
"Files deleted after processing",
|
||||
@@ -1004,6 +1009,11 @@ const messages: Record<Locale, Record<string, string>> = {
|
||||
"dashboard.translate.provider.upgrade": "Passer Pro",
|
||||
"dashboard.translate.provider.upgradeSuffix":
|
||||
"pour débloquer la traduction IA",
|
||||
"dashboard.translate.provider.tabStandard": "Standard",
|
||||
"dashboard.translate.provider.tabLLM": "Multi-Modèles IA",
|
||||
"translate.glossary.selectGlossary": "Sélectionner un glossaire...",
|
||||
"dashboard.translate.translateImages": "Traduire les images",
|
||||
"dashboard.translate.translateImagesDesc": "Extraire et traduire le texte des images (vision requise)",
|
||||
"dashboard.translate.trust.zeroRetention": "Rétention zéro",
|
||||
"dashboard.translate.trust.deletedAfter":
|
||||
"Fichiers supprimés après traitement",
|
||||
|
||||
Reference in New Issue
Block a user