Translator
ADP automatically intercepts translation calls in your application and records every lookup — including missing translations. No code changes required.
TranslatorCollector
TranslatorCollectorAppDevPanel\Kernel\Collector\TranslatorCollectorCaptures translation lookups during request execution. implements SummaryCollectorInterfaceAppDevPanel\Kernel\Collector\SummaryCollectorInterfaceSummary data collector responsibility is to collect summary data for a collector. Summary is used to display a list of previous requests and select one to display full info. Its data set is specific to the list and is reduced compared to full data collected in {@see CollectorInterface}. and captures every translation lookup during request execution.
TranslationRecord
Each translation call produces a TranslationRecordAppDevPanel\Kernel\Collector\TranslationRecordClass TranslationRecord. DTO:
| Field | Type | Description |
|---|---|---|
category | string | Translation domain/group (e.g., messages, app, validation) |
locale | string | Target locale (e.g., en, de, fr) |
message | string | Original message ID / translation key |
translation | ?string | Translated string, or null if missing |
missing | bool | true when no translation was found |
fallbackLocale | ?string | Fallback locale used (if applicable) |
Collected Data
getCollected() returns:
[
'translations' => [
['category' => 'messages', 'locale' => 'de', 'message' => 'welcome', 'translation' => 'Willkommen!', 'missing' => false, 'fallbackLocale' => null],
['category' => 'messages', 'locale' => 'de', 'message' => 'goodbye', 'translation' => null, 'missing' => true, 'fallbackLocale' => null],
],
'missingCount' => 1,
'totalCount' => 2,
'locales' => ['de'],
'categories' => ['messages'],
]Summary
getSummary() returns:
[
'translator' => [
'total' => 2,
'missing' => 1,
],
]Missing Translation Detection
Each framework proxy detects missing translations differently, but the logic is consistent: if the translator returns the original message ID unchanged, the translation is considered missing.
| Framework | Detection Method |
|---|---|
| Symfony | trans() returns $id unchanged |
| Laravel | get() returns $key unchanged |
| Yii 3 | translate() returns $id unchanged |
| Yii 2 | MessageSource::translate() returns false |
Framework Proxies
Each adapter provides a translator proxy that wraps the framework's native translator and feeds data to TranslatorCollectorAppDevPanel\Kernel\Collector\TranslatorCollectorCaptures translation lookups during request execution.. Proxies are registered automatically — no manual setup needed.
Symfony — SymfonyTranslatorProxyAppDevPanel\Adapter\Symfony\Proxy\SymfonyTranslatorProxyDecorates Symfony's TranslatorInterface to feed translation lookups to TranslatorCollector.
Decorates Symfony\Contracts\Translation\TranslatorInterface. Intercepts trans() calls.
Wiring: Registered via CollectorProxyCompilerPassAppDevPanel\Adapter\Symfony\DependencyInjection\CollectorProxyCompilerPassCompiler pass that: 1. Collects all tagged collectors and injects them into the Debugger 2. Decorates PSR services (Logger, EventDispatcher, HttpClient) with proxies using Symfony's setDecoratedService() pattern.
// All trans() calls are intercepted automatically
$translator->trans('welcome', [], 'messages', 'de');- Default domain:
messages(when$domainisnull) - Uses
ProxyDecoratedCallstrait for method forwarding
Laravel — LaravelTranslatorProxyAppDevPanel\Adapter\Laravel\Proxy\LaravelTranslatorProxyDecorates Laravel's Translator to feed translation lookups to TranslatorCollector.
Decorates Illuminate\Contracts\Translation\Translator. Intercepts get() and choice() calls.
Wiring: Registered via $app->extend('translator', ...) in the service provider.
// All translation helpers are intercepted
__('messages.welcome');
trans('messages.welcome');
Lang::get('messages.welcome');- Parses Laravel's dot-notation keys:
group.key→ categorygroup, messagekey - JSON translations (no dot): category defaults to
messages - Uses
ProxyDecoratedCallstrait for method forwarding
Yii 3 — TranslatorInterfaceProxyAppDevPanel\Adapter\Yii3\Collector\Translator\TranslatorInterfaceProxyDecorates Yiisoft TranslatorInterface to feed translation lookups to TranslatorCollector.
Decorates Yiisoft\Translator\TranslatorInterface. Intercepts translate() calls.
Wiring: Registered as a trackedService in params.php — the adapter's service proxy system handles decoration automatically.
// All translate() calls are intercepted
$translator->translate('welcome', [], 'app', 'de');- Default category:
app(when$categoryisnulland nowithDefaultCategory()was called) - Supports immutable
withDefaultCategory()andwithLocale()viaclone
Yii 2 — I18NProxyAppDevPanel\Adapter\Yii2\Proxy\I18NProxyDecorates Yii 2's I18N component to feed translation lookups to TranslatorCollector.
Extends yii\i18n\I18N and overrides translate(). Replaces the i18n application component.
Wiring: The module replaces Yii::$app->i18n with the proxy instance, copying existing translations config.
// All Yii::t() calls are intercepted
Yii::t('app', 'welcome', [], 'de');- Calls
$messageSource->translate()directly — returnsfalsewhen missing (more reliable than string comparison) - Safe to use without collector (null-safe
$this->collector?->logTranslation())
Configuration
Translation interception is enabled by default when the TranslatorCollectorAppDevPanel\Kernel\Collector\TranslatorCollectorCaptures translation lookups during request execution. is active. No additional configuration is needed.
# config/packages/app_dev_panel.yaml
app_dev_panel:
collectors:
translator: true # enabled by defaultFrontend Panel
The TranslatorPanel in the debug UI displays:
- Summary badge — total translation count and missing count
- Translation table — all recorded translations with category, locale, message, translated value, and missing status
- Filters — filter by locale, category, or missing status
- Missing highlights — missing translations are visually highlighted for quick identification