Internacionalización (i18n) en Rust: bibliotecas gettext-rs y fluent-rs

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Internacionalización (i18n) en Rust: gettext-rs y fluent-rs



La internacionalización (i18n) es un aspecto clave en el desarrollo de aplicaciones modernas, que permite adaptar el software para usuarios de diferentes países y culturas. En el ecosistema de Rust existen varias bibliotecas potentes para implementar i18n. En este artículo veremos las dos más populares: gettext-rs (enfoque clásico basado en gettext) y fluent-rs (sistema de localización moderno de Mozilla).



1. Biblioteca gettext-rs



gettext-rs es un envoltorio de Rust para el sistema clásico GNU gettext. Es ideal para proyectos que ya usan gettext o para quienes prefieren soluciones probadas a lo largo del tiempo.



Instalación y configuración



Añade la dependencia en Cargo.toml:



[dependencies]gettext-rs = "0.7"gettext-sys = "0.21"


Ejemplo básico de uso



use gettextrs::*;

fn main() { // Establecemos la configuración regional y el dominio de traducción setlocale(LocaleCategory::LcAll, "es_ES.UTF-8"); bindtextdomain("myapp", "/usr/share/locale").unwrap(); textdomain("myapp").unwrap();

// Usamos la traducción let greeting = gettext("Hello, world!"); println!("{}", greeting);

// Formas plurales let items = 5; let message = ngettext("{} item", "{} items", items); println!("{}", message.replace("{}", &items.to_string()));}


Trabajo con contexto



Para diferenciar cadenas iguales en contextos distintos, usa pgettext:



let menu_item = pgettext("menu", "File");let dialog_title = pgettext("dialog", "File");


2. Biblioteca fluent-rs



fluent-rs es un sistema de localización moderno, flexible y potente, desarrollado por Mozilla. Soporta construcciones gramaticales complejas, formas plurales y traducciones contextuales.



Instalación



[dependencies]fluent = "0.16"fluent-bundle = "0.15"fluent-resmgr = "0.5"fluent-langneg = "0.4"unic-langid = "0.9"


Creación de archivos de traducción (FTL)



Fluent usa su propio formato de archivos .ftl. Ejemplo para español (es.ftl):



hello-world = ¡Hola, mundo!greeting = ¡Hola, {$name}!items-count = { $count ->    [one] {$count} elemento    [many] {$count} elementos    *[other] {$count} elementos}


Ejemplo de uso de fluent-rs



use fluent_bundle::{FluentBundle, FluentResource};use unic_langid::langid;use std::fs;

fn main() { // Cargamos el archivo de traducción let ftl_string = fs::read_to_string("locales/es.ftl") .expect("No se pudo leer el archivo de localización"); let resource = FluentResource::try_new(ftl_string) .expect("Error al analizar FTL");

// Creamos un bundle para español let lang_es = langid!("es"); let mut bundle = FluentBundle::new(&[lang_es]); bundle.add_resource(&resource).unwrap();

// Obtenemos la traducción con parámetros let mut errors = vec![]; let msg = bundle.get_message("greeting").unwrap(); let mut args = fluent_bundle::FluentArgs::new(); args.set("name", "Alejandro"); let pattern = msg.value().unwrap(); let value = bundle.format_pattern(pattern, Some(&args), &mut errors); println!("{}", value);

// Formas plurales let msg = bundle.get_message("items-count").unwrap(); let mut args = fluent_bundle::FluentArgs::new(); args.set("count", 3); let pattern = msg.value().unwrap(); let value = bundle.format_pattern(pattern, Some(&args), &mut errors); println!("{}", value);}


3. Comparación entre gettext-rs y fluent-rs



Recommendations