impl IntoView {
- **Actix Web integration**: `actix`
- **Axum integration**: `axum`
- **Nightly toolchain**: `nightly`
+- **Desktop applications**: `system`
- **JSON languages file**: `json` (enabled by default)
- **YAML languages file**: `yaml`
- **JSON5 languages file**: `json5`
@@ -240,7 +254,7 @@ fn LanguageSelector() -> impl IntoView {
[leptos]: https://leptos.dev/
[fluent-templates]: https://github.com/XAMPPRocky/fluent-templates
-[quickstart]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.leptos_fluent.html
+[quickstart]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
[examples]: https://github.com/mondeja/leptos-fluent/tree/master/examples
[book]: https://mondeja.github.io/leptos-fluent/
[documentation]: https://docs.rs/leptos-fluent
diff --git a/book/book.toml b/book/book.toml
index ceb0d64e..27c33f0c 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -17,7 +17,23 @@ build-dir = "dist"
site-url = "/leptos-fluent/"
git-repository-url = "https://github.com/mondeja/leptos-fluent/tree/master/book"
edit-url-template = "https://github.com/mondeja/leptos-fluent/edit/master/book/{path}"
+additional-css = ["./mdbook-admonish.css"]
[output.html.playground]
editable = true
line-numbers = true
+
+[preprocessor.admonish]
+on_failure = "bail"
+command = "mdbook-admonish"
+assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
+
+[preprocessor.admonish.default]
+collapsible = false
+
+[preprocessor.admonish.renderer.test]
+render_mode = "strip"
+
+[preprocessor.toc]
+command = "mdbook-toc"
+renderer = ["html"]
diff --git a/book/mdbook-admonish.css b/book/mdbook-admonish.css
new file mode 100644
index 00000000..960b806c
--- /dev/null
+++ b/book/mdbook-admonish.css
@@ -0,0 +1,373 @@
+@charset "UTF-8";
+:is(.admonition) {
+ display: flow-root;
+ margin: 1.5625em 0;
+ padding: 0 1.2rem;
+ color: var(--fg);
+ page-break-inside: avoid;
+ background-color: var(--bg);
+ border: 0 solid black;
+ border-inline-start-width: 0.4rem;
+ border-radius: 0.2rem;
+ box-shadow:
+ 0 0.2rem 1rem rgba(0, 0, 0, 0.05),
+ 0 0 0.1rem rgba(0, 0, 0, 0.1);
+}
+@media print {
+ :is(.admonition) {
+ box-shadow: none;
+ }
+}
+:is(.admonition) > * {
+ box-sizing: border-box;
+}
+:is(.admonition) :is(.admonition) {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+:is(.admonition) > .tabbed-set:only-child {
+ margin-top: 0;
+}
+html :is(.admonition) > :last-child {
+ margin-bottom: 1.2rem;
+}
+
+a.admonition-anchor-link {
+ display: none;
+ position: absolute;
+ left: -1.2rem;
+ padding-right: 1rem;
+}
+a.admonition-anchor-link:link,
+a.admonition-anchor-link:visited {
+ color: var(--fg);
+}
+a.admonition-anchor-link:link:hover,
+a.admonition-anchor-link:visited:hover {
+ text-decoration: none;
+}
+a.admonition-anchor-link::before {
+ content: "§";
+}
+
+:is(.admonition-title, summary.admonition-title) {
+ position: relative;
+ min-height: 4rem;
+ margin-block: 0;
+ margin-inline: -1.6rem -1.2rem;
+ padding-block: 0.8rem;
+ padding-inline: 4.4rem 1.2rem;
+ font-weight: 700;
+ background-color: rgba(68, 138, 255, 0.1);
+ print-color-adjust: exact;
+ -webkit-print-color-adjust: exact;
+ display: flex;
+}
+:is(.admonition-title, summary.admonition-title) p {
+ margin: 0;
+}
+html :is(.admonition-title, summary.admonition-title):last-child {
+ margin-bottom: 0;
+}
+:is(.admonition-title, summary.admonition-title)::before {
+ position: absolute;
+ top: 0.625em;
+ inset-inline-start: 1.6rem;
+ width: 2rem;
+ height: 2rem;
+ background-color: #448aff;
+ print-color-adjust: exact;
+ -webkit-print-color-adjust: exact;
+ mask-image: url('data:image/svg+xml;charset=utf-8,
');
+ -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,
');
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ content: "";
+}
+:is(.admonition-title, summary.admonition-title):hover
+ a.admonition-anchor-link {
+ display: initial;
+}
+
+details.admonition > summary.admonition-title::after {
+ position: absolute;
+ top: 0.625em;
+ inset-inline-end: 1.6rem;
+ height: 2rem;
+ width: 2rem;
+ background-color: currentcolor;
+ mask-image: var(--md-details-icon);
+ -webkit-mask-image: var(--md-details-icon);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ content: "";
+ transform: rotate(0deg);
+ transition: transform 0.25s;
+}
+details[open].admonition > summary.admonition-title::after {
+ transform: rotate(90deg);
+}
+
+:root {
+ --md-details-icon: url("data:image/svg+xml;charset=utf-8,
");
+}
+
+:root {
+ --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,
");
+ --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,
");
+}
+
+:is(.admonition):is(.admonish-note) {
+ border-color: #448aff;
+}
+
+:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(68, 138, 255, 0.1);
+}
+:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #448aff;
+ mask-image: var(--md-admonition-icon--admonish-note);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-note);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
+ border-color: #00b0ff;
+}
+
+:is(.admonish-abstract, .admonish-summary, .admonish-tldr)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 176, 255, 0.1);
+}
+:is(.admonish-abstract, .admonish-summary, .admonish-tldr)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00b0ff;
+ mask-image: var(--md-admonition-icon--admonish-abstract);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-info, .admonish-todo) {
+ border-color: #00b8d4;
+}
+
+:is(.admonish-info, .admonish-todo)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 184, 212, 0.1);
+}
+:is(.admonish-info, .admonish-todo)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00b8d4;
+ mask-image: var(--md-admonition-icon--admonish-info);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-info);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
+ border-color: #00bfa5;
+}
+
+:is(.admonish-tip, .admonish-hint, .admonish-important)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 191, 165, 0.1);
+}
+:is(.admonish-tip, .admonish-hint, .admonish-important)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00bfa5;
+ mask-image: var(--md-admonition-icon--admonish-tip);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-tip);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
+ border-color: #00c853;
+}
+
+:is(.admonish-success, .admonish-check, .admonish-done)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(0, 200, 83, 0.1);
+}
+:is(.admonish-success, .admonish-check, .admonish-done)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #00c853;
+ mask-image: var(--md-admonition-icon--admonish-success);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-success);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
+ border-color: #64dd17;
+}
+
+:is(.admonish-question, .admonish-help, .admonish-faq)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(100, 221, 23, 0.1);
+}
+:is(.admonish-question, .admonish-help, .admonish-faq)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #64dd17;
+ mask-image: var(--md-admonition-icon--admonish-question);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-question);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
+ border-color: #ff9100;
+}
+
+:is(.admonish-warning, .admonish-caution, .admonish-attention)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 145, 0, 0.1);
+}
+:is(.admonish-warning, .admonish-caution, .admonish-attention)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff9100;
+ mask-image: var(--md-admonition-icon--admonish-warning);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-warning);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
+ border-color: #ff5252;
+}
+
+:is(.admonish-failure, .admonish-fail, .admonish-missing)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 82, 82, 0.1);
+}
+:is(.admonish-failure, .admonish-fail, .admonish-missing)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff5252;
+ mask-image: var(--md-admonition-icon--admonish-failure);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-failure);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-danger, .admonish-error) {
+ border-color: #ff1744;
+}
+
+:is(.admonish-danger, .admonish-error)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(255, 23, 68, 0.1);
+}
+:is(.admonish-danger, .admonish-error)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #ff1744;
+ mask-image: var(--md-admonition-icon--admonish-danger);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-danger);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-bug) {
+ border-color: #f50057;
+}
+
+:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(245, 0, 87, 0.1);
+}
+:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #f50057;
+ mask-image: var(--md-admonition-icon--admonish-bug);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-bug);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-example) {
+ border-color: #7c4dff;
+}
+
+:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(124, 77, 255, 0.1);
+}
+:is(.admonish-example)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #7c4dff;
+ mask-image: var(--md-admonition-icon--admonish-example);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-example);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+:is(.admonition):is(.admonish-quote, .admonish-cite) {
+ border-color: #9e9e9e;
+}
+
+:is(.admonish-quote, .admonish-cite)
+ > :is(.admonition-title, summary.admonition-title) {
+ background-color: rgba(158, 158, 158, 0.1);
+}
+:is(.admonish-quote, .admonish-cite)
+ > :is(.admonition-title, summary.admonition-title)::before {
+ background-color: #9e9e9e;
+ mask-image: var(--md-admonition-icon--admonish-quote);
+ -webkit-mask-image: var(--md-admonition-icon--admonish-quote);
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-size: contain;
+ -webkit-mask-repeat: no-repeat;
+}
+
+.navy :is(.admonition) {
+ background-color: var(--sidebar-bg);
+}
+
+.ayu :is(.admonition),
+.coal :is(.admonition) {
+ background-color: var(--theme-hover);
+}
+
+.rust :is(.admonition) {
+ background-color: var(--sidebar-bg);
+ color: var(--sidebar-fg);
+}
+.rust .admonition-anchor-link:link,
+.rust .admonition-anchor-link:visited {
+ color: var(--sidebar-fg);
+}
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index f45b768f..d60c465c 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -12,3 +12,7 @@
- [Languages](./languages.md)
- [Checking translations](./checking-translations.md)
- [FAQs](./faqs.md)
+
+# Reference
+
+- [`leptos_fluent!`](./leptos_fluent.md)
diff --git a/book/src/basic-usage.md b/book/src/basic-usage.md
index 80c1e9a3..0adca733 100644
--- a/book/src/basic-usage.md
+++ b/book/src/basic-usage.md
@@ -1,5 +1,9 @@
# Basic usage
+
+
+## Minimal skeleton
+
The most basic CSR app is reproduced here:
```plaintext
@@ -134,16 +138,16 @@ move_tr!("language-selected-is", { "lang" => i18n.language.get().name })
Additionally, you can use the [`tr!`] macro to translate a string inside
a reactive context. Note that if you're not inside a reactive context,
the translation won't be updated on the fly when the language changes.
-This can lead to errors in console output like:
+This can lead to warnings in console output like:
-```text
-At
.rs:ln, you access a signal or memo (defined at .rs:ln)
-outside of a reactive context. This might mean your app is not responding
-to changes in signal values in the way you expect.
+```admonish warning
+At `./path/to/file.rs:ln`, you access a signal or memo (defined at
+`./path/to/file.rs:ln`) outside of a reactive context. This might mean your
+app is not responding to changes in signal values in the way you expect.
```
-Can be fixed by replacing calls to `tr!` with `move_tr!` or wrapping the
-`tr!` calls in a reactive context.
+Can be fixed by replacing calls to [`tr!`] with [`move_tr!`] or wrapping the
+[`tr!`] calls in a reactive context.
The previous code _could_ be rewritten as:
@@ -153,8 +157,8 @@ move || tr!("select-a-language")
move || tr!("language-selected-is", { "lang" => i18n.language.get().name })
```
-The main difference is that `move_tr!` encapsulates the movement in a
-`leptos::Signal` (wich is copyable), strictly would be rewritten as:
+The main difference is that [`move_tr!`] encapsulates the movement in a
+[`leptos::Signal`], strictly would be rewritten as:
```rust
leptos::Signal::derive(move || tr!("select-a-language"))
@@ -168,14 +172,13 @@ Use the [`expect_i18n`] function to get the current i18n context:
let i18n = leptos_fluent::expect_i18n();
```
-It is exported as `i18n()` too:
+It is exported as [`i18n`] too:
```rust
let i18n = leptos_fluent::i18n();
```
-With the function `use_i18n()` context you'll get an `Option` with the current
-i18n context:
+The function [`use_i18n`] returns an `Option` with the current i18n context:
```rust
let i18n = leptos_fluent::use_i18n().expect("No `leptos_fluent::I18n` context found");
@@ -192,32 +195,35 @@ The i18n context has the following fields:
### Update language
-To update the language, use `set` method of `language` field or just
-[`lang.activate()`] (new in v0.1.1):
+To update the language, use [`lang.activate`] or the `set` method of [`language`]:
```rust
-expect_i18n().language.set(lang);
+lang.activate();
-lang.activate(); // New in v0.1.1
+expect_i18n().language.set(lang);
+```
-// features = ["nightly"]
-let i18n = leptos_fluent::expect_i18n();
-i18n(lang);
+```admonish tip title='Nightly'
+When `nightly` feature is enabled, you update it passing a new language to the
+context as a function with `(leptos_fluent::i18n())(lang)`.
```
### Get active language
-To get the current active language, use `get` method of `language` field:
+To get the current active language, use `get` method of [`language`] field:
```rust
i18n.language.get()
+```
-i18n() // features = ["nightly"]
+```admonish tip title='Nightly'
+When `nightly` enabled, you can get the active language with
+`(leptos_fluent::i18n())()`.
```
### Get available languages
-To get the available languages, iterate over the `languages` field:
+To get the available languages, iterate over the [`languages`] field:
```rust
i18n.languages.iter()
@@ -225,7 +231,7 @@ i18n.languages.iter()
### Check if a language is active
-To check if a language is the active one, use `is_active` method of a
+To check if a language is the active one, use [`is_active`] method of a
[`leptos_fluent::Language`] struct:
```rust
@@ -236,9 +242,13 @@ lang.is_active()
[`move_tr!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.move_tr.html
[`leptos_fluent::I18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html
[`leptos_fluent::Language`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.Language.html
-[`lang.activate()`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.Language.html#method.activate
-[`expect_i18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/fn.expect_i18n.html
+[`lang.activate`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.Language.html#method.activate
[`language`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html#structfield.language
[`languages`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html#structfield.languages
[`translations`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html#structfield.translations
[fluent-templates]: https://docs.rs/fluent-templates/latest/fluent_templates
+[`leptos::Signal`]: https://docs.rs/leptos/latest/leptos/struct.Signal.html
+[`expect_i18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/fn.expect_i18n.html
+[`i18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/fn.i18n.html
+[`use_i18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/fn.use_i18n.html
+[`is_active`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.Language.html#method.is_active
diff --git a/book/src/checking-translations.md b/book/src/checking-translations.md
index b81ee02d..f6f824b8 100644
--- a/book/src/checking-translations.md
+++ b/book/src/checking-translations.md
@@ -11,7 +11,6 @@ For single crate projects, it would be something like:
```rust
leptos_fluent! {{
check_translations: "./src/**/*.rs",
- // ...
}}
```
@@ -65,9 +64,11 @@ The mechanism of translations checking needs to know where reside the calls to
This is performed by parsing the source code looking for these macros
invocations.
-This is the main reason why **leptos-fluent** doesn't provide
-ways to translate directly using methods of the [`leptos_fluent::I18n`]
-context, as it would be impossible to extract the translations at compile time.
+```admonish note title='Why macros'
+**leptos-fluent** doesn't provide ways to translate directly using
+[`leptos_fluent::I18n`] context methods, as it would be impossible to extract
+the translations at compile time.
+```
The only limitation for checking translations with glob patterns is that the
[`tr!`] and [`move_tr!`] macros that consume each context must be in
@@ -77,4 +78,4 @@ separation of contexts in the codebase.
[`tr!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.tr.html
[`move_tr!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.move_tr.html
[`leptos_fluent::I18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html
-[`leptos_fluent!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.leptos_fluent.html
+[`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
diff --git a/book/src/faqs.md b/book/src/faqs.md
index 61708a52..da6a9801 100644
--- a/book/src/faqs.md
+++ b/book/src/faqs.md
@@ -2,24 +2,27 @@
# FAQs
+
+
### How to get `unic_langid::LanguageIdentifier` if not installed?
```rust
use fluent_templates::LanguageIdentifier;
```
-`fluent-templates` also depends externally on [`fluent-bundle`] whichs
-provides utilities for parsing the Fluent syntax.
-
-[`fluent-bundle`]: https://docs.rs/fluent-bundle/latest/fluent_bundle/
+```admonish tip
+`fluent-templates` also depends externally on
+[`fluent-bundle`](https://docs.rs/fluent-bundle/latest/fluent_bundle/)
+whichs provides utilities for parsing the Fluent syntax.
+```
### How to get the i18n context at initialization?
```rust
use leptos_fluent::leptos_fluent;
-let i18n = leptos_fluent!{{
- // ... options
+let i18n = leptos_fluent! {{
+ // ...
}};
leptos::logging::log!("i18n context: {i18n:?}");
@@ -33,8 +36,7 @@ Use an expression to set the cookie attributes and will not be validated.
let attrs = "SameSite=Strict; MyCustomAttr=MyCustomValue;";
leptos_fluent! {{
cookie_attrs: attrs,
-
- // ... other options
+ // ...
}}
```
@@ -46,14 +48,16 @@ From fluent-templates `v0.9.5` onwards you can get it from your translations.
let fallback_language = expect_i18n().translations.get()[0].fallback();
```
-### Why examples don't use ` ` component?
+### Why examples don't use [` `] component?
-There are some cases in which the `For` component is not reproducible between
+```admonish bug
+There are some cases in which the [` `] component is not reproducible between
SSR and hydrate modes leading to different renders, so decided to use a
simple vector to not bring confusion to main examples.
+```
-In any case, the ` ` component is secure on CSR contexts and
-`leptos_fluent::Language`s implement `Hash` and `Eq` traits to be
+In any case, the [` `] component is secure on CSR contexts and
+[`leptos_fluent::Language`]s implement `Hash` and `Eq` traits to be
able to be passed directly to `key`s properties trigerring reactivity
depending on the current active language.
@@ -75,7 +79,7 @@ fn render_language(lang: &'static Language) -> impl IntoView { ... }
### How to manage translations on server actions
-The translations reside on the client side, so the `leptos_fluent::I18n`
+The translations reside on the client side, so the [`leptos_fluent::I18n`]
can not be accessed as context on server actions. Pass the translations
as values if the bandwidth is not a problem or use your own statics on
server side.
@@ -122,3 +126,32 @@ fn render_language(lang: &'static Language) -> impl IntoView {
}
}
```
+
+### How to change `` attributes on SSR
+
+Use the component [`leptos_fluent::SsrHtmlTag`]:
+
+```rust
+use leptos::*;
+use leptos_fluent::{leptos_fluent, SsrHtmlTag};
+
+#[component]
+pub fn App() -> impl IntoView {
+ leptos_fluent! {{
+ // ...
+ }};
+
+ view! {
+
+
+ }
+}
+
+#[component]
+fn LanguageSelector() -> impl IntoView { ... }
+```
+
+[` `]: https://docs.rs/leptos/latest/leptos/fn.For.html
+[`leptos_fluent::SsrHtmlTag`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/fn.SsrHtmlTag.html
+[`leptos_fluent::Language`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.Language.html
+[`leptos_fluent::I18n`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html
diff --git a/book/src/install.md b/book/src/install.md
index 50ccafe5..043d187d 100644
--- a/book/src/install.md
+++ b/book/src/install.md
@@ -1,5 +1,7 @@
# Installation
+
+
## CSR
For client side rendering apps you only need to install **leptos-fluent** and
@@ -55,6 +57,51 @@ ssr = [
watch-additional-files = ["locales"]
```
+## Desktop applications
+
+**leptos-fluent** can be installed on non-wasm targets, like desktop
+applications. You need to install **leptos-fluent**, [`fluent-templates`]
+and enable the `system` feature:
+
+```toml
+[dependencies]
+leptos-fluent = { version = "0.1", features = ["system"] }
+fluent-templates = "0.9"
+```
+
+```admonish example
+See the [GTK example](https://github.com/mondeja/leptos-fluent/tree/master/examples/system-gtk).
+```
+
+## Nightly toolchain
+
+**leptos-fluent** builds nightly functionalities by enabling the `nightly`
+feature:
+
+```toml
+[dependencies]
+leptos-fluent = { version = "0.1", features = ["nightly"] }
+fluent-templates = "0.9"
+```
+
+## Language files
+
+By default, **leptos-fluent** supports JSON languages files. If you want to
+use other formats to load your custom languages, you can enable the
+`json5` or `yaml` features:
+
+```toml
+[dependencies]
+fluent-templates = "0.9"
+leptos-fluent = {
+ version = "0.1", features = ["json5"], default-features = false
+}
+```
+
+```admonish tip
+See [**4. Languages**](https://mondeja.github.io/leptos-fluent/languages.html).
+```
+
## Features
- **Server Side Rendering**: `ssr`
@@ -62,9 +109,10 @@ watch-additional-files = ["locales"]
- **Actix Web integration**: `actix`
- **Axum integration**: `axum`
- **Nightly toolchain**: `nightly`
+- **Desktop applications**: `system`
- **JSON languages file**: `json` (enabled by default)
- **YAML languages file**: `yaml`
- **JSON5 languages file**: `json5`
[`fluent-templates`]: https://github.com/XAMPPRocky/fluent-templates
-[`leptos_fluent!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.leptos_fluent.html
+[`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
diff --git a/book/src/languages.md b/book/src/languages.md
index 83197d62..68a645f4 100644
--- a/book/src/languages.md
+++ b/book/src/languages.md
@@ -41,8 +41,10 @@ This standard enforces that an user will always be able to select their
language in their own language, and not in the current language of the
application.
-Note that the order of the languages will be defined based on the alphabetical
+```admonish abstract title='Order'
+The order of the languages will be defined based on the alphabetical
order of their names, not their codes.
+```
## The languages file
@@ -68,13 +70,17 @@ The languages file must expose an array of arrays with the structure:
```json5
[
- // Code, Name, "ltr"/"rtl"/"auto" (optional)
+ // Code, Name, "ltr"/"rtl"/"auto" (optional)
["code", "Language name", "Writing direction"],
]
```
-The order of the languages in [`leptos_fluent::I18n::languages`] will be
-the same as in the file regardless of the alphabetical order of the names.
+```admonish abstract title='Order'
+The order of the languages in
+[`leptos_fluent::I18n::languages`](https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html#structfield.languages)
+will be the same as in the file regardless of the alphabetical order
+of the names.
+```
The first in the languages file will used as the initial of the user when any
other initialization value is discovered. Use the same as the one configured
@@ -122,9 +128,9 @@ Available features for languages file formats are:
- `yaml`: YAML
- `json5`: JSON5
-## Tracking locales files with `cargo leptos`
+## Tracking locales files with [`cargo leptos`]
-Using [`cargo-leptos`] the _locales/_ folder must be manually
+Using [`cargo leptos`] the _locales/_ folder must be manually
configured to be watched:
```toml
@@ -143,6 +149,5 @@ watch-additional-files = ["examples/csr/locales"]
```
[ISO 639-1 code]: https://en.wikipedia.org/wiki/ISO_639-1
-[`leptos_fluent::I18n::languages`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/struct.I18n.html#structfield.languages
-[`cargo-leptos`]: https://github.com/leptos-rs/cargo-leptos
-[`leptos_fluent!`]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.leptos_fluent.html
+[`cargo leptos`]: https://github.com/leptos-rs/cargo-leptos
+[`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
diff --git a/book/src/leptos_fluent.md b/book/src/leptos_fluent.md
new file mode 100644
index 00000000..ad226ecd
--- /dev/null
+++ b/book/src/leptos_fluent.md
@@ -0,0 +1,555 @@
+
+
+# `leptos_fluent!`
+
+The `leptos_fluent!` macro is used to load the translations and set the current
+locale. It is used in the root component of the application.
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+}}
+```
+
+
+
+## Common configurations
+
+### CSR | Local storage from navigator
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+
+ set_language_to_localstorage: true,
+ initial_language_from_localstorage: true,
+ initial_language_from_navigator: true,
+ initial_language_from_navigator_to_localstorage: true,
+ initial_language_from_url_param: true,
+ initial_language_from_url_param_to_localstorage: true,
+}}
+```
+
+### CSR + SSR | Cookie from navigator and header
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+
+ set_language_to_cookie: true,
+ initial_language_from_cookie: true,
+ initial_language_from_navigator: true,
+ initial_language_from_navigator_to_cookie: true,
+ initial_language_from_url_param: true,
+ initial_language_from_url_param_to_cookie: true,
+ initial_language_from_accept_language_header: true,
+}}
+```
+
+
+
+### feat system | Data files on Desktop applications
+
+
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+
+ initial_language_from_system: true,
+ initial_language_from_system_to_data_file: true,
+ initial_language_from_data_file: true,
+ set_language_to_data_file: true,
+ data_file_key: "system-language-example",
+}}
+```
+
+## Parameters
+
+### `translations`
+
+Set the translations to be used in the application. It must be a reference
+to a static array of [`fluent_templates::static_loader!`] instances.
+
+```rust
+use fluent_templates::static_loader;
+use leptos_fluent::leptos_fluent;
+
+static_loader! {
+ pub static TRANSLATIONS = {
+ locales: "./locales",
+ fallback_language: "en",
+ };
+}
+
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
+}}
+```
+
+Must be the same identifier used in the [`fluent_templates::static_loader!`]
+macro, which returns an [`once_cell:sync::Lazy`] variable.
+
+### `locales`
+
+Set the path to the locales directory which contain the Fluent
+files for the translations. Must be relative to the _Cargo.toml_ file, the same
+used in the [`fluent_templates::static_loader!`] macro.
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ // ^^^^^^^^^^^^^^^^^
+ translations: [TRANSLATIONS],
+}}
+```
+
+### `core_locales`
+
+Common locale resources that are shared across all locales.
+Must be relative to the _Cargo.toml_ file, the same
+used in the [`fluent_templates::static_loader!`] macro:
+
+```rust
+static_loader! {
+ pub static TRANSLATIONS = {
+ locales: "./locales",
+ core_locales: "./locales/core",
+ };
+}
+
+leptos_fluent! {{
+ locales: "./locales",
+ core_locales: "./locales/core",
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ translations: [TRANSLATIONS],
+}}
+```
+
+### `languages`
+
+Path to a file containing the list of languages supported by the application.
+Must be relative to the _Cargo.toml_ file.
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ languages: "./locales/languages.json",
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ translations: [TRANSLATIONS],
+}}
+```
+
+```admonish tip
+See [**4. Languages**](https://mondeja.github.io/leptos-fluent/languages.html)
+```
+
+The languages file should contain an array of arrays where each inner array
+contains a language identifier and a language name, respectively, at least.
+
+The language identifier should be a valid language tag, such as `en-US`, `en`,
+`es-ES`, etc. By default, the languages file should be a JSON with a `.json`
+extension because the `json` feature is enabled. For example:
+
+```json
+[
+ ["en-US", "English (United States)"],
+ ["es-ES", "Español (España)"]
+]
+```
+
+You can set `default-features = false` and enable the `yaml` or the `json5` feature
+to be able to use a YAML or JSON5 file. For example:
+
+```yaml
+# locales/languages.yaml
+- - en-US
+ - English (United States)
+- - es-ES
+ - Español (España)
+```
+
+```json5
+// locales/languages.json5
+[
+ ["en-US", "English (United States)"],
+ ["es-ES", "Español (España)"],
+]
+```
+
+You can define a third element in the inner array with the direction of the language,
+to use it in the [`` attribute] (see `sync_html_tag_dir`). For example:
+
+```json
+[
+ ["en-US", "English (United States)", "ltr"],
+ ["es-ES", "Español (España)", "auto"],
+ ["ar", "العربية", "rtl"],
+ ["it", "Italiano"]
+]
+```
+
+### `check_translations`
+
+Check the translations at compile time. It is useful to ensure that all
+translations are correct and that there are no missing translations.
+
+Must be a glob relative to the _Cargo.toml_ file. For single crate projects:
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+ check_translations: "./src/**/*.rs",
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+}}
+```
+
+For workspace projects:
+
+```rust
+leptos_fluent! {{
+ locales: "./locales",
+ translations: [TRANSLATIONS],
+ check_translations: "../{app,components}/src/**/*.rs",
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+}}
+```
+
+### CSR | `sync_html_tag_lang`
+
+Synchronize the global [`` attribute] with current language
+using [`leptos::create_effect`]. Can be a literal boolean or an expression
+that will be evaluated at runtime.
+
+```rust
+leptos_fluent! {{
+ // ...
+ sync_html_tag_lang: true,
+}}
+```
+
+### CSR | `sync_html_tag_dir`
+
+Synchronize the global [`` attribute] with current language
+using [`leptos::create_effect`].
+
+Can be a literal boolean or an expression that will be evaluated at runtime.
+
+```rust
+leptos_fluent! {{
+ // ...
+ sync_html_tag_dir: true,
+}}
+```
+
+For custom languages from a languages file, you can specify a third element in
+the inner array with the direction of the language, which can be `"auto"`,
+`"ltr"`, or `"rtl"`.
+
+For automatic languages will be defined depending on the language. For example,
+Arabic will be `"rtl"`, English will be `"ltr"` and Japanese will be `"auto"`.
+
+### CSR + SSR | `url_param`
+
+Set the name of the URL parameter that will be used to manage the current
+language. By default it is `"lang"`.
+
+```rust
+leptos_fluent! {{
+ // ...
+ url_param: "lang",
+}}
+```
+
+### CSR + SSR | `initial_language_from_url_param`
+
+Set the initial language from the URL parameter.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_url_param: true,
+}}
+```
+
+### CSR | `initial_language_from_url_param_to_localstorage`
+
+Set the initial language from the URL parameter and save it in the local storage.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_url_param_to_localstorage: true,
+}}
+```
+
+### CSR | `initial_language_from_url_param_to_cookie`
+
+Set the initial language from the URL parameter and save it in a cookie.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_url_param_to_cookie: true,
+}}
+```
+
+### CSR | `set_language_to_url_param`
+
+Set the current language to the URL parameter.
+
+```rust
+leptos_fluent! {{
+ // ...
+ set_language_to_url_param: true,
+}}
+```
+
+### CSR | `localstorage_key`
+
+Key to manage the current language in the local storage. By default it is
+`"lang"`.
+
+```rust
+leptos_fluent! {{
+ // ...
+ localstorage_key: "lang",
+}}
+```
+
+### CSR | `initial_language_from_localstorage`
+
+Get the initial language from the local storage.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_localstorage: true,
+}}
+```
+
+### CSR | `initial_language_from_localstorage_to_cookie`
+
+Get the initial language from the local storage and save it in a cookie.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_localstorage_to_cookie: true,
+}}
+```
+
+### CSR | `set_language_to_localstorage`
+
+Set the current language to the local storage.
+
+```rust
+leptos_fluent! {{
+ // ...
+ set_language_to_localstorage: true,
+}}
+```
+
+### CSR | `initial_language_from_navigator`
+
+Get the initial language from [`navigator.languages`].
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_navigator: true,
+}}
+```
+
+### CSR | `initial_language_from_navigator_to_localstorage`
+
+Get the initial language from [`navigator.languages`] and save it in the [local storage].
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_navigator_to_localstorage: true,
+}}
+```
+
+### CSR | `initial_language_from_navigator_to_cookie`
+
+Get the initial language from [`navigator.languages`] and save it in a cookie.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_navigator_to_cookie: true,
+}}
+```
+
+### SSR | `initial_language_from_accept_language_header`
+
+Get the initial language from the [`Accept-Language`] header.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_accept_language_header: true,
+}}
+```
+
+### CSR + SSR | `cookie_name`
+
+Name of the cookie that will be used to manage the current language. By default
+it is `"lf-lang"`.
+
+```rust
+leptos_fluent! {{
+ // ...
+ cookie_name: "lang",
+}}
+```
+
+### CSR | `cookie_attrs`
+
+[Cookie attributes] to set on the language cookie. By default it is `""` (empty).
+
+```rust
+leptos_fluent! {{
+ // ...
+ cookie_attrs: "SameSite=Strict; Secure",
+}}
+```
+
+If the passed value is an expression the cookie will not be validated at
+compile time:
+
+```rust
+let attrs = "SameSite=Strict; Secure; MyCustomCookie=value"
+leptos_fluent! {{
+ // ...
+ cookie_attrs: attrs,
+}}
+```
+
+### CSR + SSR | `initial_language_from_cookie`
+
+Get the initial language from the cookie.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_cookie: true,
+}}
+```
+
+### CSR | `initial_language_from_cookie_to_localstorage`
+
+Get the initial language from the cookie and save it in the [local storage].
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_cookie_to_localstorage: true,
+}}
+```
+
+### CSR | `set_language_to_cookie`
+
+Set the current language to the cookie.
+
+```rust
+leptos_fluent! {{
+ // ...
+ set_language_to_cookie: true,
+}}
+```
+
+
+
+### feat system | `initial_language_from_system`
+
+
+
+Get the initial language from the system.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_system: true,
+}}
+```
+
+
+
+### feat system | `initial_language_from_data_file`
+
+
+
+Get the initial language from a data file.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_data_file: true,
+}}
+```
+
+
+
+### feat system | `initial_language_from_system_to_data_file`
+
+
+
+Get the initial language from the system and save it in a data file.
+
+```rust
+leptos_fluent! {{
+ // ...
+ initial_language_from_system_to_data_file: true,
+}}
+```
+
+
+
+### feat system | `set_language_to_data_file`
+
+
+
+Set the current language to a data file.
+
+```rust
+leptos_fluent! {{
+ // ...
+ set_language_to_data_file: true,
+}}
+```
+
+
+
+### feat system | `data_file_key`
+
+
+
+Key to manage the current language in the data file. It should be unique
+per application. By default it is `"leptos-fluent"`.
+
+```rust
+leptos_fluent! {{
+ // ...
+ data_file_key: "my-app",
+}}
+```
+
+[`fluent_templates::static_loader!`]: https://docs.rs/fluent-templates/latest/fluent_templates/macro.static_loader.html
+[`once_cell:sync::Lazy`]: https://docs.rs/once_cell/latest/once_cell/sync/struct.Lazy.html
+[`` attribute]: https://developer.mozilla.org/es/docs/Web/HTML/Global_attributes/lang
+[`` attribute]: https://developer.mozilla.org/es/docs/Web/HTML/Global_attributes/dir
+[local storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
+[`navigator.languages`]: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
+[`leptos::create_effect`]: https://docs.rs/leptos/latest/leptos/fn.create_effect.html
+[cookie attributes]: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie
+[`Accept-Language`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
diff --git a/book/src/strategies.md b/book/src/strategies.md
index 7ea36974..fed3ebc2 100644
--- a/book/src/strategies.md
+++ b/book/src/strategies.md
@@ -1,21 +1,25 @@
-# Features
+# Strategies
All the features of the framework are optional, following a declarative
"opt-in" configuration method.
+
+
## Loading the initial language of the user
The initial language of the user can be set in different ways:
-| Strategy | CSR | SSR | [`leptos_fluent!`] parameter |
-| :----------------------------------------- | :-: | :-: | :--------------------------------------------- |
-| [URL parameter] | ✅ | ✅ | `initial_language_from_url_param` |
-| [Cookie] | ✅ | ✅ | `initial_language_from_cookie` |
-| Browser [local storage] | ✅ | ❌ | `initial_language_from_localstorage` |
-| Browser language ([`navigator.languages`]) | ✅ | ❌ | `initial_language_from_navigator` |
-| [`Accept-Language`] header | ❌ | ✅ | `initial_language_from_accept_language_header` |
+| Strategy | CSR | SSR | Desktop | [`leptos_fluent!`] |
+| :----------------------------------------- | :-: | :-: | :-----: | :--------------------------------------------- |
+| [URL parameter] | ✅ | ✅ | ❌ | `initial_language_from_url_param` |
+| [Cookie] | ✅ | ✅ | ❌ | `initial_language_from_cookie` |
+| Browser [local storage] | ✅ | ❌ | ❌ | `initial_language_from_localstorage` |
+| Browser language ([`navigator.languages`]) | ✅ | ❌ | ❌ | `initial_language_from_navigator` |
+| [`Accept-Language`] header | ❌ | ✅ | ❌ | `initial_language_from_accept_language_header` |
+| System language | ❌ | ❌ | ✅ | `initial_language_from_system` |
+| Data file | ❌ | ❌ | ✅ | `initial_language_from_data_file` |
All of them can be used at the same time or just one of them. The first setting
found will be used. The order of precedence is:
@@ -29,6 +33,9 @@ found will be used. The order of precedence is:
2. [Cookie].
3. Browser [local storage].
4. Browser language from [`navigator.languages`].
+- **Desktop** ([`system` feature][desktop-applications])
+ 1. Data file.
+ 2. System language.
## Updating the language on the client
@@ -36,19 +43,25 @@ When the user changes the language and `I18n::language.set` is called, the
framework can perform a side effect to update the language in the client. The
following strategies are available:
-| Strategy | [`leptos_fluent!`] parameter |
+| Strategy | [`leptos_fluent!`] |
| :---------------------- | :----------------------------- |
| [URL parameter] | `set_language_to_url_param` |
| [Cookie] | `set_language_to_cookie` |
| Browser [local storage] | `set_language_to_localstorage` |
-### Updating the language from initialization on the client
+### Desktop applications ([`system`][desktop-applications])
+
+| Strategy | [`leptos_fluent!`] |
+| :-------- | :-------------------------- |
+| Data file | `set_language_to_data_file` |
+
+## Updating the language from initialization on the client
When a language is loaded from initialization, the framework can perform a side
effect to persistently storage the language in the client. The following strategies
are available:
-| Strategy | [`leptos_fluent!`] parameter |
+| Strategy | [`leptos_fluent!`] |
| :----------------------------------------- | :------------------------------------------------ |
| [URL parameter] to [local storage] | `initial_language_from_url_param_to_localstorage` |
| [URL parameter] to [cookie] | `initial_language_from_url_param_to_cookie` |
@@ -57,15 +70,21 @@ are available:
| [`navigator.languages`] to [local storage] | `initial_language_from_navigator_to_localstorage` |
| [`navigator.languages`] to [cookie] | `initial_language_from_navigator_to_cookie` |
+### Desktop applications ([`system`][desktop-applications])
+
+| Strategy | [`leptos_fluent!`] |
+| :--------------------------- | :------------------------------------------ |
+| System language to data file | `initial_language_from_system_to_data_file` |
+
## Client side effects
When the user updates the language, the framework can perform side effects to
update the language in the client. The following side effects are available:
-| Side effect | [`leptos_fluent!`] parameter |
-| :------------------------------ | :--------------------------- |
-| [``] attribute | `sync_html_tag_lang` |
-| [``] attribute | `sync_html_tag_dir` |
+| Side effect | [`leptos_fluent!`] |
+| :------------------------------ | :------------------- |
+| [``] attribute | `sync_html_tag_lang` |
+| [``] attribute | `sync_html_tag_dir` |
[``]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang
[``]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir
@@ -74,52 +93,24 @@ update the language in the client. The following side effects are available:
The names of the settings can be configured using the following parameters:
-| Strategy | [`leptos_fluent!`] parameter | Default value |
-| :---------------------- | :--------------------------- | :------------ |
-| [Cookie] | `cookie_name` | `"lf-lang"` |
-| [Cookie attributes] | `cookie_attrs` | `""` |
-| Browser [local storage] | `localstorage_key` | `"lang"` |
-| [URL parameter] | `url_param` | `"lang"` |
+| Strategy | [`leptos_fluent!`] | Default value |
+| :---------------------- | :----------------- | :------------ |
+| [Cookie] | `cookie_name` | `"lf-lang"` |
+| [Cookie attributes] | `cookie_attrs` | `""` |
+| Browser [local storage] | `localstorage_key` | `"lang"` |
+| [URL parameter] | `url_param` | `"lang"` |
+
+### Desktop applications ([`system`][desktop-applications])
-[`leptos_fluent!`]: https://docs.rs/leptos-fluent-macros/latest/leptos_fluent_macros/macro.leptos_fluent.html
+| Strategy | [`leptos_fluent!`] | Default value |
+| :-------- | :----------------- | :---------------- |
+| Data file | `data_file_key` | `"leptos-fluent"` |
+
+[`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
[local storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
[`navigator.languages`]: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
[`Accept-Language`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
[Cookie]: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
[Cookie attributes]: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie
[URL parameter]: https://developer.mozilla.org/es/docs/Web/API/URLSearchParams
-
-# Common configurations
-
-## Local storage from navigator (CSR)
-
-```rust
-leptos_fluent! {{
- locales: "./locales",
- translations: [TRANSLATIONS],
-
- set_language_to_localstorage: true,
- initial_language_from_localstorage: true,
- initial_language_from_navigator: true,
- initial_language_from_navigator_to_localstorage: true,
- initial_language_from_url_param: true,
- initial_language_from_url_param_to_localstorage: true,
-}}
-```
-
-## Cookie from navigator and header (SSR + CSR)
-
-```rust
-leptos_fluent! {{
- locales: "./locales",
- translations: [TRANSLATIONS],
-
- set_language_to_cookie: true,
- initial_language_from_cookie: true,
- initial_language_from_navigator: true,
- initial_language_from_navigator_to_cookie: true,
- initial_language_from_url_param: true,
- initial_language_from_url_param_to_cookie: true,
- initial_language_from_accept_language_header: true,
-}}
-```
+[desktop-applications]: https://mondeja.github.io/leptos-fluent/install.html#desktop-applications
diff --git a/examples/ssr-hydrate-axum/Cargo.toml b/examples/ssr-hydrate-axum/Cargo.toml
index fcdfccc8..d0735065 100644
--- a/examples/ssr-hydrate-axum/Cargo.toml
+++ b/examples/ssr-hydrate-axum/Cargo.toml
@@ -19,16 +19,14 @@ leptos = "0.6"
leptos_meta = "0.6"
leptos_axum = { version = "0.6", optional = true }
leptos_router = "0.6"
-leptos-fluent = { path = "../../leptos-fluent", features = ["yaml"], default-features = false}
+leptos-fluent = { path = "../../leptos-fluent", features = [
+ "yaml"
+], default-features = false }
fluent-templates = "0.9"
wasm-bindgen = "=0.2.92"
[features]
-csr = [
- "leptos/csr",
- "leptos_meta/csr",
- "leptos_router/csr",
-]
+csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = [
"leptos/hydrate",
"leptos_meta/hydrate",
@@ -77,9 +75,4 @@ lib-features = ["hydrate"]
lib-profile-release = "wasm-release"
[package.metadata.cargo-all-features]
-skip_feature_sets = [
- [],
- ["csr", "ssr"],
- ["csr", "hydrate"],
- ["ssr", "hydrate"],
-]
+skip_feature_sets = [[], ["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
diff --git a/examples/system-gtk/README.md b/examples/system-gtk/README.md
index 0ec58549..f61688e0 100644
--- a/examples/system-gtk/README.md
+++ b/examples/system-gtk/README.md
@@ -9,6 +9,6 @@ sudo apt install libgtk-4-dev
## Build and run
```sh
-cd examples/gtk
+cd examples/system-gtk
cargo run
```
diff --git a/examples/system-gtk/src/main.rs b/examples/system-gtk/src/main.rs
index 16ce6c51..6c80bbf5 100644
--- a/examples/system-gtk/src/main.rs
+++ b/examples/system-gtk/src/main.rs
@@ -25,11 +25,11 @@ fn main() {
translations: [TRANSLATIONS],
locales: "./locales",
check_translations: "./src/**/*.rs",
- initial_language_from_system: true,
- set_language_to_data_file: true,
initial_language_from_data_file: true,
- data_file_key: "gtk-example",
+ initial_language_from_system: true,
initial_language_from_system_to_data_file: true,
+ set_language_to_data_file: true,
+ data_file_key: "leptos-fluent-gtk-example",
}};
// Run the application
diff --git a/leptos-fluent-macros/src/files_tracker.rs b/leptos-fluent-macros/src/files_tracker.rs
index 52af011b..95abcb8b 100644
--- a/leptos-fluent-macros/src/files_tracker.rs
+++ b/leptos-fluent-macros/src/files_tracker.rs
@@ -5,35 +5,58 @@ pub(crate) fn build_files_tracker_quote(
languages_path: &Option,
core_locales_path: &Option,
) -> proc_macro2::TokenStream {
- let mut files_tracker_str = "{".to_string();
- for (lang, paths) in fluent_resources {
- for (i, path) in paths.iter().enumerate() {
+ #[cfg(feature = "nightly")]
+ {
+ for (_, paths) in fluent_resources {
+ for path in paths {
+ proc_macro::tracked_path::path(path);
+ }
+ }
+
+ if let Some(languages_file_path) = &languages_path {
+ proc_macro::tracked_path::path(languages_file_path);
+ }
+
+ if let Some(core_locales_file_path) = &core_locales_path {
+ proc_macro::tracked_path::path(core_locales_file_path);
+ }
+
+ "".parse::().unwrap()
+ }
+
+ #[cfg(not(feature = "nightly"))]
+ {
+ let mut files_tracker_str = "{".to_string();
+ for (lang, paths) in fluent_resources {
+ for (i, path) in paths.iter().enumerate() {
+ files_tracker_str.push_str(&format!(
+ "let s{}{} = include_bytes!(\"{}\");",
+ lang.replace('-', "_"),
+ i,
+ &escape_string(path)
+ ));
+ }
+ }
+ if let Some(languages_file_path) = &languages_path {
files_tracker_str.push_str(&format!(
- "let s{}{} = include_bytes!(\"{}\");",
- lang.replace('-', "_"),
- i,
- &escape_string(path)
+ "let languages = include_bytes!(\"{}\");",
+ &escape_string(languages_file_path)
));
}
+ if let Some(core_locales_file_path) = &core_locales_path {
+ files_tracker_str.push_str(&format!(
+ "let core_locales = include_bytes!(\"{}\");",
+ &escape_string(core_locales_file_path)
+ ));
+ }
+ files_tracker_str.push_str("};");
+ files_tracker_str
+ .parse::()
+ .unwrap()
}
- if let Some(languages_file_path) = &languages_path {
- files_tracker_str.push_str(&format!(
- "let languages = include_bytes!(\"{}\");",
- &escape_string(languages_file_path)
- ));
- }
- if let Some(core_locales_file_path) = &core_locales_path {
- files_tracker_str.push_str(&format!(
- "let core_locales = include_bytes!(\"{}\");",
- &escape_string(core_locales_file_path)
- ));
- }
- files_tracker_str.push_str("};");
- files_tracker_str
- .parse::()
- .unwrap()
}
+#[cfg(not(feature = "nightly"))]
fn escape_string(s: &str) -> String {
s.replace('"', "\\\"")
// Windows path separator
diff --git a/leptos-fluent-macros/src/languages.rs b/leptos-fluent-macros/src/languages.rs
index 80867ab5..8466d395 100644
--- a/leptos-fluent-macros/src/languages.rs
+++ b/leptos-fluent-macros/src/languages.rs
@@ -459,6 +459,8 @@ fn language_name_from_language_code(
if use_country_code {
let c = code.to_string().to_lowercase().replace('_', "-");
match c.as_str() {
+ // lang (3 letter) -> number
+ "jbo-001" => return "Lojban (World)",
// lang (2 letter) -> country (2 letter)
"af-na" => return "Afrikaans (Namibia)",
"af-za" => return "Afrikaans (South Africa)",
@@ -499,8 +501,8 @@ fn language_name_from_language_code(
"bm-ml" => return "ߓߊߡߊߣߊߣߞߊߣ (ߞߊ߲ߞߊ߲)",
"bn-bd" => return "বাংলা (বাংলাদেশ)",
"bn-in" => return "বাংলা (ভারত)",
- "bo-cn" => return "བོད་སྐད་ (ཀྲུང་ཧྭ)",
- "bo-in" => return "བོད་སྐད་ (ཀྲུང་ཧྭ)", // TODO: The same as bo-cn, looks bad
+ "bo-cn" => return "བོད་སྐད་ (རྒྱ་ནག)",
+ "bo-in" => return "བོད་སྐད་ (ི་ཝི)",
"br-fr" => return "Brezhoneg (Frañs)",
"bs-ba" => return "Bosanski (Bosna i Hercegovina)",
"ca-ad" => return "Català (Andorra)",
@@ -821,7 +823,7 @@ fn language_name_from_language_code(
"it-va" => return "Italiano (Città del Vaticano)",
"iu-ca" => return "ᐃᓄᒃᑎᑐᑦ (Canada)",
"ja-jp" => return "日本語 (日本)",
- "jv-id" => return "Basa Jawa (Indonesia)", // TODO: check this
+ "jv-id" => return "ꦧꦱꦗꦮ (Indonesia)", // TODO: check this
"ka-ge" => return "ქართული (საქართველო)",
"ki-ke" => return "Gĩkũyũ (Kenya)",
"kk-kz" => return "Қазақ тілі (Қазақстан)",
@@ -831,7 +833,7 @@ fn language_name_from_language_code(
"ko-kp" => return "한국어(북한)",
"ks-in" => return "कश्मीरी (भारत)",
"ku-tr" => return "Kurdî (Tirkiye)",
- "kw-gb" => return "Cornish (United Kingdom)", // TODO: check this
+ "kw-gb" => return "Cornish (United Kingdom)",
"ky-kg" => return "Кыргызстандык (Кыргызстан)",
"lb-lu" => return "Lëtzebuergesch (Lëtzebuerg)",
"lg-ug" => return "Luganda (Yuganda)", // TODO: check this
@@ -868,7 +870,7 @@ fn language_name_from_language_code(
"nn-no" => return "Norsk nynorsk (Noreg)",
"nr-za" => return "isiNdebele (South Africa)",
"ny-mw" => return "Chichewa (Malawi)",
- "oc-fr" => return "Occitan (France)", // TODO: Check this
+ "oc-fr" => return "Occitan (France)",
"os-ge" => return "Ирон æвзаг (Росси)",
"om-et" => return "Afaan Oromoo (Itoophiyaa)",
"om-ke" => return "Afaan Oromoo (Keeniyaa)",
@@ -1013,8 +1015,8 @@ fn language_name_from_language_code(
"bm-mli" => return "ߓߊߡߊߣߊߣߞߊߣ (ߞߊ߲ߞߊ߲)",
"bn-bgd" => return "বাংলা (বাংলাদেশ)",
"bn-ind" => return "বাংলা (ভারত)",
- "bo-chn" => return "བོད་སྐད་ (ཀྲུང་ཧྭ)",
- "bo-ind" => return "བོད་སྐད་ (ཀྲུང་ཧྭ)", // TODO: The same as bo-cn, looks bad
+ "bo-chn" => return "བོད་སྐད་ (རྒྱ་ནག)",
+ "bo-ind" => return "བོད་སྐད་ (ི་ཝི)",
"br-fra" => return "Brezhoneg (Frañs)",
"bs-bih" => return "Bosanski (Bosna i Hercegovina)",
"ca-and" => return "Català (Andorra)",
@@ -1343,7 +1345,7 @@ fn language_name_from_language_code(
"io-001" => return "Ido",
"iu-can" => return "ᐃᓄᒃᑎᑐᑦ (Canada)",
"ja-jpn" => return "日本語 (日本)",
- "jv-idn" => return "Basa Jawa (Indonesia)", // TODO: check this
+ "jv-idn" => return "ꦧꦱꦗꦮ (Indonesia)", // TODO: check this
"ka-geo" => return "ქართული (საქართველო)",
"ki-ken" => return "Gĩkũyũ (Kenya)",
"kk-kaz" => return "Қазақ тілі (Қазақстан)",
@@ -1353,7 +1355,7 @@ fn language_name_from_language_code(
"ko-prk" => return "한국어(북한)",
"ks-ind" => return "कश्मीरी (भारत)",
"ku-tur" => return "Kurdî (Tirkiye)",
- "kw-gbr" => return "Cornish (United Kingdom)", // TODO: check this
+ "kw-gbr" => return "Cornish (United Kingdom)",
"ky-kgz" => return "Кыргызстандык (Кыргызстан)",
"lb-lux" => return "Lëtzebuergesch (Lëtzebuerg)",
"lg-uga" => return "Luganda (Yuganda)", // TODO: check this
@@ -1390,7 +1392,7 @@ fn language_name_from_language_code(
"nn-nor" => return "Norsk nynorsk (Noreg)",
"nr-zaf" => return "isiNdebele (South Africa)",
"ny-mwi" => return "Chichewa (Malawi)",
- "oc-fra" => return "Occitan (France)", // TODO: Check this
+ "oc-fra" => return "Occitan (France)",
"om-eth" => return "Afaan Oromoo (Itoophiyaa)",
"om-ken" => return "Afaan Oromoo (Keeniyaa)",
"or-ind" => return "ଓଡ଼ିଆ (ଭାରତ)",
@@ -1501,119 +1503,218 @@ fn language_name_from_language_code(
// Chakma language, an Indo-Aryan language spoken in Bangladesh
// TODO: How is written "Bangladesh" in Chakma language?
"cpp-bd" => return "𑄌𑄋𑄴𑄟𑄳𑄦 𑄞𑄌𑄴 (Bangladesh)",
+ "agq-CM" => return "Aghem (Cameroon)",
+ "ksf-CM" => return "Bafia (Cameroon)",
+ "bas-CM" => return "Ɓasaá (Cameroon)",
+ "dua-CM" => return "Duala (Cameroon)",
+ "ewo-CM" => return "Ewondo (Cameroon)",
+ "kkj-CM" => return "Kako (Cameroon)",
+ "nmg-CM" => return "Kwasio (Cameroon)",
+ "mgo-CM" => return "Metaʼ (Cameroon)",
+ "mua-CM" => return "Mundang (Cameroon)",
+ "nnh-CM" => return "Ngiemboon (Cameroon)",
+ "jgo-CM" => return "Ngomba (Cameroon)",
+ "yav-CM" => return "Yɔɔŋmbɔ (Cameroon)",
+ "moh-CA" => return "Mohawk (Canada)",
+ "kea-CV" => return "Kabuverdianu (Cabo Verde)",
+ "arn-CL" => return "Mapudungun (Chile)",
+ "yue-CN" => return "粤语 (中国)",
+ "byn-ER" => return "Blin (Eritrea)",
+ "gez-ER" => return "ግዕዝ (ኤርትራ)",
+ "tig-ER" => return "Tigre (Eritrea)",
+ "gez-ET" => return "ግዕዝ (ኤርትራ)",
+ "wal-ET" => return "Wolaytta (Ethiopia)",
+ "smn-FI" => return "anarâškielâ (Suopma)",
+ "gsw-FR" => return "Elsässisch (Frankreich)",
+ "ksh-DE" => return "Kölsch (Deutschland)",
+ "nds-DE" => return "Plattdüütsch (Deutschland)",
+ "dsb-DE" => return "Niedersorbisch (Deutschland)",
+ "hsb-DE" => return "Hornjoserbšćina (Němska)",
+ "gaa-GH" => return "Ga (Ghana)",
+ "kpe-GN" => return "Kpelle (Guinea)",
+ "nqo-GN" => return "N'Ko (Guinea)",
+ "yue-HK" => return "粤语 (中国)",
+ "brx-IN" => return "बोड़ो (भारत)",
+ "ccp-IN" => return "बोड़ो (भारत)", // TODO: same as brx-IN
+ "kok-IN" => return "कोंकणी (भारत)",
+ "mni-IN" => return "Manipuri (India)",
+ "sat-IN" => return "Santali (India)",
+ "ckb-IR" => return "کوردی (ایران)",
+ "mzn-IR" => return "مازِرونی (ایران)",
+ "lrc-IR" => return "لۊری شومالی (ایران)",
+ "ckb-IQ" => return "کوردی (ایران)",
+ "lrc-IQ" => return "لۊری شومالی (ایران)",
+ "syr-IQ" => return "ܣܘܪܝܝܐ (ܩܕܝܫܐ)",
+ "fur-IT" => return "Friulian (Italy)", // TODO: check
+ "scn-IT" => return "Sicilian (Italy)", // TODO: check
+ "ebu-KE" => return "Kĩembu (Kenya)",
+ "guz-KE" => return "Ekegusii (Kenya)",
+ "kln-KE" => return "Kalenjin (Kenya)",
+ "kam-KE" => return "Kikamba (Kenya)",
+ "luo-KE" => return "Dholuo (Kenya)",
+ "luy-KE" => return "Luyia (Kenya)",
+ "mas-KE" => return "Maa (Kenya)",
+ "mer-KE" => return "Kĩmĩrũ (Kenya)",
+ "saq-KE" => return "Kisampur (Kenya)",
+ "dav-KE" => return "Kitaita (Kenya)",
+ "teo-KE" => return "Kiteso (Kenya)",
+ "kpe-LR" => return "Kpelle (Liberia)",
+ "vai-LR" => return "ꕙꔤ (ꕞꔤꔫꕩ)",
+ "gsw-LI" => return "Elsässisch (Liechtenstein)",
+ "khq-ML" => return "Koyra ciini (Maali)",
+ "ses-ML" => return "Koyraboro senni (Maali)",
+ "mfe-MU" => return "kreol morisien (Moris)",
+ "tzm-MA" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "zgh-MA" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "shi-MA" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "mgh-MZ" => return "Makua (Moçambique)",
+ "seh-MZ" => return "sena (Moçambique)",
+ "naq-NA" => return "Khoekhoegowab (Namibiab)",
+ "nds-NL" => return "Plattdüütsch (Nederland)",
+ "twq-NE" => return "Tasawaq senni (Nižer)",
+ "dje-NE" => return "Zarmaciine (Nižer)",
+ "kaj-NG" => return "Kaje (Najeriya)",
+ "kcg-NG" => return "Tyap (Najeriya)",
+ "ceb-PH" => return "Cebuano (Pilipinas)",
+ "fil-PH" => return "Filipino (Pilipinas)",
+ "myv-RU" => return "эрзянь (Россия)",
+ "sah-RU" => return "саха тыла (Россия)",
+ "dyo-SN" => return "joola (Senegal)",
+ "nso-ZA" => return "Sesotho sa Leboa (Afrika Borwa)",
+ "nus-SS" => return "Thok Nath (SS)",
+ "ast-ES" => return "asturianu (España)",
+ "gsw-CH" => return "Elsässisch (Schweiz)",
+ "wae-CH" => return "Walser (Schweiz)",
+ "syr-SY" => return "ܣܘܪܝܝܐ (ܣܘܪܝܐ)",
+ "trv-TW" => return "Sakizaya (Taiwan)",
+ "asa-TZ" => return "Kipare (Tanzania)",
+ "bez-TZ" => return "Hibena (Tanzania)",
+ "lag-TZ" => return "Kɨlaangi (Tanzania)",
+ "jmc-TZ" => return "Kimachame (Tanzania)",
+ "kde-TZ" => return "Chimakonde (Tanzania)",
+ "mas-TZ" => return "Maa (Tanzania)",
+ "rof-TZ" => return "Kihorombo (Tanzania)",
+ "rwk-TZ" => return "Kiruwa (Tanzania)",
+ "sbp-TZ" => return "Ishisangu (Tanzania)",
+ "ksb-TZ" => return "Kishambaa (Tanzania)",
+ "vun-TZ" => return "Kyuk (Tanzania)",
+ "cgg-UG" => return "Rukiga (Uganda)",
+ "nyn-UG" => return "Runyankore (Uganda)",
+ "xog-UG" => return "Olusoga (Uganda)",
+ "teo-UG" => return "Kiteso (Uganda)",
+ "chr-US" => return "ᏣᎳᎩ (ᎠᎹᏂᏟ)",
+ "haw-US" => return "ʻŌlelo Hawaiʻi (ʻAmelika Hui Pū ʻIa)",
+ "lkt-US" => return "Lakȟólʼiyapi (Mílahaŋska Tȟamákȟočhe)",
+ "bem-ZM" => return "Ichibemba (Zambia)",
// lang (3 letter) -> country (3 letter)
"kab-dza" => return "θɐqβæjlɪθ (Asenǧaq n Dzayer)",
"cpp-bgd" => return "𑄌𑄋𑄴𑄟𑄳𑄦 𑄞𑄌𑄴 (Bangladesh)",
+ "agq-CMR" => return "Aghem (Cameroon)",
+ "ksf-CMR" => return "Bafia (Cameroon)",
+ "bas-CMR" => return "Ɓasaá (Cameroon)",
+ "dua-CMR" => return "Duala (Cameroon)",
+ "ewo-CMR" => return "Ewondo (Cameroon)",
+ "kkj-CMR" => return "Kako (Cameroon)",
+ "nmg-CMR" => return "Kwasio (Cameroon)",
+ "mgo-CMR" => return "Metaʼ (Cameroon)",
+ "mua-CMR" => return "Mundang (Cameroon)",
+ "nnh-CMR" => return "Ngiemboon (Cameroon)",
+ "jgo-CMR" => return "Ngomba (Cameroon)",
+ "yav-CMR" => return "Yɔɔŋmbɔ (Cameroon)",
+ "moh-CAN" => return "Mohawk (Canada)",
+ "kea-CPV" => return "Kabuverdianu (Cabo Verde)",
+ "arn-CHL" => return "Mapudungun (Chile)",
+ "yue-CHN" => return "粤语 (中国)",
+ "byn-ERI" => return "Blin (Eritrea)",
+ "gez-ERI" => return "ግዕዝ (ኤርትራ)",
+ "tig-ERI" => return "Tigre (Eritrea)",
+ "gez-ETH" => return "ግዕዝ (ኤርትራ)",
+ "wal-ETH" => return "Wolaytta (Ethiopia)",
+ "smn-FIN" => return "anarâškielâ (Suopma)",
+ "gsw-FRA" => return "Elsässisch (Frankreich)",
+ "ksh-DEU" => return "Kölsch (Deutschland)",
+ "nds-DEU" => return "Plattdüütsch (Deutschland)",
+ "dsb-DEU" => return "Niedersorbisch (Deutschland)",
+ "hsb-DEU" => return "Hornjoserbšćina (Němska)",
+ "gaa-GHA" => return "Ga (Ghana)",
+ "kpe-GIN" => return "Kpelle (Guinea)",
+ "nqo-GIN" => return "N'Ko (Guinea)",
+ "yue-HKG" => return "粤语 (中国)",
+ "brx-IND" => return "बोड़ो (भारत)",
+ "ccp-IND" => return "बोड़ो (भारत)", // TODO: same as brx-IND
+ "kok-IND" => return "कोंकणी (भारत)",
+ "mni-IND" => return "Manipuri (India)",
+ "sat-IND" => return "Santali (India)",
+ "ckb-IRN" => return "کوردی (ایران)",
+ "mzn-IRN" => return "مازِرونی (ایران)",
+ "lrc-IRN" => return "لۊری شومالی (ایران)",
+ "ckb-IRQ" => return "کوردی (ایران)",
+ "lrc-IRQ" => return "لۊری شومالی (ایران)",
+ "syr-IRQ" => return "ܣܘܪܝܝܐ (ܩܕܝܫܐ)",
+ "fur-ITA" => return "Friulian (Italy)", // TODO: check
+ "scn-ITA" => return "Sicilian (Italy)", // TODO: check
+ "ebu-KEN" => return "Kĩembu (Kenya)",
+ "guz-KEN" => return "Ekegusii (Kenya)",
+ "kln-KEN" => return "Kalenjin (Kenya)",
+ "kam-KEN" => return "Kikamba (Kenya)",
+ "luo-KEN" => return "Dholuo (Kenya)",
+ "luy-KEN" => return "Luyia (Kenya)",
+ "mas-KEN" => return "Maa (Kenya)",
+ "mer-KEN" => return "Kĩmĩrũ (Kenya)",
+ "saq-KEN" => return "Kisampur (Kenya)",
+ "dav-KEN" => return "Kitaita (Kenya)",
+ "teo-KEN" => return "Kiteso (Kenya)",
+ "kpe-LBR" => return "Kpelle (Liberia)",
+ "vai-LBR" => return "ꕙꔤ (ꕞꔤꔫꕩ)",
+ "gsw-LIE" => return "Elsässisch (Liechtenstein)",
+ "khq-MLI" => return "Koyra ciini (Maali)",
+ "ses-MLI" => return "Koyraboro senni (Maali)",
+ "mfe-MUS" => return "kreol morisien (Moris)",
+ "tzm-MAR" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "zgh-MAR" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "shi-MAR" => return "ⵜⴰⵎⴰⵣⵉⵖⵜ (ⵍⵎⴰⵣⵉⵖ)",
+ "mgh-MOZ" => return "Makua (Moçambique)",
+ "seh-MOZ" => return "sena (Moçambique)",
+ "naq-NAM" => return "Khoekhoegowab (Namibiab)",
+ "nds-NLD" => return "Plattdüütsch (Nederland)",
+ "twq-NER" => return "Tasawaq senni (Nižer)",
+ "dje-NER" => return "Zarmaciine (Nižer)",
+ "kaj-NGA" => return "Kaje (Najeriya)",
+ "kcg-NGA" => return "Tyap (Najeriya)",
+ "ceb-PHL" => return "Cebuano (Pilipinas)",
+ "fil-PHL" => return "Filipino (Pilipinas)",
+ "myv-RUS" => return "эрзянь (Россия)",
+ "sah-RUS" => return "саха тыла (Россия)",
+ "dyo-SEN" => return "joola (Senegal)",
+ "nso-ZAF" => return "Sesotho sa Leboa (Afrika Borwa)",
+ "nus-SSD" => return "Thok Nath (SS)",
+ "ast-ESP" => return "asturianu (España)",
+ "gsw-CHE" => return "Elsässisch (Schweiz)",
+ "wae-CHE" => return "Walser (Schweiz)",
+ "syr-SYR" => return "ܣܘܪܝܝܐ (ܣܘܪܝܐ)",
+ "trv-TWN" => return "Sakizaya (Taiwan)",
+ "asa-TZA" => return "Kipare (Tanzania)",
+ "bez-TZA" => return "Hibena (Tanzania)",
+ "lag-TZA" => return "Kɨlaangi (Tanzania)",
+ "jmc-TZA" => return "Kimachame (Tanzania)",
+ "kde-TZA" => return "Chimakonde (Tanzania)",
+ "mas-TZA" => return "Maa (Tanzania)",
+ "rof-TZA" => return "Kihorombo (Tanzania)",
+ "rwk-TZA" => return "Kiruwa (Tanzania)",
+ "sbp-TZA" => return "Ishisangu (Tanzania)",
+ "ksb-TZA" => return "Kishambaa (Tanzania)",
+ "vun-TZA" => return "Kyuk (Tanzania)",
+ "cgg-UGA" => return "Rukiga (Uganda)",
+ "nyn-UGA" => return "Runyankore (Uganda)",
+ "xog-UGA" => return "Olusoga (Uganda)",
+ "teo-UGA" => return "Kiteso (Uganda)",
+ "chr-USA" => return "ᏣᎳᎩ (ᎠᎹᏂᏟ)",
+ "haw-USA" => return "ʻŌlelo Hawaiʻi (ʻAmelika Hui Pū ʻIa)",
+ "lkt-USA" => return "Lakȟólʼiyapi (Mílahaŋska Tȟamákȟočhe)",
+ "bem-ZMB" => return "Ichibemba (Zambia)",
// Followed this table: https://www.fincher.org/Utilities/CountryLanguageList.shtml
- //
- // TODO:
- // - Next dialects are iso639-3 codes. Investigate them:
- // + 'agq-CM' and 'agq-CMR'
- // + 'ksf-CM' and 'ksf-CMR'
- // + 'bas-CM' and 'bas-CMR'
- // + 'dua-CM' and 'dua-CMR'
- // + 'ewo-CM' and 'ewo-CMR'
- // + 'kkj-CM' and 'kkj-CMR'
- // + 'nmg-CM' and 'nmg-CMR'
- // + 'mgo-CM' and 'mgo-CMR'
- // + 'mua-CM' and 'mua-CMR'
- // + 'nnh-CM' and 'nnh-CMR'
- // + 'jgo-CM' and 'jgo-CMR'
- // + 'yav-CM' and 'yav-CMR'
- // + 'moh-CA' and 'moh-CAN'
- // + 'kea-CV' and 'kea-CPV'
- // + 'arn-CL' and 'arn-CHL'
- // + 'yue-CN' and 'yue-CHN'
- // + 'byn-ER' and 'byn-ERI'
- // + 'gez-ER' and 'gez-ERI'
- // + 'tig-ER' and 'tig-ERI'
- // + 'gez-ET' and 'gez-ETH'
- // + 'wal-ET' and 'wal-ETH'
- // + 'smn-FI' and 'smn-FIN'
- // + 'gsw-FR' and 'gsw-FRA'
- // + 'ksh-DE' and 'ksh-DEU'
- // + 'nds-DE' and 'nds-DEU'
- // + 'dsb-DE' and 'dsb-DEU'
- // + 'hsb-DE' and 'hsb-DEU'
- // + 'gaa-GH' and 'gaa-GHA'
- // + 'kpe-GN' and 'kpe-GIN'
- // + 'nqo-GN' and 'nqo-GIN'
- // + 'yue-HK' and 'yue-HKG'
- // + 'brx-IN' and 'brx-IND'
- // + 'ccp-IN' and 'ccp-IND'
- // + 'kok-IN' and 'kok-IND'
- // + 'mni-IN' and 'mni-IND'
- // + 'sat-IN' and 'sat-IND'
- // + 'ckb-IR' and 'ckb-IRN'
- // + 'mzn-IR' and 'mzn-IRN'
- // + 'lrc-IR' and 'lrc-IRN'
- // + 'ckb-IQ' and 'ckb-IRQ'
- // + 'lrc-IQ' and 'lrc-IRQ'
- // + 'syr-IQ' and 'syr-IRQ'
- // + 'fur-IT' and 'fur-ITA'
- // + 'scn-IT' and 'scn-ITA'
- // + 'ebu-KE' and 'ebu-KEN'
- // + 'guz-KE' and 'guz-KEN'
- // + 'kln-KE' and 'kln-KEN'
- // + 'kam-KE' and 'kam-KEN'
- // + 'luo-KE' and 'luo-KEN'
- // + 'luy-KE' and 'luy-KEN'
- // + 'mas-KE' and 'mas-KEN'
- // + 'mer-KE' and 'mer-KEN'
- // + 'saq-KE' and 'saq-KEN'
- // + 'dav-KE' and 'dav-KEN'
- // + 'teo-KE' and 'teo-KEN'
- // + 'kpe-LR' and 'kpe-LBR'
- // + 'vai-LR' and 'vai-LBR'
- // + 'gsw-LI' and 'gsw-LIE'
- // + 'khq-ML' and 'khq-MLI'
- // + 'ses-ML' and 'ses-MLI'
- // + 'mfe-MU' and 'mfe-MUS'
- // + 'tzm-MA' and 'tzm-MAR'
- // + 'zgh-MA' and 'zgh-MAR'
- // + 'shi-MA' and 'shi-MAR'
- // + 'mgh-MZ' and 'mgh-MOZ'
- // + 'seh-MZ' and 'seh-MOZ'
- // + 'naq-NA' and 'naq-NAM'
- // + 'nds-NL' and 'nds-NLD'
- // + 'twq-NE' and 'twq-NER'
- // + 'dje-NE' and 'dje-NER'
- // + 'kaj-NG' and 'kaj-NGA'
- // + 'kcg-NG' and 'kcg-NGA'
- // + 'ceb-PH' and 'ceb-PHL'
- // + 'fil-PH' and 'fil-PHL'
- // + 'myv-RU' and 'myv-RUS'
- // + 'sah-RU' and 'sah-RUS'
- // + 'dyo-SN' and 'dyo-SEN'
- // + 'nso-ZA' and 'nso-ZAF'
- // + 'nus-SS' and 'nus-SSD'
- // + 'ast-ES' and 'ast-ESP'
- // + 'gsw-CH' and 'gsw-CHE'
- // + 'wae-CH' and 'wae-CHE'
- // + 'syr-SY' and 'syr-SYR'
- // + 'trv-TW' and 'trv-TWN'
- // + 'asa-TZ' and 'asa-TZA'
- // + 'bez-TZ' and 'bez-TZA'
- // + 'lag-TZ' and 'lag-TZA'
- // + 'jmc-TZ' and 'jmc-TZA'
- // + 'kde-TZ' and 'kde-TZA'
- // + 'mas-TZ' and 'mas-TZA'
- // + 'rof-TZ' and 'rof-TZA'
- // + 'rwk-TZ' and 'rwk-TZA'
- // + 'sbp-TZ' and 'sbp-TZA'
- // + 'ksb-TZ' and 'ksb-TZA'
- // + 'vun-TZ' and 'vun-TZA'
- // + 'cgg-UG' and 'cgg-UGA'
- // + 'nyn-UG' and 'nyn-UGA'
- // + 'xog-UG' and 'xog-UGA'
- // + 'teo-UG' and 'teo-UGA'
- // + 'chr-US' and 'chr-USA'
- // + 'haw-US' and 'haw-USA'
- // + 'lkt-US' and 'lkt-USA'
- // + 'jbo-001'
- // + 'bem-ZM' and 'bem-ZMB'
_ => {}
}
}
diff --git a/leptos-fluent-macros/src/lib.rs b/leptos-fluent-macros/src/lib.rs
index b51e71ec..a3e21b7c 100644
--- a/leptos-fluent-macros/src/lib.rs
+++ b/leptos-fluent-macros/src/lib.rs
@@ -1,5 +1,6 @@
#![deny(missing_docs)]
#![forbid(unsafe_code)]
+#![cfg_attr(feature = "nightly", feature(track_path))]
//! Macros for the leptos-fluent crate.
//!
@@ -29,6 +30,8 @@ use quote::quote;
/// Create the i18n context for internationalization.
///
+/// [Reference](https://mondeja.github.io/leptos-fluent/leptos_fluent.html)
+///
/// # Example
///
/// ```rust,ignore
@@ -73,148 +76,8 @@ use quote::quote;
/// }
/// ```
///
-/// ## Arguments
-///
-/// - **`translations` \***: Translations to be used by your application. This
-/// must be the same identifier used in the [`fluent_templates::static_loader!`]
-/// macro, which returns [`once_cell:sync::Lazy`]`<[`StaticLoader`]>`.
-/// - **`locales`**: Path to the locales folder, which must contain the translations
-/// for each language in your application. Is expected to be a path relative from
-/// `Cargo.toml` file, the same used in the [`fluent_templates::static_loader!`]
-/// macro.
-/// - **`core_locales`**: Path to the core locales file, which must contain a shared
-/// translation for all languages. Is expected to be a path relative from `Cargo.toml`,
-/// the same used in the [`fluent_templates::static_loader!`] macro.
-/// - **`check_translations`**: Path to the files to check if all translations are
-/// being used and their placeholders are correct. Is expected to be a glob pattern
-/// relative from `Cargo.toml` file. Tipically, you should use `"./src/**/*.rs"` for
-/// a single crate or something like `"../{app,components}/src/**/*.rs"` to match
-/// multiple crates in a workspace.
-/// - **`languages`**: Path to a languages file, which should an array of arrays
-/// where each inner array contains a language identifier and a language name,
-/// respectively. The language identifier should be a valid language tag, such as
-/// `en-US`, `en`, `es-ES`, etc. Is expected to be a path relative from `Cargo.toml`
-/// file.
-/// By default, the languages file should be a JSON with a *.json* extension because
-/// the `json` feature is enabled. For example:
-/// ```json
-/// [
-/// ["en-US", "English (United States)"],
-/// ["es-ES", "Español (España)"]
-/// ]
-/// ```
-/// You can set `default-features = false` and enable the `yaml` or the `json5` feature
-/// to be able to use a YAML or JSON5 file. For example:
-/// ```yaml
-/// # locales/languages.yaml
-/// - - en-US
-/// - English (United States)
-/// - - es-ES
-/// - Español (España)
-/// ```
-/// ```json5
-/// // locales/languages.json5
-/// [
-/// ["en-US", "English (United States)"],
-/// ["es-ES", "Español (España)"]
-/// ]
-/// ```
-/// You can define a third element in the inner array with the direction of the language,
-/// to use it in the [`` attribute] (see `sync_html_tag_dir`). For example:
-/// ```json
-/// [
-/// ["en-US", "English (United States)", "ltr"],
-/// ["es-ES", "Español (España)", "auto"],
-/// ["ar", "العربية", "rtl"],
-/// ["it", "Italiano"]
-/// ]
-/// ```
-/// - **`sync_html_tag_lang`** (_`false`_): Synchronize the global [`` attribute]
-/// with current language using [`leptos::create_effect`]. Can be a literal boolean or an
-/// expression that will be evaluated at runtime.
-/// - **`sync_html_tag_dir`** (_`false`_): Synchronize the global [`` attribute]
-/// with current language using [`leptos::create_effect`]. Can be a literal boolean or an
-/// expression that will be evaluated at runtime. For custom languages from a languages file,
-/// you can specify a third element in the inner array with the direction of the language,
-/// which can be `"auto"`, `"ltr"`, or `"rtl"`. For automatic languages will be defined depending
-/// on the language. For example, Arabic will be `"rtl"`, English will be `"ltr"` and Japanese
-/// will be `"auto"`.
-/// - **`url_param`** (_`"lang"`_): The parameter name to manage the language in a URL parameter.
-/// Can be a literal string or an expression that will be evaluated at runtime. It will take effect
-/// on client-side and server side.
-/// - **`initial_language_from_url_param`** (_`false`_): Load the initial language of the user
-/// from a URL parameter. Can be a literal boolean or an expression that will be evaluated at
-/// runtime. It will take effect on client-side and server side.
-/// - **`set_language_to_url_param`** (_`false`_): Save the language of the user to an URL parameter
-/// when setting the language. Can be a literal boolean or an expression that will be evaluated at
-/// runtime. It will only take effect on client-side.
-/// - **`initial_language_from_url_param_to_localstorage`** (_`false`_): Save the initial language
-/// of the user from the URL to [local storage]. Can be a literal boolean or an expression that will
-/// be evaluated at runtime. It will only take effect on client-side.
-/// - **`initial_language_from_url_param_to_cookie`** (_`false`_): Save the initial language of the user
-/// from the URL to a cookie. Can be a literal boolean or an expression that will be evaluated at runtime.
-/// - **`localstorage_key`** (_`"lang"`_): The [local storage] field to get and save the current language
-/// of the user. Can be a literal string or an expression that will be evaluated at runtime.
-/// It will only take effect on client-side.
-/// - **`initial_language_from_localstorage`** (_`false`_): Load the initial language of the
-/// user from [local storage] if not found in the URL param. Can be a literal boolean or an expression
-/// that will be evaluated at runtime. It will only take effect on client-side.
-/// - **`set_language_to_localstorage`** (_`false`_): Save the language of the user to [local storage] if
-/// when setting the language. Can be a literal boolean or an expression that will be evaluated at
-/// runtime. It will only take effect on client-side.
-/// - **`initial_language_from_localstorage_to_cookie`** (_`false`_): Save the initial language of the user
-/// from [local storage] to a cookie. Can be a literal boolean or an expression that will be evaluated at
-/// runtime. It will only take effect on client-side.
-/// - **`initial_language_from_navigator`** (_`false`_): Load the initial language of the user
-/// from [`navigator.languages`] if not found in [local storage]. Can be a literal boolean or an
-/// expression that will be evaluated at runtime. It will only take effect on client-side.
-/// - **`initial_language_from_navigator_to_localstorage`** (_`false`_): Save the initial language of the user
-/// from [`navigator.languages`] to [local storage]. Can be a literal boolean or an expression that will be
-/// evaluated at runtime. It will only take effect on client-side.
-/// - **`initial_language_from_navigator_to_cookie`** (_`false`_): Save the initial language of the user
-/// from [`navigator.languages`] to a cookie. Can be a literal boolean or an expression that will be evaluated
-/// at runtime. It will only take effect on client-side.
-/// - **`initial_language_from_accept_language_header`** (_`false`_): Load the initial language of the user
-/// from the `Accept-Language` header. Can be a literal boolean or an expression that will be evaluated at
-/// runtime. It will only take effect on server-side.
-/// - **`cookie_name`** (_`"lf-lang"`_): The cookie name to manage language in a cookie. Can be a literal string or an
-/// expression that will be evaluated at runtime. It will take effect on client-side and server side.
-/// - **`cookie_attrs`** (_`""`_): The [attributes][cookie-attributes] to set in the cookie. Can be a literal string or an expression
-/// that will be evaluated at runtime. For example, `"SameSite=Strict; Secure; path=/; max-age=600"`.
-/// It will take effect on client-side.
-/// - **`initial_language_from_cookie`** (_`false`_): Load the initial language of the user from a cookie.
-/// Can be a literal boolean or an expression that will be evaluated at runtime. It will take effect on client-side
-/// and server side.
-/// - **`initial_language_from_cookie_to_localstorage`** (_`false`_): Save the initial language of the user
-/// from the cookie to [local storage]. Can be a literal boolean or an expression that will be evaluated at runtime.
-/// - **`set_language_to_cookie`** (_`false`_): Save the language of the user to a cookie when setting the language.
-/// Can be a literal boolean or an expression that will be evaluated at runtime. It will only take effect on client-side.
-/// - **`initial_language_from_system`** (_`false`_): Load the initial language of the user from the system language
-/// on non wasm targets. Can be a literal boolean or an expression that will be evaluated at runtime. It will only
-/// take effect on client side of desktop applications. The feature `system` must be enabled to use this option.
-/// - **`initial_language_from_system_to_data_file`** (_`false`_): Save the initial language of the user from the system
-/// language to a data file. Can be a literal boolean or an expression that will be evaluated at runtime.
-/// It will only take effect on client side of desktop applications. The feature `system` must be enabled to use
-/// this option.
-/// - **`initial_language_from_data_file`** (_`false`_): Load the initial language of the user from a data file.
-/// Can be a literal boolean or an expression that will be evaluated at runtime. It will only take effect on client
-/// side of desktop applications. The feature `system` must be enabled to use this option.
-/// - **`data_file_key`** (_`"leptos-fluent"`_): The key to store the language in the data file. Can be a literal string
-/// or an expression that will be evaluated at runtime. It will only take effect on client side of desktop applications.
-/// The feature `system` must be enabled to use this option.
-/// - **`set_language_to_data_file`** (_`false`_): Save the language of the user to a data file when setting the language.
-/// Can be a literal boolean or an expression that will be evaluated at runtime. It will only take effect on client side
-/// of desktop applications. The feature `system` must be enabled to use this option.
-///
-/// [`fluent_templates::static_loader!`]: https://docs.rs/fluent-templates/latest/fluent_templates/macro.static_loader.html
-/// [`once_cell:sync::Lazy`]: https://docs.rs/once_cell/latest/once_cell/sync/struct.Lazy.html
-/// [`StaticLoader`]: https://docs.rs/fluent-templates/latest/fluent_templates/struct.StaticLoader.html
-/// [`` attribute]: https://developer.mozilla.org/es/docs/Web/HTML/Global_attributes/lang
-/// [`` attribute]: https://developer.mozilla.org/es/docs/Web/HTML/Global_attributes/dir
-/// [local storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
-/// [`navigator.languages`]: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
-/// [`leptos::create_effect`]: https://docs.rs/leptos/latest/leptos/fn.create_effect.html
-/// [cookie-attributes]: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#write_a_new_cookie
+/// See the reference with all the parameters explained in detail at
+/// https://mondeja.github.io/leptos-fluent/leptos_fluent.html
#[proc_macro]
pub fn leptos_fluent(
input: proc_macro::TokenStream,
diff --git a/leptos-fluent-macros/src/loader.rs b/leptos-fluent-macros/src/loader.rs
index 9463049f..8922698c 100644
--- a/leptos-fluent-macros/src/loader.rs
+++ b/leptos-fluent-macros/src/loader.rs
@@ -355,9 +355,7 @@ impl Parse for I18nLoader {
let mut initial_language_from_data_file_expr: Option<
syn::Expr,
> = None;
- #[cfg(feature = "system")]
let mut data_file_key_str: Option = None;
- #[cfg(feature = "system")]
let mut data_file_key_expr: Option = None;
while !fields.is_empty() {
@@ -586,14 +584,14 @@ impl Parse for I18nLoader {
),
));
}
- } else if k == "initial_language_from_system_to_data_file" {
+ } else if k == "initial_language_from_data_file" {
#[cfg(feature = "system")]
{
if let Some(err) = parse_litbool_or_expr_param(
&fields,
- &mut initial_language_from_system_to_data_file_bool,
- &mut initial_language_from_system_to_data_file_expr,
- "initial_language_from_system_to_data_file",
+ &mut initial_language_from_data_file_bool,
+ &mut initial_language_from_data_file_expr,
+ "initial_language_from_data_file",
) {
return Err(err);
}
@@ -604,20 +602,20 @@ impl Parse for I18nLoader {
return Err(syn::Error::new(
k.span(),
concat!(
- "The parameter 'initial_language_from_system_to_data_file' of",
+ "The parameter 'initial_language_from_data_file' of",
" leptos_fluent! macro requires the feature",
" 'system' enabled.",
),
));
}
- } else if k == "set_language_to_data_file" {
+ } else if k == "initial_language_from_system_to_data_file" {
#[cfg(feature = "system")]
{
if let Some(err) = parse_litbool_or_expr_param(
&fields,
- &mut set_language_to_data_file_bool,
- &mut set_language_to_data_file_expr,
- "set_language_to_data_file",
+ &mut initial_language_from_system_to_data_file_bool,
+ &mut initial_language_from_system_to_data_file_expr,
+ "initial_language_from_system_to_data_file",
) {
return Err(err);
}
@@ -628,20 +626,20 @@ impl Parse for I18nLoader {
return Err(syn::Error::new(
k.span(),
concat!(
- "The parameter 'set_language_to_data_file' of",
+ "The parameter 'initial_language_from_system_to_data_file' of",
" leptos_fluent! macro requires the feature",
" 'system' enabled.",
),
));
}
- } else if k == "initial_language_from_data_file" {
+ } else if k == "set_language_to_data_file" {
#[cfg(feature = "system")]
{
if let Some(err) = parse_litbool_or_expr_param(
&fields,
- &mut initial_language_from_data_file_bool,
- &mut initial_language_from_data_file_expr,
- "initial_language_from_data_file",
+ &mut set_language_to_data_file_bool,
+ &mut set_language_to_data_file_expr,
+ "set_language_to_data_file",
) {
return Err(err);
}
@@ -652,14 +650,13 @@ impl Parse for I18nLoader {
return Err(syn::Error::new(
k.span(),
concat!(
- "The parameter 'initial_language_from_data_file' of",
+ "The parameter 'set_language_to_data_file' of",
" leptos_fluent! macro requires the feature",
" 'system' enabled.",
),
));
}
} else if k == "data_file_key" {
- #[cfg(feature = "system")]
{
if let Some(err) = parse_litstr_or_expr_param(
&fields,
@@ -670,18 +667,6 @@ impl Parse for I18nLoader {
return Err(err);
}
}
-
- #[cfg(not(feature = "system"))]
- {
- return Err(syn::Error::new(
- k.span(),
- concat!(
- "The parameter 'data_file_key' of",
- " leptos_fluent! macro requires the feature",
- " 'system' enabled.",
- ),
- ));
- }
} else {
return Err(syn::Error::new(
k.span(),
diff --git a/leptos-fluent/README.md b/leptos-fluent/README.md
index 2122b9b5..7b1a7aba 100644
--- a/leptos-fluent/README.md
+++ b/leptos-fluent/README.md
@@ -161,6 +161,21 @@ fn App() -> impl IntoView {
url_param: "lang",
// Discover the initial language of the user from an URL parameter.
initial_language_from_url_param: true,
+
+ // Desktop applications (feature `system`)
+ // ---------------------------------------
+ // Set the initial language from the system locale.
+ initial_language_from_system: true,
+ // Set the discovered initial language of the user from
+ // the system locale to a data file.
+ initial_language_from_system_to_data_file: true,
+ // Get the initial language from a data file.
+ initial_language_from_data_file: true,
+ // Key to use to name the data file. Should be unique per
+ // application. By default is `"leptos-fluent"`.
+ data_file_key: "my-app",
+ // Set the language selected to a data file.
+ set_language_to_data_file: true,
}};
view! {
@@ -188,9 +203,7 @@ fn TranslatableComponent() -> impl IntoView {
#[component]
fn LanguageSelector() -> impl IntoView {
- // Use `expect_i18n()` to get the current i18n context:
- let i18n = expect_i18n();
-
+ // `expect_i18n()` to get the i18n context
// `i18n.languages` is a static array with the available languages
// `i18n.language.get()` to get the current language
// `lang.activate()` to set the current language
@@ -199,7 +212,7 @@ fn LanguageSelector() -> impl IntoView {
view! {
{
- move || i18n.languages.iter().map(|lang| {
+ move || expect_i18n().languages.iter().map(|lang| {
view! {
impl IntoView {
- **Actix Web integration**: `actix`
- **Axum integration**: `axum`
- **Nightly toolchain**: `nightly`
+- **Desktop applications**: `system`
- **JSON languages file**: `json` (enabled by default)
- **YAML languages file**: `yaml`
- **JSON5 languages file**: `json5`
@@ -240,7 +254,7 @@ fn LanguageSelector() -> impl IntoView {
[leptos]: https://leptos.dev/
[fluent-templates]: https://github.com/XAMPPRocky/fluent-templates
-[quickstart]: https://docs.rs/leptos-fluent/latest/leptos_fluent/macro.leptos_fluent.html
+[quickstart]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html
[examples]: https://github.com/mondeja/leptos-fluent/tree/master/examples
[book]: https://mondeja.github.io/leptos-fluent/
[documentation]: https://docs.rs/leptos-fluent
diff --git a/leptos-fluent/src/lib.rs b/leptos-fluent/src/lib.rs
index 5c26c4de..f8db62df 100644
--- a/leptos-fluent/src/lib.rs
+++ b/leptos-fluent/src/lib.rs
@@ -2,6 +2,7 @@
#![forbid(unsafe_code)]
#![cfg_attr(feature = "nightly", feature(fn_traits))]
#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
+
//! [![Crates.io](https://img.shields.io/crates/v/leptos-fluent?logo=rust)](https://crates.io/crates/leptos-fluent)
//! [![License](https://img.shields.io/crates/l/leptos-fluent?logo=mit)](https://github.com/mondeja/leptos-fluent/blob/master/LICENSE.md)
//! [![Tests](https://img.shields.io/github/actions/workflow/status/mondeja/leptos-fluent/ci.yml?label=tests&logo=github)](https://github.com/mondeja/leptos-fluent/actions)
@@ -158,6 +159,21 @@
//! url_param: "lang",
//! // Discover the initial language of the user from an URL parameter.
//! initial_language_from_url_param: true,
+//!
+//! // Desktop applications (feature `system`)
+//! // ---------------------------------------
+//! // Set the initial language from the system locale.
+//! initial_language_from_system: true,
+//! // Set the discovered initial language of the user from
+//! // the system locale to a data file.
+//! initial_language_from_system_to_data_file: true,
+//! // Get the initial language from a data file.
+//! initial_language_from_data_file: true,
+//! // Key to use to name the data file. Should be unique per
+//! // application. By default is `"leptos-fluent"`.
+//! data_file_key: "my-app",
+//! // Set the language selected to a data file.
+//! set_language_to_data_file: true,
//! }};
//!
//! view! {
@@ -185,9 +201,7 @@
//!
//! #[component]
//! fn LanguageSelector() -> impl IntoView {
-//! // Use `expect_i18n()` to get the current i18n context:
-//! let i18n = expect_i18n();
-//!
+//! // `expect_i18n()` to get the i18n context
//! // `i18n.languages` is a static array with the available languages
//! // `i18n.language.get()` to get the current language
//! // `lang.activate()` to set the current language
@@ -196,7 +210,7 @@
//! view! {
//!
//! {
-//! move || i18n.languages.iter().map(|lang| {
+//! move || expect_i18n().languages.iter().map(|lang| {
//! view! {
//!
//! impl IntoView {
}
/// Reactive HTML tag to set attributes on SSR
+///
+/// Currently there is not a way to set the `dir` and `lang` attributes
+/// of `` tags on SSR. This components updates it on SSR. Must be
+/// rendered in a view.
+///
+/// ```rust,ignore
+/// use leptos_fluent::SsrHtmlTag;
+///
+/// view! {
+///
+/// }
+/// ```
#[component(transparent)]
#[cfg(not(feature = "ssr"))]
pub fn SsrHtmlTag() -> impl IntoView {}