purjus/loco-importer-bundle
A Symfony bundle for importing translations from Loco into your application. It streamlines pulling localization data from the Loco API into your project's translation files. Early-stage package with limited adoption; a useful starting point for Loco-to-Symfony translation sync.
Architecture fit — poor, and the premise needs correcting. Despite the framing as a Laravel/PHP package, purjus/loco-importer-bundle is a Symfony bundle, not a Laravel package. Its integration surface is Symfony's DependencyInjection Extension/CompilerPass, the Symfony console application, and Symfony's translations/ directory conventions. Laravel applications have no mechanism to register or boot a bundle; there is no service provider, no config/*.php publish path, and no Laravel console command registration. Nothing in this package can be composer required into a Laravel app and "just work."
What is reusable is the narrow core: an HTTP client that pulls a translation export from Loco's API and writes files. That logic is likely 100–300 lines and can be lifted into an Artisan command. The surrounding bundle scaffolding is dead weight in a Laravel context.
Integration feasibility — low directly, moderate via extraction. The realistic paths are, in order of preference:
php artisan loco:pull). Loco exposes stable export endpoints per format and per locale; this is a well-bounded integration.Technical risk — high, and dominated by abandonment rather than defects. Signals are unambiguous:
symfony/* (4.x/5.x era) and guzzlehttp/guzzle (6.x) that will collide with Laravel 10/11 (Symfony 6/7 components, Guzzle 7).The score of 0.005 is consistent with "unmaintained and unadopted," not with "hidden gem." There is no security surface to speak of (it is a CLI import tool), but there is also no one to patch it.
Key questions to resolve before any decision:
:placeholder interpolation, {0} {1} pluralization, and JSON-key vs nested-array conventions?LOCO_API_KEY env vs Symfony parameters) and any retry/backoff behavior?Stack fit — mismatched by construction. The package targets a Symfony application on PHP 7.x. A current Laravel app is on PHP 8.2/8.3 with Symfony 6/7 components and Guzzle 7. Composer will very likely refuse to resolve the bundle's constraints alongside a modern Laravel requirement, and even if forced, the bundle's runtime wiring expects a Symfony kernel that does not exist. Treat "install the package" as a non-option and plan around extraction from the start.
Migration path — build a thin Laravel-native importer. The correct shape is:
loco:pull {--locale=} {--dry-run}) that authenticates with a Loco API key from config/services.php / .env.lang/{locale}/{domain}.php arrays and/or lang/{locale}.json — which Loco supports natively via its export endpoint.rename), never a partial in-place write.If we fork instead, the port is mechanical: delete the DI extension and console registration, expose the client as a singleton from a service provider, register the command in routes/console.php or via Kernel::commands. Budget roughly a day for a Symfony-familiar engineer to read the bundle and a few days to produce a tested Laravel equivalent.
Compatibility — the real work is format and semantics, not code. Translation catalogues are deceptively format-sensitive:
|-delimited forms vs ICU MessageFormat. A naive format pass-through mangles plural rules in Slavic and Arabic locales.:name as {name} or %name% depending on export format; Laravel's __() replaces :name. This must be pinned and asserted in tests.Sequencing. (1) Confirm the Loco plan/tier exposes the export API for our catalogs. (2) Spike a ~50-line direct API call in a throwaway branch — this almost certainly obviates the dependency entirely. (3) Only if the spike reveals nontrivial logic (pagination, multi-file assembly, auth quirks) does the fork-and-strip option earn its keep. (4) Ship as internal code with CI coverage on a golden-file fixture set, not as a Composer dependency.
Maintenance — we would own it permanently. Upstream is dormant; issues and PRs effectively do not get answered. Any adopted or forked version becomes a permanent internal fork, and a fork of an unmaintained 1-star package is a liability with no upgrade path — every Loco API change and every Laravel major becomes our ticket. Building the ~150-line in-house client is cheaper over a two-year horizon than owning a fork.
Support — self-service only. No documentation beyond the README, no issue history to mine, no vendor contact. Institutional knowledge must be written down, because the engineer who builds this will be the only person who understands it. That argues strongly for internal code with comments and tests over an opaque vendored bundle.
Scaling — low risk; this is batch work. Translation imports are infrequent, small (kilobytes to low megabytes), and CLI-bound. Scaling concerns are not about throughput but about blast radius: one command run mutates every locale's catalogue. Practical guards: per-locale invocation, rate-limit/backoff respect for Loco's API, timeouts on large exports, and running in CI or on a release step rather than ad hoc on production.
Failure modes — these matter more than the package choice:
lang/ files are clobbered by the next pull. Requires a clear ownership rule (Loco is source of truth, or a namespace split) and a --dry-run diff.:name or broken plural selection — a user-visible defect that tests, not code review, will catch.Ramp-up — low effort, but not zero-cost. The bundle's code is small and readable, but reading it requires Symfony fluency that Laravel-focused engineers may not have. A replacement command is approachable for any mid-level Laravel engineer in a few days. The genuine ramp-up cost is domain knowledge: Loco's export semantics, our locale matrix, and our pluralization conventions — none of which this package documents.
Recommendation. Do not adopt purjus/loco-importer-bundle as a dependency. Treat it as a reference implementation at most, and build a small, tested, Laravel-native Artisan command against Loco's export API. The package's value is that it confirms the integration is tractable in a few hundred lines — not that its code should ship in our stack.
How can I help you explore Laravel packages today?