Skip to main content

Translations

authentik uses @lit/localize for frontend translations and Django's translation tools for backend messages. English is the source language for both.

  • Translation contributors translate existing messages through Transifex.
  • Code contributors mark messages for translation in the source code. Bots extract and compile the translation catalogs in follow-up PRs.

For translation contributors

Submit translations through the authentik project on Transifex. You do not need to clone the repository, install development tools, or open a PR.

  1. Sign in to Transifex and join the project for your language.
  2. Choose the frontend or backend resource and translate its messages.
  3. Save your translations. The Transifex integration brings them into the repository automatically, and bots compile them in follow-up PRs.

Preserve placeholders, markup, and plural forms when translating. These represent values or formatting that authentik supplies at runtime.

Use Transifex for corrections to existing translations too. Local catalog edits are useful for previewing a translation, but submit the final translation through Transifex.

For code contributors

In normal code PRs, add or change the marked strings in the source code. Do not extract or compile translations for your PR. Bots handle extraction and compilation in follow-up PRs.

Do not run make i18n-extract, make web-i18n-extract, or make core-i18n-extract as a PR preparation step. Leave generated catalog and compiled translation changes out of your PR, including any generated during a local build or preview.

Mark frontend strings

Wrap user-visible strings with msg from @lit/localize:

import { msg } from "@lit/localize";

msg("New text to be translated.");

For messages containing expressions or HTML, follow the Lit localization guide.

Mark backend strings

Use Django's translation functions. For strings declared at module level, such as model field labels, use gettext_lazy so that Django translates them when they are used:

from django.utils.translation import gettext_lazy as _

_("New text to be translated.")

Use gettext for immediate translation while handling a request. In Django templates, use {% trans %} or {% blocktrans %} after loading i18n. See the Django translation guide for placeholders, pluralization, and template examples.

Register a frontend language

Adding support for a new frontend language requires source configuration as well as translations:

  1. Add the language tag to targetLocales in web/lit-localize.json, keeping the existing entries.

  2. Add a matching entry to LocaleLoaderRecord in web/src/common/ui/locale/definitions.ts. For example, a new sv-SE locale needs:

    "sv-SE": () => import("#locales/sv-SE"),

The locale's catalog uses the same tag, for example web/xliff/sv-SE.xlf. The frontend build requires that catalog to exist. For a local preview, generate it with make web-i18n-extract, then follow the frontend preview steps. Submit translations through Transifex and leave generated files out of the code PR.

en is the source locale. en-XA is a generated pseudo-locale for testing the UI and does not need translation.

Optional local previews

Use these steps to check how a translation appears in authentik. They are not required for a normal PR. Run commands from the repository root and keep generated translation changes out of your PR.

Frontend

Set up the frontend development environment, including the backend that serves your local frontend build.

  1. Edit web/xliff/<locale>.xlf, such as web/xliff/de-DE.xlf, with a text editor or an editor that supports XLIFF. Translate the <target> content while preserving the <source>, message IDs, and placeholders such as <x .../>.

  2. Start the frontend watcher. It compiles the catalogs at startup:

    make web-watch
  3. Open your local instance with a locale query parameter, for example http://localhost:9000/if/user/?locale=de-DE.

After further .xlf edits, rebuild the locale modules in another terminal, then reload the page:

pnpm --dir web run build-locales

The build generates web/src/locales/ and web/src/locale-codes.ts. Edit the XLIFF catalogs rather than these generated files.

Backend

Set up the full development environment and install GNU gettext, which provides xgettext, msgmerge, and msgfmt.

  1. Edit locale/<locale>/LC_MESSAGES/django.po with a text editor or a PO editor such as Poedit. Translate msgstr entries while preserving msgid values, placeholders, and plural forms. Backend directory names can differ from frontend language tags; for example, German uses de_DE in the backend and de-DE in the frontend.

  2. Compile the catalog, using German as an example:

    uv run ak compilemessages -l de_DE
  3. Restart the local backend and select the language in authentik to check the translated messages. Django loads the generated django.mo file at runtime.

Extract new strings for a preview

If a string you added is missing from the local catalogs, extract it before translating it locally:

  • make web-i18n-extract updates the frontend XLIFF catalogs in web/xliff/.
  • make core-i18n-extract updates only the English backend source catalog, locale/en/LC_MESSAGES/django.po.
  • make i18n-extract runs both extraction targets.

To create or refresh a backend catalog for another language locally, specify its locale with Django's extraction command:

uv run ak makemessages --add-location file --no-obsolete \
--ignore web --ignore internal --ignore packages/client-ts --ignore website \
-l de_DE

After extraction, follow the frontend or backend preview steps above. Bots perform this work for submitted source changes; these local commands are only for previewing them.