feat(i18n): Phase 1 — migrate 5 critical files from hardcoded text to i18n
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m51s

47 new i18n keys added across all 13 locales (en, fr, es, de, pt, it,
nl, ru, ja, ko, zh, ar, fa). English and French are fully translated,
remaining locales use French as placeholder.

Files migrated:
- EditGlossaryDialog.tsx (18 strings)
- DeleteGlossaryDialog.tsx (7 strings)
- ProUpgradePrompt.tsx (10 strings)
- WebhookSnippet.tsx (4 strings)
- TranslationModeToggle.tsx (8 strings)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 00:28:24 +02:00
parent c82e70681f
commit 6d27dc4cda
6 changed files with 666 additions and 47 deletions

View File

@@ -5,6 +5,7 @@ import { Webhook, Copy, Check } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { API_BASE_URL } from '@/lib/apiClient';
import { useI18n } from '@/lib/i18n';
function getWebhookSnippet(): string {
const baseUrl = API_BASE_URL.replace(/\/$/, '');
@@ -18,6 +19,7 @@ function getWebhookSnippet(): string {
}
export function WebhookSnippet() {
const { t } = useI18n();
const [copied, setCopied] = useState(false);
const webhookSnippet = useMemo(() => getWebhookSnippet(), []);
@@ -33,13 +35,12 @@ export function WebhookSnippet() {
<CardHeader>
<div className="flex items-center gap-2">
<Webhook className="h-5 w-5 text-accent" />
<CardTitle className="text-base">Webhook Integration</CardTitle>
<CardTitle className="text-base">{t('apiKeys.webhook.title')}</CardTitle>
</div>
</CardHeader>
<CardContent className="space-y-3">
<p className="text-sm text-muted-foreground">
Pass a <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">webhook_url</code> parameter
to receive a POST request when your translation is complete.
{t('apiKeys.webhook.descriptionBefore')}<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">{t('apiKeys.webhook.codeParam')}</code>{t('apiKeys.webhook.descriptionAfter')}
</p>
<div className="relative">
<Button

View File

@@ -10,6 +10,7 @@ import {
DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { useI18n } from '@/lib/i18n';
interface DeleteGlossaryDialogProps {
open: boolean;
@@ -26,13 +27,14 @@ export function DeleteGlossaryDialog({
isDeleting,
glossaryName,
}: DeleteGlossaryDialogProps) {
const { t } = useI18n();
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Delete Glossary</DialogTitle>
<DialogTitle>{t('glossaries.delete.title')}</DialogTitle>
<DialogDescription>
Are you sure you want to delete this glossary?
{t('glossaries.delete.description')}
{glossaryName && (
<span className="block mt-1 font-medium text-foreground">
"{glossaryName}"
@@ -45,9 +47,9 @@ export function DeleteGlossaryDialog({
<div className="flex items-start gap-3">
<AlertTriangle className="h-5 w-5 text-destructive shrink-0 mt-0.5" />
<div className="space-y-1">
<p className="text-sm font-medium text-destructive">This action cannot be undone</p>
<p className="text-sm font-medium text-destructive">{t('glossaries.delete.warning')}</p>
<p className="text-sm text-muted-foreground">
All term pairs will be permanently removed.
{t('glossaries.delete.warningDesc')}
</p>
</div>
</div>
@@ -59,14 +61,14 @@ export function DeleteGlossaryDialog({
onClick={() => onOpenChange(false)}
disabled={isDeleting}
>
Cancel
{t('glossaries.delete.cancel')}
</Button>
<Button
variant="destructive"
<Button
variant="destructive"
onClick={onConfirm}
disabled={isDeleting}
>
{isDeleting ? 'Deleting...' : 'Delete'}
{isDeleting ? t('glossaries.delete.deleting') : t('glossaries.delete.deleteBtn')}
</Button>
</DialogFooter>
</DialogContent>

View File

@@ -18,6 +18,7 @@ import { exportGlossaryToCsv, parseCsvToTerms } from './csvUtils';
import { useToast } from '@/components/ui/toast';
import type { Glossary, GlossaryTermInput } from './types';
import { MAX_TERMS_PER_GLOSSARY, SUPPORTED_LANGUAGES } from './types';
import { useI18n } from '@/lib/i18n';
interface EditGlossaryDialogProps {
open: boolean;
@@ -41,6 +42,7 @@ export function EditGlossaryDialog({
onSave,
isSaving,
}: EditGlossaryDialogProps) {
const { t } = useI18n();
const [name, setName] = useState('');
const [sourceLanguage, setSourceLanguage] = useState('fr');
const [targetLanguage, setTargetLanguage] = useState('multi');
@@ -133,22 +135,22 @@ export function EditGlossaryDialog({
if (importedTerms.length > MAX_TERMS_PER_GLOSSARY) {
toast({
variant: 'destructive',
title: 'Import failed',
description: `CSV contains ${importedTerms.length} terms, but maximum is ${MAX_TERMS_PER_GLOSSARY}. Please reduce the number of terms.`,
title: t('glossaries.edit.importFailedTitle'),
description: t('glossaries.edit.importFailedMaxDesc', { count: importedTerms.length, max: MAX_TERMS_PER_GLOSSARY }),
});
e.target.value = '';
return;
}
setTerms(importedTerms);
toast({
title: 'Import successful',
description: `${importedTerms.length} terms imported successfully.`,
title: t('glossaries.edit.importSuccessTitle'),
description: t('glossaries.edit.importSuccessDesc', { count: importedTerms.length }),
});
} else {
toast({
variant: 'destructive',
title: 'Import failed',
description: 'No valid terms found in CSV file.',
title: t('glossaries.edit.importFailedTitle'),
description: t('glossaries.edit.importFailedEmptyDesc'),
});
}
}
@@ -156,8 +158,8 @@ export function EditGlossaryDialog({
reader.onerror = () => {
toast({
variant: 'destructive',
title: 'Import failed',
description: 'Failed to read CSV file.',
title: t('glossaries.edit.importFailedTitle'),
description: t('glossaries.edit.importFailedReadDesc'),
});
};
reader.readAsText(file);
@@ -171,27 +173,27 @@ export function EditGlossaryDialog({
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Edit Glossary</DialogTitle>
<DialogTitle>{t('glossaries.edit.title')}</DialogTitle>
<DialogDescription>
Update the glossary name, language pair, and terms.
{t('glossaries.edit.description')}
</DialogDescription>
</DialogHeader>
<div className="space-y-6 py-4">
<div className="space-y-2">
<Label htmlFor="glossary-name">Glossary Name</Label>
<Label htmlFor="glossary-name">{t('glossaries.edit.nameLabel')}</Label>
<Input
id="glossary-name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter glossary name..."
placeholder={t('glossaries.edit.namePlaceholder')}
disabled={isSaving}
/>
</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>
<Label className="text-xs text-muted-foreground mb-1 block">{t('glossaries.edit.sourceLang')}</Label>
<select
value={sourceLanguage}
onChange={e => setSourceLanguage(e.target.value)}
@@ -205,7 +207,7 @@ export function EditGlossaryDialog({
</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>
<Label className="text-xs text-muted-foreground mb-1 block">{t('glossaries.edit.targetLang')}</Label>
<select
value={targetLanguage}
onChange={e => handleTargetLanguageChange(e.target.value)}
@@ -220,7 +222,7 @@ export function EditGlossaryDialog({
</div>
<div className="space-y-2">
<Label>Terms ({validTermsCount} valid)</Label>
<Label>{t('glossaries.edit.termsLabel', { count: validTermsCount })}</Label>
<TermEditor
terms={terms}
onChange={setTerms}
@@ -238,7 +240,7 @@ export function EditGlossaryDialog({
className="gap-1.5"
>
<Download className="size-3.5" />
Export CSV
{t('glossaries.edit.exportCsv')}
</Button>
<Button
type="button"
@@ -249,7 +251,7 @@ export function EditGlossaryDialog({
className="gap-1.5"
>
<Upload className="size-3.5" />
Import CSV
{t('glossaries.edit.importCsv')}
</Button>
<input
ref={fileInputRef}
@@ -267,13 +269,13 @@ export function EditGlossaryDialog({
onClick={() => onOpenChange(false)}
disabled={isSaving}
>
Cancel
{t('glossaries.edit.cancel')}
</Button>
<Button
onClick={handleSave}
disabled={isSaving || !name.trim()}
>
{isSaving ? 'Saving...' : 'Save Changes'}
{isSaving ? t('glossaries.edit.saving') : t('glossaries.edit.saveChanges')}
</Button>
</DialogFooter>
</DialogContent>

View File

@@ -4,8 +4,10 @@ import { BookText, Sparkles } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import Link from 'next/link';
import { useI18n } from '@/lib/i18n';
export function ProUpgradePrompt() {
const { t } = useI18n();
return (
<div className="flex items-center justify-center min-h-[60vh] p-6">
<Card className="max-w-md w-full border-border/50 bg-gradient-to-br from-card via-card to-accent/5">
@@ -13,39 +15,38 @@ export function ProUpgradePrompt() {
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-accent/20 to-accent/5">
<BookText className="h-8 w-8 text-accent" />
</div>
<CardTitle className="text-2xl font-semibold">Glossaries</CardTitle>
<CardTitle className="text-2xl font-semibold">{t('glossaries.upgrade.title')}</CardTitle>
<CardDescription className="text-base">
Customize your translations with custom terminology
{t('glossaries.upgrade.description')}
</CardDescription>
</CardHeader>
<CardContent className="text-center space-y-6">
<div className="space-y-3">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Sparkles className="h-4 w-4 text-accent shrink-0" />
<span>Create multiple glossaries</span>
<span>{t('glossaries.upgrade.feature1')}</span>
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Sparkles className="h-4 w-4 text-accent shrink-0" />
<span>Define sourcetarget term pairs</span>
<span>{t('glossaries.upgrade.feature2')}</span>
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Sparkles className="h-4 w-4 text-accent shrink-0" />
<span>Import/export via CSV</span>
<span>{t('glossaries.upgrade.feature3')}</span>
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Sparkles className="h-4 w-4 text-accent shrink-0" />
<span>Apply to LLM translations</span>
<span>{t('glossaries.upgrade.feature4')}</span>
</div>
</div>
<div className="pt-2">
<p className="text-sm text-muted-foreground mb-4">
Glossaries are a <span className="text-accent font-medium">Pro</span> feature.
Upgrade to unlock custom terminology.
{t('glossaries.upgrade.proFeatureBefore')}<span className="text-accent font-medium">{t('glossaries.upgrade.proLabel')}</span>{t('glossaries.upgrade.proFeatureAfter')}
</p>
<Button asChild className="w-full bg-accent hover:bg-accent/90">
<Link href="/pricing">
Upgrade to Pro
{t('glossaries.upgrade.upgradeBtn')}
</Link>
</Button>
</div>

View File

@@ -9,6 +9,7 @@ import {
TooltipTrigger,
} from '@/components/ui/tooltip';
import type { TranslationMode } from './types';
import { useI18n } from '@/lib/i18n';
interface TranslationModeToggleProps {
mode: TranslationMode;
@@ -21,11 +22,12 @@ export function TranslationModeToggle({
onModeChange,
isPro,
}: TranslationModeToggleProps) {
const { t } = useI18n();
return (
<TooltipProvider>
<div className="flex flex-col gap-1.5">
<label className="text-xs font-medium text-muted-foreground">
Translation Mode
{t('translate.mode.label')}
</label>
<div className="flex rounded-lg border border-border bg-muted p-1">
<button
@@ -38,9 +40,9 @@ export function TranslationModeToggle({
)}
onClick={() => onModeChange('classic')}
>
Classic
{t('translate.mode.classic')}
<span className="ms-1.5 text-xs text-muted-foreground">
Fast
{t('translate.mode.classicDesc')}
</span>
</button>
<Tooltip>
@@ -57,9 +59,9 @@ export function TranslationModeToggle({
onClick={() => isPro && onModeChange('llm')}
disabled={!isPro}
>
Pro LLM
{t('translate.mode.proLlm')}
<span className="ms-1.5 text-xs text-muted-foreground">
Context-Aware
{t('translate.mode.proLlmDesc')}
</span>
{!isPro && (
<Lock className="absolute right-2 top-1/2 -translate-y-1/2 size-3 text-muted-foreground" />
@@ -68,7 +70,7 @@ export function TranslationModeToggle({
</TooltipTrigger>
{!isPro && (
<TooltipContent side="top">
<p>Upgrade to Pro for LLM translation</p>
<p>{t('translate.mode.tooltip')}</p>
</TooltipContent>
)}
</Tooltip>
@@ -76,9 +78,9 @@ export function TranslationModeToggle({
{!isPro && (
<p className="text-xs text-muted-foreground">
<a href="/pricing" className="text-primary hover:underline">
Upgrade to Pro
{t('translate.mode.upgradeLink')}
</a>{' '}
for LLM-powered translations
{t('translate.mode.upgradeDesc')}
</p>
)}
</div>

View File

@@ -323,6 +323,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "terms imported",
"glossaries.dialog.changeFile": "Change file",
"glossaries.dialog.retry": "Retry",
"glossaries.edit.title": "Edit Glossary",
"glossaries.edit.description": "Update the glossary name, language pair, and terms.",
"glossaries.edit.nameLabel": "Glossary Name",
"glossaries.edit.namePlaceholder": "Enter glossary name...",
"glossaries.edit.sourceLang": "Source language",
"glossaries.edit.targetLang": "Target language",
"glossaries.edit.termsLabel": "Terms ({count} valid)",
"glossaries.edit.exportCsv": "Export CSV",
"glossaries.edit.importCsv": "Import CSV",
"glossaries.edit.cancel": "Cancel",
"glossaries.edit.saving": "Saving...",
"glossaries.edit.saveChanges": "Save Changes",
"glossaries.edit.importFailedTitle": "Import failed",
"glossaries.edit.importFailedMaxDesc": "CSV contains {count} terms, but maximum is {max}. Please reduce the number of terms.",
"glossaries.edit.importSuccessTitle": "Import successful",
"glossaries.edit.importSuccessDesc": "{count} terms imported successfully.",
"glossaries.edit.importFailedEmptyDesc": "No valid terms found in CSV file.",
"glossaries.edit.importFailedReadDesc": "Failed to read CSV file.",
"glossaries.delete.title": "Delete Glossary",
"glossaries.delete.description": "Are you sure you want to delete this glossary?",
"glossaries.delete.warning": "This action cannot be undone",
"glossaries.delete.warningDesc": "All term pairs will be permanently removed.",
"glossaries.delete.cancel": "Cancel",
"glossaries.delete.deleting": "Deleting...",
"glossaries.delete.deleteBtn": "Delete",
"glossaries.upgrade.title": "Glossaries",
"glossaries.upgrade.description": "Customize your translations with custom terminology",
"glossaries.upgrade.feature1": "Create multiple glossaries",
"glossaries.upgrade.feature2": "Define source→target term pairs",
"glossaries.upgrade.feature3": "Import/export via CSV",
"glossaries.upgrade.feature4": "Apply to LLM translations",
"glossaries.upgrade.proFeatureBefore": "Glossaries are a ",
"glossaries.upgrade.proFeatureAfter": " feature. Upgrade to unlock custom terminology.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Upgrade to Pro",
"apiKeys.webhook.title": "Webhook Integration",
"apiKeys.webhook.descriptionBefore": "Pass a ",
"apiKeys.webhook.descriptionAfter": " parameter to receive a POST request when your translation is complete.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Translation Mode",
"translate.mode.classic": "Classic",
"translate.mode.classicDesc": "Fast",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Context-Aware",
"translate.mode.tooltip": "Upgrade to Pro for LLM translation",
"translate.mode.upgradeLink": "Upgrade to Pro",
"translate.mode.upgradeDesc": "for LLM-powered translations",
// ── Pricing page ──
"pricing.nav.back": "Back",
@@ -1140,6 +1187,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "termes importés",
"glossaries.dialog.changeFile": "Changer le fichier",
"glossaries.dialog.retry": "Réessayer",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
// ── Pricing page ──
"pricing.nav.back": "Retour",
@@ -1943,6 +2037,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "términos importados",
"glossaries.dialog.changeFile": "Cambiar archivo",
"glossaries.dialog.retry": "Reintentar",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Volver",
"pricing.nav.home": "Inicio",
"pricing.nav.mySubscription": "Mi suscripción",
@@ -2701,6 +2842,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "Begriffe importiert",
"glossaries.dialog.changeFile": "Datei ändern",
"glossaries.dialog.retry": "Erneut versuchen",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Zurück",
"pricing.nav.home": "Startseite",
"pricing.nav.mySubscription": "Mein Abonnement",
@@ -3459,6 +3647,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "termos importados",
"glossaries.dialog.changeFile": "Trocar arquivo",
"glossaries.dialog.retry": "Tentar novamente",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Voltar",
"pricing.nav.home": "Início",
"pricing.nav.mySubscription": "Minha assinatura",
@@ -4217,6 +4452,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "termini importati",
"glossaries.dialog.changeFile": "Cambia file",
"glossaries.dialog.retry": "Riprova",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Indietro",
"pricing.nav.home": "Home",
"pricing.nav.mySubscription": "Il mio abbonamento",
@@ -4975,6 +5257,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "termen geïmporteerd",
"glossaries.dialog.changeFile": "Bestand wijzigen",
"glossaries.dialog.retry": "Opnieuw proberen",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Terug",
"pricing.nav.home": "Home",
"pricing.nav.mySubscription": "Mijn abonnement",
@@ -5733,6 +6062,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "терминов импортировано",
"glossaries.dialog.changeFile": "Изменить файл",
"glossaries.dialog.retry": "Повторить",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "Назад",
"pricing.nav.home": "Главная",
"pricing.nav.mySubscription": "Моя подписка",
@@ -6493,6 +6869,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "件インポート済み",
"glossaries.dialog.changeFile": "ファイルを変更",
"glossaries.dialog.retry": "再試行",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "戻る",
"pricing.nav.home": "ホーム",
"pricing.nav.mySubscription": "マイサブスクリプション",
@@ -7250,6 +7673,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "개 용어 가져옴",
"glossaries.dialog.changeFile": "파일 변경",
"glossaries.dialog.retry": "다시 시도",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "뒤로",
"pricing.nav.home": "홈",
"pricing.nav.mySubscription": "내 구독",
@@ -8007,6 +8477,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "个术语已导入",
"glossaries.dialog.changeFile": "更换文件",
"glossaries.dialog.retry": "重试",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "返回",
"pricing.nav.home": "首页",
"pricing.nav.mySubscription": "我的订阅",
@@ -8722,6 +9239,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "مصطلحات مستوردة",
"glossaries.dialog.changeFile": "تغيير الملف",
"glossaries.dialog.retry": "إعادة المحاولة",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
"pricing.nav.back": "رجوع",
"pricing.nav.home": "الرئيسية",
"pricing.nav.mySubscription": "اشتراكي",
@@ -9446,6 +10010,53 @@ const messages: Record<Locale, Record<string, string>> = {
"glossaries.dialog.termsImported": "اصطلاح وارد شد",
"glossaries.dialog.changeFile": "تغییر فایل",
"glossaries.dialog.retry": "تلاش مجدد",
"glossaries.edit.title": "Modifier le glossaire",
"glossaries.edit.description": "Modifiez le nom, la paire de langues et les termes du glossaire.",
"glossaries.edit.nameLabel": "Nom du glossaire",
"glossaries.edit.namePlaceholder": "Entrez le nom du glossaire...",
"glossaries.edit.sourceLang": "Langue source",
"glossaries.edit.targetLang": "Langue cible",
"glossaries.edit.termsLabel": "Termes ({count} valides)",
"glossaries.edit.exportCsv": "Exporter CSV",
"glossaries.edit.importCsv": "Importer CSV",
"glossaries.edit.cancel": "Annuler",
"glossaries.edit.saving": "Enregistrement...",
"glossaries.edit.saveChanges": "Enregistrer les modifications",
"glossaries.edit.importFailedTitle": "Échec de l'importation",
"glossaries.edit.importFailedMaxDesc": "Le CSV contient {count} termes, le maximum est de {max}. Veuillez réduire le nombre de termes.",
"glossaries.edit.importSuccessTitle": "Importation réussie",
"glossaries.edit.importSuccessDesc": "{count} termes importés avec succès.",
"glossaries.edit.importFailedEmptyDesc": "Aucun terme valide trouvé dans le fichier CSV.",
"glossaries.edit.importFailedReadDesc": "Impossible de lire le fichier CSV.",
"glossaries.delete.title": "Supprimer le glossaire",
"glossaries.delete.description": "Êtes-vous sûr de vouloir supprimer ce glossaire ?",
"glossaries.delete.warning": "Cette action est irréversible",
"glossaries.delete.warningDesc": "Toutes les paires de termes seront définitivement supprimées.",
"glossaries.delete.cancel": "Annuler",
"glossaries.delete.deleting": "Suppression...",
"glossaries.delete.deleteBtn": "Supprimer",
"glossaries.upgrade.title": "Glossaires",
"glossaries.upgrade.description": "Personnalisez vos traductions avec une terminologie personnalisée",
"glossaries.upgrade.feature1": "Créez plusieurs glossaires",
"glossaries.upgrade.feature2": "Définissez des paires de termes source→cible",
"glossaries.upgrade.feature3": "Importez/exportez via CSV",
"glossaries.upgrade.feature4": "Appliquez aux traductions LLM",
"glossaries.upgrade.proFeatureBefore": "Les glossaires sont une fonctionnalité ",
"glossaries.upgrade.proFeatureAfter": ". Passez à un forfait supérieur pour débloquer la terminologie personnalisée.",
"glossaries.upgrade.proLabel": "Pro",
"glossaries.upgrade.upgradeBtn": "Passer à Pro",
"apiKeys.webhook.title": "Intégration Webhook",
"apiKeys.webhook.descriptionBefore": "Passez un paramètre ",
"apiKeys.webhook.descriptionAfter": " pour recevoir une requête POST lorsque votre traduction est terminée.",
"apiKeys.webhook.codeParam": "webhook_url",
"translate.mode.label": "Mode de traduction",
"translate.mode.classic": "Classique",
"translate.mode.classicDesc": "Rapide",
"translate.mode.proLlm": "Pro LLM",
"translate.mode.proLlmDesc": "Contextuel",
"translate.mode.tooltip": "Passez à Pro pour la traduction LLM",
"translate.mode.upgradeLink": "Passer à Pro",
"translate.mode.upgradeDesc": "pour des traductions alimentées par LLM",
// ── Pricing page ──
"pricing.nav.back": "بازگشت",