Glossa
Glossa is a language localisation library.
Functionality
By functional type, it can be divided into two categories.
- Compile-time: Converts the configuration file into constant (
const fn) Rust code to achieve efficient localisation.- Pros: High efficiency
- Cons:
- Requires codegen, which may result in some redundant code expansion.
- Currently only supports simple key-value (K-V) pairs.
- Runtime: Manages
fluentresources.- Pros: Fluent syntax may be more suitable for localisation.
- Cons: Occupies more resources than
const fn.
Note: Fluent also supports loading localisation resources (localised files) at compile time, but data needs to be parsed at runtime.
The former is just the simple K-V pair that uses some const maps from phf to store data. Because it's simple, it's efficient.
The two types of functionalities are independent of each other. For the latter, please read Fluent.md.
Codegen
Use a code generator to generate code.
glossa-codegen has the following features:
- yaml
- Enabled by default.
- The default file extension is ".yaml" or ".yml"
- ron
- The default ext is ".ron"
- toml
- The ext is ".toml"
- json
- ext: ".json"
This corresponds to different types of configuration files. You can enable all features or add them as needed.
By default, the file type is determined based on the file name suffix, and the map name (table name) is set based on the file name. Whether deserialisation is needed at compile-time is determined by the enabled feature.
Assuming there are two files under the directory assets/l10n/en, named test.yaml and test.yml. Then we can consider them to have the same name, resulting in two tables(maps):
- test
- test.yml
When using
.get()withMapLoader, you need to pass in the map-name
To avoid this situation, it is recommended to use different names for different files.
Preparations
Before writing build.rs, we need to prepare the localisation resource files.
de (Deutsch, Lateinisch, Deutschland):
- "assets/l10n/de/error.yaml"
text-not-found: Kein lokalisierter Text gefunden
en (English, Latin, United States):
- "assets/l10n/en/error.yaml"
text-not-found: No localized text found
en-GB (English, Latin, Great Britain):
assets/l10n/en-GB/error.yaml
text-not-found: No localised text found
es (español, latino, España):
assets/l10n/es/error.yaml
text-not-found: No se encontró texto localizado
pt (português, latim, Brasil)
assets/l10n/pt/error.yaml
Note: "pt" refers to "Portuguese (Brazil)", not "Portuguese (Portugal)" (português, Portugal).
text-not-found: Nenhum texto localizado encontrado
build.rs
First, add the compile-time dependency:
Then start creating build.rs.
This file is at the same level as Cargo.toml.
For a simple single-project structure:
.
├── assets
├── build.
├──
├──
├── src
└── target
A slightly more complex multi-project structure:
.
├── assets
│ └── l10n
├──
├──
├── codegen
│ ├──
│ ├── src
│ └── tests
├── glossa
│ ├── build.
│ ├──
│ └── src
├── target
└── tests
Of course, you can also specify the path to build.rs manually, instead of using the default.
build.rs:
use ;
use ;
Get Text
Now that the code has been generated, let's write a function to test it!
But before that, we need to add some dependencies.
The test function is as follows:
If your system language is "en", the test should pass.
Note that locale_hashmap() is not a const fn but a regular function.
However, this does not mean that it is particularly expensive.
Its value points to a sub-map, and all sub-maps and their sub-maps are consts.
The time complexity of HashMap query operation is O(1).
In addition, if the ahash feature is enabled, the RandomState of ahash will be used by default instead of the std::collections.
You can also use OnceCell to create global static data, creating data only once.
pub
Wait a minute, don't waste time on these things, our previous test failed.
All right, let's revisit what we did before.
We have previously created localisation resource files for German, Spanish and Portuguese.
Firstly, it will automatically detect the system language. If the localisation resource does not exist, it will automatically use a fallback chain. If the localisation resource exists and your system language is not English, then the above test will fail.
Let's continue to test:
let loader = locales;
let msg = loader.get?;
Assuming your language is German (de-Latn-DE)
assert_eq!;
Spanish (es-Latn-ES)
assert_eq!;
Portuguese (pt-Latn-BR)
assert_eq!;