feat(wasm-api): port i18n module for plugin and host use (#1898)

This commit is contained in:
Daniel Wang
2026-03-25 22:20:26 +08:00
committed by GitHub
parent 83199db6a1
commit 7a57b026a0
4 changed files with 55 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
interface i18n {
use common.{locale};
/// Retrieves a translated string from the host.
///
/// # Arguments
/// * `key`: The namespaced translation key (e.g. `pumpkin:my_key`).
/// * `locale`: The target locale.
///
/// # Returns
/// The localized string, falling back to English or the key itself.
translate: func(key: string, locale: locale) -> string;
/// Loads custom translations from a JSON string.
///
/// # Arguments
/// * `namespace`: The namespace to associate these keys with.
/// * `json`: A JSON string containing a flat map of translations.
/// * `locale`: The target locale for these translations.
load-translations: func(namespace: string, json: string, locale: locale);
}

View File

@@ -12,6 +12,7 @@ world plugin {
import text;
import command;
import context;
import i18n;
// This is what the plugin should provide
export init-plugin: func();

View File

@@ -0,0 +1,32 @@
use crate::plugin::loader::wasm::wasm_host::{
state::PluginHostState,
wit::v0_1_0::pumpkin::plugin::{common::Locale as WitLocale, i18n::Host},
};
use pumpkin_util::translation::{Locale as UtilLocale, add_translation_file, get_translation};
use std::str::FromStr;
impl Host for PluginHostState {
async fn translate(&mut self, key: String, locale: WitLocale) -> String {
let util_locale = wit_to_util_locale(locale);
get_translation(&key, util_locale)
}
async fn load_translations(&mut self, namespace: String, json: String, locale: WitLocale) {
let util_locale = wit_to_util_locale(locale);
add_translation_file(namespace, json, util_locale);
}
}
/// Converts a WIT Locale to a pumpkin-util Locale.
fn wit_to_util_locale(wit: WitLocale) -> UtilLocale {
// WIT names are kebab-case (e.g., AfZa -> af-za in .wit, but in generated Rust it might vary)
// We can use the debug representation or a custom mapping.
// Given the amount of variants, we use a string-based approach if possible.
let s = format!("{wit:?}").to_lowercase();
// pumpkin-util::Locale::from_str expects "af_za" or similar.
// WIT might generate "AfZa" or "af_za" depending on bindgen config.
// Let's assume standard bindgen which might produce "AfZa".
// We'll replace kebab-case if necessary.
let s = s.replace('-', "_");
UtilLocale::from_str(&s).unwrap_or(UtilLocale::EnUs)
}

View File

@@ -11,6 +11,7 @@ pub mod common;
pub mod context;
pub mod entity;
pub mod events;
pub mod i18n;
pub mod logging;
pub mod permission;
pub mod player;