Content Translator

Examples

Multiple examples to help you get started with the plugin.

Janitor Panel Button

While you can run Kirby commands from the CLI, you can also create a custom Kirby Janitor command to translate content and run it from the Panel. Below is an example of a Janitor command that translates the metadata of all files of a specific page to German:

Kirby Tools section preview

First, create a field in your blueprint that triggers the Janitor command. Make sure to replace de with the target language you want to translate the files metadata to:

fields/janitor-translate-files.yml
label: Translate Files Metadata
type: janitor
command: janitor-translate-files --language de

Then, create the Janitor command in your site/commands folder:

site/commands/janitor-translate-files.php
use Bnomei\Janitor;
use Kirby\CLI\CLI;

return [
    'description' => 'Translates all files metadata of a specific page.',
    'args' => [
        'language' => [
            'longPrefix' => 'language',
            'description' => 'The target language to translate the content to.',
            'required' => true
        ]
    ] + Janitor::ARGS,
    'command' => static function (CLI $cli): void {
        $kirby = $cli->kirby();
        $defaultLanguage = $kirby->defaultLanguage()->code();
        $targetLanguage = $cli->arg('language');
        $page = $kirby->page($cli->arg('page'));

        foreach ($page->files() as $file) {
            $translator = $file->translator();
            $translator->copyContent($targetLanguage, $defaultLanguage);
            $translator->translateContent($targetLanguage, $targetLanguage, $defaultLanguage);
        }

        Janitor::singleton()->data($cli->arg('command'), [
            'status' => 200,
            'message' => 'Files translated successfully!'
        ]);
    }
];

CLI Commands

You can leverage the Kirby CLI to automate the translation process. Below are four examples of CLI commands that you can use to translate content.

For these examples to work, install the Kirby CLI and create a new site/commands folder if it doesn't exist yet.

Translate Content of a Page

The most common use case is to copy the content from the default language to a secondary language and then translate the duplicated content to the target language. You can create a CLI command to automate this process:

site/commands/translate-page.php
use Kirby\CLI\CLI;

return [
    'description' => 'Translates the content of a specific page.',
    'args' => [
        'language' => [
            'description' => 'The target language to translate the content to.',
            'defaultValue' => 'de'
        ]
    ],
    'command' => static function (CLI $cli): void {
        $kirby = $cli->kirby();
        $defaultLanguage = $kirby->defaultLanguage()->code();
        $targetLanguage = $cli->arg('language');

        $siteChildren = $kirby->site()->children();
        $input = $cli->radio(
            'Which page should be translated?',
            $siteChildren->pluck('title')
        );
        $response = $input->prompt();
        $cli->success('Selected page: ' . $response);

        $page = $siteChildren->findBy('title', $response);
        $translator = $page->translator();
        $translator->copyContent($targetLanguage, $defaultLanguage);
        $translator->translateContent($targetLanguage, $targetLanguage, $defaultLanguage);

        $cli->success('Successfully translated ' . $page->id());
    }
];

Run the command in your terminal:

# Translate the content of a specific page to German
kirby translate-page de

Translate All Children of a Page

By leveraging the prompts, you can create a CLI command to translate all children of a specific page to a target language:

site/commands/translate-children.php
use Kirby\CLI\CLI;

return [
    'description' => 'Translates the content of all children of a specific page.',
    'args' => [
        'language' => [
            'description' => 'The target language to translate the content to.',
            'defaultValue' => 'de'
        ]
    ],
    'command' => static function (CLI $cli): void {
        $kirby = $cli->kirby();
        $defaultLanguage = $kirby->defaultLanguage()->code();
        $targetLanguage = $cli->arg('language');

        $siteChildren = $kirby->site()->children();
        $input = $cli->radio(
            'Which page\'s children should be translated?',
            $siteChildren->pluck('title')
        );
        $response = $input->prompt();
        $cli->success('Selected parent page: ' . $response);

        $page = $siteChildren->findBy('title', $response);

        foreach ($page->children()->listed() as $child) {
            $translator = $child->translator();
            $translator->copyContent($targetLanguage, $defaultLanguage);
            $translator->translateContent($targetLanguage, $targetLanguage, $defaultLanguage);
            $cli->out('Translated ' . $child->id());
        }

        $cli->success('Successfully translated all ' . $page->id() . ' children');
    }
];

Run the command in your terminal:

# Translate all children of a selected page to German
kirby translate-children de

Translate Files Metadata of a Page

Most of the time, you will want to translate the content of a page. But sometimes, you might want to translate the metadata of files (like the title or description) of a page. Use the translate-files.php command to translate the files metadata of all children of a specific page:

site/commands/translate-files.php
use Kirby\CLI\CLI;

return [
    'description' => 'Translates the files metadata of listed children pages.',
    'args' => [
        'language' => [
            'description' => 'The target language to translate the content to.',
            'defaultValue' => 'de'
        ]
    ],
    'command' => static function (CLI $cli): void {
        $kirby = $cli->kirby();
        $defaultLanguage = $kirby->defaultLanguage()->code();
        $targetLanguage = $cli->arg('language');

        $siteChildren = $kirby->site()->children();
        $input = $cli->radio(
            'Which page\'s files metadata should be translated?',
            $siteChildren->pluck('title')
        );
        $response = $input->prompt();
        $cli->success('Selected parent page: ' . $response);

        $page = $siteChildren->findBy('title', $response);

        foreach ($page->children()->listed() as $child) {
            foreach ($child->files() as $file) {
                $translator = $file->translator();
                $translator->copyContent($targetLanguage, $defaultLanguage);
                $translator->translateContent($targetLanguage, $targetLanguage, $defaultLanguage);
                $cli->out('Translated ' . $file->id() . ' metadata');
            }
        }

        $cli->success('Successfully translated all ' . $page->id() . ' files');
    }
];

Run the command in your terminal:

# Translate all children of a selected page to German
kirby translate-files de

Translate Content of the Whole Website

For large projects, you might want to translate the content of the whole website from the primary language to the secondary languages.

Use the translate-all.php command to translate the content of the whole website:

site/commands/translate-all.php
use Kirby\CLI\CLI;
use Kirby\Cms\Language;

$defaultAllLanguagesLabel = 'All Languages';

return [
    'description' => 'Translates the content of the whole website',
    'args' => [],
    'command' => static function (CLI $cli) use ($defaultTranslatorOptions, $defaultAllLanguagesLabel): void {
        $kirby = $cli->kirby();
        $defaultLanguage = $kirby->defaultLanguage()->code();
        $nonDefaultLanguages = $kirby->languages()->filter(fn(Language $language) => !$language->isDefault());

        $input = $cli->radio(
            'Content of which language/languages should be translated?',
            [
                $defaultAllLanguagesLabel,
                ...$nonDefaultLanguages->pluck('name')
            ]
        );

        $targetLanguage = $input->prompt();
        $hasAllLanguagesSelected = $targetLanguage === $defaultAllLanguagesLabel;
        $selectedLanguages = $hasAllLanguagesSelected
            ? $nonDefaultLanguages
            : $nonDefaultLanguages->filter(fn(Language $language) => $language->name() === $targetLanguage);

        $cli->success('Translating to: ' . implode(', ', $selectedLanguages->pluck('name')));

        // Translate all site translations
        foreach ($selectedLanguages as $language) {
            /** @var \JohannSchopplich\ContentTranslator\Translator */
            $translator = $kirby->site()->translator($defaultTranslatorOptions);

            $translator->copyContent($language->code(), $defaultLanguage);
            $translator->translateContent($language->code(), $language->code(), $defaultLanguage);
            $cli->{$hasAllLanguagesSelected ? 'out' : 'success'}('Translated site data to ' . $language->name());
        }

        if ($hasAllLanguagesSelected) {
            $cli->success('Successfully translated all ' . $kirby->site()->title() . ' site data');
        }

        // Recursively translate all pages
        foreach ($kirby->site()->index() as $page) {
            /** @var \JohannSchopplich\ContentTranslator\Translator */
            $translator = $page->translator($defaultTranslatorOptions);

            foreach ($selectedLanguages as $language) {
                /** @var \Kirby\Cms\Language $language */
                $translator->copyContent($language->code(), $defaultLanguage);
                $translator->translateContent($language->code(), $language->code(), $defaultLanguage);
                $translator->translateTitle($language->code(), $language->code(), $defaultLanguage);
            }

            $cli->out('Translated ' . $page->id());
        }

        $cli->success('Successfully translated all ' . $kirby->site()->title() . ' pages');
    }
];

Run the command in your terminal:

# Translate all pages of the selected language/languages to their target language
kirby translate-all