Translate Related Pages and Files
Some content lives outside the page an editor has open: the module pages of a page builder, the metadata of a page's files, the children of an overview page. The cascade option names these models with a Kirby query, and every translation started from the view translates them too.
The model whose view starts the translation is the host. The models its cascade option names are its cascade.
Name the Cascade
Set cascade on the view button or the section of the host's blueprint. It takes one Kirby query or a list of them:
buttons:
open: true
preview: true
settings: true
content-translator:
cascade: page.files
languages: true
status: true
sections:
contentTranslator:
type: content-translator
cascade:
- page.files
- page.children.listed
On the view button, cascade needs the map form shown above. A map replaces Kirby's default buttons, so keep naming every button you want.
A translation cascades only when the view button or section it starts from sets cascade. With both in one blueprint, give them the same queries.
A query can use kirby, site, and model – the host itself – plus the alias of the host's own type: page, file, or site. The null-safe operator keeps a query valid while the model it starts from does not exist yet:
cascade: page.find("modules")?.children
Only pages and files take part, drafts included when a query such as page.drafts reaches them. The host itself and the models the current user may not open or edit are left out. A query that fails or finds nothing adds nothing and shows no error, so a typo shows up only as a missing or too-low count in the dialog before a translation.
site.index translates the whole site from one button.The Cascade Is Saved Directly
The cascade is always translated from the saved content of the default language and saved directly in the target language, so Discard on the host does not revert it. The dialog before a translation states how many pages and files come along.
- Batch translation translates the host and its cascade into every selected language.
- Single-language translation saves the cascade in the current language, while the host's fields stay in the form for review. Nothing is cascaded while the default language is open, while another user edits the host, or without the permission to update the host.
- Import does not cascade.
A model of the cascade is translated by the host's options:
- The host's
fieldTypes,kirbyTags, andsystemPromptapply. Acontent-translatorsection or view button on the model's own blueprint is not read, buttranslate: falseon its fields holds. includeFieldsandexcludeFieldsfrom the host's blueprint do not apply, since they name the host's fields. Those set in the global configuration do.- A page gets a translated title when the host's
titleoption is on and the current user may change that page's title. - The slug is never translated.
Three things hold a model of the cascade back, and the translation results say which:
- Another user edits it. The remaining models are still translated.
- Its default language has unsaved changes. The translation would miss them, so save or discard them first.
- A target language has unsaved changes. Only that language of the model is held back, as for the host.
Kirby Modules
Kirby Modules stores the modules of a section as child pages of a container page named after the section. For a section named modules, one line in the host's blueprint translates them along with the page:
buttons:
open: true
preview: true
settings: true
content-translator:
cascade: page.find("modules")?.children
languages: true
status: true
sections:
modules:
type: modules
For more than one modules section, list one query per section. A section named sidebar keeps its modules in page.find("sidebar").
The query reads the container's children rather than Kirby Modules' page.modules method, because that method leaves out hidden modules, and new modules start hidden.
For modules that contain modules, collect the whole tree and keep only the module pages:
cascade: page.find("modules")?.index.filterBy("isModule", true)
Module blueprints set changeTitle: false by default, so module titles stay as they are.
From PHP
The PHP API has no cascade. Loop over the same models instead:
$targetLanguage = 'de';
$defaultLanguage = kirby()->defaultLanguage()->code();
$page = page('about');
$models = [$page, ...$page->files(), ...($page->find('modules')?->children() ?? [])];
foreach ($models as $model) {
$translator = $model->translator();
$translator->copyContent($targetLanguage, $defaultLanguage);
$translator->translateContent($targetLanguage, $targetLanguage, $defaultLanguage);
}