Internationalization: 7 languages with live switching
Custom signal-based runtime (no i18n dependency): shared src/shared/i18n dictionaries, ui I18nService.t() reactive by construction so language switches live, and a backend i18n.ts for native menus + thrown errors. Every user-facing string keyed across templates, toasts, dialogs, file kinds, columns, macOS menu/context menus, and errors. Language picker in Options (auto-detects OS locale, falls back to English); switching relabels the webview and native chrome instantly. English/Spanish/French/ German fully drafted; Chinese/Japanese/Basque drafted, flagged for native review. Docs updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
// French translations. Missing keys fall back to English (see en.ts / index.ts).
|
||||
export const fr = {
|
||||
common: {
|
||||
cancel: "Annuler",
|
||||
save: "Enregistrer",
|
||||
close: "Fermer",
|
||||
delete: "Supprimer",
|
||||
rename: "Renommer",
|
||||
create: "Créer",
|
||||
apply: "Appliquer",
|
||||
choose: "Choisir…",
|
||||
connect: "Connecter",
|
||||
local: "Local",
|
||||
},
|
||||
app: {
|
||||
notConnectedTitle: "Non connecté à l'application",
|
||||
notConnectedBody: "Cette page s'exécute dans un navigateur classique. Lancez l'application de bureau pour l'utiliser.",
|
||||
managerOpen: "Le gestionnaire de connexions est ouvert.",
|
||||
showConnections: "Afficher les connexions",
|
||||
},
|
||||
tabBar: {
|
||||
connections: "Connexions",
|
||||
manageConnections: "Gérer les connexions",
|
||||
newTab: "Nouvel onglet ({mod}T)",
|
||||
closeTab: "Fermer l'onglet ({mod}W)",
|
||||
options: "Options",
|
||||
},
|
||||
options: {
|
||||
title: "Options",
|
||||
language: "Langue",
|
||||
system: "Système",
|
||||
theme: { label: "Thème", system: "Système", light: "Clair", dark: "Sombre" },
|
||||
tone: { label: "Ton", dark: "Sombre", darker: "Plus sombre" },
|
||||
accent: { label: "Accent" },
|
||||
accentNames: {
|
||||
graphite: "Graphite",
|
||||
blue: "Bleu",
|
||||
indigo: "Indigo",
|
||||
purple: "Violet",
|
||||
rose: "Rose",
|
||||
orange: "Orange",
|
||||
green: "Vert",
|
||||
teal: "Sarcelle",
|
||||
},
|
||||
fileIcons: { label: "Icônes", plain: "Simple", multi: "Couleur" },
|
||||
interface: { label: "Interface", compact: "Compacte", default: "Normale", large: "Grande" },
|
||||
speedUnit: { label: "Unité de vitesse" },
|
||||
transfers: { label: "Transferts", single: "Un", multi: "Plusieurs" },
|
||||
atOnce: "Simultanés",
|
||||
editor: { label: "Éditeur", builtin: "Intégré", custom: "Personnalisé" },
|
||||
systemDefault: "Valeur par défaut du système",
|
||||
resetDefault: "Réinitialiser par défaut",
|
||||
finishedTransfers: { label: "Transferts terminés", autoClear: "Effacer auto.", keep: "Garder" },
|
||||
},
|
||||
kinds: {
|
||||
folder: "Dossier",
|
||||
symlink: "Lien symbolique",
|
||||
file: "Fichier",
|
||||
image: "Image",
|
||||
audio: "Audio",
|
||||
video: "Vidéo",
|
||||
archive: "Archive",
|
||||
code: "Code",
|
||||
document: "Document",
|
||||
},
|
||||
columns: {
|
||||
name: "Nom",
|
||||
size: "Taille",
|
||||
mtime: "Modifié",
|
||||
kind: "Type",
|
||||
rights: "Droits",
|
||||
owner: "Propriétaire",
|
||||
group: "Groupe",
|
||||
},
|
||||
panel: {
|
||||
choosePanel: "Choisir ce qu'affiche ce panneau",
|
||||
copy: "Copier",
|
||||
copyToRight: "Copier vers le panneau droit (F5)",
|
||||
copyToLeft: "Copier vers le panneau gauche (F5)",
|
||||
edit: "Éditer",
|
||||
editFile: "Éditer le fichier (F4)",
|
||||
rename: "Renommer (F2)",
|
||||
newFolder: "Nouveau dossier (F7)",
|
||||
newFile: "Nouveau fichier",
|
||||
permissions: "Autorisations",
|
||||
delete: "Supprimer",
|
||||
deleteHint: "Supprimer (F8 / Suppr)",
|
||||
parentDir: "Dossier parent (Retour arrière)",
|
||||
refresh: "Actualiser",
|
||||
clearFilter: "Effacer le filtre (Échap)",
|
||||
sshConfig: "~/.ssh/config",
|
||||
connectingTo: "Connexion à {name}…",
|
||||
emptyDir: "Dossier vide",
|
||||
noMatches: "Aucun résultat",
|
||||
matches: { one: "{count} résultat · Échap", other: "{count} résultats · Échap" },
|
||||
},
|
||||
connMgr: {
|
||||
title: "Connexions",
|
||||
importWinscp: "Importer depuis WinSCP…",
|
||||
importWinscpHint: "Importer des sessions depuis un export WinSCP.ini",
|
||||
newConnection: "Connexion",
|
||||
newConnectionHint: "Nouvelle connexion",
|
||||
newStack: "Groupe",
|
||||
newStackHint: "Nouveau groupe",
|
||||
expand: "Développer",
|
||||
collapse: "Réduire",
|
||||
renameStack: "Renommer le groupe",
|
||||
deleteStack: "Supprimer le groupe",
|
||||
openStack: "Ouvrir le groupe dans des onglets",
|
||||
empty: "vide",
|
||||
connectionsHeader: "Connexions",
|
||||
noneTitle: "Aucune connexion enregistrée.",
|
||||
noneBody: "Créez-en une ou importez vos sessions WinSCP.",
|
||||
name: "Nom",
|
||||
namePlaceholder: "mon serveur",
|
||||
host: "Hôte",
|
||||
port: "Port",
|
||||
stack: "Groupe",
|
||||
stackNone: "(aucun)",
|
||||
username: "Utilisateur",
|
||||
remotePath: "Chemin distant (facultatif)",
|
||||
remotePathPlaceholder: "dossier personnel",
|
||||
auth: "Authentification",
|
||||
authPassword: "Mot de passe",
|
||||
authKey: "Clé privée",
|
||||
password: "Mot de passe",
|
||||
privateKeyFile: "Fichier de clé privée",
|
||||
passphrase: "Phrase secrète (facultative)",
|
||||
localDir: "Dossier local (facultatif)",
|
||||
localDirPlaceholder: "~/projets/mon-serveur",
|
||||
localDirHint: "L'autre panneau s'ouvre ici lorsqu'il est sur Local et n'a pas été parcouru.",
|
||||
more: "Plus…",
|
||||
less: "Moins…",
|
||||
selectPrompt: "Sélectionnez une connexion ou créez-en une nouvelle.",
|
||||
newStackTitle: "Nouveau groupe",
|
||||
newStackPrompt: "nom du groupe",
|
||||
renameStackTitle: "Renommer le groupe",
|
||||
deleteStackTitle: "Supprimer le groupe",
|
||||
deleteStackBody: 'Supprimer le groupe « {name} » ? Ses connexions sont conservées, sans groupe.',
|
||||
deleteConnectionTitle: "Supprimer la connexion",
|
||||
deleteConnectionBody: 'Supprimer « {name} » ?',
|
||||
},
|
||||
editor: {
|
||||
noFileTitle: "Aucun fichier à éditer",
|
||||
noFileBody: "Cette fenêtre a été ouverte sans contexte d'éditeur. Ouvrez des fichiers depuis l'application.",
|
||||
wrap: "Retour",
|
||||
wrapHint: "Retour à la ligne — masque les numéros de ligne ({alt}Z)",
|
||||
findHint: "Rechercher ({mod}F)",
|
||||
findPlaceholder: "Rechercher dans le fichier",
|
||||
prevMatch: "Résultat précédent (⇧↵)",
|
||||
nextMatch: "Résultat suivant (↵)",
|
||||
closeHint: "Fermer (Échap)",
|
||||
disconnected: "Déconnecté de {name} — l'enregistrement échouera, mais votre texte est conservé dans cette fenêtre.",
|
||||
cantOpen: "Impossible d'ouvrir {name}",
|
||||
closeWindow: "Fermer la fenêtre",
|
||||
shortcuts: "{mod}S enregistrer · {mod}F rechercher · {mod}W fermer",
|
||||
lines: { one: "{count} ligne", other: "{count} lignes" },
|
||||
close: "Fermer",
|
||||
save: "Enregistrer",
|
||||
saveChangesTitle: 'Enregistrer les modifications de « {name} » ?',
|
||||
saveChangesBody: "Vos modifications seront perdues si vous ne les enregistrez pas.",
|
||||
dontSave: "Ne pas enregistrer",
|
||||
countLabel: "{current} sur {total}",
|
||||
noMatches: "Aucun résultat",
|
||||
},
|
||||
transfer: {
|
||||
summary: "{active} en cours · {finished} terminés",
|
||||
clearFinished: "Effacer les terminés",
|
||||
cancel: "Annuler",
|
||||
dismiss: "Ignorer",
|
||||
showDetails: "Afficher les détails des transferts",
|
||||
copying: "Copie de {name} · {percent}%{speed}",
|
||||
queued: "{count} en file",
|
||||
failed: { one: "{count} transfert échoué", other: "{count} transferts échoués" },
|
||||
finished: "Transferts terminés",
|
||||
ready: "Prêt",
|
||||
items: "{count} éléments",
|
||||
selected: "{count} sélectionnés",
|
||||
queuedState: "En file",
|
||||
scanning: "Analyse…",
|
||||
failedState: "Échec",
|
||||
cancelled: "Annulé",
|
||||
completedFiles: { one: "{count} fichier · {size}", other: "{count} fichiers · {size}" },
|
||||
left: "{eta} restant",
|
||||
},
|
||||
dialogs: {
|
||||
chmodTitle: "Autorisations",
|
||||
chmodItems: "{count} éléments",
|
||||
read: "Lecture",
|
||||
write: "Écriture",
|
||||
execute: "Exécution",
|
||||
roleOwner: "Propriétaire",
|
||||
roleGroup: "Groupe",
|
||||
roleOthers: "Autres",
|
||||
octal: "Octal",
|
||||
mergeFolder: "Fusionner le dossier",
|
||||
replace: "Remplacer",
|
||||
merge: "Fusionner",
|
||||
mergeAll: "Tout fusionner",
|
||||
replaceAll: "Tout remplacer",
|
||||
skip: "Ignorer",
|
||||
skipAll: "Tout ignorer",
|
||||
ofTotal: "{index} sur {total}",
|
||||
overwriteDirBody: "La destination contient déjà un dossier de ce nom. La fusion peut remplacer des fichiers.",
|
||||
overwriteFileBody: "La destination contient déjà un fichier de ce nom.",
|
||||
source: "Source",
|
||||
destination: "Destination",
|
||||
newer: "plus récent",
|
||||
},
|
||||
toasts: {
|
||||
movedToTrash: '« {name} » mis à la corbeille',
|
||||
editingExternal: "Édition de {name} — les enregistrements sont envoyés automatiquement",
|
||||
nothingToCopy: "Rien à copier (les liens symboliques sont ignorés)",
|
||||
nothingToCopyAllSkipped: "Rien à copier — tous les éléments en conflit ont été ignorés",
|
||||
sameFolder: "Les deux panneaux affichent le même dossier",
|
||||
sameFile: "« {name} » ignoré — c'est le même fichier",
|
||||
typeMismatch: "« {name} » ignoré — un autre type d'élément est déjà là",
|
||||
transferFailed: 'Le transfert « {name} » a échoué : {error}',
|
||||
unknownError: "erreur inconnue",
|
||||
saved: "{name} enregistré",
|
||||
disconnectedReason: "{title} : déconnecté ({reason})",
|
||||
imported: { one: "{count} connexion importée", other: "{count} connexions importées" },
|
||||
importedIntoStacks: { one: " dans {count} nouveau groupe", other: " dans {count} nouveaux groupes" },
|
||||
importedSkipped: " ({skipped} ignorées)",
|
||||
leftoverTitle: "Fichiers édités restants",
|
||||
leftoverMore: ", +{count} de plus",
|
||||
leftoverBody: {
|
||||
one: "Une session précédente a laissé {count} fichier édité temporaire ({names}). Les supprimer ?",
|
||||
other: "Une session précédente a laissé {count} fichiers édités temporaires ({names}). Les supprimer ?",
|
||||
},
|
||||
leftoverClear: "Supprimer",
|
||||
},
|
||||
fileActions: {
|
||||
deleteTitle: "Supprimer",
|
||||
deleteBody: "Supprimer {what} ? Les dossiers sont supprimés récursivement. Action irréversible.",
|
||||
deleteConfirm: "Supprimer",
|
||||
renameTitle: 'Renommer « {name} »',
|
||||
renameConfirm: "Renommer",
|
||||
newFolderTitle: "Nouveau dossier",
|
||||
newFolderPlaceholder: "nom du dossier",
|
||||
newFileTitle: "Nouveau fichier",
|
||||
newFilePlaceholder: "nom du fichier",
|
||||
createConfirm: "Créer",
|
||||
itemsCount: "{count} éléments",
|
||||
},
|
||||
menu: {
|
||||
about: "À propos de {app}",
|
||||
quit: "Quitter",
|
||||
file: "Fichier",
|
||||
newTab: "Nouvel onglet",
|
||||
closeTab: "Fermer l'onglet",
|
||||
newFolder: "Nouveau dossier",
|
||||
newFile: "Nouveau fichier",
|
||||
editFile: "Éditer le fichier",
|
||||
connect: "Connecter",
|
||||
connectionManager: "Gestionnaire de connexions…",
|
||||
edit: "Édition",
|
||||
view: "Affichage",
|
||||
refresh: "Actualiser",
|
||||
window: "Fenêtre",
|
||||
},
|
||||
ctx: {
|
||||
size: "Taille",
|
||||
modified: "Modifié",
|
||||
kind: "Type",
|
||||
rights: "Droits",
|
||||
owner: "Propriétaire",
|
||||
group: "Groupe",
|
||||
revealFinder: "Afficher dans le Finder",
|
||||
revealExplorer: "Afficher dans l'Explorateur",
|
||||
revealFileManager: "Afficher dans le gestionnaire de fichiers",
|
||||
moveToTrash: "Mettre à la corbeille",
|
||||
moveToRecycleBin: "Mettre à la corbeille",
|
||||
newFolder: "Nouveau dossier",
|
||||
newFile: "Nouveau fichier",
|
||||
refresh: "Actualiser",
|
||||
open: "Ouvrir",
|
||||
openDefault: "Ouvrir avec l'application par défaut",
|
||||
edit: "Éditer",
|
||||
copyToOther: "Copier vers l'autre panneau",
|
||||
rename: "Renommer",
|
||||
permissions: "Autorisations",
|
||||
copyPath: "Copier le chemin",
|
||||
delete: "Supprimer",
|
||||
columns: "Colonnes",
|
||||
trashTooltip: "La restauration du Finder n'est pas disponible pour les éléments mis à la corbeille d'ici",
|
||||
},
|
||||
errors: {
|
||||
sshAgentUnavailable: "ssh-agent indisponible (SSH_AUTH_SOCK non défini)",
|
||||
identityFileNotFound: "fichier d'identité introuvable : {path}",
|
||||
sessionNotConnected: "La session « {id} » n'est pas connectée",
|
||||
localCannotDisconnect: "La session locale ne peut pas être déconnectée",
|
||||
notADirectory: "« {path} » existe et n'est pas un dossier",
|
||||
sameFileTransfer: '« {name} » : la source et la destination sont le même fichier',
|
||||
sameFileNoName: "La source et la destination sont le même fichier",
|
||||
folderOntoItself: "Impossible de copier un dossier sur lui-même",
|
||||
folderIntoItself: "Impossible de copier un dossier dans lui-même",
|
||||
},
|
||||
} as const;
|
||||
Reference in New Issue
Block a user