core: Add i18n module using Fluent

This commit is contained in:
Nathan Adams 2023-04-22 01:44:01 +02:00
parent 01a69b60bc
commit 229c301e18
9 changed files with 337 additions and 3 deletions

280
Cargo.lock generated
View File

@ -221,6 +221,12 @@ dependencies = [
"x11rb",
]
[[package]]
name = "arc-swap"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "arrayref"
version = "0.3.7"
@ -428,6 +434,16 @@ dependencies = [
"objc2-encode",
]
[[package]]
name = "bstr"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "build_playerglobal"
version = "0.1.0"
@ -1259,6 +1275,17 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "displaydoc"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "dlib"
version = "0.5.0"
@ -1268,6 +1295,12 @@ dependencies = [
"libloading 0.7.4",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "downcast-rs"
version = "1.2.0"
@ -1474,6 +1507,98 @@ dependencies = [
"num-traits",
]
[[package]]
name = "fluent"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7"
dependencies = [
"fluent-bundle",
"unic-langid",
]
[[package]]
name = "fluent-bundle"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd"
dependencies = [
"fluent-langneg",
"fluent-syntax",
"intl-memoizer",
"intl_pluralrules",
"rustc-hash",
"self_cell",
"smallvec",
"unic-langid",
]
[[package]]
name = "fluent-langneg"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94"
dependencies = [
"unic-langid",
]
[[package]]
name = "fluent-syntax"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78"
dependencies = [
"thiserror",
]
[[package]]
name = "fluent-template-macros"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec7592cd1f45c1afe9084ce59c62a3a7c266c125c4c2ec97e95b0563c4aa914"
dependencies = [
"flume",
"ignore",
"once_cell",
"proc-macro2",
"quote",
"syn 1.0.109",
"unic-langid",
]
[[package]]
name = "fluent-templates"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3ef2c2152757885365abce32ddf682746062f1b6b3c0824a29fbed6ee4d080"
dependencies = [
"arc-swap",
"fluent",
"fluent-bundle",
"fluent-langneg",
"fluent-syntax",
"fluent-template-macros",
"flume",
"heck",
"ignore",
"intl-memoizer",
"lazy_static",
"log",
"once_cell",
"serde_json",
"snafu",
"unic-langid",
]
[[package]]
name = "flume"
version = "0.10.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
dependencies = [
"spin",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1758,6 +1883,19 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "globset"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "glow"
version = "0.12.1"
@ -1997,6 +2135,23 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "ignore"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
dependencies = [
"globset",
"lazy_static",
"log",
"memchr",
"regex",
"same-file",
"thread_local",
"walkdir",
"winapi-util",
]
[[package]]
name = "image"
version = "0.24.6"
@ -2060,6 +2215,25 @@ dependencies = [
"web-sys",
]
[[package]]
name = "intl-memoizer"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f"
dependencies = [
"type-map",
"unic-langid",
]
[[package]]
name = "intl_pluralrules"
version = "7.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
dependencies = [
"unic-langid",
]
[[package]]
name = "io-lifetimes"
version = "1.0.10"
@ -3199,6 +3373,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.56"
@ -3455,6 +3635,7 @@ dependencies = [
"enumset",
"flash-lso",
"flate2",
"fluent-templates",
"fnv",
"futures",
"gc-arena",
@ -3512,6 +3693,7 @@ dependencies = [
"tracing",
"tracing-subscriber",
"tracing-tracy",
"unic-langid",
"url",
"webbrowser",
"winapi",
@ -3845,6 +4027,12 @@ dependencies = [
"tiny-skia",
]
[[package]]
name = "self_cell"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
[[package]]
name = "semver"
version = "1.0.17"
@ -4019,6 +4207,28 @@ dependencies = [
"wayland-protocols",
]
[[package]]
name = "snafu"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0656e7e3ffb70f6c39b3c2a86332bb74aa3c679da781642590f3c1118c5045"
dependencies = [
"doc-comment",
"snafu-derive",
]
[[package]]
name = "snafu-derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "socket2"
version = "0.4.9"
@ -4029,6 +4239,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "spirv"
version = "0.2.0+1.5.4"
@ -4331,6 +4550,15 @@ dependencies = [
"strict-num",
]
[[package]]
name = "tinystr"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef"
dependencies = [
"displaydoc",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
@ -4540,6 +4768,15 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746"
[[package]]
name = "type-map"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46"
dependencies = [
"rustc-hash",
]
[[package]]
name = "typed-arena"
version = "2.0.2"
@ -4552,6 +4789,49 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unic-langid"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"
dependencies = [
"unic-langid-impl",
"unic-langid-macros",
]
[[package]]
name = "unic-langid-impl"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"
dependencies = [
"tinystr",
]
[[package]]
name = "unic-langid-macros"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe"
dependencies = [
"proc-macro-hack",
"tinystr",
"unic-langid-impl",
"unic-langid-macros-impl",
]
[[package]]
name = "unic-langid-macros-impl"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8"
dependencies = [
"proc-macro-hack",
"quote",
"syn 1.0.109",
"unic-langid-impl",
]
[[package]]
name = "unicode-bidi"
version = "0.3.13"

View File

@ -51,6 +51,7 @@ realfft = "3.2.0"
once_cell = "1.17.1"
hashbrown = { version = "0.13.2", features = ["raw"] }
scopeguard = "1.1.0"
fluent-templates = "0.8.0"
[target.'cfg(not(target_family = "wasm"))'.dependencies.futures]
version = "0.3.28"

View File

@ -186,7 +186,7 @@ impl<'gc> XmlObject<'gc> {
}
Event::Decl(bd) => {
let mut xml_decl = WString::from_buf(b"<?".to_vec());
xml_decl.push_str(WStr::from_units(bd.as_ref()));
xml_decl.push_str(WStr::from_units(&*bd));
xml_decl.push_str(WStr::from_units(b"?>"));
self.0.write(activation.context.gc_context).xml_decl =
Some(AvmString::new(activation.context.gc_context, xml_decl));

View File

@ -1,8 +1,11 @@
use crate::events::{KeyCode, PlayerEvent};
use fluent_templates::loader::langid;
pub use fluent_templates::LanguageIdentifier;
use std::borrow::Cow;
use std::collections::HashSet;
pub type FullscreenError = Cow<'static, str>;
pub static US_ENGLISH: LanguageIdentifier = langid!("en-US");
pub trait UiBackend {
fn mouse_visible(&self) -> bool;
@ -31,6 +34,8 @@ pub trait UiBackend {
// Only used on web.
fn open_virtual_keyboard(&self);
fn language(&self) -> &LanguageIdentifier;
}
/// A mouse cursor icon displayed by the Flash Player.
@ -153,6 +158,10 @@ impl UiBackend for NullUiBackend {
fn message(&self, _message: &str) {}
fn open_virtual_keyboard(&self) {}
fn language(&self) -> &LanguageIdentifier {
&US_ENGLISH
}
}
impl Default for NullUiBackend {

30
core/src/i18n.rs Normal file
View File

@ -0,0 +1,30 @@
use fluent_templates::fluent_bundle::FluentValue;
use fluent_templates::{static_loader, LanguageIdentifier, Loader};
use std::collections::HashMap;
static_loader! {
pub static TEXTS = {
locales: "./assets/texts",
fallback_language: "en-US"
};
}
pub fn text(language: &LanguageIdentifier, id: &str) -> String {
TEXTS.lookup(language, id).unwrap_or_else(|| {
tracing::error!("Unknown text id '{id}'");
id.to_string()
})
}
pub fn text_with_args<T: AsRef<str>>(
language: &LanguageIdentifier,
id: &str,
args: &HashMap<T, FluentValue>,
) -> String {
TEXTS
.lookup_with_args(language, id, args)
.unwrap_or_else(|| {
tracing::error!("Unknown text id '{id}'");
id.to_string()
})
}

View File

@ -48,6 +48,7 @@ pub mod backend;
pub mod compatibility_rules;
pub mod config;
pub mod external;
pub mod i18n;
pub mod stub;
pub use avm1::globals::system::SandboxType;

View File

@ -27,6 +27,7 @@ rfd = "0.11.3"
anyhow = "1.0"
bytemuck = "1.13.1"
os_info = { version = "3", default-features = false }
unic-langid = "0.9.1"
# Deliberately held back to match tracy client used by profiling crate
tracing-tracy = { version = "=0.10.0", optional = true }

View File

@ -1,7 +1,9 @@
use anyhow::{Context, Error};
use arboard::Clipboard;
use rfd::{MessageButtons, MessageDialog, MessageLevel};
use ruffle_core::backend::ui::{FullscreenError, MouseCursor, UiBackend};
use ruffle_core::backend::ui::{
FullscreenError, LanguageIdentifier, MouseCursor, UiBackend, US_ENGLISH,
};
use std::rc::Rc;
use tracing::error;
use winit::window::{Fullscreen, Window};
@ -97,4 +99,8 @@ impl UiBackend for DesktopUiBackend {
// Unused on desktop
fn open_virtual_keyboard(&self) {}
fn language(&self) -> &LanguageIdentifier {
&US_ENGLISH
}
}

View File

@ -1,5 +1,7 @@
use super::JavascriptPlayer;
use ruffle_core::backend::ui::{FullscreenError, MouseCursor, UiBackend};
use ruffle_core::backend::ui::{
FullscreenError, LanguageIdentifier, MouseCursor, UiBackend, US_ENGLISH,
};
use ruffle_web_common::JsResult;
use std::borrow::Cow;
use wasm_bindgen::JsCast;
@ -116,4 +118,8 @@ impl UiBackend for WebUiBackend {
fn open_virtual_keyboard(&self) {
self.js_player.open_virtual_keyboard()
}
fn language(&self) -> &LanguageIdentifier {
&US_ENGLISH
}
}