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

Translation Bundle Laravel Package

alvadi-it/translation-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require jms/translation-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        JMS\TranslationBundle\JMSTranslationBundle::class => ['all' => true],
    ];
    
  2. Configuration: Add to config/packages/jms_translation.yaml:

    jms_translation:
        configs:
            app:
                dirs: ["%kernel.project_dir%/translations"]
                output_dir: "%kernel.project_dir%/translations"
                excluded_namespaces: []
                excluded_dirs: [cache, logs]
                file_template: "%%locale%%_%%domain%%.xliff"
                ignored_domains: []
                extractors: [twig, validation, form]
    
  3. First Use Case: Extract translations from Twig templates:

    php bin/console translation:extract
    

    This generates .xliff files in your translations/ directory.


Implementation Patterns

Core Workflows

1. Translation Extraction

  • Twig Templates: Automatically extracts trans and transchoice calls in Twig:

    {{ 'welcome.message'|trans({'%name%': user.name}) }}
    

    Run:

    php bin/console translation:extract twig
    
  • Validation Messages: Extracts Symfony validator constraints:

    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @Assert\NotBlank(message="user.email.not_blank")
     */
    private $email;
    

    Run:

    php bin/console translation:extract validation
    
  • Forms: Extracts form labels, placeholders, and constraints:

    $builder->add('email', EmailType::class, [
        'label' => 'user.email.label',
        'constraints' => [new NotBlank(['message' => 'user.email.not_blank'])]
    ]);
    

    Run:

    php bin/console translation:extract form
    

2. Translation Management

  • Web UI: Access the translation editor at /_translations (configured in routing.yaml):

    jms_translation:
        routing:
            prefix: /_translations
    
    • Filter translations by domain, locale, or status.
    • Edit translations directly in the browser.
  • ICU Format: Dump translations to ICU format (useful for JavaScript/i18n libraries):

    php bin/console translation:dump --format=icu
    

3. Integration with Symfony Forms

  • Dynamic Forms: Use translation_domain option to specify the domain for form translations:

    $builder->add('email', EmailType::class, [
        'translation_domain' => 'validation'
    ]);
    
  • Choice Lists: Translate choices in ChoiceType:

    $builder->add('gender', ChoiceType::class, [
        'choices' => [
            'male' => 'user.gender.male',
            'female' => 'user.gender.female',
        ],
        'translation_domain' => 'forms',
    ]);
    

4. Custom Extractors

  • Extend Extractors: Create a custom extractor by implementing JMS\TranslationBundle\Extractor\ExtractorInterface:

    namespace App\Extractor;
    
    use JMS\TranslationBundle\Extractor\ExtractorInterface;
    
    class CustomExtractor implements ExtractorInterface {
        public function extract(array $config, $source) {
            // Custom logic to extract translations
            return ['custom.key' => 'Custom Translation'];
        }
    }
    

    Register in config/packages/jms_translation.yaml:

    jms_translation:
        configs:
            app:
                extractors: [custom]
    
  • Register Extractor: Use a compiler pass to add your extractor:

    namespace App\DependencyInjection\Compiler;
    
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Reference;
    
    class AddCustomExtractorPass implements CompilerPassInterface {
        public function process(ContainerBuilder $container) {
            $definition = $container->findDefinition('jms_translation.extractor');
            $definition->addMethodCall('addExtractor', [new Reference('app.custom_extractor')]);
        }
    }
    

Gotchas and Tips

Pitfalls and Debugging

1. Common Errors

  • simplexml_load_file() expects parameter 1 to be a valid path: Ensure .xliff files are generated in the correct directory. Verify output_dir in jms_translation.yaml.

  • strtolower() expects parameter 1 to be string: Update to v1.5.1+ to fix strict type issues. If stuck on an older version, cast objects to strings manually in your templates:

    {{ ('welcome.message' ~ { '%name%': user.name|string })|trans }}
    
  • The format "yml" does not exist: Use yaml instead of yml in configuration. The bundle supports xliff, yaml, and icu formats.

  • Missing Twig Nodes: If trans calls aren’t extracted, ensure your Twig templates are compiled. Run:

    php bin/console cache:clear
    

2. Configuration Quirks

  • Excluded Directories: The excluded_dirs option in jms_translation.yaml does not support glob patterns. Use absolute paths:

    excluded_dirs: ["%kernel.project_dir%/var/cache"]
    
  • Translation Domains: If translations aren’t found, verify the translation_domain is set in Twig:

    {{ 'welcome.message'|trans({}, 'messages') }}
    

    Or in forms:

    $builder->add('field', TextType::class, ['translation_domain' => 'forms']);
    
  • Web UI Access: The default route /_translations may conflict with other routes. Customize the prefix:

    jms_translation:
        routing:
            prefix: /admin/translations
    

3. Performance Tips

  • Memory Limits: Large projects may hit memory limits during extraction. Increase PHP memory:

    php -d memory_limit=-1 bin/console translation:extract
    

    Or split extraction by domain:

    php bin/console translation:extract twig --domain=messages
    
  • Caching: Disable caching during development to see real-time changes:

    # config/packages/framework.yaml
    framework:
        twig:
            cache: false
    

4. Extension Points

  • Custom XLIFF Headers: Override the XLIFF template in Resources/views/JMSTranslationBundle/base.html.twig to add custom metadata.

  • Post-Extraction Hooks: Use Symfony events to modify extracted translations:

    namespace App\EventListener;
    
    use JMS\TranslationBundle\Event\ExtractionEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class TranslationExtractorSubscriber implements EventSubscriberInterface {
        public static function getSubscribedEvents() {
            return [
                'jms_translation.extraction' => 'onExtraction',
            ];
        }
    
        public function onExtraction(ExtractionEvent $event) {
            $translations = $event->getTranslations();
            $translations['custom.key'] = 'Overridden Value';
            $event->setTranslations($translations);
        }
    }
    
  • Validation Constraint Extraction: To exclude specific constraints from extraction, use the translation option:

    use Symfony\Component\Validator\Constraints as Assert;
    
    /**
     * @Assert\NotBlank(translation="user.email.not_blank")
     * @Assert\Email(translation="user.email.invalid")
     */
    private $email;
    

    Only translation-annotated constraints will be extracted.

5. Debugging Tips

  • Log Extracted Messages: Enable debug logging to see what’s being extracted:

    # config/packages/monolog.yaml
    monolog:
        handlers:
            main:
                level: debug
                channels: ["translation"]
    

    Then run:

    php bin/console translation:extract --debug
    
  • Compare XLIFF Files: Use diff to compare before/after extraction:

    diff <(php bin/console translation:dump --format=xliff) translations/en.xliff
    
  • Test Extraction: Use the translation:test command to validate extracted messages:

    php bin/console translation:test
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware