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
- gettext-rs:
-
También en la biblioteca
Recommendations
-