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

Localization Helper Laravel Package

awes-io/localization-helper

A Laravel localization helper that scans your codebase for translation keys, finds missing or unused strings, and helps keep language files in sync. Streamline multi-language app management with handy Artisan commands and a clear view of translation coverage.

Deep Wiki
Context7

Getting Started

  1. Install the package into an existing Laravel app (it targets Laravel's Blade compiler and translator, so it should be added to the same app you render views from):

    composer require awes-io/localization-helper
    
  2. Check for a publishable config and any registered Blade directive / helper function:

    php artisan vendor:publish --provider="AwesIO\LocalizationHelper\LocalizationHelperServiceProvider"
    php artisan list | grep -i locali
    

    You are looking for two things: a config file (usually controlling the key-generation strategy / prefix) and an artisan command that scans Blade views and writes translation files.

  3. First use case — replace a hardcoded string in a Blade view with the package directive:

    {{-- before --}}
    <h1>Welcome to our app</h1>
    
    {{-- after --}}
    <h1>@l('Welcome to our app')</h1>
    

    Then run the collect/extract command (whatever php artisan list shows — commonly localization:collect). It scans resources/views for every @l(...) / __l(...) call and generates a translation file for the source locale. That generated file is the artifact you hand to translators or feed into your TMS.

  4. Verify by switching locale (app()->setLocale('...')) and confirming the rendered output. If the key isn't found, the generated file is stale — re-run the collect command.

The mental model: the package is a build-time string extractor bolted onto Blade, not a runtime translation engine. __()/@lang() need the key to exist already; @l() lets you write source text inline and have the key materialized later.

Implementation Patterns

Inline strings with placeholders. The value of the directive is that the source text and its parameters live in the same place:

<p>@l('Hello, :name! You have :count unread messages.', ['name' => $user->name, 'count' => $count])</p>

This keeps the view readable and gives the extractor everything it needs to produce a key plus a parameterized string for translators.

Treat generated keys as opaque. Don't try to hand-edit keys the package generates (hash/slug from the source text). If you need a stable, human-readable key, prefer a hybrid workflow: use __('messages.welcome') for long-lived strings, and @l() for content-heavy marketing views where inline authoring beats managing a key.

Programmatic helper in PHP. Mirror the Blade usage in controllers/services with the corresponding helper (__l(...) if exposed) so strings authored outside views are also picked up by the same extraction pass. Don't mix @l() and __() in the same feature if you rely on extraction — __() calls are invisible to the scanner.

CI / build pipeline. The collect command is the crux of the workflow. A sane pipeline:

# in CI, after code changes
php artisan localization:collect --source=en   # or equivalent flags
git diff --exit-code lang/ || (echo "translations out of date" && exit 1)

This turns "did someone forget to re-run the extractor?" into a build failure instead of a production bug.

Namespacing / file organization. If the package lets you split by file or directory (most do via a config paths option), split by feature (lang/en/auth.json, lang/en/billing.json). It keeps diffs reviewable and lets translators work on isolated domains.

Locale bootstrapping. Wrap your first usage in a small feature test with a second locale to prove the generated key actually resolves:

public function test_welcome_string_translates(): void
{
    app()->setLocale('fr');
    $this->blade('<h1>@l(\'Welcome to our app\')</h1>')
         ->assertSee(__('_hash_or_key_for_welcome'));
}

Gotchas and Tips

  • Stale keys are the number one failure mode. @l() compiles to a key derived from the source string. Change the source text → key changes → the generated file no longer contains it → you get the raw source string (or an empty output) at runtime. Always re-run the collect command after editing @l() text.
  • View compilation cache. The directive expands at Blade compile time. After upgrading the package or changing its config, php artisan view:clear — otherwise you're debugging the old compiled PHP in storage/framework/views.
  • Quotes in directives. Nesting quotes inside @l('...') (apostrophes like "it's") breaks Blade parsing. Escape or use @l("It's ready"), and prefer the helper function inside PHP.
  • Escaping and HTML. Determine whether @l() output is escaped by default. If it isn't, you're opening an XSS hole the moment a translation file is sourced from a translator or API. Prefer explicit {{ }} wrapping or the built-in escaped variant; keep raw output for a deliberately small allowlist.
  • Do not rename strings for "clarity." The key is the text. Rewording a @l() string is an untranslated string — every edit is a translation-churn event. For frequently-worded UI copy, fall back to explicit keys.
  • Key collisions. Hash-based keys are safe; slug-based keys (if that's your config) can collide on near-identical strings ("Save" vs "save."). Confirm the strategy in the config and, if it's slug-based, add a prefix.
  • Extraction scope is literal. The scanner reads Blade files, not runtime-built strings. @l($dynamicVar) cannot be extracted. Keep the first argument a literal at all times if you want it picked up.
  • Config quirks. Cache the merged config (php artisan config:cache) in production — the package's paths/output config is read at boot; a half-cached config is a common "works locally, not on prod" cause.
  • Extension point. The package's real customization surface is its config (source path, output locale, key strategy) — if you need a custom key format, override the config rather than forking. The extraction command is usually the right place to hook into a TMS sync step or a linter.
  • Lock in the version. At ~35 stars the package moves quietly; pin it in composer.json and re-run your translation-diff CI job on upgrade to catch API drift in the directive signature.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource