---
title: "Translator"
description: "Translate any page, file, or site model in place from PHP – with static helpers when you only have raw strings."
canonical_url: "https://kirby.tools/docs/content-translator/php-classes/translator"
---

# Translator

> Translate any page, file, or site model in place from PHP – with static helpers when you only have raw strings.

Two ways to build one: `new Translator($model)` or the model method `$model->translator()`. Static helpers (`translateText`, `translateTexts`) bypass the instance for raw-string translation.

```php
use JohannSchopplich\ContentTranslator\Translator;

$translator = new Translator(page('blog/article'));
$translator->copyContent('de', 'en');
$translator->translateContent('de', 'de', 'en');

$page = $translator->model();
```

<tip>

The same instance is exposed as a model method on `Site`, `Page`, and `File`: `$page->translator()`. The `translator()` global helper mirrors the constructor.

</tip>

## Construction

```php
public function __construct(Site|Page|File $model, array $options = [])
```

<field-group>
<field name="model" type="Site | Page | File">

The Kirby model whose content you want to translate.

</field>

<field name="options" type="Array">

Per-instance overrides for the same scoping options as the [global config](/docs/content-translator/configuration/global) – `fieldTypes`, `includeFields`, `excludeFields`, `kirbyTags`.

</field>
</field-group>

```php
$translator = translator(page('blog/article'), [
    'fieldTypes' => ['text', 'textarea', 'blocks'],
    'excludeFields' => ['date', 'author'],
]);
```

## Instance Methods

### `copyContent`

Copy a source language's content over to a target language. Overwrites the target.

```php
public function copyContent(string $toLanguageCode, string $fromLanguageCode): void
```

```php
$translator->copyContent('de', 'en'); // Copy English → German
```

<note>

When you copy from the default language to a secondary language on Kirby 5+, the target content file is **deleted** instead of overwritten – Kirby's built-in language inheritance keeps it in sync until you actually translate it.

</note>

### `translateContent`

Translate the content already stored in `$contentLanguageCode` and save it back. The fourth parameter overrides the configured strategy for this call only.

```php
public function translateContent(
    string $contentLanguageCode,
    string $toLanguageCode,
    string|null $fromLanguageCode = null,
    Strategy|null $strategy = null,
): void
```

Typical pattern – copy first, then translate the duplicated content:

```php
$translator->copyContent('de', 'en');
$translator->translateContent('de', 'de', 'en');
```

<warning>

Throws `TranslationException` when the strategy fails for every collected unit. See [Exceptions](/docs/content-translator/php-classes/exceptions).

</warning>

### `translateTitle`

```php
public function translateTitle(
    string $contentLanguageCode,
    string $toLanguageCode,
    string|null $fromLanguageCode = null,
): void
```

Translate the model title. Falls back to the source language when the target-language title is empty.

```php
$translator->translateTitle('de', 'de', 'en');
```

### `translateSlug`

```php
public function translateSlug(
    string $contentLanguageCode,
    string $toLanguageCode,
    string|null $fromLanguageCode = null,
): void
```

Translate the page's current slug and rename the page to the result. Independent of `translateTitle` – the slug string is what goes to the strategy, not the title. No-op for the homepage, the error page, and non-page models.

```php
$translator->translateSlug('de', 'de', 'en');
```

### `model`

```php
public function model(): Site|Page|File
```

Mutating methods don't return the new model. Reach for `model()` to grab the up-to-date instance:

```php
$translator->translateContent('de', 'de');

// $page still holds the pre-translation model
echo $page->content()->get('text');

// Reassign to read the translation
$page = $translator->model();
echo $page->content()->get('text');
```

## Static Helpers

Translate raw strings without a model. Both methods return the source unchanged for text a provider would only corrupt: blanks, pure numbers, standalone URLs, and prose that is only KirbyTag placeholders. Those entries never leave your server – when a batch contains nothing else, no provider request is made at all.

```php
public static function translateText(
    string $text,
    string $targetLanguage,
    string|null $sourceLanguage = null,
    Strategy|null $strategy = null,
): string

public static function translateTexts(
    array $texts,
    string $targetLanguage,
    string|null $sourceLanguage = null,
    Strategy|null $strategy = null,
): array
```

Prefer `translateTexts()` over a loop – DeepL packs up to 50 texts per request, and the AI strategy chunks intelligently.

```php
echo Translator::translateText('Hello world', 'de', 'en');
// "Hallo Welt"

$translated = Translator::translateTexts(['Hello', 'Goodbye'], 'de', 'en');
// ['Hallo', 'Auf Wiedersehen']
```

The optional `$strategy` parameter on `translateText`, `translateTexts`, and `translateContent` overrides the configured strategy for one call:

```php
use JohannSchopplich\ContentTranslator\Translation\Strategies\CopilotAIStrategy;

Translator::translateText('Hello', 'de', 'en', new CopilotAIStrategy());
```

See [Strategies](/docs/content-translator/php-classes/strategies) for the full interface and built-in implementations.

---

Every page of this site as Markdown: <https://kirby.tools/sitemap.md>
