runroom-packages/doctrine-translatable-bundle
Doctrine Translatable Bundle adds per-locale translations to Doctrine entities in Symfony, storing translated fields in separate translation tables and wiring them into queries and hydration. Simple setup for building multilingual applications.
Architecture fit. Despite the Laravel framing in the brief, this is a Symfony bundle built on Doctrine ORM, not an Eloquent/Laravel package. That distinction is the single most important architectural fact for a TPM. If the target stack is Symfony (or any PHP application already using Doctrine), the package fits the native extension model: a bundle registered in config/bundles.php, a trait applied to entity classes, and repository helpers for locale-aware retrieval. If the target stack is Laravel, fit is poor — Laravel ships Eloquent by default, and adopting Doctrine purely to use this bundle imports a second ORM, a second migration system, and a second identity-map/session lifecycle. That is a large, ongoing architectural tax for a small convenience layer.
Integration feasibility. Mechanically straightforward where Doctrine is already present: Composer install, bundle registration, add the translatable trait to entities, define a translations collection and a translation entity, then use the provided repository methods to fetch with locale fallback. The surface area appears small (traits + repository helpers + likely a listener/subscriber), which is good for a spike. The real feasibility questions are dependency-related and must be answered from composer.json, not the README: PHP version floor, Doctrine ORM major (2.x vs 3.x), Symfony version constraints, and whether it pulls in KnpLabs DoctrineBehaviors, Gedmo, or Sonata Admin. Any of those as a hard dependency meaningfully expands the blast radius.
Technical risk. Signal is weak: zero stars, zero dependents, and an explicitly [READ-ONLY] repository. That pattern is almost always a subtree split or mirror of a monorepo, which means issues and PRs likely do not live here and there is no visible community, no security disclosure path, and no upgrade policy. The functional risk of translatable entities is well understood and non-trivial: N+1 queries when hydrating translations, locale-fallback semantics that are easy to get subtly wrong (null vs. empty string vs. missing row), and index requirements on (translatable_id, locale). A small, opinionated package can be excellent, but with no adoption footprint you are effectively the first production user and should plan to own the code.
Key questions.
composer.json constraints — PHP, Doctrine ORM, Symfony, and transitive deps (Sonata, Knp, Gedmo)?Stack fit. Green-light only for Symfony + Doctrine. For a Laravel codebase, the honest recommendation is to reject this package and instead evaluate a native Eloquent translation approach (JSON columns, per-locale tables, or a maintained Laravel translation package). Introducing Doctrine into Laravel for one bundle is not a defensible trade at this scale.
Migration path. If replacing Gedmo Translatable or KnpLabs DoctrineBehaviors, the migration is schema-sensitive: translation table shapes, FK naming, and cascade rules differ between libraries. Plan a data migration that backfills translation rows and a side-by-side validation pass comparing old and new query output for a sample of records across at least two locales before cutover. If this is greenfield, skip migration entirely and adopt it only if the dependency audit is clean.
Compatibility. Pin explicitly. Verify against the project's PHP runtime, Doctrine ORM major, and Symfony LTS. Because the package is read-only and low-traffic, do not assume a release will arrive to fix a version conflict — assume you will patch locally via a Composer repositories VCS/path override or a fork.
Sequencing.
composer.json and CI config (½ day).Maintenance. Treat this as an internally-owned dependency, not a community library. Budget for periodic version bumps, Doctrine major upgrades, and local patches. The low adoption means upstream breakage is unlikely to be caught by anyone but you. Forking under the org with a pinned SHA is the pragmatic default; a subtree-split mirror is not a stable supply chain.
Support. No visible issue tracker or SLA. Escalation path is effectively "Runroom, if reachable." For anything business-critical, that is a documented risk to record rather than a solved problem. Keep the dependency surface small so replacement cost stays low.
Scaling. Translation joins grow with record count × locale count. Enforce composite indexes on translation tables, avoid hydrating full translation collections in list views, and cache fallback-resolved values at the read path where hot. Watch for query count regressions in CI as entity count grows.
Failure modes. The dangerous ones are silent: fallback returning the wrong locale, missing translations surfacing as nulls in templates, schema drift after a Doctrine upgrade, and locale configuration mismatches between app and database. Add explicit tests asserting fallback order and missing-translation behavior — do not rely on the library's defaults being what your product needs.
Ramp-up. The concept (translatable entity pattern) is standard, but the ramp is gated on Doctrine fluency, not on this package. A Doctrine-comfortable Symfony developer is productive in 1–2 days; an Eloquent-only team faces a multi-week Doctrine learning curve that dwarfs the value of the bundle. Factor that into the build-vs-buy decision — at zero adoption and one small feature surface, writing twenty lines of repository code is often cheaper than taking the dependency.
How can I help you explore Laravel packages today?