Machine translation for Marble CMS item field values using DeepL or Google Translate.
composer require marblecms/marble-translate
php artisan marble:translate:installPublish config:
php artisan vendor:publish --tag=translate-config| Key | Default | Description |
|---|---|---|
provider |
deepl |
Default provider: deepl or google |
api_key |
'' |
API key for the chosen provider |
deepl_pro |
false |
Use DeepL Pro endpoint (api.deepl.com vs api-free.deepl.com) |
.env variables:
TRANSLATE_PROVIDER=deepl
TRANSLATE_API_KEY=your-key-here
TRANSLATE_DEEPL_PRO=false
- Admin visits Structure → Translate to see all published items with translatable fields
- Items show a per-language coverage indicator (tick = translated, "Missing" = not yet)
- Click the arrow button to open the translation workspace for an item
- Select source language, target language, and provider; click Translate
- The plugin calls the API and creates a pending TranslationJob with the results
- Review the source vs. translated values in the diff table
- Click Apply All to write the translations back to
item_values, or Reject to discard
Applying a job fires the ItemTranslated event.
Uses the DeepL API v2. Free tier uses api-free.deepl.com; Pro tier uses api.deepl.com (set TRANSLATE_DEEPL_PRO=true).
Uses the Cloud Translation Basic (v2) API. Requires a Cloud Translation API key.
Accessible via Structure → Translate.
| Method | URL | Route name | Description |
|---|---|---|---|
| GET | /{prefix}/translate |
marble.translate.index |
Items needing translation |
| GET | /{prefix}/translate/item/{item} |
marble.translate.show |
Translation workspace |
| POST | /{prefix}/translate/item/{item} |
marble.translate.translate |
Trigger API translation |
| POST | /{prefix}/translate/job/{job}/apply |
marble.translate.apply |
Apply pending job |
| POST | /{prefix}/translate/job/{job}/reject |
marble.translate.reject |
Reject pending job |
| Event | Properties |
|---|---|
ItemTranslated |
$item, $job |
| Command | Description |
|---|---|
marble:translate:install |
Run migrations |
translation_jobs
| Column | Type | Notes |
|---|---|---|
id |
bigint | PK |
item_id |
bigint | FK → items (cascade delete) |
source_language_id |
bigint | FK → languages |
target_language_id |
bigint | FK → languages |
provider |
string | deepl or google |
status |
string | pending, applied, rejected |
translated_fields |
json | {field_identifier: translated_value} |
created_at / updated_at |
timestamps | |
applied_at |
timestamp | nullable — when job was applied |
Implement a provider class with this interface:
public function translate(array $texts, string $sourceLang, string $targetLang): array;Then extend TranslationService::resolveProvider() or bind your provider in a service provider.