Интернационализация (i18n) в Rust: лучшие библиотеки и практики

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Интернационализация (i18n) в Rust: обзор библиотек и инструментов

Интернационализация (сокращённо i18n — от 18 букв между 'i' и 'n') — процесс проектирования приложения, позволяющий адаптировать его под различные языки и региональные стандарты без изменения исходного кода. В экосистеме Rust существует несколько зрелых библиотек для реализации i18n. В этой статье мы рассмотрим три основных подхода: классический gettext, макрос-ориентированная rust-i18n и современный fluent-rs от Mozilla.

1. Библиотека gettext (crate gettext-rs)

gettext — де-факто стандарт Unix-локализации. Rust-обёртка gettext-rs предоставляет полный доступ к функциям GNU gettext.

Установка

[dependencies]
gettext-rs = "0.7"

Пример использования

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

fn main() {
    // Устанавливаем локаль и домен
    setlocale(LocaleCategory::LcAll, "ru_RU.UTF-8");
    bindtextdomain("myapp", "/usr/share/locale").unwrap();
    textdomain("myapp");

    // Перевод строки
    println!("{}", gettext("Hello, world!"));
    
    // Плюрализация (множественное число)
    let n = 5;
    println!("{}", ngettext("{} apple", "{} apples", n, n));
}

Плюсы: зрелость, поддержка плюрализации, контекстных переводов (pgettext), интеграция с Poedit и Transifex.
Минусы: требует установки системного gettext, неидеальная поддержка Unicode на Windows.

2. Библиотека rust-i18n

Чисто Rust-реализация без внешних зависимостей. Использует YAML-файлы для хранения переводов и макросы для извлечения строк.

Установка

[dependencies]
rust-i18n = "3.0"

Структура проекта

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

Пример locales/ru.yml:

hello: "Привет, мир!"
apples: 
  zero: "Нет яблок"
  one: "{} яблоко"
  few: "{} яблока"
  many: "{} яблок"

Использование в коде

use rust_i18n::t;

rust_i18n::i18n!("locales");

fn main() {
    // Простой перевод
    println!("{}", t!("hello"));

    // Плюрализация с учётом русских правил
    let n = 3;
    println!("{}", t!("apples", count = n, n));
}

Плюсы: простота, автоматическое определение локали, поддержка плейсхолдеров и плюрализации для сложных языков (русский, арабский).
Минусы: менее гибкая, чем gettext, нет поддержки контекстов.

3. Библиотека fluent-rs

Разработана Mozilla для Firefox. Использует собственный синтаксис FTL (Fluent Translation List).

Установка

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

Пример FTL-файла (locales/ru/main.ftl)

hello = Привет, мир!
apples = 
    { $count ->
        [0] Нет яблок
        [one] { $count } яблоко
        [few] { $count } яблока
       *[many] { $count } яблок
    }

Использование в 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);

    // Плюрализация
    let mut args = fluent_bundle::FluentArgs::new();
    args.set("count", 3);
    let                    

Рекомендаций