-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #144 from Baptistemontan/reduce_icu
Reduce ICU4X footprint
- Loading branch information
Showing
67 changed files
with
1,849 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
# ICU4X Datagen | ||
|
||
This library use ICU4X as a backend for formatters and plurals, and the default baked data provider can take quite a lot of space as it contains informations for _every possible locale_. So if you use only a few this is a complete waste. | ||
|
||
## Disable compiled data | ||
|
||
The first step to remove those excess informations is to disable the default data provider, it is activated by the `"icu_compiled_data"` feature that is enabled by default. So turn off default features or remove this feature. | ||
|
||
## Custom provider | ||
|
||
Great we lost a lot of size, but now instead of having too much informations we have 0 informations. You will now need to bring your own data provider. For that you will need multiple things. | ||
|
||
## 1. Datagen | ||
|
||
First generate the informations, you can use [`icu_datagen`](https://docs.rs/icu_datagen/latest/icu_datagen/) for that, either as a CLI of with a build.rs (we will come back to it later). | ||
|
||
## 2. Load | ||
|
||
Then you need to load those informations, this is as simple as | ||
|
||
```rust | ||
include!(concat!(env!("OUT_DIR"), "/baked_data/mod.rs")); | ||
|
||
pub struct MyDataProvider; | ||
impl_data_provider!(MyDataProvider); | ||
``` | ||
|
||
This is explained in the `icu_datagen` doc | ||
|
||
## 3. Supply to leptos_i18n the provider | ||
|
||
You now just need to tell `leptos_i18n` what provider to use, for that you first need to impl `IcuDataProvider` for you provider, you can do it manually as it is straight forward, but the lib comes with a derive macro: | ||
|
||
```rust | ||
include!(concat!(env!("OUT_DIR"), "/baked_data/mod.rs")); | ||
|
||
#[derive(leptos_i18n::custom_provider::IcuDataProvider)] | ||
pub struct MyDataProvider; | ||
impl_data_provider!(MyDataProvider); | ||
``` | ||
|
||
And then pass it to the `set_icu_data_provider` function when the program start, | ||
so for CSR apps in the main function: | ||
|
||
```rust | ||
fn main() { | ||
leptos_i18n::custom_provider::set_icu_data_provider(MyDataProvider); | ||
console_error_panic_hook::set_once(); | ||
leptos::mount::mount_to_body(|| leptos::view! { <App /> }) | ||
} | ||
``` | ||
|
||
and for SSR apps in both on hydrate and on server startup: | ||
|
||
```rust | ||
#[wasm_bindgen::prelude::wasm_bindgen] | ||
pub fn hydrate() { | ||
leptos_i18n::custom_provider::set_icu_data_provider(MyDataProvider); | ||
console_error_panic_hook::set_once(); | ||
leptos::mount::hydrate_body(App); | ||
} | ||
``` | ||
|
||
```rust | ||
// example for actix | ||
#[actix_web::main] | ||
async fn main() -> std::io::Result<()> { | ||
leptos_i18n::custom_provider::set_icu_data_provider(MyDataProvider); | ||
// .. | ||
} | ||
``` | ||
|
||
## Build.rs datagen | ||
|
||
The doc for ICU4X datagen can be quite intimidating, but it is actually quite straight forward. Your build.rs can look like this: | ||
|
||
```rust | ||
use icu_datagen::baked_exporter::*; | ||
use icu_datagen::prelude::*; | ||
use std::path::PathBuf; | ||
|
||
fn main() { | ||
println!("cargo:rerun-if-changed=build.rs"); | ||
|
||
let mod_directory = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()).join("baked_data"); | ||
|
||
let exporter = BakedExporter::new(mod_directory, Default::default()).unwrap(); | ||
|
||
DatagenDriver::new() | ||
// Keys needed for plurals | ||
.with_keys(icu_datagen::keys(&[ | ||
"plurals/cardinal@1", | ||
"plurals/ordinal@1", | ||
])) | ||
// Used locales, no fallback needed | ||
.with_locales_no_fallback([langid!("en"), langid!("fr")], Default::default()) | ||
.export(&DatagenProvider::new_latest_tested(), exporter) | ||
.unwrap(); | ||
} | ||
``` | ||
|
||
Here we are generating the informations for locales `"en"` and `"fr"`, with the data needed for plurals. | ||
|
||
## Is it worth the trouble ? | ||
|
||
YES. With `opt-level = "z"` and `lto = true`, the plurals example is at 394ko (at the time of writing), now by just providing a custom provider tailored to the used locales ("en" and "fr"), it shrinks down to 248ko! It almost cutted in half the binary size! | ||
I highly suggest to take the time to implement this. | ||
|
||
## Example | ||
|
||
You can take a look at the `counter_icu_datagen` example, this is a copy of the `counter_plurals` example but with a custom provider. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# How To Reduce Binary Size | ||
|
||
This chapter is about the few options you have to reduce the binary footprint of this library, other than compiler options such as `opt-level = "z"` and other things that are common for every builds. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Cargo.lock | ||
target | ||
dist | ||
!.vscode | ||
node_modules/ | ||
/test-results/ | ||
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"recommendations": [ | ||
"lokalise.i18n-ally", | ||
] | ||
} |
10 changes: 10 additions & 0 deletions
10
examples/csr/counter_icu_datagen/.vscode/i18n-ally-custom-framework.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
languageIds: | ||
- rust | ||
|
||
usageMatchRegex: | ||
- "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" | ||
- "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" | ||
- "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" | ||
- "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" | ||
|
||
monopoly: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"i18n-ally.keystyle": "nested", | ||
"i18n-ally.localesPaths": "locales", | ||
"rust-analyzer.cargo.buildScripts.enable": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[package] | ||
name = "counter_icu_datagen" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
leptos = { version = "0.7.0-gamma2", features = ["csr"] } | ||
leptos_meta = { version = "0.7.0-gamma2" } | ||
leptos_i18n = { path = "../../../leptos_i18n", default-features = false, features = [ | ||
"json_files", | ||
"csr", | ||
"plurals", | ||
] } | ||
serde = { version = "1", features = ["derive"] } | ||
console_error_panic_hook = { version = "0.1" } | ||
wasm-bindgen = { version = "0.2" } | ||
|
||
icu = { version = "1.5", default-features = false } # turn off compiled_data | ||
icu_provider = "1.5" # for databake | ||
zerovec = "0.10" # for databake | ||
|
||
[package.metadata.leptos-i18n] | ||
default = "en" | ||
locales = ["en", "fr"] | ||
|
||
[build-dependencies] | ||
icu = "1.5" | ||
icu_datagen = "1.5" | ||
|
||
[profile.release] | ||
opt-level = "z" | ||
lto = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Counter Plurals Example | ||
|
||
This example showcase how you can use plurals to display a different text based on a count. | ||
|
||
## How to run | ||
|
||
Simply use `trunk` to run it: | ||
|
||
```bash | ||
trunk serve --open | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use icu_datagen::baked_exporter::*; | ||
use icu_datagen::prelude::*; | ||
use std::path::PathBuf; | ||
|
||
fn main() { | ||
println!("cargo:rerun-if-changed=build.rs"); | ||
|
||
let mod_directory = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()).join("baked_data"); | ||
|
||
// This is'nt really needed, but ICU4X wants the directory to be empty | ||
// and Rust Analyzer can trigger the build.rs without cleaning the out directory. | ||
if mod_directory.exists() { | ||
std::fs::remove_dir_all(&mod_directory).unwrap(); | ||
} | ||
|
||
let exporter = BakedExporter::new(mod_directory, Default::default()).unwrap(); | ||
|
||
DatagenDriver::new() | ||
// Keys needed for plurals | ||
.with_keys(icu_datagen::keys(&[ | ||
"plurals/cardinal@1", | ||
"plurals/ordinal@1", | ||
])) | ||
// Used locales, no fallback needed | ||
.with_locales_no_fallback([langid!("en"), langid!("fr")], Default::default()) | ||
.export(&DatagenProvider::new_latest_tested(), exporter) | ||
.unwrap(); | ||
} |
Oops, something went wrong.