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

Locale Laravel Package

escalated-dev/locale

Central source of truth for Escalated translations. Consolidates locale catalogs from the Vue frontend and framework plugins into canonical locales/{locale}.json files, then republishes them as npm, Composer, RubyGem, PyPI, Maven, NuGet, Hex, and Go packages.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and inspect, in that order.

composer require escalated-dev/locale

Before writing any code, look at what actually landed:

ls vendor/escalated-dev/locale
cat vendor/escalated-dev/locale/composer.json
find vendor/escalated-dev/locale -name "*.json" -o -name "*.php" | head -50

Two things to look for in composer.json:

  1. "type" — if it is library and there is no extra.laravel.providers, this is a data package, not a Laravel package. Nothing will auto-register, and no vendor:publish tag exists. You load the files yourself.
  2. The version — this package is versioned and republished per release, so pin it ("escalated-dev/locale": "^1.0" style) and treat upgrades as data changes, not bugfixes.

Where to look first: the locales/ directory. The README describes locales/{locale}.json as the canonical source of truth, with framework-native artifacts (Ruby YAML, Django gettext, Symfony, etc.) generated alongside it by scripts/sync.sh. For Laravel specifically, expect either:

  • flat locales/en.json files you load manually, or
  • a framework-native artifact (Symfony .yaml/.xlf) that Laravel's translator cannot read natively — you would need Symfony\Component\Translation loaders or a conversion step.

Confirm which one you got before planning around it.

