Table des matières

Chapitre 2 : Internationalisation (i18n)

SmartCommon utilise i18next pour les traductions.

Structure des fichiers

mobile/
├── public/
│   └── locales/
│       ├── fr/
│       │   └── translation.json
│       └── en/
│           └── translation.json
└── src/
    └── i18n/
        └── index.js

Configuration i18next

snippet.javascript
// src/i18n/index.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
 
i18n
    .use(Backend)
    .use(LanguageDetector)
    .use(initReactI18next)
    .init({
        fallbackLng: 'fr',
        supportedLngs: ['fr', 'en'],
        debug: import.meta.env.DEV,
 
        backend: {
            loadPath: '/locales/{{lng}}/translation.json'
        },
 
        interpolation: {
            escapeValue: false
        }
    });
 
export default i18n;

Fichiers de traduction

Français

snippet.json
{
    "common": {
        "loading": "Chargement...",
        "save": "Enregistrer",
        "cancel": "Annuler",
        "delete": "Supprimer",
        "edit": "Modifier",
        "close": "Fermer",
        "confirm": "Confirmer",
        "yes": "Oui",
        "no": "Non"
    },
    "auth": {
        "login": "Connexion",
        "logout": "Déconnexion",
        "email": "Email",
        "password": "Mot de passe",
        "loginButton": "Se connecter",
        "loginError": "Identifiants incorrects"
    },
    "tasks": {
        "title": "Mes tâches",
        "new": "Nouvelle tâche",
        "edit": "Modifier la tâche",
        "label": "Titre",
        "description": "Description",
        "priority": "Priorité",
        "status": {
            "todo": "À faire",
            "done": "Terminée"
        },
        "empty": "Aucune tâche",
        "deleteConfirm": "Supprimer cette tâche ?"
    },
    "errors": {
        "network": "Erreur de connexion",
        "notFound": "Page non trouvée",
        "server": "Erreur serveur"
    }
}

Anglais

snippet.json
{
    "common": {
        "loading": "Loading...",
        "save": "Save",
        "cancel": "Cancel",
        "delete": "Delete",
        "edit": "Edit",
        "close": "Close",
        "confirm": "Confirm",
        "yes": "Yes",
        "no": "No"
    },
    "auth": {
        "login": "Login",
        "logout": "Logout",
        "email": "Email",
        "password": "Password",
        "loginButton": "Sign in",
        "loginError": "Invalid credentials"
    },
    "tasks": {
        "title": "My tasks",
        "new": "New task",
        "edit": "Edit task",
        "label": "Title",
        "description": "Description",
        "priority": "Priority",
        "status": {
            "todo": "To do",
            "done": "Done"
        },
        "empty": "No tasks",
        "deleteConfirm": "Delete this task?"
    },
    "errors": {
        "network": "Network error",
        "notFound": "Page not found",
        "server": "Server error"
    }
}

Utilisation dans les composants

Avec useTranslation

snippet.javascript
import { useTranslation } from 'react-i18next';
import { Page, Block, Button } from '@cap-rel/smartcommon';
 
export const TasksPage = () => {
    const { t } = useTranslation();
 
    return (
        <Page title={t('tasks.title')}>
            <Block>
                <Button>{t('tasks.new')}</Button>
 
                {tasks.length === 0 && (
                    <p>{t('tasks.empty')}</p>
                )}
            </Block>
        </Page>
    );
};

Avec paramètres

snippet.json
{
    "tasks": {
        "count": "{{count}} tâche",
        "count_plural": "{{count}} tâches",
        "greeting": "Bonjour {{name}}"
    }
}
snippet.javascript
const { t } = useTranslation();
 
// Avec paramètre
t('tasks.greeting', { name: 'Jean' })  // "Bonjour Jean"
 
// Pluriel
t('tasks.count', { count: 1 })   // "1 tâche"
t('tasks.count', { count: 5 })   // "5 tâches"

Changer de langue

snippet.javascript
import { useTranslation } from 'react-i18next';
import { useGlobalStates } from '@cap-rel/smartcommon';
import { Select } from '@cap-rel/smartcommon';
 
export const LanguageSelector = () => {
    const { i18n } = useTranslation();
    const [settings, setSettings] = useGlobalStates('settings');
 
    const changeLanguage = (lng) => {
        i18n.changeLanguage(lng);
        setSettings({ ...settings, lng });
    };
 
    return (
        <Select
            value={i18n.language}
            onChange={(e) => changeLanguage(e.target.value)}
            options={[
                { value: 'fr', label: 'Français' },
                { value: 'en', label: 'English' }
            ]}
        />
    );
};

Formatage des dates et nombres

Utiliser useIntl de SmartCommon :

snippet.javascript
import { useIntl } from '@cap-rel/smartcommon';
 
function DateDisplay({ date }) {
    const intl = useIntl();
 
    // Utilise la locale courante
    const formatted = intl.DateTimeFormat(date, undefined, {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    });
 
    return <span>{formatted}</span>;
}

Points clés à retenir

  1. Fichiers JSON dans public/locales/{lng}/
  2. useTranslation pour accéder aux traductions
  3. t('key') pour traduire une chaîne
  4. Paramètres avec dans les traductions
  5. i18n.changeLanguage() pour changer de langue

← Chapitre précédent | Retour au module | Chapitre suivant : Autres fonctionnalités →