Search K
Guide de traduction
SnapOtter est livré avec 21 langues prêtes à l'emploi. Le système i18n s'appuie sur un moteur d'exécution personnalisé et léger, avec une complétude des locales garantie par TypeScript et un découpage dynamique du code.
Langues prises en charge
| Code | Langue | Native Name | Direction |
|---|---|---|---|
en | Anglais | English | LTR |
zh-CN | Chinois (simplifié) | 简体中文 | LTR |
zh-TW | Chinois (traditionnel) | 繁體中文 | LTR |
ja | Japonais | 日本語 | LTR |
ko | Coréen | 한국어 | LTR |
es | Espagnol | Español | LTR |
fr | Français | Français | LTR |
it | Italien | Italiano | LTR |
pt-BR | Portugais (Brésil) | Português (Brasil) | LTR |
de | Allemand | Deutsch | LTR |
nl | Néerlandais | Nederlands | LTR |
sv | Suédois | Svenska | LTR |
ru | Russe | Русский | LTR |
pl | Polonais | Polski | LTR |
uk | Ukrainien | Українська | LTR |
ar | Arabe | العربية | RTL |
tr | Turc | Türkçe | LTR |
hi | Hindi | हिन्दी | LTR |
vi | Vietnamien | Tiếng Việt | LTR |
id | Indonésien | Bahasa Indonesia | LTR |
th | Thaï | ไทย | LTR |
Fonctionnement de la détection de langue
SnapOtter utilise un ordre de résolution à trois niveaux :
- Préférence de l'utilisateur - stockée dans
localStorage("snapotter-locale")et synchronisée avec les paramètres de l'utilisateur une fois authentifié - Détection automatique du navigateur - parcourt le tableau
navigator.languagesavec une correspondance de préfixe BCP 47 - Valeur par défaut de l'instance - la variable d'environnement
DEFAULT_LOCALEde l'administrateur (récupérée depuisGET /api/v1/config/locale) - Repli sur l'anglais - toujours disponible
Les utilisateurs peuvent changer de langue depuis :
- Le sélecteur Globe du pied de page (bureau, toujours visible)
- Le sélecteur de langue de la page de connexion (avant l'authentification)
- La section Paramètres > Général (préférence par utilisateur)
- La liste déroulante de langue de la barre latérale mobile
- La section Paramètres > Système définit la valeur par défaut à l'échelle de l'instance (administrateur uniquement)
Fonctionnement des traductions
Toutes les chaînes de l'interface se trouvent dans packages/shared/src/i18n/. Le fichier de référence est en.ts, qui exporte un objet typé contenant chaque chaîne utilisée par l'application (~1500 clés). Les autres langues sont des fichiers distincts (par ex. de.ts, fr.ts) qui exportent la même structure.
Le type TranslationKeys utilise DeepStringRecord pour accepter n'importe quelle valeur de chaîne tout en imposant la structure des clés. TypeScript détecte les clés manquantes dans n'importe quel fichier de traduction au moment de la compilation.
Seule la locale active est chargée à l'exécution via un import() dynamique, ce qui maintient le bundle principal petit.
Utiliser les traductions dans les composants
tsx
import { useTranslation } from "@/contexts/i18n-context";
import { format, plural } from "@/lib/format";
function MyComponent() {
const { t, locale, setLocale } = useTranslation();
return (
<div>
<h1>{t.common.settings}</h1>
<p>{format(t.settings.people.deleteConfirm, { username: "admin" })}</p>
<p>{plural(count, t.automate.fileCount, t.automate.fileCountPlural)}</p>
</div>
);
}Contribuer à une traduction
Nous accueillons directement les PR de traduction. Vous pouvez améliorer une locale existante ou en ajouter une nouvelle.
Pour signaler une erreur de traduction sans soumettre de code, ouvrez une issue GitHub en indiquant la langue, la chaîne incorrecte et la correction suggérée.
TIP
Les PR de traduction ne nécessitent pas d'approbation préalable. Forkez le dépôt, apportez vos modifications et ouvrez une PR. Consultez le guide de contribution pour le processus complet de PR et l'exigence de CLA.
Comment créer ou mettre à jour une traduction
1. Forker et cloner
bash
git clone https://github.com/<your-username>/snapotter.git
cd snapotter
pnpm install2. Copier le fichier de référence (nouvelle langue uniquement)
Ignorez cette étape si vous améliorez une traduction existante.
bash
cp packages/shared/src/i18n/en.ts packages/shared/src/i18n/XX.ts3. Traduire les chaînes
Ouvrez votre nouveau fichier et traduisez chaque valeur de chaîne. Conservez exactement la même structure d'objet et les mêmes clés.
ts
import type { TranslationKeys } from "./en.js";
export const xx: TranslationKeys = {
common: {
upload: "Your translation here",
// ... translate all entries
},
// ... translate all sections
} as const;Règles :
- Ne traduisez pas les clés d'objet, uniquement les valeurs de chaîne
- Conservez
as constà la fin - Importez
TranslationKeysdepuis./en.jset typez votre export - Conservez les espaces réservés
{variable}exactement tels quels - Les tableaux (
rotatingPhrases,progressMessages) doivent comporter le même nombre d'entrées - Ne traduisez pas : SnapOtter, JPEG, PNG, WebP, EXIF, API et autres termes techniques
4. Enregistrer la locale (nouvelle langue uniquement)
Ajoutez votre locale à SUPPORTED_LOCALES dans packages/shared/src/i18n/index.ts :
ts
{ code: "xx", name: "Language Name", nativeName: "Native Name", dir: "ltr" },5. Vérifier
bash
pnpm typecheck # catches missing or mistyped keys
pnpm lint # formatting check
pnpm dev # manually verify strings appear correctly6. Soumettre
Ouvrez une PR sur main avec un titre du type feat(i18n): add Swedish translation ou fix(i18n): correct German typos. Le bot CLA vous demandera de signer lors de votre première contribution.
Ajouter de nouvelles clés de traduction
Lorsque vous ajoutez une nouvelle fonctionnalité qui nécessite de nouvelles chaînes d'interface :
- Ajoutez d'abord les nouvelles clés à
en.ts(le fichier de référence) - Exécutez
pnpm typecheck- chaque fichier de locale échouera s'il manque la nouvelle clé - Ajoutez la nouvelle clé à tous les fichiers de locale (utilisez l'anglais comme repli temporaire)
Configuration
Définissez la langue par défaut de l'instance via une variable d'environnement :
yaml
DEFAULT_LOCALE: "de" # German as the default for all new usersRéférence des fichiers
| Fichier | Rôle |
|---|---|
packages/shared/src/i18n/en.ts | Chaînes anglaises (locale de référence, ~1500 clés) |
packages/shared/src/i18n/index.ts | SUPPORTED_LOCALES, loadTranslations(), exports de types |
packages/shared/src/i18n/<locale>.ts | Fichiers de traduction par langue |
apps/web/src/contexts/i18n-context.tsx | I18nProvider, hook useTranslation() |
apps/web/src/lib/format.ts | Fonctions utilitaires format(), plural(), formatFileSize() |
apps/api/src/routes/config.ts | Point de terminaison public GET /api/v1/config/locale |
Traduire le site web, la documentation et la référence de l'API
La prise en charge de 21 langues décrite ci-dessus couvre l'application. Le site web public (snapotter.com), ce site de documentation et la référence de l'API REST sont également traduits dans les 21 langues, par un pipeline distinct verrouillé par hachage qui réutilise les mêmes noms et descriptions d'outils issus de packages/shared/src/i18n, afin que la terminologie reste cohérente partout.
Traduction automatique par défaut
Chaque page non anglaise du site web et de la documentation est traduite automatiquement lors du premier passage (par une session Claude Code, et non un service tiers) et porte une petite bannière fermable qui l'indique, avec un lien renvoyant ici. C'est délibéré : cela permet de livrer les 21 langues rapidement et honnêtement, puis d'inviter la communauté à affiner les pages qui comptent le plus. La traduction automatique fait passer le sens ; la relecture humaine la rend naturelle à lire.
Comment le pipeline décide de ce qu'il faut traduire
Chaque unité traduisible de la source anglaise est hachée, et le hachage est stocké à côté de sa traduction. À chaque exécution, le pipeline :
- traduit toute unité qui n'a pas encore de traduction,
- ignore toute unité dont le hachage stocké correspond toujours à la source anglaise,
- retraduit une unité machine lorsque sa source anglaise change,
- et signale une unité affinée par un humain comme
stale(à relire) lorsque sa source anglaise change, au lieu d'écraser votre travail.
Affiner une traduction web par PR
Vous améliorez une traduction du site web, de la documentation ou de la référence de l'API de la même manière que vous améliorez une locale de l'application : en modifiant le fichier généré et en ouvrant une PR.
- Trouvez la traduction générée pour votre langue :
- chaînes d'interface du site web :
apps/landing/src/i18n/<locale>.json - une page de documentation :
apps/docs/<locale>/**.md - la référence de l'API :
apps/api/src/openapi.<locale>.yaml
- chaînes d'interface du site web :
- Modifiez le texte. Conservez le code, les liens,
{placeholders}et tous les marqueurs⸤I18N…⸥exactement tels quels ; le validateur du pipeline rejette une traduction qui les supprime ou les réordonne. - Ouvrez une PR. La modification d'une unité fait passer sa provenance de
machineàhuman, de sorte que le pipeline ne l'écrasera jamais lors d'une exécution ultérieure. Si la source anglaise change par la suite, votre unité est signaléestalepour relecture plutôt que remplacée silencieusement.
Pour signaler une erreur de traduction sans soumettre de code, ouvrez une issue GitHub en indiquant l'URL de la page, la langue, le texte incorrect et votre correction suggérée.
TIP
Les mainteneurs exécutent le pipeline de traduction ; vous n'avez pas besoin de clé API pour contribuer. Modifiez simplement le fichier généré et ouvrez une PR. Consultez scripts/i18n/README.md pour savoir comment le pipeline s'exécute.
