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

Js Localization Laravel Package

andywer/js-localization

Bring Laravel's translations to JavaScript. An artisan command exports your PHP lang files, and a lightweight client-side translator looks up keys and replaces placeholders at runtime, so backend and frontend share the same strings with no duplication. Works with any frontend stack.

View on GitHub
Deep Wiki
Context7

Getting Started

The package's whole job is to turn Laravel lang/ files into a public/js/localization.js that exposes a browser-side Lang.get() / Lang.choice() helper. Integration is three steps.

Install and publish

composer require andywer/js-localization
php artisan vendor:publish --provider="Andywer\JsLocalization\JsLocalizationServiceProvider"

On Laravel 5.5+ the provider is auto-discovered. On older versions, register Andywer\JsLocalization\JsLocalizationServiceProvider in config/app.php and add the JS facade alias — you need the alias if any code calls JS::.

Publishing gives you config/js-localization.php (the output path, typically public/js/localization.js) and a JS stub.

Export a group of strings

Don't scatter JS::put() across controllers. Put it in one place — AppServiceProvider::boot() or a dedicated LocalizationServiceProvider:

use JS;

public function boot()
{
    JS::put(['messages' => 'messages', 'validation' => 'validation']);
}

The array is ['filename' => 'lang/group-name']. Only list groups the front end actually renders — this is the single biggest lever on payload size.

Consume in the browser

<script src="{{ asset('js/localization.js') }}?v={{ filemtime(public_path('js/localization.js')) }}"></script>
<script>
  console.log(Lang.get('messages.welcome'));
  console.log(Lang.choice('messages.apples', 3));
</script>

Where to look first when it doesn't work

  1. Does public/js/localization.js exist after a request? If not, JS::put() never ran or the web server can't write to public/js.
  2. Is it non-empty? Open it and read the raw object — this file is the integration surface.
  3. Is public/js writable in dev? chmod/chown the directory.

Everything after that is ordinary Laravel translations plus a small JS helper. There is no route, no middleware, no database — one file.

Implementation Patterns

Treat the export as a build step, not a request step. The default behavior writes on boot, on every request. That's fine in local, but in staging/production write it at deploy time instead:

// app/Console/Commands/ExportLang.php
public function handle()
{
    JS::put(['messages' => 'messages']);
}
php artisan app:export-lang   # in your deploy script

This eliminates runtime writes to public/ (mandatory on Heroku, Lambda, read-only Docker images) and removes the concurrent-overwrite race entirely.

Pin the group set; never vary it by page. If page A exports messages and page B exports validation, whichever request finishes last wins and you get nondeterministic missing keys in users' browsers. Export a stable superset.

Cache-bust aggressively. Browsers and CDNs will happily serve yesterday's file. filemtime() in the query string is the minimum; running it through Mix/Vite is cleaner; setting Cache-Control on the file at the web-server level is best.

One source of truth per key. Pick Lang.get() for anything client-rendered and stop mirroring those keys with @lang(). Mixing both for the same key guarantees drift the moment copy changes.

Multi-locale: generate per locale, don't regenerate per request. The package captures whichever locale is active when JS::put() runs, so a locale-switching app needs either separate output files (localization.en.js, localization.de.js) or a regeneration step that sets app()->setLocale() first. If neither is comfortable, this is the point to replace the package with a small controller returning per-locale JSON and have a ~30-line Lang helper hydrate from it — you keep the Lang.get() contract and gain caching headers, lazy loading, and no file writes.

Keep the export behind your own interface. Wrap JS::put() in a LangExporter service or a Blade directive. The package is ~100 lines of glue; isolating it makes a future swap to a hand-rolled Artisan command or a TMS-driven JSON artifact a one-file change rather than a hunt.

Test parity where it matters. Write one test comparing PHP trans() output against the generated JS Lang.get() for keys with :placeholders and for Lang.choice with {0}/[1,19] ranges. Divergence here is quiet and user-visible.

Gotchas and Tips

  • Writable public/ in production is a trap. Read-only filesystems fail loudly or silently no-op. Switch to deploy-time generation before you hit this, not after.
  • Only flat string groups survive cleanly. Nested arrays and complex trans() structures don't round-trip reliably. Validate plural ranges, :placeholder replacement, JSON lang/en.json files, and vendor:: namespaced keys against what actually lands in the generated file — don't assume Laravel parity.
  • Everything you export is public. The file is a static asset served to anonymous users. Validation messages are usually fine; admin panel strings, email templates, and internal error copy are not. Audit group-by-group.
  • Escaping is on you to verify. Translation values containing quotes, backticks, or </script> can break the file or produce XSS. Test with a deliberately nasty string.
  • Lang is undefined almost always means one of three things: the <script> tag is missing, the generated file is empty, or JS::put() was never called. Inspect public/js/localization.js directly before opening devtools.
  • Concurrent requests can corrupt the file. Two requests rewriting localization.js with different group sets can yield partial content. Deploy-time generation is the real fix.
  • Facade alias still matters on old Laravel. Auto-discovery registers the provider but does not register JS:: — add the alias or import the class fully qualified.
  • Republishing overwrites your JS stub. Keep customizations under version control and re-apply after vendor:publish. Better: don't customize the stub.
  • Verify compatibility before you commit. This is Laravel 4/5-era code with a single maintainer and no dependents. Check composer.json constraints and the last commit date against your Laravel/PHP versions; expect to need a fork or an "illuminate/support": "*" constraint override.
  • Treat maturity as a design input. With 143 stars and zero dependents, budget for owning the code. Pin the version, vendor the ~100 lines if it's in a critical path, and know that the escape hatch (JSON endpoint + hand-rolled Lang) is genuinely cheap.
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.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr