lib-humus 0.6.0

Helps creating configurable frontends for humans and computers using axum, Tera and toml.
Documentation
// SPDX-FileCopyrightText: 2026 Slatian <baschdel@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! # Language Manifest
//!
//! The language manifest in read from the template directory from the file `languages/manifest.toml`.
//!
//! Direct keys:
//! * `default_language` - `LanguageCode` Language code of the default language
//! * `available_messages` - `List<String>` List of available message ids
//! * `language` - `Map<LanguageCode, LanguageDescriptor>` Map of available language codes
//! * `format` - `Map<HumusFormatIdentifier, FormatDescription>`
//! * `message` - `Map<String, MessageDescription>`
//!
//! Minimum viable language manifest:
//!
//! ```toml
//! default_language = "en"
//! available_messages = [
//! 	"test",
//! 	"hello",
//! ]
//!
//! [language.en]
//! name = "English"
//! abbreviation = "EN"
//! ```
//!
//! This describes a laguage manifest that can translate the message ids `test` and `hello` to english with the language code `en`.
//!
//! Every message that can be localized must be listed in `available_messages`.
//!
//! The file `languages/en.ftl` should list the `test` and `hello` messages, for example:
//!
//! ```ftl
//! hello = Hello World!
//! test = This is a test message.
//! ```
//!
//! ## Why the bureaucracy?
//!
//! You might be wondering now why all the buerocracy with `available_messages` is neccessary since the language engine could do its job wihtout.
//!
//! This is implemented to make sure that incomplete translations fail early when a developer or admin are wtching instead of later when someone is unable to use the service because of a broken translation.
//!
//! ## Format settings
//!
//! The language engine can be configured to integrate with the ouput format to distinguish localizations that output plain text from those that output markup.
//!
//! ```toml
//! [format.html]
//! safe_suffix = "_html"
//! ```
//!
//! Currently only `safe_suffix` is available which causes the `text()` function to output text with the tera safe marker set for matching message ids. For message ids `-` are treated as `_` so both `example-message-id-html` and `example_message_id_html` would match the above example. Messages that have the `safe_suffix` on their id get their inputs autoescaped unless they also end with the `safe_suffix` (arguments need to match exactly, unlike message ids).
//!
//! This frees translators from manually having to juggle escaping functions and template writers don't have to litter `| safe` filters making both translations and templates more readable and easier to check for correctness.
//!
//! ## Custom Arguments
//!
//! Messages that support custom arguments need an message description entry in the language manifest describing their arguments. This is done to ensure that all arguments are documented in one place.
//!
//! ```toml
//! [message.test-with-argument]
//! arg.foo.type = "text"
//! ```
//!
//! This example adds the text argument `foo` to the already existing message `test-with-argument` as a required argument.
//!
//! In the `.ftl` file the entry could look like this (don't forget to add the message id to the `available_messages` list):
//! ```ftl
//! test-with-argument = The value of foo is {$foo}.
//! ```
//!
//! Available types are:
//! * `text` - All kinds of text
//! * `bool` - Boolean that will be encoded as the texts `true` and `false`
//! * `cardinal` - Nummber in the generic sense of an number
//!
//! Available, but not yet implemented (by fluent) types are:
//! * `ordinal` - Number to count (1st, 2nd, 3rd, …) things
//! * `percent` - Number representing a percent value
//! * `default_number` - A number type that works around [fluent-rs issue #401](https://github.com/projectfluent/fluent-rs/issues/401)
//!
//! Additional keys that can be added to the `args` value (all of them are optional):
//! * `optional` - `bool` when set to true a null value becomes valid
//! * `default_value` - `string`, `number` or `bool` value to use as the default value, setting `optional` is not required when this one is set
//! * `one_of` - `List<string|number|bool>` A list of valid values to pass, can be used to represent enums. When a non null value is passed it must be one of the listed ones.
//! * `minimum_fraction_digits` - `integer` make sure that the number has at least the given number of fraction digits.
//!
//! Other values to control number formatting are read, but remain undocumented until they are implemented by fluent.
//! If you need those working please consider helping the [fluent crate](https://github.com/projectfluent/fluent-rs), search for `number options` in the issues.