Expand description
cratefield-i18n: the strings a venture owns, in the languages it owns
them in (issue #190).
Nothing here is notification-specific. A Catalog answers “render
message booking-confirmed, attribute .title, in id-ID”, and the
caller decides what to do with the answer — a push title, a mail
subject, a waitlist template.
use cratefield_i18n::{Args, Catalog, FluentCatalog, TITLE, localize};
let catalog = FluentCatalog::builder()
.default_locale("en")
.locale("en", "booking-confirmed =\n .title = Booking confirmed\n")
.locale("id", "booking-confirmed =\n .title = Pesanan dikonfirmasi\n")
.build()
.expect("the catalog parses");
let asked = "id-ID".parse().expect("a language tag");
let rendered = localize(&catalog, &asked, "booking-confirmed", TITLE, &Args::new());
assert_eq!(rendered.text, "Pesanan dikonfirmasi");
assert_eq!(rendered.locale.to_string(), "id"); // id-ID negotiated down to id
assert!(!rendered.missing);§The three things this crate exists to get right
Thread safety. The default FluentBundle is built on Rc and
RefCell: it is neither Send nor Sync, so it cannot live behind a
port that is. SendWrapper does not fix it — that grants Send alone,
and panics if the value is dropped on another thread. This crate uses
the concurrent memoizer (Arc/RwLock) instead, and a static
assertion in the fluent module pins it so the day somebody swaps the import
back is a compile error rather than a runtime one.
Direction. unic-langid parses language identifiers and carries no
directionality data at all: there is no is_rtl() to call. Direction
therefore comes from an explicit script and language list here — see
direction — and is tested.
A missing key is visible. localize never returns an empty
string for a key the catalog does not have. It renders the key itself
and sets Localized::missing, so the caller can say so on the bus and
whoever reads the notification sees booking-confirmed.title rather
than a blank line.
§What a caller must not do with the answer
Args values come from the caller of a notification — a coach’s name,
a place, a booking reference. A rendered string is therefore personal
data: it belongs in the message that is delivered and nowhere else. No
error, event or log line in this crate ever carries an argument value or
a rendered string, and a caller must keep that boundary too.
Structs§
- Fluent
Catalog - A catalog built from embedded
.ftlsources. - Fluent
Catalog Builder - Assembles a
FluentCatalog. - Language
Identifier LanguageIdentifieris a core struct representing a Unicode Language Identifier.- Localized
- One rendered string, and what it took to get there.
- Missing
- One
key.attributea locale does not have, as the completeness check reports it. - Static
Catalog - A catalog of literal strings.
Enums§
- Catalog
Error - Why a catalog could not be built.
- Direction
- Which way a locale’s text runs, as
dirtakes it.
Constants§
- BODY
- The attribute a body is stored under.
- SUBJECT
- The attribute a mail subject is stored under, where a venture wants one that is not the title.
- TITLE
- The attribute a title is stored under:
booking-confirmed.title.
Traits§
- Catalog
- A catalog of a venture’s own strings.
Functions§
- accept_
language - The locales
headerasks for, best first. - direction
- Which way
locale’s text runs. - localize
- Renders
key.attributefor a recipient who asked forrequested. - missing_
messages - Every
key.attributepair that some locale incatalogcannot render, in locale order then key order. - missing_
text - What a message no locale has renders as: the key and the attribute, exactly as a caller wrote them.
- parse_
locale - The one place a language tag enters this system from outside it.
Type Aliases§
- Args
- The placeables a message is rendered with:
{ $coach },{ $count }.