Customize and translate the pages
This guide makes the pages your users see look and read like your product, in their language.
There are three levels, from a setting in the admin console to your own copy of the pages. Start with the first: most deployments need nothing more.
Brand the pages
Section titled “Brand the pages”-
In the admin console, open Admin, General and set App name, up to 30 characters. It’s shown at the top of the sign-in pages and ends their titles, as in “Sign in – Acme”. It also signs every email, and it’s the name authenticator apps list your users’ accounts under.
-
Open Admin, Theme and choose a Color theme. It applies to the sign-in pages and the admin console alike. A new install starts on Automatic, which follows each visitor’s device. To use your own colors, see Regenerate the CSS.
-
Give each client a display name and a logo, so users see which app they’re signing in to. See Clients.
Add a language
Section titled “Add a language”The pages come in English, Portuguese (Brazil), Spanish, French, Italian and German. To add another language, you translate one file of text and point both servers at it, with no rebuild.
-
Get the English text of the release you run:
src/core/i18n/catalogs/active.en.tomlin the source at that release’s tag, such asv1.7.0. The release is in the image tag and in thebuild informationline each server logs when it starts. -
Copy it into a folder named
catalogs, asactive.<language>.toml, named with the language’s BCP 47 tag:active.nl.tomlfor Dutch. Translate the text on the right of each=and leave the keys on the left as they are:catalogs/active.nl.toml "auth.pwd.title" = "Aanmelden""auth.pwd.email_label" = "E-mailadres""auth.pwd.password_label" = "Wachtwoord""auth.pwd.button" = "Aanmelden"Keep a placeholder such as
{{.appName}}exactly as it is: the server writes the value there. A key you leave out, or leave empty, shows in English. -
Make the folder that holds
catalogsreadable by both servers, and setGOIABADA_I18N_OVERRIDES_DIRto it on the auth server and on the admin console. In a container, mount it read-only, as the templates are mounted below. -
Restart both servers. Each reads the catalogs once, at start, and refuses to start when one doesn’t parse, naming the file.
-
Users choose the language under Account, Profile in the admin console, and your app can ask for it on the sign-in pages with
ui_locales. See how the language is chosen.
Change a few words
Section titled “Change a few words”To reword a page in a language Goiabada already has, override only the keys you change, in the same folder:
"auth.pwd.title" = "Sign in to Acme"Every key you don’t name keeps the built-in text. Set GOIABADA_I18N_OVERRIDES_DIR and restart, as in Add a language.
Change the templates
Section titled “Change the templates”To change the layout of a page, or an email’s body, you give a server its own copy of the templates. The templates and static files are compiled into each server’s binary, and the images hold the binary alone, so there’s no web folder inside a container to copy out.
-
Copy the web files from the source of the release you run, since a template from another release may use data the server no longer passes to it:
Terminal window RELEASE=v1.7.0 # replace with the release you rungit clone --depth 1 --branch "$RELEASE" https://github.com/leodip/goiabada.git goiabada-sourcemkdir authserver-web adminconsole-webcp -r goiabada-source/src/authserver/web/{template,static,tailwindcss} authserver-web/cp -r goiabada-source/src/adminconsole/web/{template,static,tailwindcss} adminconsole-web/tailwindcssisn’t served: it’s what regenerating the CSS reads. -
Edit the templates. They’re Go
html/templatefiles. Keep the element IDs and the scripts the pages use, or the forms stop working. -
Make the files readable by the containers. Both images run as uid 10001 and gid 10001 (see the user the images run as), and a page whose template the server can’t read fails with a 500:
Terminal window chmod -R a+rX authserver-web adminconsole-web -
Mount each directory read-only and point its server at it, in
docker-compose.override.yml, which a run of the setup wizard with--keep-secretsleaves as it is. Add the volumes and the variables to the two services already there, beside their secrets. They add to the volumesdocker-compose.ymlgives each service, and win over the empty values it lists:goiabada-authserver:volumes:- ./authserver-web/template:/app/web/template:ro- ./authserver-web/static:/app/web/static:roenvironment:- "GOIABADA_AUTHSERVER_STATICDIR=/app/web/static"- "GOIABADA_AUTHSERVER_TEMPLATEDIR=/app/web/template"goiabada-adminconsole:volumes:- ./adminconsole-web/template:/app/web/template:ro- ./adminconsole-web/static:/app/web/static:roenvironment:- "GOIABADA_ADMINCONSOLE_STATICDIR=/app/web/static"- "GOIABADA_ADMINCONSOLE_TEMPLATEDIR=/app/web/template"Leave a server’s pair empty if you haven’t changed its files. Then run
docker compose up -d. With the native binaries, set the same variables in the env file, naming directories the binaries’ user can read. -
Open every page you changed. A mistake in a template shows only when its page is rendered.
Regenerate the CSS
Section titled “Regenerate the CSS”The pages are styled with Tailwind CSS, and main.css holds only the classes the templates used when it was generated. A class you add to a template does nothing until you regenerate it.
The colors are tokens at the top of tailwindcss/ui.css: the light palette in its @theme block, and the dark one under @variant dark just below. Change them there and regenerate, keeping each text color readable on the background it’s drawn on, in both palettes. Each server has its own copy of ui.css, so change both if you want the sign-in pages and the admin console to match.
-
Download the standalone Tailwind CLI for your platform from Tailwind’s releases, at the version the release you copied pins:
tools.tailwindingoiabada-source/src/authserver/versions.yaml. Rename it totailwindcssand make it executable. -
Run it in each web directory whose templates or
ui.cssyou changed. Add--minifyfor a smaller file:Terminal window cd authserver-webtailwindcss -i ./tailwindcss/input.css -o ./static/main.cssinput.csslooks for class names in../templateand in the JavaScript in../static, so keep the three folders side by side. -
The new
main.cssis in the static directory you mounted, so the server serves it at once. The pages link it by a fingerprint of its contents, so browsers fetch the new one on their next page load.
How the language is chosen
Section titled “How the language is chosen”On the auth server’s pages, the sign-in, one-time code, consent, sign-out, registration and password reset pages, the language is the first of these that names one:
- The
ui_localesparameter of the authorization request, or of the sign-out: one or more language tags in your order of preference, separated by single spaces, such asui_locales=es pt-BR. It’s kept for the rest of that sign-in, and applies to the error page the auth server shows when it refuses the request outright. - The browser’s
Accept-Languageheader. - English.
In the admin console, the user’s own choice comes first: the Language and region they picked under Account, Profile, which reaches the console as the locale claim of their ID token. The console picks a change up the next time it refreshes the user’s tokens, within five minutes with the default token lifetime. Without one, the browser’s Accept-Language decides, then English.
Whichever of these decides, it gets the first of its languages Goiabada has text for, or English when it has none of them: ui_locales=sv nl shows Dutch when you’ve added Dutch but not Swedish, and ui_locales=sv alone shows English.
A value an admin console form won’t take is refused by the auth server, in the console page’s language, which is why both servers need your override catalogs.
An email is written in its recipient’s language: the Language and region on their profile, or English when they haven’t picked one. The activation link and the welcome email a user gets when they register are written in the language of the page they registered on, since their account has no language yet.
Catalogs
Section titled “Catalogs”The text of every page, message and email subject is in the built-in catalogs. A key with no text in the chosen language shows in English.
GOIABADA_I18N_OVERRIDES_DIR names a folder whose catalogs subfolder holds active.<language>.toml files. Nothing else in the folder is read: files put in the folder itself are ignored, and the server logs override directory has no catalogs subdirectory, skipping it when it starts. Each file is merged over the built-in catalog of its language, key by key, and the file wins. A value left empty removes the built-in text, so the key shows in English. Every value is a plain string: a [table] section stops the server at start.
The names of countries and phone country codes, and the country in each time zone’s label, come from Unicode’s CLDR data, in the page’s language, and each language on the Language and region list is named in itself and in English, so none of them needs translating.
The durations the admin console writes in words, under a duration field and in how long to wait before asking for another verification code, come from the browser’s own CLDR data in the page’s language, or in English where the browser has none, so they need no translating either.
Email bodies
Section titled “Email bodies”An email’s subject is in the catalogs, and its body is a template under emails/ in the auth server’s templates. To translate a body, add a copy beside the English one named with the language, such as emails/email_forgot_password.nl.html, in your own templates directory. A copy named for exactly the recipient’s language wins. Otherwise the closest copy in their language does: nl serves a recipient reading nl-BE, and pt-BR serves one reading pt. A recipient with no copy in their language gets the English template.
Templates and static files
Section titled “Templates and static files”A server reads a template each time it renders the page, so an edited template shows on the next request with no restart. Static files are served with Cache-Control: public, max-age=300. The four directory variables are on Environment variables.