fix(forgejo): make the footer links follow the reader's language, in label and destination #343

Sammanfogat
supernaut sammanfogade 2 incheckningar från fix/forgejo-footer-i18n in i main 2026-08-02 19:23:52 +00:00
Ägare

Closes #333, closes #334.

Both are our own defects, not upstream translation gaps.

#333 — the three portal links in the footer render in Swedish whatever the interface language.
custom/templates/custom/* hook fragments are not routed through the translation pipeline unless
they ask for it, and ours was plain HTML with hardcoded labels. Verified by diffing the en-US and
sv-SE responses: those lines were byte-identical while the upstream strings beside them
("Powered by Forgejo", "Licenses") translated correctly.

#334 — separately, all three pointed at the portal's Swedish URLs unconditionally. The site
serves Swedish at / and English under /en/ and does no Accept-Language detection, so an English
reader clicking "Privacy Policy" landed on the Swedish page even once the label was fixed.

Both are fixed in the same fragment by branching on ctx.Locale.Lang, which the application injects
per request into every template including custom/* hooks. The stale comment claiming the legal
pages detect English themselves is removed — they do not, and it is what caused #334.

A trap worth recording, now in the fragment's comment: do not add translation keys under
custom/options/locale/. Locale files are read through a layered asset filesystem whose ReadFile
returns the first matching layer and stops, so a custom locale_en-US.ini would replace the entire
built-in English locale rather than extend it.

Rendered output

en-US   https://www.gitborg.se/en/          gitborg.se
        https://www.gitborg.se/en/terms     Terms of Service
        https://www.gitborg.se/en/privacy   Privacy Policy

sv-SE   https://www.gitborg.se/             gitborg.se
        https://www.gitborg.se/terms        Användarvillkor
        https://www.gitborg.se/privacy      Integritetspolicy

Swedish output is byte-identical to production, proven rather than asserted: the whole footer
region was extracted from the live sv-SE page and from a local render and compared — identical,
including the leading newlines, which survive because comments are stripped as nodes rather than
lines.

Two details checked while in there: an explicitly chosen language wins over header sniffing (with a
sv-SE header plus the switcher's en-US cookie, the footer renders English); and {{$portal}}
sits in the path part of the href, so the normaliser rather than the escaper applies and /en
stays /en.

Verification

Rendered and served through the local podman preview. ansible-playbook site.yml --syntax-check
clean, ansible-lint 0 failures across 191 files, Prettier and markdownlint clean, gitleaks clean
over 264 commits.

Closes #333, closes #334. Both are our own defects, not upstream translation gaps. **#333** — the three portal links in the footer render in Swedish whatever the interface language. `custom/templates/custom/*` hook fragments are not routed through the translation pipeline unless they ask for it, and ours was plain HTML with hardcoded labels. Verified by diffing the `en-US` and `sv-SE` responses: those lines were byte-identical while the upstream strings beside them ("Powered by Forgejo", "Licenses") translated correctly. **#334** — separately, all three pointed at the portal's Swedish URLs unconditionally. The site serves Swedish at `/` and English under `/en/` and does no `Accept-Language` detection, so an English reader clicking "Privacy Policy" landed on the Swedish page even once the label was fixed. Both are fixed in the same fragment by branching on `ctx.Locale.Lang`, which the application injects per request into every template including `custom/*` hooks. The stale comment claiming the legal pages detect English themselves is removed — they do not, and it is what caused #334. A trap worth recording, now in the fragment's comment: **do not** add translation keys under `custom/options/locale/`. Locale files are read through a layered asset filesystem whose `ReadFile` returns the first matching layer and stops, so a custom `locale_en-US.ini` would *replace* the entire built-in English locale rather than extend it. ### Rendered output ``` en-US https://www.gitborg.se/en/ gitborg.se https://www.gitborg.se/en/terms Terms of Service https://www.gitborg.se/en/privacy Privacy Policy sv-SE https://www.gitborg.se/ gitborg.se https://www.gitborg.se/terms Användarvillkor https://www.gitborg.se/privacy Integritetspolicy ``` **Swedish output is byte-identical to production**, proven rather than asserted: the whole footer region was extracted from the live `sv-SE` page and from a local render and compared — identical, including the leading newlines, which survive because comments are stripped as nodes rather than lines. Two details checked while in there: an explicitly chosen language wins over header sniffing (with a `sv-SE` header plus the switcher's `en-US` cookie, the footer renders English); and `{{$portal}}` sits in the path part of the `href`, so the normaliser rather than the escaper applies and `/en` stays `/en`. ### Verification Rendered and served through the local podman preview. `ansible-playbook site.yml --syntax-check` clean, `ansible-lint` 0 failures across 191 files, Prettier and markdownlint clean, gitleaks clean over 264 commits.
supernaut lade till 2 incheckningar 2026-08-02 15:56:08 +00:00
The three portal links in the Forgejo footer were plain HTML with hardcoded
Swedish labels, so an English UI showed "Användarvillkor" and
"Integritetspolicy" next to correctly translated Forgejo strings.

Forgejo hands every template — including the custom/* hook fragments, which are
included with the full page context — a per-request `ctx`, so the fragment can
branch on `ctx.Locale.Lang` and emit the label for the language the reader
selected. English wording matches the portal's own navigation.

Custom translation keys are deliberately not used: locale files are read through
a layered asset filesystem that returns the first matching layer and stops, so a
custom locale_en-US.ini would replace the built-in English locale rather than
extend it.

Swedish output is unchanged, byte for byte.

Closes #333
fix(forgejo): send english footer readers to the english portal pages
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m56s
46568abe45
The footer pointed at the portal's Swedish URLs unconditionally, so a reader
using Forgejo in English who clicked "Privacy Policy" landed on the Swedish
"Integritetspolicy" page.

The portal serves Swedish at / and English under /en/, and does no
Accept-Language detection, so whoever emits the link has to build the prefix.
Derive it from the Forgejo UI language — sv-SE gets no prefix, anything else
gets /en — which honours the language the reader explicitly selected and needs
no change to the website. It applies to all three links, including the bare
gitborg.se one, whose label stays as it is: a hostname, not translatable text.

Also drops the stale claim in the header comment that the legal pages do their
own English detection. They do not.

Swedish output is unchanged, byte for byte.

Closes #334
supernaut tvångsskickade fix/forgejo-footer-i18n från 46568abe45
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m56s
till 1584aee698
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m38s
2026-08-02 16:15:13 +00:00
Jämför
supernaut tvångsskickade fix/forgejo-footer-i18n från 1584aee698
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m38s
till cd6ce47f45
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m38s
2026-08-02 16:35:42 +00:00
Jämför
supernaut tvångsskickade fix/forgejo-footer-i18n från cd6ce47f45
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m38s
till 84bac4d01b
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m28s
2026-08-02 16:53:42 +00:00
Jämför
supernaut tvångsskickade fix/forgejo-footer-i18n från 84bac4d01b
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m28s
till d71b95ea98
Alla kontroller lyckades
ci / ci (pull_request) Successful in 2m3s
2026-08-02 18:30:11 +00:00
Jämför
supernaut tvångsskickade fix/forgejo-footer-i18n från d71b95ea98
Alla kontroller lyckades
ci / ci (pull_request) Successful in 2m3s
till 04f9342347
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m32s
2026-08-02 19:13:38 +00:00
Jämför
supernaut tvångsskickade fix/forgejo-footer-i18n från 04f9342347
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m32s
till bec37e477b
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m40s
2026-08-02 19:19:05 +00:00
Jämför
supernaut sammanfogade incheckning 81ab22ccad till main 2026-08-02 19:23:52 +00:00
supernaut tog bort grenen fix/forgejo-footer-i18n 2026-08-02 19:23:52 +00:00
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra!343
Ingen beskrivning angiven.