Weave Code
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

Motranslator Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require phpmyadmin/motranslator:^6.0
    

    Note: PHP 8.2+ required. Drop-in replacement for prior versions.

  2. 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
    
  3. First Use Case

    • Localization in Laravel Views (PHP 8.2+):
      // 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') }}
      

Implementation Patterns

1. Integration with Laravel's Translation System

  • 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
    

2. Dynamic Locale Switching

  • Runtime Locale Handling (PHP 8.2+):
    $mo = new MoTranslator\MoFile('locale.mo');
    $mo->setLocale('fr_FR'); // Type-safe locale
    echo $mo->get('greeting');
    
  • Middleware for User-Localized Content:
    // 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);
    }
    

3. Pluralization and Contextual Translations

  • Plural Forms (PHP 8.2+):
    $mo = new MoTranslator\MoFile('locale.mo');
    echo $mo->getPlural('item', 5, ['count' => 5]); // Typed count
    
  • Context-Sensitive Translations:
    echo $mo->get('contextual_key', [], [], 'context'); // Type-safe context
    

4. Caching Translations

  • Preload and Cache MO Files (PHP 8.2+):
    // In a service provider
    $cache = new MoTranslator\Cache\FileCache(storage_path('framework/cache'));
    $mo = new MoTranslator\MoFile('locale.mo', $cache);
    
  • Cache Tags for Invalidation:
    Cache::tags(['translations'])->put('mo:locale', $mo->getAllTranslations());
    

5. Validation and Error Handling

  • Graceful Fallback (PHP 8.2+):
    try {
        echo $mo->get('missing_key');
    } catch (MissingTranslation $e) {
        echo 'Default: ' . trans('fallback.missing');
    }
    
  • Validate MO File Integrity:
    if (!$mo->isValid()) {
        Log::error('Invalid MO file: ' . $mo->getPath());
    }
    

Gotchas and Tips

Common Pitfalls

  1. PHP Version Compatibility

    • Breaking: Requires PHP 8.2+. Update composer.json:
      "require": {
          "php": "^8.2"
      }
      
    • Fix: Run composer update phpmyadmin/motranslator --with-dependencies.
  2. Type Safety Pitfalls

    • Gotcha: Non-string keys/placeholders now throw TypeError:
      $mo->get(123); // Throws TypeError
      
    • Fix: Ensure all keys/values are strings:
      $mo->get((string) $dynamicKey);
      
  3. Locale Path Resolution

    • Hardcoded paths break in shared hosting. Use Laravel's resource_path():
      $mo = new MoTranslator\MoFile(resource_path("lang/{$locale}.mo"));
      
  4. Pluralization Rules

    • Test with typed inputs:
      $mo->getPlural('apples', 1.5); // Throws TypeError (must be int)
      
  5. Context vs. Disambiguation

    • Confuse get() (disambiguation) with get() + context:
      // Disambiguation (no context)
      $mo->get('key');
      
      // Context (requires #: in .po file)
      $mo->get('key', [], [], 'context'); // Type-safe context
      

Debugging Tips

  1. Inspect MO File Contents

    print_r($mo->getAllTranslations()); // Dump all translations (typed)
    
  2. Enable Gettext Debugging

    • Set MoTranslator\MoFile::DEBUG = true to log parsing issues.
  3. Compare with PO Files

    • Use poedit to verify .po source:
      poedit locale.po
      

Extension Points

  1. 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);
        }
    }
    
  2. Integration with Laravel Scout

    • Index translations for search (type-safe):
      Scout::search('greeting')->where('locale', 'en')->get();
      
  3. Event Listeners for Translation Updates

    Event::listen('mo.file.updated', fn (string $path) => Cache::forget('mo:translations'));
    

Performance Optimizations

  1. Precompile MO Files

    • Compile .po to .mo during deployment (CI/CD):
      find resources/lang -name '*.po' -exec msgfmt -o {}.mo {} \;
      
  2. Avoid Re-parsing

    • Instantiate MoFile once and reuse (type-safe):
      $mo = new MoTranslator\MoFile('locale.mo'); // Parse once
      echo $mo->get('key'); // Reuse
      
  3. Use Laravel's Cache for Frequent Keys

    $translation = Cache::remember(
        "mo:{$locale}:{$key}",
        now()->addHours(1),
        fn () => $mo->get($key)
    );
    

Security Considerations

  1. Validate Locale Input

    • Restrict allowed locales to prevent path traversal:
      $allowedLocales: array = ['en', 'fr', 'es'];
      if (!in_array($request->locale, $allowedLocales, true)) {
          abort(403);
      }
      
  2. Sanitize Translation Output

    • Escape dynamic content:
      echo e($mo->get('user_message', ['name' => $user->name]));
      
  3. Avoid Direct File Access

    • Block public access to .mo files:
      Route::get('/mo/{locale}', fn () => abort(403, 'Forbidden.'));
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky