Internacionalización (i18n) en Rust: resumen de bibliotecas y herramientas
\n\nLa internacionalización (abreviada i18n — por las 18 letras entre la 'i' y la 'n') es el proceso de diseñar una aplicación para que pueda adaptarse a diferentes idiomas y estándares regionales sin modificar el código fuente. En el ecosistema de Rust existen varias bibliotecas maduras para implementar i18n. En este artículo veremos tres enfoques principales: el clásico gettext, el orientado a macros rust-i18n y el moderno fluent-rs de Mozilla.
1. Biblioteca gettext (crate gettext-rs)
\ngettext es el estándar de facto de localización Unix. El envoltorio de Rust gettext-rs proporciona acceso completo a las funciones de GNU gettext.
Instalación
\n[dependencies]\ngettext-rs = "0.7"\n\nEjemplo de uso
\nuse gettextrs::*;\nuse std::env;\n\nfn main() {\n // Establecer locale y dominio\n setlocale(LocaleCategory::LcAll, "ru_RU.UTF-8");\n bindtextdomain("myapp", "/usr/share/locale").unwrap();\n textdomain("myapp");\n\n // Traducción de cadena\n println!("{}", gettext("Hello, world!"));\n \n // Pluralización (número plural)\n let n = 5;\n println!("{}", ngettext("{} apple", "{} apples", n, n));\n}\n\nVentajas: madurez, soporte de pluralización, traducciones contextuales (pgettext), integración con Poedit y Transifex.
\nDesventajas: requiere instalación de gettext del sistema, soporte imperfecto de Unicode en Windows.
2. Biblioteca rust-i18n
\nImplementación pura en Rust sin dependencias externas. Utiliza archivos YAML para almacenar traducciones y macros para extraer cadenas.
\n\nInstalación
\n[dependencies]\nrust-i18n = "3.0"\n\nEstructura del proyecto
\nlocales/\n├── en.yml\n└── ru.yml\n\nEjemplo de locales/ru.yml:
hello: "¡Hola, mundo!"\napples: \n zero: "No hay manzanas"\n one: "{} manzana"\n few: "{} manzanas"\n many: "{} manzanas"\n\nUso en código
\nuse rust_i18n::t;\n\nrust_i18n::i18n!("locales");\n\nfn main() {\n // Traducción simple\n println!("{}", t!("hello"));\n\n // Pluralización con reglas rusas\n let n = 3;\n println!("{}", t!("apples", count = n, n));\n}\n\nVentajas: simplicidad, detección automática de locale, soporte de placeholders y pluralización para idiomas complejos (ruso, árabe).
\nDesventajas: menos flexible que gettext, sin soporte de contextos.
3. Biblioteca fluent-rs
\nDesarrollada por Mozilla para Firefox. Utiliza su propia sintaxis FTL (Fluent Translation List).
\n\nInstalación
\n[dependencies]\nfluent = "0.16"\nfluent-bundle = "0.15"\nfluent-resmgr = "0.4"\n\nEjemplo de archivo FTL (locales/ru/main.ftl)
\nhello = ¡Hola, mundo!\napples = \n { $count ->\n [0] No hay manzanas\n [one] { $count } manzana\n [few] { $count } manzanas\n *[many] { $count } manzanas\n }\n\nUso en Rust
\nuse fluent_bundle::{FluentBundle, FluentResource};\nuse fluent_resmgr::ResourceManager;\nuse unic_langid::langid;\n\nfn main() {\n let langid = langid!("ru");\n let res_mgr = ResourceManager::new("./locales/".into());\n \n let mut bundle = FluentBundle::new(&[langid]);\n let ftl_string = res_mgr.load("ru/main.ftl").unwrap();\n let resource = FluentResource::try_new(ftl_string).unwrap();\n bundle.add_resource(resource).unwrap();\n\n let mut errors = vec![];\n let msg = bundle.format_pattern(\n bundle.get_message("hello").unwrap().value().unwrap(),\n None,\n &mut errors\n );\n println!("{}", msg);\n\n // Pluralización\n let mut args = fluent_bundle::FluentArgs::new();\n