jjanvier/crowdin-bundle
Symfony bundle that integrates Crowdin translation management into PHP projects. Provides console commands and services to upload source files and download translated content, keeping your application's translation resources in sync with Crowdin throughout development.
Architecture fit — poor, and partly mislabeled. Despite the "Laravel/PHP package" framing, jjanvier/crowdin-bundle is a Symfony2 bundle, not a Laravel package. Laravel has no bundle system; it uses service providers, facades, and an artisan console kernel. A Symfony bundle registers itself through Bundle::boot(), DependencyInjection/Extension, and Resources/config/services.yml — none of which Laravel's container will autoload or honor. There is no maintained bridge that lets a Symfony2 bundle run natively inside a Laravel application. The functional scope is narrow and understandable — authenticate against Crowdin, push/pull translation files, report status via console commands — but the delivery mechanism is wrong for our stack. Version 0.2.0 does not change this: it is still a Symfony2 bundle.
Integration feasibility — low as a dependency, moderate as a reference implementation. Composer resolution remains the first hard blocker: the bundle constrains symfony/framework-bundle to the 2.x line. Release 0.2.0 adds a dependency on php-crowdin-lib rather than removing one. That library is itself an old, PHP 5-era Crowdin API client, so the new release widens the transitive surface (framework bundle + HTTP client + php-crowdin-lib + its own dependencies) instead of narrowing it. None of that resolves against Laravel 9/10/11 (PHP 8.1+, Symfony 6/7 components). Forcing it in with --ignore-platform-reqs produces a dependency graph we cannot patch. What remains useful is the code: the command classes are small and readable enough to port. That makes this a pattern source, not a library — and 0.2.0 makes it a slightly larger pattern source, not a better one.
Technical risk — high, marginally higher after 0.2.0.
php-crowdin-lib — another abandoned package. The maintenance surface is not reduced; it is redistributed.php-crowdin-lib does not change the endpoint generation.php-crowdin-lib all carry known or unpatchable CVE exposure; we would be importing them voluntarily.php-crowdin-lib being a plain library actually helps here — its logic is portable — but that is true of the official client too, and with far less baggage.Key questions.
Stack fit. None directly. The correct modern substitutes are: the official Crowdin CLI (declared as a CI step or a shelled-out process), the official crowdin/crowdin-api-client-php (v2 API, actively maintained, PHP 8-compatible), or a thin in-house wrapper over that client exposed as Laravel artisan commands. Any of these fits a Laravel service provider and queue system; the bundle does not. The 0.2.0 release does not introduce an alternative — php-crowdin-lib is a third-party v1 client, not a supported path.
Migration path. Treat the bundle as a specification document:
php-crowdin-lib; extract its API-call shapes as the more precise spec, then discard the library.php artisan crowdin:push / crowdin:pull commands backed by crowdin-api-client-php, with credentials in config/services.php and .env.If a stopgap is truly required, run the bundle as an isolated Symfony2 console application in its own container/CI job, invoked over the network or via artifact exchange — never inside the Laravel process or its Composer autoloader.
Compatibility. Assume PHP 5.3–5.6 and Symfony 2.x. No PHP 8 typed-property, union-type, or attribute support; likely each() and other removed functions. php-crowdin-lib carries the same vintage of constraints and does not lift PHP or Symfony requirements. Cannot coexist with Laravel's dependency versions. Crowdin API v1 endpoints must be assumed dead until proven otherwise — validate with a single read-only call before scoping any work.
Sequencing.
php-crowdin-lib is a reference, not a candidate.Estimated total effort: small and unchanged by 0.2.0. The bundle's command surface is limited, and the official client removes most of the hard work.
Maintenance. Forking means owning translation-sync code plus a dependency tree nobody else patches — and after 0.2.0 that tree now includes php-crowdin-lib in addition to the Symfony2 stack. That is a permanent, low-glamour tax on a team for functionality that is otherwise a commodity. Building on the official v2 client shifts maintenance to the vendor and reduces our surface to a few hundred lines of Laravel glue. Strong recommendation: do not run this package in production.
Support. No maintainer activity of consequence, no issue triage, no security advisories. A single dependency-bump release on a dormant project is not a support signal. Internal escalation path would be "whoever last touched the fork." There is no vendor relationship to lean on, Crowdin's own support will not troubleshoot a decade-old wrapper around a retired API, and php-crowdin-lib has its own separate (and equally thin) upstream.
Scaling. The workload is batch and low-volume — a handful of file uploads/downloads per release — so scale is a non-issue technically. The real scaling concern is organizational: every new locale, file format, or Crowdin feature (branches, glossaries, machine translation pre-translation) must be hand-added to a fork nobody wants to touch — and in 0.2.0's case, potentially re-added at the php-crowdin-lib layer too. That cost compounds with localization maturity, which is exactly when the tooling should be most capable.
Failure modes.
.xliff/.po.php-crowdin-lib.php-crowdin-lib, with no clear owner for either.
Mitigations for a reimplementation: explicit exit codes, dry-run mode, checksum-based skip-if-unchanged, exponential backoff, and a post-sync verification step that asserts expected locale/file counts.Ramp-up. Low for the code itself — it's a small, conventional Symfony2 bundle and an engineer can read the command layer in an afternoon. Reading php-crowdin-lib to understand actual API behavior adds perhaps half a day. Higher for the surrounding context: Symfony2 DI idioms, Crowdin API v1 semantics, and the archaeology of why each command exists. Budget roughly a day of reading plus a day of API-v2 spike before committing to a plan. The replacement path using the official client is materially faster than reviving the fork, and it is the path I would take.
How can I help you explore Laravel packages today?