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

Xliff Bundle Laravel Package

c975l/xliff-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require-dev c975l/xliff-bundle
    

    Note: Install only in dev environment.

  2. Enable Bundle: Register in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3):

    // config/bundles.php
    return [
        // ...
        c975L\XliffBundle\c975LXliffBundle::class => ['dev' => true, 'test' => true],
    ];
    
  3. Add Routes: In config/routes/dev.yaml (Symfony 4+):

    c975_l_xliff:
        resource: "@c975LXliffBundle/Controller/"
        type: annotation
        prefix: /_xliff
    
  4. Database Table: Create a table with columns for each language (e.g., en, fr) and a unique identifier (e.g., id or key). Example schema:

    CREATE TABLE translations (
        key VARCHAR(255) PRIMARY KEY,
        en TEXT,
        fr TEXT,
        de TEXT
    );
    
  5. First Export: Visit /_xliff/export in your browser or trigger via CLI:

    php bin/console xliff:export
    

    Outputs .xlf files to var/xliff/ (default).


Implementation Patterns

Workflow: Exporting Translations

  1. Define Table Structure: Ensure your table has a column for each target language (e.g., en, fr) and a unique key column. Example entity:

    // src/Entity/Translation.php
    #[ORM\Entity]
    class Translation {
        #[ORM\Id, ORM\Column]
        private string $key;
    
        #[ORM\Column]
        private string $en;
    
        #[ORM\Column]
        private string $fr;
    }
    
  2. Customize Export: Override the default controller or service:

    // src/Controller/XliffExportController.php
    class XliffExportController extends AbstractXliffExportController {
        protected function getEntityManager(): EntityManagerInterface {
            return $this->container->get('doctrine')->getManager();
        }
    
        protected function getEntityClass(): string {
            return Translation::class;
        }
    
        protected function getKeyColumn(): string {
            return 'key';
        }
    
        protected function getLanguageColumns(): array {
            return ['en', 'fr'];
        }
    }
    
  3. Automate with CLI: Schedule exports via cron or Symfony commands:

    php bin/console xliff:export --entity=Translation --key=key --languages=en,fr
    
  4. Integrate with CI/CD: Add to deployment pipeline to generate .xlf files for translators:

    # .github/workflows/translations.yml
    jobs:
      export-translations:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - run: composer install
          - run: php bin/console xliff:export
          - uses: actions/upload-artifact@v3
            with:
              name: xliff-files
              path: var/xliff/
    
  5. Import Workflow: After translations are updated, import back into the database:

    php bin/console doctrine:fixtures:load --append
    

    Note: Requires custom fixture logic to parse .xlf files.


Integration Tips

  • Symfony Translation System: Use exported .xlf files with tools like PoEditor or Crowdin. Example Crowdin config:

    # crowdin.yml
    files:
      - source: /var/xliff/translations.xlf
        translation: /var/xliff/%locale%.xlf
    
  • Dynamic Language Handling: Fetch supported languages from the database:

    $languages = $entityManager->getRepository(Translation::class)
        ->createQueryBuilder('t')
        ->select('DISTINCT COLUMN_GET(t, 2)') // Adjust for your DB
        ->getQuery()
        ->getScalarResult();
    
  • Partial Exports: Filter by entity state (e.g., published = true):

    protected function getQueryBuilder(EntityManagerInterface $em): QueryBuilder {
        return $em->getRepository($this->getEntityClass())
            ->createQueryBuilder('t')
            ->where('t.published = :published')
            ->setParameter('published', true);
    }
    

Gotchas and Tips

Pitfalls

  1. Dev-Only Bundle: Forgetting to restrict the bundle to dev/test environments may expose sensitive routes in production. Fix: Double-check config/bundles.php or AppKernel.php.

  2. Column Naming: The bundle assumes language columns are named exactly as ISO codes (e.g., en, fr). Fix: Override getLanguageColumns() to match your schema:

    protected function getLanguageColumns(): array {
        return ['language_en', 'language_fr']; // Custom column names
    }
    
  3. File Overwrites: By default, exports overwrite existing .xlf files. Fix: Append timestamps to filenames:

    protected function getOutputPath(): string {
        return sprintf('var/xliff/%s_%s.xlf', $this->getKey(), (new \DateTime())->format('YmdHis'));
    }
    
  4. Memory Limits: Large tables may hit PHP memory limits during export. Fix: Use chunked queries:

    protected function getQueryBuilder(EntityManagerInterface $em): QueryBuilder {
        return $em->getRepository($this->getEntityClass())
            ->createQueryBuilder('t')
            ->setMaxResults(1000); // Process in batches
    }
    
  5. Doctrine Proxy Issues: Lazy-loaded entities may cause errors in CLI exports. Fix: Use EntityManager::createQueryBuilder() instead of Repository methods.


Debugging

  1. Check Routes: Ensure routes are loaded:

    php bin/console debug:router | grep xliff
    
  2. Validate Table Structure: Run a test export manually:

    php bin/console xliff:export --dry-run
    

    Output: Shows SQL query and expected structure.

  3. Log Exports: Enable debug mode to log generated .xlf content:

    // config/packages/dev/monolog.yaml
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
            channels: ["!event"]
    

Extension Points

  1. Custom XLIFF Structure: Extend the XliffGenerator service to modify the .xlf schema:

    // src/Service/CustomXliffGenerator.php
    class CustomXliffGenerator extends XliffGenerator {
        public function generate(array $translations): string {
            $xlf = parent::generate($translations);
            // Add custom headers or namespaces
            return str_replace('<xliff>', '<xliff version="2.1" custom="attribute">', $xlf);
        }
    }
    

    Register as a service override:

    # config/services.yaml
    services:
        c975_l_xliff.xliff_generator:
            class: App\Service\CustomXliffGenerator
            tags: ['xliff.generator']
    
  2. Post-Export Hooks: Trigger actions after export (e.g., notify translators):

    // src/EventListener/XliffExportListener.php
    class XliffExportListener implements KernelEventSubscriberInterface {
        public static function getSubscribedEvents() {
            return [
                KernelEvents::TERMINATE => 'onXliffExport',
            ];
        }
    
        public function onXliffExport(KernelEvent $event) {
            if ($event->isMainRequest() && $event->getRequest()->get('_route') === 'xliff_export') {
                // Send email, log, etc.
            }
        }
    }
    
  3. Multi-Database Support: For multi-DB setups, override the EntityManager:

    protected function getEntityManager(): EntityManagerInterface {
        return $this->container->get('doctrine.orm.entity_manager.secondary');
    }
    

Configuration Quirks

  1. Output Directory: Default: var/xliff/. Change via:

    # config/packages/c975_l_xliff.yaml
    c975_l_xliff:
        output_dir: '%kernel.project_dir%/public/translations'
    
  2. Filename Template: Customize filenames

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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui