Skip to content
Nav

Automatic translation

composer require langsys/langsys-php-laravel
Packagist version Monthly downloads License PHP 8.1+ Laravel 10 / 11 / 12

Tagged mode (@t / t()) covers exactly what you wrap. TranslateResponse is the automatic mode — it runs the SDK’s page translator over the rendered HTML, translating every text node and translatable attribute (placeholder, alt, aria-label, …) with no @t at all. It’s the only way to cover text Alpine injects from a JS expression, which never becomes a DOM node you can wrap:

<span x-text="'Save changes'"></span>
<button :aria-label="open ? 'Collapse' : 'Expand'">…</button>

It is opt-in and applies to nothing until you attach it:

// routes/web.php — per route or group, never global
Route::middleware('langsys.translate-page')->group(function () {
Route::get('/', HomeController::class);
});
LANGSYS_TRANSLATE_RESPONSE=true

Only text/html responses are touched. JSON, redirects, streamed and file responses pass through untouched — which is what keeps Livewire and Inertia XHR round-trips out automatically. Scope it further with only / except path patterns in config/langsys.php (except wins), and set a category to namespace everything the page registers.

Newly discovered phrases are queued and flushed after the response, exactly as they are for t() / @t — the same terminable middleware and Octane listener drain both. Requires langsys/langsys-php ^1.3; before that, page registration made blocking HTTP calls mid-render.

Caching is off by default and should usually stay off. Translated output is keyed by a hash of the source HTML, so a page carrying a CSRF token or a timestamp produces a new key every render. Enable it only for genuinely static, high-traffic HTML.

Two markers, and the difference is not cosmetic:

<pre translate="no">composer require langsys/langsys-php-laravel</pre> {{-- nobody translates this --}}
<div data-notrans>{{ $userSuppliedHtml }}</div> {{-- Langsys skips it --}}
  • translate="no" is standards HTML, so browser translation features (Chrome, Safari, Edge “translate this page”) honour it too. Use it for code samples, brand names, identifiers — anything no translator, human or machine, should touch.
  • data-notrans excludes the subtree from Langsys only; a reader’s browser-translation is still free to act on it. Use it for content that’s already resolved, or that you handle yourself.

Presence is intent for both: a bare data-notrans excludes, and only ="false" or ="0" opts back in (trimmed, case-insensitive).

Feedback