zng/l10n.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
//! Localization service, sources and other types.
//!
//! Localized text is declared using the [`l10n!`] macro, it provides a read-only text variable that automatically
//! updates to be best localized text available given the current loaded localization and the app language.
//!
//! ```
//! use zng::prelude::*;
//! # let _scope = APP.defaults();
//!
//! let click_count = var(0u32);
//! # let _ =
//! Window! {
//! title = l10n!("window-title", "Window Title");
//! child = Button! {
//! on_click = hn!(click_count, |_| click_count.set(click_count.get() + 1));
//! child = Text!(l10n!("click-count", "Clicked {$n} times", n = click_count.clone()));
//! };
//! }
//! # ;
//! ```
//!
//! In the example above declares two localization messages, "window.title" and "btn.click_count", if
//! these messages are localized for the current language the localized text is used, otherwise the provided
//! fallback is used.
//!
//! The [`L10N`] service can be used to set the app language and load localization resources. The example below
//! sets the language to en-US and loads localization from a directory.
//!
//! ```no_run
//! use zng::prelude::*;
//!
//! APP.defaults().run_window(async {
//! // start loading localization resources
//! L10N.load_dir(zng::env::res("l10n"));
//! // set the app language, by default is the system language
//! L10N.app_lang().set(lang!("en-US"));
//! // preload the localization resources for a language
//! L10N.wait_first(lang!("en-US")).await;
//!
//! Window! {
//! // ..
//! }
//! });
//! ```
//!
//! # Fluent
//!
//! The localization files are in the [Fluent](https://projectfluent.org/) format. Fluent empowers translators to
//! script things like plural forms, for this reason a localization file should be provided even for the same
//! language the `l10n!` fallback text is written in.
//!
//! ```ftl
//! click-count = {$n ->
//! [one] Clicked {$n} time
//! *[other] Clicked {$n} times
//! }
//! ```
//!
//! The example above demonstrates a localized message that provides plural alternatives for the English language.
//!
//! # Scraper
//!
//! The `cargo zng l10n` tool can be used to generate a Fluent file from source code, the Fluent file can be
//! used as a template for translators, it will include the fallback text and comments written close the key
//! declaration.
//!
//! ```
//! use zng::prelude::*;
//! # let _scope = APP.defaults();
//!
//! // l10n-### This standalone comment is added to the scraped template file.
//!
//! let click_count = var(0u32);
//! # let _ =
//! Window! {
//! title = l10n!("window-title", "Window Title");
//! child = Button! {
//! on_click = hn!(click_count, |_| click_count.set(click_count.get() + 1));
//! // l10n-# This comment is added to the `"click-count"` entry.
//! child = Text!(l10n!("click-count", "Clicked {$n} times", n = click_count.clone()));
//! };
//! }
//! # ;
//! ```
//!
//! When the example above is scrapped it generates:
//!
//! ```ftl
//! ### This standalone comment is added to all scraped template files.
//!
//! # This comment is added to the `"click-count"` entry.
//! click-count = Clicked {$n} times
//! ```
//!
//! See the [`l10n!`] documentation for a full explanation of how the Scraper converts comments and the
//! `l10n!` calls into Fluent files.
//!
//! [`l10n!`]: crate::l10n::l10n
//!
//! # Commands
//!
//! Commands metadata can be localized and scrapped, to enable this set `l10n!:` on the [`command!`](zng::event::command) declarations.
//!
//! If the first metadata is `l10n!:` the command init will attempt to localize the other string metadata. The `cargo zng l10n`
//! command line tool scraps commands that set this special metadata.
//!
//! ```
//! # use zng_app::{event::{command, CommandNameExt, CommandInfoExt}, shortcut::{CommandShortcutExt, shortcut}};
//! command! {
//! pub static FOO_CMD = {
//! l10n!: true,
//! name: "Foo!",
//! info: "Does the foo thing",
//! };
//! }
//! ```
//!
//! The example above will be scrapped as:
//!
//! ```ftl
//! FOO_CMD =
//! .name = Foo!
//! .info = Does the foo thing.
//! ```
//!
//! The `l10n!:` meta can also be set to a localization file name:
//!
//! ```
//! # use zng_app::{event::{command, CommandNameExt, CommandInfoExt}, shortcut::{CommandShortcutExt, shortcut}};
//! command! {
//! pub static FOO_CMD = {
//! l10n!: "file",
//! name: "Foo!",
//! };
//! }
//! ```
//!
//! The example above is scrapped to `{l10n-dir}/{lang}/file.ftl` files.
//!
//! ## Limitations
//!
//! Interpolation is not supported in command localization strings.
//!
//! The `l10n!:` value must be a *textual* literal, that is, it can be only a string literal or a `bool` literal, and it cannot be
//! inside a macro expansion.
//! # Full API
//!
//! See [`zng_ext_l10n`] for the full localization API.
pub use zng_ext_l10n::{
l10n, lang, IntoL10nVar, L10nArgument, L10nDir, L10nMessageBuilder, L10nSource, Lang, LangFilePath, LangMap, LangResource,
LangResourceStatus, LangResources, Langs, NilL10nSource, SwapL10nSource, L10N, LANG_VAR,
};