Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sulu Ai Translator Bundle Laravel Package

robole/sulu-ai-translator-bundle

A Symfony bundle for Sulu CMS that brings AI-powered translation into the admin interface. Translate pages and snippets, speed up multilingual content workflows, and manage translations without leaving Sulu, with configurable AI provider integration.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: this is a Sulu CMS bundle, and Sulu is a Symfony-based CMS. It will not install or run inside a Laravel application. If you are a Laravel developer, the realistic path to using it is either (a) you are working in a Sulu/Symfony project alongside your Laravel work, or (b) you are evaluating it as a reference implementation for wiring DeepL into your own Laravel translation pipeline. The rest of this assessment assumes case (a); case (b) notes are called out where relevant.

Minimal setup in a Sulu 2.x project:

composer require robole/sulu-ai-translator-bundle
  1. Register the bundle in config/bundles.php (Sulu apps use the Symfony bundle registration pattern, not Laravel's package discovery):
    Robole\SuluAiTranslatorBundle\SuluAiTranslatorBundle::class => ['all' => true],
    
  2. Configure your DeepL credentials. Check config/packages/ for the bundle's expected config key (typically robole_ai_translator), and set the API key via env:
    robole_ai_translator:
        deepl_api_key: '%env(DEEPL_API_KEY)%'
    
  3. Add DEEPL_API_KEY to .env, then bin/console cache:clear.
  4. Confirm the DeepL client resolves: bin/console debug:container | grep -i translate.

Where to look first: the bundle's DependencyInjection/ folder for the exact config tree, and its Service/ folder for the translator entry point. Those two files tell you more than the README about what is actually configurable.

First use case: open a page in the Sulu admin, switch to the source locale, and invoke the translation action the bundle adds to the toolbar/dropdown. Translate a single page from your default locale into one target locale, verify the result in the target locale tab, then publish. Do this on a scratch page before touching production content — you want to see how it handles your structure's field types (text lines, media selections, blocks) before trusting it on a real page.

Implementation Patterns

Admin-driven translation (the intended path). The bundle's primary value is a Sulu admin integration: editors translate existing content into another locale without leaving the CMS. Day-to-day, this is your workflow — write in the source locale, use the translate action, review and adjust the machine output, publish. Treat the output as a draft, never as auto-published content.

Programmatic translation via the service. For imports, migrations, or bulk operations, inject the translator service rather than driving the UI:

use Robole\SuluAiTranslatorBundle\Service\Translator; // confirm exact FQCN

public function __construct(private Translator $translator) {}

public function translateStructure(StructureInterface $structure, string $targetLocale): void
{
    $content = $this->contentMapper->load($structure->getUuid(), $webspaceKey, $targetLocale);
    // pass translatable field values through the translator, persist via ContentMapper
}

The general pattern with Sulu is: read content via ContentMapper, walk the Structure/Property tree, translate only the properties that make sense (text, excerpt title/description), copy the rest by reference, then persist for the target locale.

Field-level whitelisting. Do not blindly translate every property. Sulu structures mix translatable text with non-translatable values — URLs, references to media IDs, checkbox flags, select values backed by fixed keys, and taxonomy IDs. Build an explicit allowlist of property names (or filter by PropertyMetadata type) and copy everything else through unchanged. This is the single biggest determinant of whether the integration is usable.

Locale mapping. Sulu locales (en, de_at, fr) do not map 1:1 onto DeepL language codes (EN, DE, FR). Keep an explicit map in config or a small resolver service, and fail loudly on unmapped locales rather than silently falling back to the source language.

Queue long jobs. DeepL calls are network-bound and quota-limited. For anything beyond a handful of pages, dispatch a Symfony Messenger message per page and let workers handle retries and throttling. A synchronous admin action that translates twenty pages will time out and burn quota on partial failures.

Glossaries for domain terms. DeepL glossaries are the correct lever for brand names, product SKUs, and legally fixed terminology. Load the glossary ID from config and pass it on every request; without it, your product names will drift across pages.

Laravel-side takeaway. If you are borrowing the pattern rather than the package, the portable parts are: an explicit field allowlist, a locale map, a queued job per model, and a glossary. Swap ContentMapper for Eloquent and the design holds.

Gotchas and Tips

  • It is not a Laravel package. No service provider auto-discovery, no config/ai-translator.php publish step, no facade. Attempting composer require in a Laravel app will pull Sulu dependencies and is very likely to conflict. Do not try to bridge it; borrow the pattern instead.
  • DeepL Free vs Pro endpoints differ. Free keys require api-free.deepl.com; Pro keys require api.deepl.com. A wrong endpoint surfaces as a confusing 403, not an auth error. Check which the bundle defaults to and whether the endpoint is configurable.
  • Quota exhaustion is silent-ish. DeepL returns 456 on quota exhaustion. Wrap calls and surface this distinctly — otherwise editors see a generic "translation failed" and retry, compounding the problem.
  • HTML and markup. DeepL handles tag_handling=html well but will still reorder or normalize markup. If Sulu text fields carry inline formatting or your own shortcodes, translate with tag handling enabled and diff a sample before rolling out.
  • Non-text content does not translate. Media selections, internal links, and page references must be copied from the source locale explicitly — the translator has no concept of them. Pages that look "translated" but have empty images are the classic symptom of skipping this.
  • Workflow state. Machine-translated content should land as draft/unpublished. Verify the bundle does not inherit the source page's published state into the target locale.
  • Extension points. The translator service is the seam. Decorate it (Symfony service decoration) to add logging, caching, glossary selection, or a different provider — that is cleaner than forking. Check whether the bundle exposes an interface before wrapping the concrete class.
  • Debugging. Translation failures are almost always credentials, endpoint, quota, or an unmapped locale. bin/console debug:container to confirm the service exists, then a one-line script calling the translator directly to isolate bundle config from admin UI issues.
  • 19 stars and 0 dependents means you are the QA team. Pin the version in composer.json, read the bundle source before relying on it (it is small enough to audit in an afternoon), and write an integration test that translates one fixture page. Last release 2026-03-03 suggests it is alive, but the bus factor is one.
  • License is MIT, so forking and maintaining internally is a legitimate fallback if the maintainer goes quiet — factor that into your risk assessment rather than treating it as a blocker.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource