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
//! `mf2-macros` — the `tr!` proc-macro.
//!
//! An application never names this crate. `mf2-build` generates, in the i18n
//! crate, an exported `tr!` wrapper that forwards to `__tr_impl` with the
//! manifest's absolute path and hash baked in as literals:
//!
//! ```text
//! __tr_impl!("<abs path>/manifest.mf2m" 0x<hash>u64 ; $crate ; "id", name = value, …)
//! __tr_impl!(bytes b"<manifest>" 0x<hash>u64 ; $crate ; "id", …)
//! ```
//!
//! so that any crate depending on the i18n crate can call `tr!`, with no
//! unstable feature and nothing to configure. The manifest is read once
//! per compiler process, keyed by the path and verified against the baked
//! hash — a manifest that hashes to anything else is reported as stale, never
//! used, which is what keeps a long-lived rust-analyzer proc-macro server
//! honest.
//!
//! `MF2_MACRO_STATS=<file>` makes each rustc process write what the macro
//! cost it — expansions, nanoseconds, manifest reads — which is how the
//! cache and the macro's time are measured (`stats`).
//!
//! What the macro checks and what it emits is the `expand` module's doc; what reaches
//! the wasm is a `MsgId` and the argument values, never an id string, an
//! argument name or a markup name.
//!
//! Both proc-macros are hidden from the documentation: only the generated
//! wrapper calls them, and 1.x promises the `tr!` forms, not these
//! (`docs/versioning.md`).
//!
//! # The user guide
//!
//! Getting started, call sites, delivery modes, switching language,
//! accessibility, migrating from `leptos-fluent`, and what 1.x promises
//! (`versioning.md`): the user guide is the `docs/` directory of the
//! mf2-two repository. An application calls `tr!` through the i18n crate that
//! `mf2-build` generates, and names [`mf2`](https://docs.rs/mf2).
// docs.rs (`cargo xtask docs-rs`): each feature-gated item says which features it needs.
use TokenStream;
use quote;
/// The call site, checked against the manifest and lowered to a positional
/// description of the message. Called only by the generated `tr!` wrapper.
/// The `MsgId` of a message, checked against the manifest — for a caller
/// that formats with arguments it does not know at compile time
/// (`mf2::TrDyn`). Called only by the generated `msg_id!` wrapper.