ServerAvatarDocs
Reference & troubleshooting

Languages

The eight locales that ship, where the message files live, how the panel picks one, and what happens to a key nobody translated.

OSS Panel ships in eight languages. This page is the reference behind them — what resolves a locale, where the text lives, and how to change or extend it.

For using the switcher day to day, see Account → Language.

The eight locales

LanguageCodeMessage file
Englishenmessages/en.json
Españolesmessages/es.json
Deutschdemessages/de.json
Françaisfrmessages/fr.json
हिन्दीhimessages/hi.json
Portuguêsptmessages/pt.json
日本語jamessages/ja.json
Русскийrumessages/ru.json

English is the default and the fallback. The list is deliberately derived from the files: a locale appears in the switcher only when frontend/messages/<code>.json exists.

How a locale is picked

In order, stopping at the first answer:

The NEXT_LOCALE cookie, if it holds one of the eight codes. This is what the switcher sets, for a year.

The browser's Accept-Language header — the first entry, cut to its two letter prefix. fr-CA therefore lands on fr.

English.

No locale in the URL

There is no /en/… or /fr/… prefix and no routing middleware. /account is /account in every language, which is why a link is safe to paste between two people reading the panel in different languages.

What a missing translation does

Two separate safety nets, and neither one shows the user a blank.

Per key, not per file. A locale's messages are deep-merged over English, so a partially translated language is a usable language: translated keys appear in that language, untranslated ones in English. A half-finished locale never takes a page down.

A key missing everywhere is rendered as a readable version of itself rather than a dotted identifier — the last segment, un-camel-cased and sentence-cased, so set_ownership becomes "Set ownership". Many keys are built from API values, so a value the frontend has never seen produces readable text instead of activity.actions.set_ownership.

Missing keys are logged in development and never thrown in production.

Changing or adding wording

The message files are plain JSON, one per locale, and they are bundled into the frontend at build time. So editing them is a build, not a restart:

Edit the file for the locale under /var/www/panel/frontend/messages/. Keep the key structure identical to en.json — the merge is by key path.

Rebuild and restart the frontend.

cd /var/www/panel/frontend
npm run build
systemctl restart panel-frontend

This is also how a re-brander changes wording rather than just the logo — and there is a shortcut for the most common case. Sentences that name the product use a {brand} placeholder filled from BRANDING_NAME, not a hardcoded word:

"subtitle": "Update {brand} itself. Hosted applications stay online; only this panel restarts."

Setting BRANDING_NAME therefore renames the product across all eight languages at once, with no message file to touch.

Caveats

  • The choice is per browser, not per account. It lives in a cookie, so signing in from another machine starts at the default again, and there is no language field on a user's profile.
  • Your own data is never translated — application names, database names, usernames, paths, log lines, command output and version numbers stay as they are.
  • Dates and numbers follow the chosen language, not the server's timezone. The clock and timezone are set separately in Settings → Server.
  • A locale with no message file cannot be selected, even if you add it to the switcher's name list — the list of names and the list of locales are checked against each other.
  • Upgrading the panel overwrites the message files. Customised wording needs re-applying after an update; prefer BRANDING_NAME where it is enough.

On this page