| name | i18n |
| description | Gère les traductions pour Motivia (FR/EN). Utilise ce skill quand l'utilisateur demande d'ajouter des traductions, traduire du texte, créer des clés i18n, ou modifier les fichiers de locales. Suit le pattern next-international. |
| allowed-tools | Read, Write, Edit, Glob, Grep |
Internationalisation (i18n) Motivia
Structure des fichiers
locales/
├── fr.ts # Traductions françaises (référence)
├── en.ts # Traductions anglaises
├── client.ts # Config client (useI18n, useScopedI18n)
└── server.ts # Config serveur (getI18n, getScopedI18n)
Format des fichiers de locale
// locales/fr.ts
export default {
common: {
add: "Ajouter",
delete: "Supprimer",
cancel: "Annuler",
save: "Sauvegarder",
},
pageName: {
section: {
title: "Titre de la section",
description: "Description détaillée",
},
},
} as const;
Convention de nommage des clés
Structure hiérarchique
namespace.section.element
| Niveau | Usage | Exemple |
|---|---|---|
| 1 | Page ou feature | landingPage, dashboard, settings |
| 2 | Section de page | hero, header, form |
| 3 | Élément spécifique | title, description, button |
Noms de clés standards
{
title: "...", // Titre principal
description: "...", // Description/sous-titre
heading: "...", // Heading alternatif
button: "...", // Texte de bouton
placeholder: "...", // Placeholder input
label: "...", // Label de champ
error: "...", // Message d'erreur
success: "...", // Message de succès
empty: "...", // État vide
loading: "...", // État de chargement
}
Utilisation côté client
"use client";
import { useI18n, useScopedI18n } from "@/locales/client";
export const MyComponent = () => {
// Hook global
const t = useI18n();
// Hook scopé (recommandé pour les pages)
const scopedT = useScopedI18n("dashboard");
return (
<div>
<h1>{scopedT("title")}</h1>
<p>{t("common.description")}</p>
</div>
);
};
Utilisation côté serveur
// Dans un Server Component ou page
import { getI18n, getScopedI18n } from "@/locales/server";
export default async function Page() {
const t = await getI18n();
const scopedT = await getScopedI18n("settings");
return (
<div>
<h1>{scopedT("title")}</h1>
<p>{t("common.save")}</p>
</div>
);
}
Variables et pluralisation
// Dans le fichier de locale
{
greeting: "Bonjour {name}",
items: "{count, plural, =0 {Aucun élément} =1 {1 élément} other {# éléments}}",
}
// Utilisation
t("greeting", { name: "Jean" }) // "Bonjour Jean"
t("items", { count: 5 }) // "5 éléments"
Workflow d'ajout de traductions
1. Ajouter au fichier français (référence)
// locales/fr.ts
export default {
// ... existing
newPage: {
title: "Nouveau titre",
description: "Nouvelle description",
},
} as const;
2. Ajouter au fichier anglais
// locales/en.ts
export default {
// ... existing
newPage: {
title: "New title",
description: "New description",
},
} as const;
3. Vérifier la cohérence
Les deux fichiers doivent avoir exactement la même structure de clés.
Codes d'erreur serveur
Les codes d'erreur des server actions sont traduits:
// locales/fr.ts
{
errors: {
FAILED_TO_FETCH_USER: "Impossible de récupérer l'utilisateur",
FAILED_TO_CREATE_LETTER: "Impossible de créer la lettre",
USER_NOT_FOUND: "Utilisateur non trouvé",
},
}
Metadata SEO
// locales/fr.ts
{
pageName: {
metadata: {
title: "Titre de la page | Motivia",
description: "Description pour le SEO",
},
},
}
// Dans la page
import { getScopedI18n } from "@/locales/server";
import type { Metadata } from "next";
export async function generateMetadata(): Promise<Metadata> {
const t = await getScopedI18n("pageName.metadata");
return {
title: t("title"),
description: t("description"),
};
}
Checklist nouvelle traduction
- Ajouter la clé dans
locales/fr.ts - Ajouter la clé dans
locales/en.ts(même structure) - Utiliser
useScopedI18npour les composants de page - Utiliser
useI18npour les clés communes - Vérifier que les variables
{name}sont présentes dans les deux langues - Tester dans les deux langues (FR et EN)