Weave 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

I18N Bundle Laravel Package

pugx/i18n-bundle

PUGX I18nBundle brings database-backed translations to Symfony: store messages in Doctrine entities, edit them via your admin, and let a translator service fall back to standard YAML/XLIFF files. Includes import/export commands and caching for fast lookups.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — and it is archived. Do not add it to a Laravel app's composer.json expecting a service provider; there is nothing here that Laravel's container will auto-discover. Treat it as reference material for the "translatable entity" pattern, not as a dependency.

Where to look first:

  1. PUGX\I18nBundle\Doctrine — the event listeners/subscribers that do the actual work (locale resolution on postLoad, metadata on loadClassMetadata).
  2. The I18n/translator and locale-resolution services — this is where the current-locale + fallback chain lives.
  3. The documented entity mapping: a parent entity with a OneToMany to a per-locale translation entity.

First use case, translated into Laravel terms: a Post model with a post_translations table (locale, title, body, post_id) where reading $post->title returns the row matching app()->getLocale(), falling back to config('app.fallback_locale'). Read the bundle's listener to see how it picks the locale from the request and how it walks the fallback chain, then reimplement that in an Eloquent accessor or a global scope.

If you are genuinely on an old Symfony 2/3/4 project: require it, register PUGXI18nBundle in AppKernel, configure locale and fallback_locale, annotate the entity. That path is legacy-only.

Implementation Patterns

The core pattern worth stealing — parent + translation table. One row per locale, joined back to the parent. All the bundle does is hide the join behind the entity's getters. In Laravel:

// Model accessor with fallback
public function getTitleAttribute(): ?string
{
    return $this->translation()?->title
        ?? $this->translations->firstWhere('locale', config('app.fallback_locale'))?->title;
}

Locale resolution from the request. The bundle reads _locale at kernel.request time and stores it in a locale-aware service. Laravel equivalent: middleware that calls App::setLocale() from a route segment, session, or Accept-Language header, before any model is touched.

Doctrine listeners → Eloquent hooks. Their postLoad maps to booted() model events or a global scope; their loadClassMetadata maps to schema/migration conventions. If you're bridging a shared Symfony domain layer into Laravel, keep the translation entity a plain POPO and do the locale swap in a Laravel accessor — don't let the bundle's listener leak into your Eloquent models.

Write path. The bundle assumes one form/CRUD per locale over the translation collection. In Laravel, use a nested translations[] payload validated with translations.*.locale unique rules, then updateOrCreate per locale.

Caching. Locale lookups are per-request; eager-load translations in list queries and cache resolved translations for hot read paths.

Gotchas and Tips

  • Archived = frozen. No PHP 8 or Symfony 5/6 (let alone Laravel 10/11) support. Its Composer constraints will conflict with any modern stack. Read it, don't install it.
  • Doctrine-only. There is no Eloquent listener equivalent; you will rebuild the behavior with accessors, global scopes, and model events. Budget for that up front rather than hunting for a config flag.
  • Fallback semantics surprise people. Distinguish missing translation row from present row with null/empty field. The bundle generally falls back on the former only — decide explicitly which you want, because "empty string" fallback is a common production bug.
  • N+1 is the default failure mode. Lazy-loading translations per entity will quietly triple your query count on index pages. Always with('translations').
  • CLI and queue contexts have no _locale. The request listener never fires there; set the locale explicitly in jobs and commands or you'll write translations into the wrong bucket.
  • Clear the metadata cache after mapping changes — the classic "my new column isn't there" symptom in the Doctrine world.
  • Best extension point to copy: the TranslatableInterface contract plus the fallback-chain service. Define your own interface and a TranslationResolver bound in the container — that gives you a testable seam the original never quite had.
  • Modern Laravel alternatives that already solve this: astrotomic/laravel-translatable or spatie/laravel-translatable for the data model, mcamara/laravel-localization for the routing/locale layer. Use this bundle only as a design reference.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle