Weblate has no native Hugo-TOML format. The strings are already the go-i18n
structure ([key]/other=), so convert site/i18n/{en,es}.toml -> {en,es}.json
({"key":{"other":"..."}}) — Hugo 0.140 reads it identically (verified with the
pinned hugomods/hugo:exts-0.140.2 image). Enables a 'site' Weblate component.
Update TRANSLATIONS.md: site is now a component (go-i18n-json), not deferred.
99 lines
4.3 KiB
Markdown
99 lines
4.3 KiB
Markdown
# Translating Tane (Weblate)
|
|
|
|
Runbook for the translation setup. Written so another agent (or a human) can
|
|
reproduce it without prior context.
|
|
|
|
Tane is translated on **[translate.comunes.org/projects/tane](https://translate.comunes.org/projects/tane/)**
|
|
(a self-hosted **Weblate 5.x**, docker-compose at `/data/weblate` on host **tesla**).
|
|
The links to the repo and to Weblate are shown both on the landing site
|
|
(`site/config.toml` → `sourceURL`, `weblateURL`) and inside the app (About screen).
|
|
|
|
## What is translatable
|
|
|
|
| Surface | Files | Format | Base locale | Locales today |
|
|
|---|---|---|---|---|
|
|
| **App** (`app` component) | `apps/app_seeds/lib/i18n/*.i18n.json` | JSON **nested** (slang, `{param}` placeholders) | `en` | en, es, pt, fr, de, ast, ja |
|
|
| **Site** (`site` component) | `site/i18n/*.json` | **go-i18n JSON** (`{"key":{"other":"…"}}`) | `en` | en, es |
|
|
|
|
Only source strings live in git; app strings use `slang`, so `strings.g.dart` /
|
|
`strings_*.g.dart` are **generated** (see the slang caveat below).
|
|
|
|
## Git connection
|
|
|
|
- Repo: `https://git.comunes.org/comunes/tane.git`, branch **`main`** (private
|
|
Gitea/Forgejo behind Cloudflare).
|
|
- Weblate must use **HTTPS + an access token** — SSH port 22 is not reachable
|
|
through Cloudflare, so the stored `Comunes Translations` SSH key is unusable here.
|
|
- Repository URL in Weblate:
|
|
`https://<user>:<token>@git.comunes.org/comunes/tane.git`
|
|
where `<token>` is a git.comunes.org access token with **read + write** on
|
|
`comunes/tane` (Weblate pushes translations back). Generate it in Gitea/Forgejo
|
|
→ Settings → Applications.
|
|
|
|
## The `app` component (create once)
|
|
|
|
The `tane` project already exists on Weblate. Add a component (admin UI
|
|
*Add new translation component*, or `docker exec weblate-weblate-1 weblate shell`):
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Project | `tane` |
|
|
| Name / slug | `app` |
|
|
| Source code repository | `https://<user>:<token>@git.comunes.org/comunes/tane.git` |
|
|
| Repository branch | `main` |
|
|
| File mask | `apps/app_seeds/lib/i18n/*.i18n.json` |
|
|
| Monolingual base language file | `apps/app_seeds/lib/i18n/en.i18n.json` |
|
|
| Template for new translations | `apps/app_seeds/lib/i18n/en.i18n.json` |
|
|
| File format | **JSON nested structure** (`json-nested`) — not flat `json` |
|
|
| Source language | English (`en`) |
|
|
|
|
Weblate auto-discovers the existing locales from the mask. Leave push-on-commit on
|
|
so translations flow back to `main`.
|
|
|
|
Sanity check after creating it:
|
|
```sh
|
|
docker exec weblate-weblate-1 weblate shell -c \
|
|
'from weblate.trans.models import Project; \
|
|
print(Project.objects.get(slug="tane").component_set.count())' # expect 1
|
|
```
|
|
Then edit a test string in the UI and confirm a commit lands on
|
|
`git.comunes.org/comunes/tane` (`main`) — that validates the token has write.
|
|
|
|
## slang regeneration caveat (important)
|
|
|
|
Weblate only edits the `*.i18n.json` sources. The committed `strings.g.dart` /
|
|
`strings_*.g.dart` are generated and go **stale** on every Weblate commit, and
|
|
there is no CI to regenerate them. Before a release, a maintainer must:
|
|
|
|
```sh
|
|
git pull
|
|
cd apps/app_seeds && dart run slang # regenerates strings*.g.dart
|
|
cd ../.. && dart analyze # workspace gate
|
|
git add -A && git commit -m "chore(i18n): regenerate slang after Weblate sync"
|
|
```
|
|
|
|
(Adding a new source string manually? Same steps — edit `en.i18n.json` first, then
|
|
regenerate. `fallback_strategy: base_locale` means locales missing a key show the
|
|
English text until translators fill it in.)
|
|
|
|
## The `site` component (landing page)
|
|
|
|
The Hugo landing strings live in `site/i18n/*.json`. Weblate has no native Hugo-TOML
|
|
format, so these were converted from TOML to **go-i18n JSON** (`{"key":{"other":"…"}}`)
|
|
— a shape Hugo 0.140 reads identically and Weblate supports natively. Component settings:
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Project | `tane` |
|
|
| Name / slug | `site` |
|
|
| Source code repository | *(link to the `app` component: `weblate://tane/app`)* |
|
|
| Repository branch | `main` |
|
|
| File mask | `site/i18n/*.json` |
|
|
| Monolingual base language file | `site/i18n/en.json` |
|
|
| Template for new translations | `site/i18n/en.json` |
|
|
| File format | **go-i18n JSON** (`go-i18n-json`) |
|
|
| Source language | English (`en`) |
|
|
|
|
Linking the repo to the `app` component (`weblate://tane/app`) shares one clone/token.
|
|
No slang step here — Hugo consumes the JSON directly. Only EN/ES today; adding a locale =
|
|
add `site/i18n/<code>.json`.
|