First real use case: wiring the catalog into Laravel's translator as a namespaced group so it doesn't collide with your lang/en/*.php files.

// AppServiceProvider::boot()
Lang::addNamespace('escalated', base_path('vendor/escalated-dev/locale/locales'));

Then reference keys as __('escalated::auth.failed') — provided the files are .php arrays. If they are .json, addNamespace still works but every key must be flat and dot-notation-indexed; verify with a quick json_decode dump of the top level before assuming nesting is supported.

If the package ships a Symfony-style Resources/translations/*.yaml, use a loader instead:

$this->app['translator']->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
$this->app['translator']->addResource('yaml', resource_path('...'), 'en', 'escalated');

Implementation Patterns

Treat it as the base layer, override at app level

The README says catalogs are "merged with repo-local overrides at app boot." Mirror that on the Laravel side rather than editing vendor files. The clean approach is a two-step load: base namespace first, then your override file with the same keys.

// 1. base catalog
Lang::addNamespace('escalated', '/vendor/escalated-dev/locale/locales');

// 2. app overrides — same namespace, same keys, loaded after
if (is_dir(lang_path('vendor/escalated'))) {
    Lang::addJsonPath(lang_path('vendor/escalated'));
}

Override files live in your repo under lang/vendor/escalated/, which is exactly what vendor:publish normally produces. Since this package likely has no publish tag, create the directory yourself and copy from vendor on demand — but never let your copy be the only source, or you'll silently drift from upstream.

Publish-once, diff-in-CI

For a data package that ships across seven ecosystems, the version you pin is a snapshot of a much larger upstream sync. Add a CI step that fails when vendor differs from the lock:

composer install --no-interaction --prefer-dist
git diff --exit-code composer.lock  # catches accidental drift

And a health check that every locale your app advertises actually exists:

foreach (config('app.supported_locales') as $locale) {
    $path = base_path("vendor/escalated-dev/locale/locales/{$locale}.json");
    throw_unless(file_exists($path), RuntimeException::class, "Missing locale: {$locale}");
}

Bridge the same catalog to the frontend

The architecture diagram already routes through npm (@escalated-dev/locale) for Vue. If you're running Inertia, do not re-read the JSON server-side and duplicate translations — pick one owner per string. A workable split:

  • Server-owned strings (validation, auth, mail) → Laravel namespace via the Composer package.
  • Client-owned strings (UI labels) → npm package, imported directly in the Vue bundle.

Sharing Lang::get() output through Inertia::share('translations', ...) works but re-sends the entire catalog on every response. Only do it if the catalog is small and you need runtime __() in the frontend.

Locale set as configuration, not code

Drive config/app.php's available_locales from the catalog directory rather than hardcoding:

$available = collect(glob(base_path('vendor/escalated-dev/locale/locales/*.json')))
    ->map(fn ($p) => basename($p, '.json'))
    ->values()
    ->all();

This keeps the app honest the moment you bump the package and it adds a locale — but see the gotcha on naming conventions below.

Testing pattern

Assert on presence, not phrasing, so upstream translation edits don't break your suite:

public function test_escalated_catalog_loads(): void
{
    $this->assertNotSame(
        'escalated::auth.failed',
        __('escalated::auth.failed')
    );
}

Gotchas and Tips

It is almost certainly not a Laravel package. No dependents, 2 stars, and a README that describes itself as a canonical data source rather than runtime infrastructure. Expect zero service providers, zero facades, zero config file. If you install this expecting php artisan vendor:publish, you will find nothing. Plan to load files manually.

Framework-native artifacts are not Laravel-native. The README lists "Symfony" as the framework-specific output — Symfony's translator consumes .yaml/.xlf; Laravel's consumes .php and .json. Those are close enough to tempt a copy-paste, but plural rules and nested keys differ. Check the file format of what actually shipped before writing Lang::addNamespace.

JSON vs PHP array semantics differ on pluralization. Flat JSON catalogs cannot express ['one' => ..., 'other' => ...] plural groups cleanly. If the shipped catalog is JSON and your UI needs plurals, you'll get either an ICU-style string ({count, plural, ...}) or a pre-composed key. Verify with a non-English locale — English hides the problem because plural forms are usually just two and simple concatenation often "reads fine."

The filename is {locale}.json, not necessarily Symfony/CLDR style. en.json vs en_US.json vs en-GB.json matters for App::setLocale(). If the package uses underscores and your app uses hyphens, Lang will silently fall back to fallback_locale and you'll debug missing strings for an hour. Normalize explicitly:

$locale = str_replace('-', '_', app()->getLocale());

Version-lock against the Escalated plugin. This package is consumed by "all backend plugins" — meaning the Escalated Laravel plugin, if you use it, pins a compatible range. Upgrading this package independently of the plugin risks key drift between the package's catalog and the plugin's code calling __('escalated::…'). Let the plugin's constraints win; if you have no plugin, you are your own compatibility manager — which is fine, but budget for it.

Debugging missing keys is opaque. When a key isn't found, Laravel returns the key itself. If keys look like escalated::validation.required in the UI, the namespace never loaded or the path is wrong. Isolate with:

dump(Lang::getLoader()->namespaces()['escalated'] ?? null);
dump(file_exists('/vendor/escalated-dev/locale/locales/' . app()->getLocale() . '.json'));

Extension point: patch at boot, not at fork. If upstream is missing a key you need, register your own namespace loader before the package's namespace — or better, keep your override in lang/vendor/escalated/ and load it last. Forking a data package to add one string guarantees you'll stop receiving upstream catalog updates, which is the entire value proposition here.

Cache invalidation after install. A fresh composer require in a booted app container will still serve stale translations until php artisan config:clear && php artisan cache:clear. When a key "still won't resolve" after adding the namespace, clear before rewriting your service provider.

Watch the sync scripts if you contribute translations. scripts/build_locales.py pulls from upstream source repos; scripts/sync.sh regenerates every ecosystem package. If you edit locales/en.json directly and the upstream still owns that key, your change gets reverted on the next build. Fix it at the source repo unless the README explicitly says the central package is now canonical for that string.

Given the maturity signals (2 stars, 0 dependents, single-digit months since first release), expect breaking changes in file layout between minors. Wrap the loading logic in one small class — EscalatedLocale::register() — rather than scattering Lang::addNamespace calls across providers. When the path or format changes, you fix it in one place.

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