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

Laravel Translation Laravel Package

vemcogroup/laravel-translation

Driver-based translation management for Laravel: store and edit translations in the database or files, scan your code for missing keys, and manage everything from a built-in web UI. Includes caching, validation, and Artisan commands for a smooth localization workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require vemcogroup/laravel-translation
php artisan vendor:publish --tag=translation   # or --provider="VemcoGroup\LaravelTranslation\...ServiceProvider"

The package registers via Laravel package auto-discovery (5.5+), so no manual provider entry is needed. After publishing you get config/translation.php — read it top to bottom before running anything; it is the only real documentation surface and it defines every path, language, and POEditor credential the commands use.

Minimum configuration:

POEDITOR_API_TOKEN=your-token
POEDITOR_PROJECT_ID=123456

In config/translation.php set at least the source language (the language your codebase is written in, usually en), the target languages list, and the paths to scan (typically app/, resources/views/, routes/).

Where to look first: the published config file, then vendor/vemcogroup/laravel-translation/src/Console to confirm the exact command signatures your installed version ships. Command names have shifted across releases, so verify with php artisan list | grep translation rather than trusting a blog post.

First use case — the happy path in four steps:

  1. php artisan translation:scan — walks your source paths, extracts literal translation keys, and writes missing ones into the source language file.
  2. php artisan translation:upload — pushes the source language file to your existing POEditor project as terms.
  3. Translators work in POEditor's UI.
  4. php artisan translation:download — pulls target-language translations back into lang/{locale}/*.php.

Note that the POEditor project must already exist with the correct source language configured; the package synchronises terms, it does not provision projects.

Implementation Patterns

One canonical source file. Upload/download operate on a single source language file (e.g. lang/en/messages.php). Keep all translatable strings there rather than spreading them across auth.php, validation.php, passwords.php. If you need Laravel's built-in validation messages translated, treat them as a separate concern — they will otherwise pollute your POEditor term list with thousands of framework strings.

Scan → upload → translate → download as a pipeline, not a developer habit. The valuable pattern is putting the sync in CI/deploy rather than in each dev's local loop:

# pseudo-CI
- run: php artisan translation:scan
- run: git diff --exit-code lang/ || (echo "New keys found — commit them" && exit 1)

This makes the scanner a linter: a PR that adds __('checkout.new_error') without adding it to the source file fails fast, rather than surfacing as a missing translation in production months later. Run translation:upload on merge to main; run translation:download either on a schedule or as a manual, reviewed step (see Gotchas).

Namespace discipline for Blade. The scanner needs literal keys. Standardise the team on {{ __('messages.checkout.title') }} and forbid @lang($variable) in code review. Adopting one call style also keeps the scanner's configured function list (which likely covers __, trans, @lang) tight and predictable.

Separate the "developer adds key" from the "translator provides value". Developers only ever touch the source language file. Target language files are build artifacts regenerated by translation:download — never hand-edited, or the next download silently reverts the fix.

Frontend translation. If you use laravel-vue-i18n or vue-i18n, add a small export step that reads the downloaded PHP arrays and emits JSON per locale into resources/js/lang/. Don't try to make the package scan .vue/.js files — write a separate extractor for the frontend and let this package own only the backend catalog.

Wrap the commands. For multi-environment setups, add your own thin artisan commands or scheduled jobs that call the package's commands with the right --env context, so the CI config doesn't encode POEditor semantics directly.

Gotchas and

Dynamic keys are invisible. __($key), __('error.' . $code), and __("messages.{$type}.title") are not found by the scanner. Any key built at runtime must still be written literally somewhere, or you'll get "missing translation" fallbacks in production with a green CI. This is the single most common failure mode.

Download overwrites; treat it with suspicion. translation:download writes target language files wholesale. Consequences: (a) any hotfix someone made directly in lang/de/messages.php is lost; (b) translations deleted in POEditor become deleted keys; (c) the diff can be enormous if a translator reorganised terms. Always run it on a branch, review the diff, and commit deliberately. Never wire it into an unattended production deploy.

Cached config masks .env changes. If php artisan config:cache runs in your deploy, POEditor credentials are baked into the cached config. Rotating the API token requires a full cache clear + redeploy, not just an .env edit. Conversely, if POEDITOR_PROJECT_ID comes back empty, check for a stale config cache before anything else.

Scanner only sees configured paths. New top-level directories (e.g. moving code into src/, or a Livewire component folder) are silently unscanned. Review the paths list whenever the project layout changes. Similarly, strings inside PHP that are built in a config array and later passed to __() won't be seen.

POEditor is flat, Laravel is nested. Nested arrays get flattened to dot-notation terms on upload and re-expanded (or not, depending on version) on download. Verify round-tripping on a two-key test file before trusting it on your whole catalog. Duplicate terms, trailing whitespace, and case differences (Save vs save) create phantom duplicate entries in POEditor.

Debugging a failed sync. Errors are typically swallowed as a generic command failure. Reproduce by calling the POEditor API directly with curl using the same token/project ID — a 401 almost always means the token isn't scoped to that project, and a 404 means the project ID is wrong or the project's source language doesn't match your config. Add -v to the artisan call and check storage/logs/laravel.log.

Extension points. The published config is the primary extension surface (paths, functions, languages). Beyond that, the package is thin — for anything non-trivial (custom key extraction, per-environment language sets, JSON export), write your own command against the same config rather than forking. The POEditor HTTP client inside is likely a single small class you can subclass or call directly.

Version risk. At ~130 stars and a single-maintainer cadence, pin the version in composer.json and check the package's Laravel constraint against your framework version before upgrading — this is a dependency you want to bump deliberately, not transitively.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route