diff --git a/Cargo.lock b/Cargo.lock
index 114c8d0b..50d1f3e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -454,6 +454,7 @@ dependencies = [
"gloo-events 0.2.0",
"gloo-file 0.3.0",
"gloo-history 0.2.2",
+ "gloo-intl",
"gloo-net 0.5.0",
"gloo-render 0.2.0",
"gloo-storage 0.3.0",
@@ -588,6 +589,14 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "gloo-intl"
+version = "0.1.0"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
[[package]]
name = "gloo-net"
version = "0.3.1"
@@ -598,7 +607,7 @@ dependencies = [
"futures-core",
"futures-sink",
"gloo-utils 0.1.7",
- "http",
+ "http 0.2.11",
"js-sys",
"pin-project",
"serde",
@@ -785,7 +794,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
- "http",
+ "http 0.2.11",
"indexmap 2.1.0",
"slab",
"tokio",
@@ -814,7 +823,7 @@ dependencies = [
"base64",
"bytes",
"headers-core",
- "http",
+ "http 0.2.11",
"httpdate",
"mime",
"sha1",
@@ -826,7 +835,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
- "http",
+ "http 0.2.11",
]
[[package]]
@@ -852,6 +861,17 @@ dependencies = [
"itoa",
]
+[[package]]
+name = "http"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http-body"
version = "0.4.6"
@@ -859,7 +879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
- "http",
+ "http 0.2.11",
"pin-project-lite",
]
@@ -886,7 +906,7 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
- "http",
+ "http 0.2.11",
"http-body",
"httparse",
"httpdate",
@@ -1049,7 +1069,7 @@ dependencies = [
"bytes",
"encoding_rs",
"futures-util",
- "http",
+ "http 0.2.11",
"httparse",
"log",
"memchr",
@@ -1699,7 +1719,7 @@ dependencies = [
"byteorder",
"bytes",
"data-encoding",
- "http",
+ "http 0.2.11",
"httparse",
"log",
"rand",
@@ -1787,7 +1807,7 @@ dependencies = [
"futures-channel",
"futures-util",
"headers",
- "http",
+ "http 0.2.11",
"hyper",
"log",
"mime",
diff --git a/Cargo.toml b/Cargo.toml
index 74e8fedc..62461b23 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,6 +24,7 @@ gloo-utils = { version = "0.2", path = "crates/utils", optional = true }
gloo-history = { version = "0.2", path = "crates/history", optional = true }
gloo-worker = { version = "0.5", path = "crates/worker", optional = true }
gloo-net = { version = "0.5", path = "crates/net", optional = true }
+gloo-intl = { version = "0.1", path = "crates/intl", optional = true }
[features]
default = [
@@ -38,6 +39,7 @@ default = [
"history",
"worker",
"net",
+ "intl",
]
futures = [
"timers",
@@ -58,6 +60,7 @@ utils = ["gloo-utils"]
history = ["gloo-history"]
worker = ["gloo-worker"]
net = ["gloo-net"]
+intl = ["gloo-intl"]
[workspace]
members = [
@@ -73,6 +76,7 @@ members = [
"crates/worker",
"crates/worker-macros",
"crates/net",
+ "crates/intl",
"examples/markdown",
"examples/clock",
diff --git a/crates/intl/Cargo.toml b/crates/intl/Cargo.toml
new file mode 100644
index 00000000..d066f882
--- /dev/null
+++ b/crates/intl/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "gloo-intl"
+version = "0.1.0"
+authors = [
+ "Rust and WebAssembly Working Group",
+ # "Mendy Berger",
+]
+edition = "2021"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rustwasm/gloo"
+description = "Clean Intl API for WASM Apps"
+readme = "README.md"
+keywords = ["intl", "i18l", "Internationalization", "localization"]
+categories = ["wasm", "api-bindings"]
+
+[dependencies]
+wasm-bindgen = "0.2"
+js-sys = "0.3"
diff --git a/crates/intl/README.md b/crates/intl/README.md
new file mode 100644
index 00000000..eb9839d9
--- /dev/null
+++ b/crates/intl/README.md
@@ -0,0 +1,24 @@
+
+
+Wraps common `js_sys` Intl with a cleaner API.
+
+See the API docs to learn more
diff --git a/crates/intl/src/date_time_format.rs b/crates/intl/src/date_time_format.rs
new file mode 100644
index 00000000..5a184bde
--- /dev/null
+++ b/crates/intl/src/date_time_format.rs
@@ -0,0 +1,103 @@
+use super::utils::options;
+
+pub struct DateTimeFormat {
+ js: js_sys::Intl::DateTimeFormat,
+}
+
+// TODO: Add a `new` method that takes a strongly types locale. Maybe an enum.
+impl DateTimeFormat {
+ /// New DateTimeFormat instance from locale &str.
+ pub fn new_str(locale: &str, options: Options) -> Self {
+ let locales = js_sys::Array::of1(&wasm_bindgen::JsValue::from_str(locale));
+ Self::new_js_array(locales, options)
+ }
+ /// New DateTimeFormat instance from js_sys::Array of locales.
+ pub fn new_js_array(locales: js_sys::Array, options: Options) -> Self {
+ let options = options.to_js_object();
+ let js = js_sys::Intl::DateTimeFormat::new(&locales, &options);
+ Self { js }
+ }
+ /// Corresponds to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format
+ pub fn format(&self, date: &js_sys::Date) -> String {
+ self.js
+ .format()
+ .call1(&self.js, &date.into())
+ .unwrap()
+ .as_string()
+ .unwrap()
+ }
+}
+
+/// Corresponds to the options in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
+// TODO: add all options here.
+#[derive(Clone, Default)]
+pub struct Options {
+ pub year: Option,
+ pub month: Option,
+ pub day: Option,
+ pub hour: Option,
+ pub minute: Option,
+ pub second: Option,
+}
+impl Options {
+ // TODO: should be a derive macro?
+ fn to_js_object(&self) -> js_sys::Object {
+ let output = js_sys::Object::new();
+ if let Some(year) = &self.year {
+ pro(&output, "year", year.string_rep());
+ }
+ if let Some(month) = &self.month {
+ pro(&output, "month", month.string_rep());
+ }
+ if let Some(day) = &self.day {
+ pro(&output, "day", day.string_rep());
+ }
+ if let Some(hour) = &self.hour {
+ pro(&output, "hour", hour.string_rep());
+ }
+ if let Some(minute) = &self.minute {
+ pro(&output, "minute", minute.string_rep());
+ }
+ if let Some(second) = &self.second {
+ pro(&output, "second", second.string_rep());
+ }
+ output
+ }
+}
+
+fn pro(obj: &js_sys::Object, key: &str, value: &str) {
+ js_sys::Reflect::set(
+ &obj,
+ &wasm_bindgen::JsValue::from_str(key),
+ &wasm_bindgen::JsValue::from_str(value),
+ )
+ .unwrap();
+}
+
+options!(Year, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+});
+options!(Month, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+ Long: "long",
+ Short: "short",
+ Narrow: "narrow",
+});
+options!(Day, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+});
+options!(Hour, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+});
+options!(Minute, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+});
+options!(Second, {
+ Numeric: "numeric",
+ Digit2: "2-digit",
+});
diff --git a/crates/intl/src/lib.rs b/crates/intl/src/lib.rs
new file mode 100644
index 00000000..4e1cce19
--- /dev/null
+++ b/crates/intl/src/lib.rs
@@ -0,0 +1,4 @@
+pub mod date_time_format;
+pub mod number_format;
+
+mod utils;
diff --git a/crates/intl/src/number_format.rs b/crates/intl/src/number_format.rs
new file mode 100644
index 00000000..b769e811
--- /dev/null
+++ b/crates/intl/src/number_format.rs
@@ -0,0 +1,84 @@
+use super::utils::options;
+
+pub struct NumberFormat {
+ js: js_sys::Intl::NumberFormat,
+}
+
+// TODO: Add a `new` method that takes a strongly types locale. Maybe an enum.
+impl NumberFormat {
+ /// New NumberFormat instance from locale &str.
+ pub fn new_str(locale: &str, options: Options) -> Self {
+ let locales = js_sys::Array::of1(&wasm_bindgen::JsValue::from_str(locale));
+ Self::new_js_array(locales, options)
+ }
+ /// New NumberFormat instance from js_sys::Array of locales.
+ pub fn new_js_array(locales: js_sys::Array, options: Options) -> Self {
+ let options = options.to_js_object();
+ let js = js_sys::Intl::NumberFormat::new(&locales, &options);
+ Self { js }
+ }
+ /// Corresponds to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format
+ pub fn format(&self, number: T) -> String
+ where
+ T: Into,
+ {
+ let number: f64 = number.into();
+ self.js
+ .format()
+ .call1(&self.js, &number.into())
+ .unwrap()
+ .as_string()
+ .unwrap()
+ }
+}
+
+/// Corresponds to the options in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
+// TODO: add all options here.
+#[derive(Clone, Default)]
+pub struct Options {
+ pub style: Option