Internationalization (i18n) in Rust: Best Libraries and Practices

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Internationalization (i18n) in Rust: Overview of Libraries and Tools



Internationalization (abbreviated as i18n — 18 letters between 'i' and 'n') is the process of designing an application so it can be adapted to various languages and regional standards without modifying the source code. In the Rust ecosystem, there are several mature libraries for implementing i18n. In this article, we will look at three main approaches: the classic gettext, the macro-oriented rust-i18n, and the modern fluent-rs from Mozilla.



1. The gettext Library (crate gettext-rs)

gettext is the de facto standard for Unix localization. The Rust wrapper gettext-rs provides full access to GNU gettext functions.



Installation

[dependencies]gettext-rs = "0.7"


Usage Example

use gettextrs::*;use std::env;

fn main() { // Set locale and domain setlocale(LocaleCategory::LcAll, "ru_RU.UTF-8"); bindtextdomain("myapp", "/usr/share/locale").unwrap(); textdomain("myapp");

// String translation println!("{}", gettext("Hello, world!")); // Pluralization let n = 5; println!("{}", ngettext("{} apple", "{} apples", n, n));}


Pros: maturity, support for pluralization, contextual translations (pgettext), integration with Poedit and Transifex.
Cons: requires system gettext installation, imperfect Unicode support on Windows.



2. The rust-i18n Library

A pure Rust implementation with no external dependencies. Uses YAML files for storing translations and macros for extracting strings.



Installation

[dependencies]rust-i18n = "3.0"


Project Structure

locales/├── en.yml└── ru.yml


Example locales/ru.yml:

hello: "Hello, world!"apples:   zero: "No apples"  one: "{} apple"  few: "{} apples"  many: "{} apples"


Usage in Code

use rust_i18n::t;

rust_i18n::i18n!("locales");

fn main() { // Simple translation println!("{}", t!("hello"));

// Pluralization considering Russian rules let n = 3; println!("{}", t!("apples", count = n, n));}


Pros: simplicity, automatic locale detection, support for placeholders and pluralization for complex languages (Russian, Arabic).
Cons: less flexible than gettext, no context support.



3. The fluent-rs Library

Developed by Mozilla for Firefox. Uses its own FTL (Fluent Translation List) syntax.



Installation

[dependencies]fluent = "0.16"fluent-bundle = "0.15"fluent-resmgr = "0.4"


Example FTL File (locales/ru/main.ftl)

hello = Hello, world!apples =     { $count ->        [0] No apples        [one] { $count } apple        [few] { $count } apples       *[many] { $count } apples    }


Usage in Rust

use fluent_bundle::{FluentBundle, FluentResource};use fluent_resmgr::ResourceManager;use unic_langid::langid;

fn main() { let langid = langid!("ru"); let res_mgr = ResourceManager::new("./locales/".into()); let mut bundle = FluentBundle::new(&[langid]); let ftl_string = res_mgr.load("ru/main.ftl").unwrap(); let resource = FluentResource::try_new(ftl_string).unwrap(); bundle.add_resource(resource).unwrap();

let mut errors = vec![]; let msg = bundle.format_pattern( bundle.get_message("hello").unwrap().value().unwrap(), None, &mut errors ); println!("{}", msg);

// Pluralization let mut args = fluent_bundle::FluentArgs::new();

Recommendations