locastic/api-platform-translation-bundle
Symfony bundle that adds multilingual support to API Platform resources. Use the provided traits to define translations for Doctrine entities, then serve locale-aware API responses based on the request's language, with automatic translation hydration and minimal configuration.
This is not a Laravel package. It is a Symfony bundle built for API Platform, and it assumes Symfony's DI container, Doctrine ORM, and API Platform's serializer and metadata pipeline. That distinction is the single most important finding in this evaluation: if the target stack is Laravel, the package is unusable regardless of its quality, and its only value is as a design reference.
On its merits, the architecture follows the Sylius translation pattern, which is a well-established and sensible shape for localized content: a parent entity with a one-to-many relation to a translation entity keyed by locale, a Doctrine query collection extension that filters on the resolved locale, a listener that hydrates the correct translation, and serializer hooks that expose it through API Platform. This maps cleanly onto how API Platform expects resources to be normalized and is the same modelling approach used by Sylius, Aimeos, and most mature multi-locale Symfony commerce systems. The design is right; the question is whether this implementation of it is right.
Integration feasibility is low to moderate. It requires per-entity translation tables and traits, bundle registration, locale resolution wiring (query parameter, request header, or serializer context), and correct serialization group configuration. Read paths are the easy part. Writes are the risk: POST and PATCH with embedded translations require the normalizer to map nested payloads into translation rows and to handle per-locale validation, which typically means custom validators because Symfony constraints on a translation entity do not naturally express "required in the request locale only."
Technical risk is high. The adoption signals are weak — 83 stars and zero dependents means there is no downstream population stress-testing upgrades ahead of you. The package sits directly on API Platform's normalizer and Doctrine extension interfaces, which changed materially between API Platform 2.x and 3.x and again with the attribute-based metadata system. Translation bundles are precisely the category of package that breaks across those boundaries, and with no dependents, the break will be discovered by you. The Sylius-derived schema is also a one-way door: once the translation table is the source of truth, reversing the model is expensive.
Key questions to resolve before any commitment: which API Platform, Symfony, and PHP version ranges are actually CI-tested (read composer.json and the test matrix, not the README); whether write operations are supported or the bundle is read-only normalization; what the fallback behaviour is when a requested locale is missing (default-locale fallback, null, or 404 — these are three very different API contracts); whether per-locale partial updates and per-locale validation are handled; how translations appear in the generated OpenAPI document and whether that schema is stable enough for typed client generation; and what the real maintenance cadence looks like in commits and issue response time, since the last-release date alone is not evidence of activity.
Stack fit is a hard blocker for Laravel. There is no adapter path — the package depends on Symfony's bundle system, API Platform's resource metadata, and Doctrine. The Laravel equivalent is a translation table with an Eloquent hasMany, a locale-scoped query scope, and a dedicated API Resource or transformer, or an existing package such as astrotomic/laravel-translatable paired with your own serialization layer. For a Laravel organisation the correct decision is: do not adopt, use this repository as a modelling reference, and budget the build in-house.
Where the stack is Symfony plus API Platform, the integration is viable but should be treated as adopting an internal component that happens to be public. Migration is additive: create translation tables alongside existing content tables, backfill one row per translatable entity seeded with current values under the default locale, then switch reads through the translation relation. Run this behind a feature flag with dual-read — parent column versus translation row — for a release cycle so rollback stays cheap. Compatibility must be pinned: lock a specific API Platform minor, run the bundle's tests against your target versions, and confirm the OpenAPI output is acceptable to downstream consumers before writing production code, because translation subresources tend to inflate schemas and can destabilise generated SDKs.
Sequence the work as: a two-day spike on one entity and one non-default locale covering both read and write; a wire-format review with the frontend and integration teams deciding between embedded translations, a subresource, and a locale query parameter; a validation design step deciding whether per-locale rules live as constraints on the translation entity or as a custom validator; the backfill migration with default-locale seeding; then rollout to a single resource before generalising to the rest of the domain.
Maintenance is the dominant cost. With zero dependents there is no community absorbing upgrade work, so every API Platform major release becomes a fork-or-fix decision on your roadmap. Plan to own a vendored fork and to patch it when normalizer or metadata interfaces shift. Document the locale resolution order and the serializer hooks internally — they are non-obvious, and debugging serialization failures is slow and expensive in engineer hours.
Scaling is generally acceptable for read-heavy APIs, since the pattern adds one join per translated resource. The two things to watch are N+1 queries when serializing collections with translations, which is your responsibility to eager-load, and write amplification on multi-locale PATCH operations. Caching requires discipline: cache keys must include locale, responses must Vary on the locale signal, and invalidation must cover every locale or fall back to clearing the resource. Decide this up front rather than retrofitting it.
Failure modes to instrument for: silent fallback, where a missing translation returns the wrong language or null depending on configuration and only surfaces in production for one locale; serializer drift after an API Platform upgrade, where translations move from flat to nested and break consumers; partial writes where the parent updates but the translation upsert fails, leaving the tables inconsistent; and OpenAPI changes that cascade into generated client breakage. Ramp-up is one to two weeks for a developer already fluent in Doctrine and API Platform, and materially longer for a Laravel-centric team, who would be learning the framework and the bundle simultaneously — a real scheduling risk worth naming explicitly. Pair the spike with existing API Platform experience rather than learning both at once.
Overall, the recommendation is conditional approval for a bounded spike on Symfony plus API Platform only, with the plan explicitly assuming fork-and-own, and outright rejection for Laravel. The low adoption signal is not disqualifying for a small, well-shaped bundle, but it does mean this should be adopted as internal code rather than as an unexamined vendor dependency.
How can I help you explore Laravel packages today?