Appearance
Phrases
Every text the site and its admin say, per module, theme and language: change a word, or translate the site into a language of your own — without a file.
kitloom/ · admins: kitloom/, kitloom/
Video lessons
Recorded in the Filament admin; the Nova admin works the same way.
Every text your site and its admin say — a button, a label, a message of a module, a theme or the application — listed per package and per language, so you can change a word or translate the site into a language kitloom does not ship, without touching a file. The Phrases screen is in both admins; kitloom/ and kitloom/ draw it.
What a phrase is — and what it is not
A phrase is a text written by a developer in the code: Read more, Add to cart, Leave a comment, Your order is on its way. Laravel calls these translation lines; the English sentence is the key, and a package may ship a translation of it in lang/. Phrases shows them to you, with the package's own line beside yours.
What you typed is not a phrase: the site's title, a page, a menu item, a product's name, a form's placeholders. Those are content, options and — with kitloom/languages — Site Texts, translated with the rest of the site. Phrases never touches them.
The Phrases screen
The first screen lists where the phrases come from — each module, each theme, the core packages, and This site (the application's own code) — with how many texts each says and, for every language, how many have a line. Open a package in a language to see its texts:
- Source — the English text, as the code says it. Under it, also in N packages when other packages say the very same text: Laravel keeps one dictionary, so your line is read everywhere the text appears.
- Shipped — what the package itself translates it as, when it does. Read-only: the file belongs to the package.
- Yours — your line. Type it and it is shown on the site at once, on every page in that language. Empty it and the shipped text stands again.
A line must keep what the text fills in: :, :, %s, %1$s, and the | that separates plural forms (:). A line that lost one is refused with a note — the page would draw the text without its value otherwise.
Filters show the texts missing a line, those you changed, and the drafts. Sync reads the packages' code anew after an update.
Languages
The editor offers the site's own language, the languages of kitloom/languages when it is installed, and any you add under More languages (a locale: de, uk, pt_). A line written for fr is read on a Canadian French page (fr_) too, unless fr_ has a line of its own.
To make the site speak a language you translated, set Site Language in Settings → General to that locale: every language here is on its list. What has no line in it yet stays in English. With kitloom/languages, a page speaks that module's languages instead: add German there, and its lines come from here.
With an AI model
With kitloom/ai-writer set up, Translate empty with AI sends the texts that have no line in a language to the site's model, in the background. The answers come back as drafts: kept, marked, shown nowhere until you have read them — Publish drafts puts them on the site. A line the model returned without its placeholders is dropped and counted.
Files in and out
- Import JSON — a dictionary file (
"English text":) into a language: a translator's work, a"line" lang/from another site.<locale>. json - Export JSON — a package's lines as its
lang/, with the shipped lines merged in if you ask: the file a developer commits into the package, so the next site gets your translation out of the box.<locale>. json - Move to code — every line of a language written into the application's own
lang/, which Laravel reads over the packages'; tick remove the rows and the file alone speaks from then on. For a site that has settled and keeps its words in git. The web server must be allowed to write<locale>. json lang/; the screen says when it is not.
The same from the console:
bash
php artisan phrases:scan # read the packages anew; counts per package
php artisan phrases:scan --check # the texts without a line, per package and language; fails when any
php artisan phrases:export fr --package=kitloom/shop --merge # the shop's lang/fr.json
php artisan phrases:export de --application --prune # every German line into lang/de.json, rows removed
php artisan phrases:import translations.json --locale=de # a dictionary into GermanFor developers
- Lines live in the
phrasestable — group, key, locale, text, status, source, who wrote it — and reach Laravel's translator through spatie/laravel-translation-loader: its manager reads a group from the language files as Laravel does, then lays the loaders' lines over them. This module names itself as the one loader (translation-); spatie's ownloader. translation_ loaders Dbloader and itslanguage_table are not used. The manager is the module'slines Translation(Manager translation-): spatie's, built with the framework's own language files under the application's, as Laravel builds its loader — spatie leaves them out, andloader. translation_ manager auth.would come back as the key. Namespaced groups (failed filament::) never reach a loader, by spatie's design — Filament ships its own languages.… - The lines of a group and a locale are read once into the cache and forgotten when one is written. A long-lived worker (Octane, a queue) compares a version in the cache at the start of each request and job, and drops the translator's lines when another worker wrote one.
- Which texts a package says is read from its code with the same scanner the packages' translation tests use (
Kitloom\):Wp Schema\ Translations\ Code Texts __,() trans_,choice() @lang(), a post type's declared labels,t()and__in a theme's scripts, and the keys of its own() lang/. Scans are cached per package version; Sync or*. json phrases:forgets them.scan - A line may also stand in for one of Laravel's own group files —
auth,validation,passwords,pagination(validation.) — throughrequired phrases:/import phrases_with that group; other group files are the packages' alone. Laravel tries every text its files lack as a group (set Read more→lang/), so the loader answers for those four groups and the JSON lines only, and touches the table for nothing else.en/ Read more. php - A page cache is cleared whole when a line changes: the loader reads the cache, not the table, so no page's reads name the row.
- Events:
Kitloom\,Phrases\ Events\ Phrase Saved Phrase(the row, the actor),Deleted Phrases(the AI job is done).Translated - Agents (kitloom/ai):
phrases_,packages phrases_,list phrases_, behindset manage_; off withphrases kitloom-.phrases. ai. register - Permission:
manage_— administrators. Settings:phrases kitloom_,phrases_ locales kitloom_.phrases_ scan_ application - Config
kitloom-: the admin switches, the AI switch, andphrases. php scan./paths scan.— which directories of a package are read and which are passed over (except tests,node_,modules vendor,dist).