Vai al contenuto
Rust

Rust i18n

Non esiste un crate Better I18N. Un servizio Rust legge lo stesso JSON dalla CDN che leggono tutti gli SDK: bastano reqwest e serde_json, e i nuovi testi arrivano senza ricompilare.

Setup

Usa Better I18N da Rust

Aggiungi i crate HTTP e JSON

Bastano reqwest e serde_json: non c'è nessun crate Better I18N da installare.

Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }

Recupera un namespace

La CDN serve un file JSON per namespace e lingua e risponde sempre 200.

src/i18n.rs
use std::collections::HashMap;

/// The CDN serves one JSON file per namespace, per locale:
///   https://cdn.better-i18n.com/{org}/{project}/{locale}/{namespace}.json
/// It always answers 200 — an unknown locale returns `{}` rather than an error.
pub async fn fetch_messages(
    locale: &str,
    namespace: &str,
) -> reqwest::Result<HashMap<String, serde_json::Value>> {
    let url = format!(
        "https://cdn.better-i18n.com/your-org/your-project/{locale}/{namespace}.json"
    );

    reqwest::get(&url).await?.json().await
}

Aggiorna in background

Metti la mappa in cache nel processo e rileggila ogni 60 secondi, in linea con il max-age della CDN.

src/main.rs
use std::time::Duration;

// Cache in process and re-read on an interval: the CDN sets
// `Cache-Control: max-age=60`, so a 60s refresh matches it exactly.
tokio::spawn(async move {
    let mut ticker = tokio::time::interval(Duration::from_secs(60));
    loop {
        ticker.tick().await;
        if let Ok(next) = fetch_messages("en", "common").await {
            *messages.write().await = next;
        }
    }
});
Capabilities

Cosa ottengono i servizi Rust

Nessun SDK richiesto — e non esiste un crate Rust, quindi non c'è nulla da aspettare
JSON semplice su HTTPS, analizzato con serde_json
Funziona con axum, actix-web, Rocket o un semplice binario
I nuovi testi arrivano in circa 60 secondi senza ricompilare
L'API REST copre tutto ciò che la CDN non copre
Convive con rust-i18n se lo usi già per i cataloghi locali
Example

Un handler axum che legge i messaggi dalla CDN

I messaggi stanno dietro un RwLock e vengono aggiornati da un timer.

use axum::{extract::State, routing::get, Json, Router};
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;

type Messages = Arc<RwLock<HashMap<String, serde_json::Value>>>;

async fn greeting(State(messages): State<Messages>) -> Json<serde_json::Value> {
    let messages = messages.read().await;

    let hello = messages
        .get("greeting.hello")
        .and_then(|v| v.as_str())
        .unwrap_or("Hello");

    Json(serde_json::json!({ "message": hello }))
}

#[tokio::main]
async fn main() {
    let messages: Messages = Arc::new(RwLock::new(
        fetch_messages("en", "common").await.unwrap_or_default(),
    ));

    let app = Router::new()
        .route("/greeting", get(greeting))
        .with_state(messages);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Altri framework

Get started

Localizza il tuo servizio Rust

Crea un progetto, pubblica la prima lingua e leggila da Rust via HTTPS.