Internationalisation des applications Rust : de zéro au multilinguisme

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi votre application Rust a besoin d'internationalisation (et comment éviter les pièges)

\n\n

Vous avez écrit un analyseur parfait en Rust. Il vole plus vite que l'éclair et consomme moins de mémoire qu'une modeste mésange. Mais il y a un problème : votre texte s'affiche uniquement en anglais. Et les utilisateurs de Tokyo, Berlin et Saint-Pétersbourg veulent voir l'interface dans leur langue maternelle.

\n\n

L'internationalisation (i18n) n'est pas simplement « traduire les boutons ». C'est une décision architecturale qui peut transformer votre code en un constructeur élégant ou en un dépotoir infernal de if-else. Dans cet article, nous allons voir comment faire de l'internationalisation en Rust correctement : sans douleur, avec des exemples et dans le respect du cerveau du futur développeur (le vôtre).

\n\n

Nous parlerons de deux approches puissantes : la bibliothèque fluent (recommandation de Mozilla) et le classique rust-i18n basé sur gettext. À la fin de cet article, vous pourrez ajouter la prise en charge du russe, de l'anglais et de toute autre langue à votre outil en 15 minutes.

\n\n

Plan de bataille : qu'est-ce que i18n et l10n dans le monde Rust

\n\n

Avant de se jeter dans le code, mettons-nous d'accord sur les termes :

\n
    \n
  • Internationalisation (i18n) — la préparation du code à la traduction. Vous extrayez toutes les chaînes dans des fichiers séparés et apprenez au programme à charger la locale appropriée.
  • \n
  • Localisation (l10n) — la traduction elle-même. Création de fichiers pour chaque langue.
  • \n
  • Locale — une combinaison de langue et de région (par exemple, ru-RU, en-US, de-DE).
  • \n
\n\n

En Rust, il existe plusieurs chemins. Nous allons examiner les deux plus populaires :

\n
    \n
  • Fluent — un système moderne de Mozilla. Puissant, flexible, avec prise en charge de la pluralisation et du contexte.
  • \n
  • rust-i18n — des macros inspirées de Ruby on Rails. Plus simple, mais moins flexible.
  • \n
\n\n

Le choix dépend de la tâche. Pour les utilitaires CLI, rust-i18n suffit. Pour les applications web ou les GUI complexes (par exemple, sur Tauri), il est préférable d'utiliser Fluent.

\n\n

Méthode n°1 : Internationalisation Rust avec Fluent (approche professionnelle)

\n\n

Installation et configuration de Fluent

\n\n

Créons un nouveau projet et ajoutons les dépendances :

\n\n
cargo new i18n_demo\ncd i18n_demo\ncargo add fluent fluent-bundle fluent-langtag unic-langid\n
\n\n

La structure des fichiers sera la suivante :

\n\n
projet/\n├── Cargo.toml\n├── locales/\n│   ├── ru/\n│   │   └── main.ftl\n│   └── en/\n│       └── main.ftl\n└── src/\n    └── main.rs\n
\n\n

Création des fichiers de localisation (FTL)

\n\n

Fluent utilise le format FTL (Fluent Translation List). C'est la pureté et la puissance :

\n\n

locales/en/main.ftl :

\n
greeting = Hello, { $name }!\ngoodbye = Goodbye\napples = { $count ->\n    [one] { $count } apple\n    [few] { $count } apples\n    *[other] { $count } apples\n}\n
\n\n

locales/ru/main.ftl :

\n
greeting = Привет, { $name }!\ngoodbye = До свидания\napples = { $count ->\n    [one] { $count } яблоко\n    [few] { $count } яблока\n    [many] { $count } яблок\n    *[other] { $count } яблок\n}\n
\n\n

Remarquez la pluralisation. En russe, il y a quatre formes (un, deux-quatre, cinq-vingt, le reste), tandis qu'en anglais il y en a deux (un, le reste). Fluent gère cela automatiquement.

\n\n

Écriture du code Rust pour charger les locales

\n\n

Maintenant, la partie intéressante — le code qui sélectionnera la langue appropriée en fonction du système de l'utilisateur :

\n\n
use fluent_bundle::{FluentBundle, FluentResource};\nuse unic_langid::LanguageIdentifier;\nuse std::fs;\nuse std::path::Path;\n\nfn load_locale(locale: &str) -> FluentBundle<FluentResource> {\n    let langid: LanguageIdentifier = locale.parse().expect("Locale invalide");\n    let mut bundle = FluentBundle::new(vec![langid]);\n\n    let file_path = format!("locales/{}/main.ftl", locale);\n    let source = fs::read_to_string(&file_path)\n        .expect(&fo                

Blogs

Book Recommendations