Chaînes partagées
Comment internationaliser des chaînes utilisées dans plusieurs composants et fichiers
Les chaînes partagées sont des valeurs textuelles utilisées à plusieurs endroits dans votre application — comme des libellés de navigation, des messages de formulaire ou des données de configuration. Plutôt que de dupliquer la logique de traduction partout, utilisez msg pour marquer les chaînes à traduire et useMessages pour les décoder.
Le problème du contenu partagé
Prenez cette configuration de navigation utilisée dans l’ensemble de votre application :
// navData.ts
export const navData = [
{
label: 'Accueil',
description: 'La page d'accueil',
href: '/'
},
{
label: 'À propos',
description: 'Informations sur l'entreprise',
href: '/about'
}
];Pour l’internationaliser, vous auriez généralement besoin de :
- Le transformer en une fonction qui accepte une fonction de traduction
- Mettre à jour chaque utilisation pour appeler la fonction avec
t - Gérer la complexité à l’échelle de l’ensemble du code
Cela génère une charge de maintenance et rend votre code moins lisible. La fonction msg résout ce problème en permettant de marquer les chaînes à traduire directement dans le code, puis de les décoder au besoin.
Démarrage rapide
Utilisez msg pour marquer les chaînes et useMessages pour les décoder :
// navData.ts - Marquer les chaînes pour la traduction
import { msg } from 'gt-react';
export const navData = [
{
label: msg('Accueil'),
description: msg('La page d'accueil'),
href: '/'
},
{
label: msg('À propos'),
description: msg('Informations sur l'entreprise'),
href: '/about'
}
];// Utilisation du composant - Décoder les chaînes marquées
import { useMessages } from 'gt-react';
import { navData } from './navData';
function Navigation() {
const m = useMessages();
return (
<nav>
{navData.map((item) => (
<a key={item.href} href={item.href} title={m(item.description)}>
{m(item.label)}
</a>
))}
</nav>
);
}Fonctionnement des chaînes partagées
Le système de chaînes partagées fonctionne en deux phases :
- Phase de marquage :
msgencode les chaînes avec des métadonnées de traduction - Phase de décodage :
useMessagesdécode et traduit les chaînes
// msg() encode la chaîne avec des métadonnées
const encoded = msg('Hello, world!');
console.log(encoded); // "Hello, world!:eyIkX2hhc2giOiJkMjA3MDliZGExNjNlZmM2In0="
// useMessages() décode et traduit
const m = useMessages();
const translated = m(encoded); // "Hello, world!" dans la langue de l'utilisateurLes chaînes encodées provenant de msg ne peuvent pas être utilisées directement : elles doivent être décodées avec useMessages.
Composants
Utilisez le hook useMessages :
import { useMessages } from 'gt-react';
const encodedString = msg('Hello, world!');
function MyComponent() {
const m = useMessages();
return <div>{m(encodedString)}</div>;
}Récupérer les chaînes d’origine avec decodeMsg
Parfois, vous avez besoin d’accéder à la chaîne d’origine sans traduction, par exemple pour la consignation des journaux, le débogage ou des comparaisons. Utilisez decodeMsg pour extraire le texte d’origine :
import { decodeMsg } from 'gt-react';
const encoded = msg('Hello, world!');
const original = decodeMsg(encoded); // "Hello, world!" (original)
const translated = m(encoded); // "Hello, world!" (dans la langue de l'utilisateur)
// Utile pour les logs ou le débogage
console.log('Chaîne d'origine :', decodeMsg(encoded));
console.log('Chaîne traduite :', m(encoded));Cas d’usage de decodeMsg
- Développement et débogage : journaliser les chaînes d’origine pour le dépannage
- Gestion du secours : utiliser le texte d’origine lorsque les traductions échouent
- Comparaison de chaînes : comparer à des valeurs d’origine connues
- Analytique : suivre l’utilisation des chaînes d’origine
// Exemple : Gestion du secours
function getDisplayText(encodedStr) {
const m = useMessages();
try {
return m(encodedStr);
} catch (error) {
console.warn('Échec de la traduction, utilisation de l\'original :', decodeMsg(encodedStr));
return decodeMsg(encodedStr);
}
}Utilisation des variables
Pour les chaînes à contenu dynamique, utilisez des espaces réservés et transmettez des variables :
// Marquer une chaîne avec des variables
const items = 100;
export const pricing = [
{
name: 'Basic',
price: 100,
description: msg('Le forfait de base inclut {items} éléments', { items })
}
];// Utilisation dans un composant
function PricingCard() {
const m = useMessages();
return (
<div>
<h3>{pricing[0].name}</h3>
<p>{m(pricing[0].description)}</p>
</div>
);
}Format de message ICU
Pour un formatage avancé, utilisez la syntaxe ICU :
const count = 10;
const message = msg('Il y a {count, plural, =0 {aucun article} =1 {un article} other {{count} articles}} dans le panier', { count });Pour en savoir plus sur le format de message ICU, consultez la documentation Unicode.
Exemples
Configuration de la navigation
// config/navigation.ts
import { msg } from 'gt-react';
export const mainNav = [
{
label: msg('Accueil'),
href: '/',
icon: 'home'
},
{
label: msg('Produits'),
href: '/products',
icon: 'package'
},
{
label: msg('À propos de nous'),
href: '/about',
icon: 'info'
}
];
export const footerLinks = [
{
title: msg('Entreprise'),
links: [
{ label: msg('À propos'), href: '/about' },
{ label: msg('Carrières'), href: '/careers' },
{ label: msg('Contact'), href: '/contact' }
]
},
{
title: msg('Assistance'),
links: [
{ label: msg('Centre d'aide'), href: '/help' },
{ label: msg('Documentation'), href: '/docs' },
{ label: msg('Référence de l'API'), href: '/api' }
]
}
];// components/Navigation.tsx
import { useMessages } from 'gt-react';
import { mainNav } from '../config/navigation';
function Navigation() {
const m = useMessages();
return (
<nav>
{mainNav.map((item) => (
<a key={item.href} href={item.href}>
<Icon name={item.icon} />
{m(item.label)}
</a>
))}
</nav>
);
}Configuration du formulaire
// config/forms.ts
import { msg } from 'gt-react';
export const formMessages = {
placeholders: {
email: msg('Saisissez votre adresse e-mail'),
password: msg('Saisissez votre mot de passe'),
message: msg('Saisissez votre message ici...'),
},
actions: {
send: msg('Envoyer le message'),
save: msg('Enregistrer les modifications'),
cancel: msg('Annuler')
},
validation: {
required: msg('Ce champ est obligatoire'),
email: msg('Veuillez saisir une adresse e-mail valide'),
minLength: msg('Doit contenir au moins {min} caractères', { min: 8 }),
maxLength: msg('Ne peut pas dépasser {max} caractères', { max: 100 })
},
success: {
saved: msg('Modifications enregistrées avec succès'),
sent: msg('Message envoyé avec succès'),
updated: msg('Profil mis à jour')
},
errors: {
network: msg('Erreur réseau - veuillez réessayer'),
server: msg('Erreur serveur - veuillez contacter le support'),
timeout: msg('Délai d'attente de la requête dépassé - veuillez réessayer')
}
};// components/ContactForm.tsx
import { useMessages } from 'gt-react';
import { formMessages } from '../config/forms';
function ContactForm() {
const m = useMessages();
const [errors, setErrors] = useState({});
return (
<form>
<input
type="email"
placeholder={m(formMessages.placeholders.email)}
required
/>
{errors.email && <span>{m(formMessages.validation.email)}</span>}
<button type="submit">
{m(formMessages.actions.send)}
</button>
</form>
);
}Génération dynamique de contenu
// utils/productData.ts
import { msg } from 'gt-react';
function mockProducts() {
return [
{ name: 'iPhone 15', company: 'Apple', category: 'Électronique' },
{ name: 'Galaxy S24', company: 'Samsung', category: 'Électronique' }
];
}
export function getProductData() {
const products = mockProducts();
return products.map(product => ({
...product,
description: msg('{name} est un produit de {category} de {company}', {
name: product.name,
category: product.category,
company: product.company
})
}));
}// components/ProductList.tsx
import { useMessages } from 'gt-react';
import { getProductData } from '../utils/productData';
function ProductList() {
const m = useMessages();
const products = getProductData();
return (
<div>
{products.map(product => (
<div key={product.name}>
<h3>{product.name}</h3>
<p>{m(product.description)}</p>
</div>
))}
</div>
);
}Problèmes fréquents
Utiliser directement les chaînes encodées
N’utilisez jamais directement la sortie de msg :
// ❌ Incorrect - chaîne encodée utilisée directement
const encoded = msg('Hello, world!');
return <div>{encoded}</div>; // Affiche la chaîne encodée, pas la traduction
// ✅ Correct - décoder la chaîne d'abord
const encoded = msg('Hello, world!');
const m = useMessages();
return <div>{m(encoded)}</div>; // Affiche la traduction correcteContenu dynamique dans msg()
Les chaînes doivent être connues à la compilation :
// ❌ Incorrect - littéral de template dynamique
const name = 'John';
const message = msg(`Hello, ${name}`); // Erreur à la compilation
// ✅ Correct - utiliser des variables
const name = 'John';
const message = msg('Hello, {name}', { name });Oubli du décodage
Chaque chaîne msg doit être décodée :
// ❌ Décodage manquant
const config = {
title: msg('Tableau de bord'),
subtitle: msg('Bon retour')
};
// Plus tard dans le composant - décodage oublié
return <h1>{config.title}</h1>; // Affiche la chaîne encodée
// ✅ Correct - décoder lors de l'utilisation
const m = useMessages();
return <h1>{m(config.title)}</h1>; // Affiche le titre traduitProchaines étapes
- Guide des dictionnaires - Organisez les traductions avec des données structurées
- Guide des langues - Configurez les langues prises en charge
- Références de l’API :
Comment trouvez-vous ce guide ?