phpmyadmin/motranslator
A PHP library used by phpMyAdmin to extract and work with translation strings. Helps parse and handle gettext-style messages and localization data, making it easier to manage and generate language files as part of i18n workflows.
Installation
composer require phpmyadmin/motranslator:^6.0
Note: PHP 8.2+ required. Drop-in replacement for prior versions.
Basic Usage
Load a .mo file (compiled Gettext translation) with type safety:
use MoTranslator\MoFile;
$mo = new MoFile('path/to/locale.mo');
echo $mo->get('greeting', ['name' => 'John']); // Typed parameters
First Use Case
// In a service provider (e.g., AppServiceProvider)
$translator = new MoFile(resource_path('lang/en/messages.mo'));
view()->share('translator', $translator);
// In a Blade view (type-safe)
{{ $translator->get('welcome_message') }}
Override Default Translator (PHP 8.2+):
// app/Providers/AppServiceProvider.php
public function register(): void
{
$this->app->singleton(Translator::class, function ($app) {
$loader = new MoTranslator\Loader();
$loader->addNamespace('messages', resource_path('lang'));
return new Translator($loader, $app['locale']);
});
}
Note: Use Translator::class for type safety.
Fallback to .mo/.php Hybrid:
$mo = new MoTranslator\MoFile('locale.mo');
$fallback = trans('fallback.key');
echo $mo->get('key', [], $fallback); // Typed fallback
$mo = new MoTranslator\MoFile('locale.mo');
$mo->setLocale('fr_FR'); // Type-safe locale
echo $mo->get('greeting');
// app/Http/Middleware/LocaleMiddleware.php
public function handle(Request $request, Closure $next): Response
{
$mo = new MoTranslator\MoFile(resource_path("lang/{$request->locale}.mo"));
view()->share('translator', $mo);
return $next($request);
}
$mo = new MoTranslator\MoFile('locale.mo');
echo $mo->getPlural('item', 5, ['count' => 5]); // Typed count
echo $mo->get('contextual_key', [], [], 'context'); // Type-safe context
// In a service provider
$cache = new MoTranslator\Cache\FileCache(storage_path('framework/cache'));
$mo = new MoTranslator\MoFile('locale.mo', $cache);
Cache::tags(['translations'])->put('mo:locale', $mo->getAllTranslations());
try {
echo $mo->get('missing_key');
} catch (MissingTranslation $e) {
echo 'Default: ' . trans('fallback.missing');
}
if (!$mo->isValid()) {
Log::error('Invalid MO file: ' . $mo->getPath());
}
PHP Version Compatibility
composer.json:
"require": {
"php": "^8.2"
}
composer update phpmyadmin/motranslator --with-dependencies.Type Safety Pitfalls
TypeError:
$mo->get(123); // Throws TypeError
$mo->get((string) $dynamicKey);
Locale Path Resolution
resource_path():
$mo = new MoTranslator\MoFile(resource_path("lang/{$locale}.mo"));
Pluralization Rules
$mo->getPlural('apples', 1.5); // Throws TypeError (must be int)
Context vs. Disambiguation
get() (disambiguation) with get() + context:
// Disambiguation (no context)
$mo->get('key');
// Context (requires #: in .po file)
$mo->get('key', [], [], 'context'); // Type-safe context
Inspect MO File Contents
print_r($mo->getAllTranslations()); // Dump all translations (typed)
Enable Gettext Debugging
MoTranslator\MoFile::DEBUG = true to log parsing issues.Compare with PO Files
poedit to verify .po source:
poedit locale.po
Custom Loaders (PHP 8.2+)
class RemoteMoLoader extends MoTranslator\Loader {
public function load(string $locale, string $namespace): MoFile {
$mo = file_get_contents("https://example.com/mo/{$locale}.mo");
return new MoTranslator\MoFile($mo, false);
}
}
Integration with Laravel Scout
Scout::search('greeting')->where('locale', 'en')->get();
Event Listeners for Translation Updates
Event::listen('mo.file.updated', fn (string $path) => Cache::forget('mo:translations'));
Precompile MO Files
.po to .mo during deployment (CI/CD):
find resources/lang -name '*.po' -exec msgfmt -o {}.mo {} \;
Avoid Re-parsing
MoFile once and reuse (type-safe):
$mo = new MoTranslator\MoFile('locale.mo'); // Parse once
echo $mo->get('key'); // Reuse
Use Laravel's Cache for Frequent Keys
$translation = Cache::remember(
"mo:{$locale}:{$key}",
now()->addHours(1),
fn () => $mo->get($key)
);
Validate Locale Input
$allowedLocales: array = ['en', 'fr', 'es'];
if (!in_array($request->locale, $allowedLocales, true)) {
abort(403);
}
Sanitize Translation Output
echo e($mo->get('user_message', ['name' => $user->name]));
Avoid Direct File Access
.mo files:
Route::get('/mo/{locale}', fn () => abort(403, 'Forbidden.'));
How can I help you explore Laravel packages today?