Skip to content

Languages

An installation speaks as many languages as it says it does, and it says so in the panel rather than in a file. This is the operator’s side of it: what to expect on disk, what an upgrade does, and what a second language costs.

The one language an installation ships with

Section titled “The one language an installation ships with”

APP_LOCALE (pl by default) seeds the first language when hilms:install runs, as the default one: it is enabled, it cannot be deleted, and its addresses carry no prefix. Nothing reads APP_LOCALE afterwards — Settings → Languages is the list from then on.

APP_FALLBACK_LOCALE stays en and means something different: it is the language a missing translation falls back to, and the code’s own language is English.

Settings → Region and time in the panel (administrators only) holds one time zone, from PHP’s own list. It is the clock the installation shows its times in and reads typed ones back from, in the panel and on the site alike: an administrator in Warsaw types 17:14 and 17:14 is what the course is published at, and a visitor who has said nothing reads every date on the same clock.

It is a default rather than the last word. A person may keep a clock of their own — on My account → Profile, or set for them on the Users form — and every date they are shown or type then follows theirs instead. Every panel field that carries a time says which zone it is in beside its label, so nobody has to infer it.

Times are stored in UTC whatever is chosen, which is why changing the zone later moves nothing and never makes an autumn hour ambiguous. Keep date.timezone=UTC in php.ini and leave APP_TIMEZONE alone. /api/v1 is a contract with no person in front of it and stays UTC on both sides of the wire, whatever this page says.

hilms:install asks for the zone once on a fresh installation, or takes it from --timezone=Europe/Warsaw. With --no-interaction — which is what the container entrypoint passes — it asks nothing and leaves the installation on UTC, and Settings → Region and time is where it is chosen afterwards. hilms:upgrade never asks.

The one exception is the AI assistants’ preferred window (Settings → AI assistants), which a worker applies with nobody present: those two fields are UTC and say so.

Settings → Languages in the panel (administrators only):

  1. “New language” offers every BCP-47 tag laravel-lang knows, with the name each language calls itself; the name is yours to correct.
  2. Drag the list into the order the switcher should show.
  3. “Make default” moves the unprefixed addresses to another language. It enables that language on the way, because a language nobody may see cannot be the one / serves.
  4. A language that is off can be edited in the panel but is never served: /de/o-nas answers 404 while German is off.
  5. A language cannot be deleted while it still holds courses or pages; the page says how many.

A new language costs nothing but the content you write in it. Nothing is copied automatically: a course or a page is written again in that language from its editor (“Add a translation”), which copies everything — the blocks, their files, the template and who the page is for — and leaves the copy a draft for somebody to read through.

Laravel’s own strings — validation messages, the paginator, the password reset mail — come from laravel-lang and live in lang/<code>/. Polish ships with the repository. For another language, a developer runs

php artisan lang:add de

and commits lang/de/. Without it, the framework’s own sentences stay English while everything HiLMS writes itself is translated.

Phrases in the panel lists everything the application can say — its own strings, its modules’, Laravel’s and the packages’ — with the English behind each one and what the chosen language says now. “Correct” stores one row that wins over one line of a file; “Back to the file” deletes it. Nothing in lang/ or vendor/ is ever edited, so an upgrade brings new and corrected files without touching what an installation decided to call things.

A correction must keep the :placeholders of the phrase it replaces: the application puts a value there.

Every public address exists twice: bare for the default language and behind a language prefix for the others (/kurs, /en/kurs). The panel, the API, the MCP server, the signed media and download links, the OAuth callbacks and /health carry no prefix.

A visitor’s language is decided by the address first, then the session, then the cookie, then Accept-Language; a signed-in person’s choice is remembered on their account and follows them onto another machine and into their mail.

artisan optimize and route:cache work exactly as before: the routes are static, and only which of them a visitor may reach depends on the table.

hilms:upgrade seeds the language from APP_LOCALE when the table is empty and never touches it again. Nothing else changes, and nothing is translated for you.

HiLMS is MIT-licensed. No replicants were harmed in the writing of these books.