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

Php Scanner Laravel Package

gettext/php-scanner

Scan PHP source to extract gettext translations for use with gettext/gettext. Supports multiple domains, default domain selection, and extracting translator/i18n comments. Produces Translations you can export to .po files with generators like PoGenerator.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

  1. Install the package:

    composer require gettext/php-scanner
    
  2. Basic extraction script (artisan command or standalone script):

    use Gettext\Scanner\PhpScanner;
    use Gettext\Generator\PoGenerator;
    use Gettext\Translations;
    
    $scanner = new PhpScanner(
        Translations::create('messages') // Default domain
    );
    $scanner->extractCommentsStartingWith('i18n:', 'Translators:');
    $scanner->scanFile(base_path('app/Http/Controllers/AuthController.php'));
    
    $generator = new PoGenerator();
    $generator->generateFile(
        $scanner->getTranslations()['messages'],
        resource_path('lang/messages.po')
    );
    
  3. First use case:

    • Add i18n: comments above translatable strings in your PHP files:
      // i18n: Welcome to our platform!
      echo __('Welcome to our platform!');
      
    • Run the script to generate messages.po.
  4. Where to look first:


Implementation Patterns

Core Workflows

1. Domain-Specific Scanning

  • Pattern: Separate translations by domain (e.g., messages, validation).
  • Example:
    $scanner = new PhpScanner(
        Translations::create('messages'),
        Translations::create('validation')
    );
    $scanner->setDefaultDomain('messages'); // Fallback for unassigned strings
    
  • Laravel Integration: Map domains to Laravel’s language files (e.g., messages.poresources/lang/en/messages.php).

2. Comment-Based Extraction

  • Pattern: Use i18n: or Translators: comments to annotate strings.
  • Example:
    // i18n: This is a translatable string with %s placeholder
    $user->greeting = sprintf(__('Hello, %s!'), $name);
    
  • Laravel Tip: Add a phpcs rule to enforce these comments in your codebase.

3. Sprintf/Format Support

  • Pattern: Automatically detect sprintf/printf patterns and add php-format flags to .po files.
  • Example Output in .po:
    msgid "User %s logged in"
    msgstr ""
    "php-format": "sprintf"
    

4. Incremental Scanning

  • Pattern: Scan only changed files in CI/CD (e.g., Git hooks or Laravel Forge deploy scripts).
  • Example:
    # Run only on changed PHP files
    git diff --name-only HEAD~1 HEAD | grep '\.php$' | xargs -I{} php artisan scan:translations {}
    

5. Blade Template Workaround

  • Pattern: Pre-process Blade files to PHP or use inline comments.
  • Example:
    {{-- i18n: Welcome back, {name}! --}}
    <h1>{{ __('Welcome back, ') . $name . '!' }}</h1>
    
  • Tooling: Use laravel-blade-compiler to convert Blade to PHP before scanning.

Laravel-Specific Patterns

1. Artisan Command

Create a custom command (php artisan make:command ScanTranslations):

use Gettext\Scanner\PhpScanner;
use Gettext\Generator\PoGenerator;

class ScanTranslations extends Command {
    protected $signature = 'scan:translations {--path= : Path to scan}';
    protected $description = 'Scan PHP files for translatable strings';

    public function handle() {
        $scanner = new PhpScanner(Translations::create('messages'));
        $scanner->extractCommentsStartingWith('i18n:');
        $scanner->scanFile($this->option('path') ?: app_path('*'));

        $generator = new PoGenerator();
        $generator->generateFile(
            $scanner->getTranslations()['messages'],
            resource_path('lang/messages.po')
        );
        $this->info('Translations scanned and saved!');
    }
}

2. Service Provider Integration

Bootstrap scanning in AppServiceProvider:

public function boot() {
    $this->scanTranslations();
}

protected function scanTranslations() {
    $scanner = new PhpScanner(Translations::create('messages'));
    $scanner->extractCommentsStartingWith('i18n:');
    foreach (glob(app_path('*.php')) as $file) {
        $scanner->scanFile($file);
    }
    // Save translations (e.g., via queue job)
}

3. Git Hook Integration

Add a post-merge hook to auto-scan:

# .git/hooks/post-merge
#!/bin/bash
php artisan scan:translations --path=$(git diff --name-only HEAD~1 HEAD | grep '\.php$')

4. CI/CD Pipeline

Example GitHub Actions workflow:

name: Scan Translations
on: [push]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
      - run: composer install -n
      - run: php artisan scan:translations --path=app/Http
      - uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: "chore: Update translations from scan"

Gotchas and Tips

Pitfalls

  1. False Negatives with Dynamic Strings

    • Issue: The scanner may miss strings built at runtime (e.g., concat($var1, $var2)).
    • Fix: Use comments to explicitly mark translatable strings:
      // i18n: Concatenated string: {var1} {var2}
      echo $var1 . ' ' . $var2;
      
  2. Blade Template Limitations

    • Issue: Blade files (.blade.php) are not parsed natively.
    • Fix:
      • Pre-process Blade to PHP (e.g., with laravel-blade-compiler).
      • Use inline comments in Blade:
        {{-- i18n: Submit button --}}
        <button>{{ __('Submit') }}</button>
        
  3. PHP 8.4+ Features

    • Issue: New PHP features (e.g., typed properties, match expressions) may not be fully supported.
    • Fix: Test with your PHP version and report issues to the GitHub repo.
  4. Comment Parsing Quirks

    • Issue: Multi-line comments or comments with special characters may break extraction.
    • Fix: Stick to single-line comments (// i18n:) and avoid nested quotes:
      // i18n: "Hello" (with quotes)
      
  5. Performance with Large Codebases

    • Issue: Scanning 10,000+ files can be slow.
    • Fix:
      • Use --path to limit scanning (e.g., app/Http only).
      • Cache results or run in a queue job.
  6. Domain Mismatches

    • Issue: Strings may end up in the wrong .po file if domains are misconfigured.
    • Fix: Always set a defaultDomain and validate domains in your scanner config.

Debugging Tips

  1. Enable Verbose Output

    • Use nikic/php-parser’s debug mode to inspect parsed code:
      $scanner->setParserDebug(true); // Hypothetical; check latest API
      
  2. Inspect Parsed AST

    • Dump the parsed AST to understand why a string wasn’t extracted:
      $parser = new PhpParser\Parser(new PhpParser\Lexer);
      $ast = $parser->parse(file_get_contents($file));
      var_dump($ast); // Inspect nodes
      
  3. Test with Simple Files First

    • Start with a single file (e.g., AuthController.php) to validate extraction before scaling.
  4. Validate .po Output

    • Use msgfmt to check for syntax errors:
      msgfmt --statistics locales/messages.po
      

Extension Points

  1. **Custom Comment Patterns
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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
spatie/mailcoach-vapor