2024-05-21 20:39:19 +00:00
|
|
|
# Kielet - GNU Gettext for Gleam
|
2024-05-09 15:49:58 +00:00
|
|
|
|
|
|
|
[![Package Version](https://img.shields.io/hexpm/v/kielet)](https://hex.pm/packages/kielet)
|
|
|
|
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/kielet/)
|
|
|
|
|
2024-05-21 20:39:19 +00:00
|
|
|
Kielet is a [GNU Gettext](https://www.gnu.org/software/gettext/) implementation for Gleam. With Kielet,
|
|
|
|
you can translate your Gleam or BEAM application without needing to change its source code or recompile
|
|
|
|
it. Kielet implements translation functions for singular and plural forms and an MO file parser to read
|
|
|
|
compiled translations. Gleam source code can be processed with the `xgettext` program to automatically
|
|
|
|
generate the translation templates (POT files).
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
First add Kielet to your project:
|
|
|
|
|
2024-05-09 15:49:58 +00:00
|
|
|
```sh
|
|
|
|
gleam add kielet
|
|
|
|
```
|
2024-05-21 20:39:19 +00:00
|
|
|
|
|
|
|
Then you can start annotating your source code to prepare it for translation (skip the file reading and
|
|
|
|
language loading when you don't have languages yet):
|
|
|
|
|
2024-05-09 15:49:58 +00:00
|
|
|
```gleam
|
2024-05-21 20:39:19 +00:00
|
|
|
import gleam/io
|
|
|
|
import kielet.{gettext as g_, ngettext as n_}
|
|
|
|
import kielet/context.{Context}
|
|
|
|
import kielet/database
|
|
|
|
import kielet/language
|
|
|
|
import simplifile
|
2024-05-09 15:49:58 +00:00
|
|
|
|
|
|
|
pub fn main() {
|
2024-05-21 20:39:19 +00:00
|
|
|
// This example uses simplifile to read the MO data
|
|
|
|
let assert Ok(mo_data) = simplifile.read_bits("./path/to/fi.mo")
|
|
|
|
|
|
|
|
// Load language from MO file
|
|
|
|
let assert Ok(finnish) = language.load("fi", mo_data)
|
|
|
|
|
|
|
|
// Create language database
|
|
|
|
let db = database.new() |> database.add_language(finnish)
|
|
|
|
|
|
|
|
// Create translation context to choose active language
|
|
|
|
let ctx = Context(db, "fi")
|
|
|
|
|
|
|
|
// "Morjens, maailma!"
|
|
|
|
io.println(
|
|
|
|
g_(ctx, "Hello, world!")
|
|
|
|
)
|
|
|
|
|
|
|
|
// "Ou jee, mulla on %s euroa" -- The correct plural form is chosen based on the amount provided
|
|
|
|
io.println(
|
|
|
|
n_(ctx, "Nice, I have %s euro", "Nice, I have %s euros", 15)
|
|
|
|
)
|
2024-05-09 15:49:58 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2024-05-21 20:39:19 +00:00
|
|
|
When you have annotated your code, but have no translations, the original messages will be returned.
|
|
|
|
Thus it's safe to add new strings to your program, the worst that can happen is that the original
|
|
|
|
strings will be shown.
|
|
|
|
|
|
|
|
To start translating your program, first extract the strings from your source code. You should read
|
|
|
|
the documentation of the `xgettext` program to do this, but here is an example command that works for
|
|
|
|
Gleam source code, when you have imported the functions as `g_` and `n_`:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
xgettext src/**/*.gleam --keyword=g_:2 --keyword=n_:2,3 -o - --copyright-holder='Your Name' --package-name='Your App' --package-version='X.Y.Z' --msgid-bugs-address='email@example.com'
|
|
|
|
```
|
|
|
|
|
|
|
|
Store this output into a template file with the `.pot` extension and then use a translation app such as
|
|
|
|
[Poedit](https://poedit.net) to create language specific translation files. The output should be human
|
|
|
|
readable PO files that you can add to your version tracking if wanted, and binary MO files that Kielet
|
|
|
|
can read.
|
|
|
|
|
|
|
|
### String replacement
|
|
|
|
|
|
|
|
Note that Kielet does not do any string replacement. It's convention to use `%s` to denote the number
|
|
|
|
of items in a translatable string, but it's not enforced and has no special meaning. This means that
|
|
|
|
the translated message will contain the `%s` unchanged, and it is up to you to replace it with the
|
|
|
|
appropriate number, taking into account the target locale's number format.
|
|
|
|
|
|
|
|
## Gettext limitations
|
|
|
|
|
|
|
|
Due to how Gettext is built, the source language (the language used in your source files) can only be a
|
|
|
|
language with two plural forms. This means that there is a singular form, used when there is one item,
|
|
|
|
and a plural form that is used for every other amount of items. Unfortunately Gettext does not support
|
|
|
|
languages with more plural forms such as Arabic as the source language. They are supported as
|
|
|
|
translation targets, though.
|
|
|
|
|
|
|
|
If you do not have any usage of `ngettext` in your code, your source language can be any language. This
|
|
|
|
may be a risky choice, though, since it's quite likely you will need plural forms in the future.
|
2024-05-09 15:49:58 +00:00
|
|
|
|
|
|
|
## Development
|
|
|
|
|
|
|
|
```sh
|
|
|
|
gleam test # Run the tests
|
|
|
|
```
|