You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/conformance.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -475,6 +475,19 @@ Two areas are explicitly out of scope:
475
475
| Function | Notes |
476
476
|----------|-------|
477
477
|`:list`| Formats a list operand by delegating to `Localize.List.to_string/2`. Each element is itself formatted via `Localize.Chars`, so a list of dates, numbers, units, etc. picks up the message's locale and forwarded options. Supports a `style` (or `type`) option whose values map to CLDR list styles: `"and"`, `"and-short"`, `"and-narrow"`, `"or"`, `"or-short"`, `"or-narrow"`, `"unit"`, `"unit-short"`, `"unit-narrow"`. Default is `"and"`. |
478
+
|`:l:inflect`| Inflects a phrase operand for the grammatical constraints in its options (`grammaticalCase`, `grammaticalGender`, `grammaticalNumber`, `grammaticalDefiniteness`, `grammaticalPerson`), delegating to `Localize.Inflection.inflect/3`. Requires the locale's inflection data; a missing locale or absent data is a clean error, never a crash. |
479
+
|`:l:pronoun`| Selects a pronoun, or re-inflects the operand pronoun, via `Localize.Inflection.pronoun/2,3`. |
480
+
|`:l:quantify`| Joins a `count` option with the noun operand so the noun agrees with the number (Slavic numeral government, the Arabic counted-noun cases, per-language number agreement), delegating to `Localize.Inflection.quantify/4`. |
481
+
482
+
These live in the reserved single-letter `l:` namespace; see *MF2 function namespaces* below.
483
+
484
+
### MF2 function namespaces
485
+
486
+
| Feature | Status | Notes |
487
+
|---------|--------|-------|
488
+
| Namespaced function names (`:ns:name`) | Implemented | The parser accepts `namespace:name`; the interpreter resolves the namespace after the built-in functions. |
489
+
| Reserved namespaces (`l`, `u`) | Implemented |`l` is Localize's own (`:l:inflect` / `:l:pronoun` / `:l:quantify`); `u` is the CLDR-managed namespace the spec reserves for options. Neither routes to a user handler, and an unhandled `l:` / `u:` function is an Unknown Function error — which the spec permits, since implementations are not required to support every namespace. |
490
+
| Custom namespace handlers | Implemented | Register a `Localize.Message.Namespace` handler for a namespace via `config :localize, :mf2_namespaces` or the per-call `:namespaces` option; one handler dispatches every function in its namespace by local name. The flat-string `:mf2_functions` custom registry continues to work for back-compat. Built-in functions are authoritative and cannot be shadowed by a custom function or namespace. |
Inflection is available inside MF2 messages through the `l:` namespace: `:l:inflect` inflects its operand phrase, and `:l:pronoun` selects or re-inflects a pronoun. Grammatical constraints are passed as `grammatical*` options — `grammaticalCase`, `grammaticalGender`, `grammaticalNumber`, `grammaticalDefiniteness`, `grammaticalPerson` — mirroring the `:unit` function's naming:
282
+
Inflection is available inside MF2 messages through the `l:` namespace: `:l:inflect` inflects its operand phrase, `:l:pronoun` selects or re-inflects a pronoun, and `:l:quantify` joins a `count` with a noun operand so the noun agrees with the number. Grammatical constraints are passed as `grammatical*` options — `grammaticalCase`, `grammaticalGender`, `grammaticalNumber`, `grammaticalDefiniteness`, `grammaticalPerson` — mirroring the `:unit` function's naming:
283
283
284
284
```elixir
285
285
iex>Localize.Message.format("{$w :l:inflect grammaticalNumber=plural}", %{w:"light on the patio"}, locale::en)
The functions need the locale's inflection data present; a missing locale or absent data resolves to an error rather than crashing the format.`:l:quantify` is not yet available.
295
+
The functions need the locale's inflection data present; a missing locale or absent data resolves to an error rather than crashing the format.
Copy file name to clipboardExpand all lines: guides/message_formatting.md
+54-1Lines changed: 54 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -291,6 +291,26 @@ Selects or re-inflects a pronoun for the locale. Given a pronoun operand, it re-
291
291
292
292
Takes the same `grammatical*` options as `:l:inflect`, and likewise requires the locale's inflection data, degrading to an error when the data or locale is unavailable.
293
293
294
+
### `:l:quantify`
295
+
296
+
Joins a number with a noun so the noun agrees with it grammatically — the count-and-noun phrase that languages build differently (Slavic numeral government, the Arabic counted-noun cases, the Finnish partitive, and so on). The operand is the noun; the number is the required `count` option.
297
+
298
+
```
299
+
{$item :l:quantify count=$n}
300
+
{|kilometer| :l:quantify count=2}
301
+
```
302
+
303
+
The `count` drives both the number joined to the noun (formatted with the message's locale) and the plural category the noun agrees with, so one template produces the right form across categories:
It also accepts the same `grammatical*` options as `:l:inflect`, to fix a case or gender the surrounding sentence requires. Like the other `l:` functions it needs the locale's inflection data; a missing or non-numeric `count`, a non-string operand, or absent data all resolve to a clean error, never a crash.
313
+
294
314
## Declarations
295
315
296
316
Declarations appear at the start of a complex message, before the body.
@@ -585,6 +605,7 @@ The Localize MF2 implementation targets the [Unicode MessageFormat 2.0 specifica
585
605
| `:list` | Localize | Locale-aware list join via `Localize.List` |
586
606
| `:l:inflect` | Localize | Grammatical inflection via `Localize.Inflection` |
587
607
| `:l:pronoun` | Localize | Pronoun selection via `Localize.Inflection` |
608
+
| `:l:quantify` | Localize | Number-and-noun agreement via `Localize.Inflection` |
Per-call functions take precedence over application-level functions, which take precedence over built-in functions. A function name with no built-in implementation and no registry entry is an unknown-function error, per the MF2 specification: `format/3` returns `{:error, %Localize.FormatError{reason: :unknown_function}}`.
688
+
Per-call functions take precedence over application-level functions. Both registries are consulted only for a function name that no built-in already handles — the built-in functions are authoritative and cannot be shadowed. A function name with no built-in implementation and no registry entry is an unknown-function error, per the MF2 specification: `format/3` returns `{:error, %Localize.FormatError{reason: :unknown_function}}`.
668
689
669
690
**Implementing a custom function:**
670
691
@@ -686,6 +707,38 @@ end
686
707
687
708
See `Localize.Message.Function` for the full callback specification.
688
709
710
+
### Function namespaces
711
+
712
+
A function name may carry a namespace — `:acme:price`. Namespaced functions resolve after the built-ins, so one handler can own an entire namespace rather than registering each function by its flattened name. Register a `Localize.Message.Namespace` handler per namespace, application-wide or per call:
The single-letter namespaces `l` (Localize's own `:l:inflect` / `:l:pronoun` / `:l:quantify`) and `u` (CLDR-managed) are reserved: registering a handler for them has no effect, and an `l:` or `u:` function that no built-in handles is an unknown-function error. See `Localize.Message.Namespace` for the full callback specification.
741
+
689
742
## Syntax highlighting
690
743
691
744
For docs, playgrounds, editor tooling, or error reporting, Localize can render an MF2 message as a *classified token stream* and format it as HTML (with CSS classes) or ANSI-coloured terminal output. Highlighting runs after parsing, so only valid MF2 input is highlighted — parse errors surface the same `{:error, %ParseError{}}` tuple as elsewhere.
0 commit comments