PHPackages                             brunoscode/laravel-translation-handler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. brunoscode/laravel-translation-handler

ActiveLibrary[Localization &amp; i18n](/categories/localization)

brunoscode/laravel-translation-handler
======================================

This is my package laravel-translation-handler

v2.6.1(2w ago)03.0k↑216.7%[1 PRs](https://github.com/BrunosCode/LaravelTranslationHandler/pulls)1MITPHPPHP ^8.2CI passing

Since Feb 10Pushed 2w ago1 watchersCompare

[ Source](https://github.com/BrunosCode/LaravelTranslationHandler)[ Packagist](https://packagist.org/packages/brunoscode/laravel-translation-handler)[ Docs](https://github.com/brunoscode/laravel-translation-handler)[ GitHub Sponsors](https://github.com/BrunosCode)[ RSS](/packages/brunoscode-laravel-translation-handler/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (55)Versions (35)Used By (1)

Laravel Translation Handler
===========================

[](#laravel-translation-handler)

> Manage Laravel translations across PHP, JSON, CSV, and the database — keep the formats in sync, edit them live in production, and let an AI agent handle them via Laravel Boost.

[![Latest Version on Packagist](https://camo.githubusercontent.com/f28ab551abe925136007b58e37530318d17132ec81729b8987e6a5e3c8e43bc9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6272756e6f73636f64652f6c61726176656c2d7472616e736c6174696f6e2d68616e646c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/brunoscode/laravel-translation-handler)[![GitHub Tests Action Status](https://camo.githubusercontent.com/95a31d644018508d51b31d1b1a9485eb10faec402da5a52a21289230684d2d15/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4272756e6f73436f64652f4c61726176656c5472616e736c6174696f6e48616e646c65722f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/BrunosCode/LaravelTranslationHandler/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/3d40afd08471e4c560331d55a6cdc3e5a37497d3e4f7349c864ab5f3ffa44ebb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4272756e6f73436f64652f4c61726176656c5472616e736c6174696f6e48616e646c65722f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/BrunosCode/LaravelTranslationHandler/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/85f50c53393dadf38f04fc26fc7610a0ead6cc94ef252a35d3bbcbc1f58ab561/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6272756e6f73636f64652f6c61726176656c2d7472616e736c6174696f6e2d68616e646c65722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/brunoscode/laravel-translation-handler)[![License](https://camo.githubusercontent.com/94ca66183c796916de2b63bc0eb32e24ccd47d6bc1860fd42d3865f2685850cc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6272756e6f73636f64652f6c61726176656c2d7472616e736c6174696f6e2d68616e646c65722e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

Laravel translations end up split across `lang/*.php` files and a JSON copy the frontend consumes — two sources that drift apart, and neither editable in production without a redeploy. This package treats PHP files, JSON files, CSV files, and the database as interchangeable views of one set of translations. Two workflows it was built around:

- **Client-managed translations on staging/production.** Store translations in the `db` format so they can be edited in the running environment — by the client, without touching files or redeploying — then synced back to files.
- **PHP files as the single source, frontend generated from them (or the reverse).** Keep `php_file` as the source of truth and generate the JSON the frontend consumes — or go the other way (`json_file` → `php_file`). Edit one side, regenerate the other.

```
                    sync · import · export
        ┌───────────┬───────────┬───────────┬───────────┐
        │  php_file │ json_file │  csv_file │     db    │
        └───────────┴───────────┴───────────┴───────────┘
              translations move between any two formats

```

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Supported Formats](#supported-formats)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Commands](#commands)
- [Facade API](#facade-api)
- [Linter-friendly Writes](#linter-friendly-writes)
- [AI Translation Management with Laravel Boost](#ai-translation-management-with-laravel-boost)
- [Configuration](#configuration)
- [Testing](#testing)
- [Changelog](#changelog)
- [Credits](#credits)
- [Contributing](#contributing)
- [License](#license)

Requirements
------------

[](#requirements)

LaravelPHP12.x8.2, 8.3, 8.411.x8.2, 8.3, 8.4Supported Formats
-----------------

[](#supported-formats)

FormatConstantDescriptionphp\_file`TranslationOptions::PHP`Standard Laravel PHP translation filesjson\_file`TranslationOptions::JSON`JSON translation filescsv\_file`TranslationOptions::CSV`CSV translation filesdb`TranslationOptions::DB`Database-backed translationsInstallation
------------

[](#installation)

```
composer require brunoscode/laravel-translation-handler
```

Publish the configuration file:

```
php artisan vendor:publish --provider="BrunosCode\TranslationHandler\TranslationHandlerServiceProvider"
```

For database-backed translations, run the migrations:

```
php artisan migrate
```

Quick Start
-----------

[](#quick-start)

```
# Sync translations between formats
php artisan translation-handler:sync php_file json_file

# Import / export using config defaults
php artisan translation-handler:import
php artisan translation-handler:export --force

# List all translations from PHP files
php artisan translation-handler:list php_file

# List translations filtered by locale and group
php artisan translation-handler:list php_file --locale=en --group=auth

# List top-level key groups
php artisan translation-handler:list-groups php_file

# List second-level groups, filtered by search
php artisan translation-handler:list-groups php_file --level=1 --search=messages

# Find a specific translation
php artisan translation-handler:find php_file auth.welcome en

# Get the raw value of a translation
php artisan translation-handler:get php_file auth.welcome en

# Set a specific translation
php artisan translation-handler:set php_file auth.welcome en "Welcome!"

# Delete a translation key (all locales)
php artisan translation-handler:delete php_file auth.welcome

# Delete a translation key for a specific locale
php artisan translation-handler:delete php_file auth.welcome --locale=en

# Delete all keys under a group
php artisan translation-handler:delete-group php_file auth

# Sort all keys alphabetically
php artisan translation-handler:sort php_file

# Sort only specific locales and groups
php artisan translation-handler:sort php_file --locale=en --group=auth

# Check source code for missing (or orphan) translation keys
php artisan translation-handler:check php_file --show-keys --orphans
```

Or use the Facade:

```
use BrunosCode\TranslationHandler\Facades\TranslationHandler;
use BrunosCode\TranslationHandler\Data\TranslationOptions;

// Copy PHP → JSON (explicit formats)
TranslationHandler::sync(TranslationOptions::PHP, TranslationOptions::JSON);

// Copy JSON → PHP, overwriting existing
TranslationHandler::sync(TranslationOptions::JSON, TranslationOptions::PHP, force: true);

// Import using config defaults
TranslationHandler::import();

// Export using config defaults
TranslationHandler::export();
```

Commands
--------

[](#commands)

### Shared Options

[](#shared-options)

These options are available on `translation-handler:sync`, `translation-handler:import`, and `translation-handler:export`:

OptionTypeDefaultDescription`--force`bool`false`Overwrite values that already exist in the destination (see conflict behavior below)`--fresh`bool`false`Delete existing translations before writing`--file-names`arrayconfig `fileNames`Translation file names to process`--locales`arrayconfig `locales`Locales to process`--from-path`stringformat defaultCustom source path`--to-path`stringformat defaultCustom destination path`--guided`bool`false`Interactive mode, prompts for each option### `translation-handler:sync`

[](#translation-handlersync)

Sync translations from one format to another. Source and destination are positional arguments.

```
php artisan translation-handler:sync {from?} {to?} [options]
```

If `from` or `to` are omitted, you will be prompted to choose.

**Conflict behavior.** By default a sync is a **non-destructive merge**: keys missing in the destination are added; keys that already exist keep their current destination value (the source value is ignored). It never fails or prompts on a conflict. Pass `--force` to overwrite existing values with the source, or `--fresh` to wipe the destination before writing. The same applies to `import` and `export`.

### `translation-handler` *(deprecated)*

[](#translation-handler-deprecated)

> **Deprecated.** Use `translation-handler:sync` instead.

```
php artisan translation-handler {from?} {to?} [options]
```

### `translation-handler:import`

[](#translation-handlerimport)

Import translations. Source and destination are passed via `--from` and `--to` options, defaulting to config values (`defaultImportFrom`, `defaultImportTo`).

```
php artisan translation-handler:import [options]
```

### `translation-handler:export`

[](#translation-handlerexport)

Export translations. Source and destination are passed via `--from` and `--to` options, defaulting to config values (`defaultExportFrom`, `defaultExportTo`).

```
php artisan translation-handler:export [options]
```

### `translation-handler:list`

[](#translation-handlerlist)

List translations from a storage format. Optionally filter by locale or key group prefix.

```
php artisan translation-handler:list {from?} {--from-path=} {--locale=} {--group=}
```

OptionDescription`--locale`Filter by locale (e.g. `en`)`--group`Filter by key group prefix (e.g. `auth` returns all `auth.*` keys)### `translation-handler:list-groups`

[](#translation-handlerlist-groups)

List unique translation key groups from a storage format. A group is a key prefix at a given depth level. Optionally filter by search string.

```
php artisan translation-handler:list-groups {from?} {--from-path=} {--level=0} {--search=}
```

OptionDescription`--level`Number of delimiters in the group name. `0` = top-level (e.g. `auth`), `1` = second-level (e.g. `auth.messages`). Defaults to `0`.`--search`Case-insensitive filter on group names### `translation-handler:find`

[](#translation-handlerfind)

Find a specific translation by key and locale. Outputs a table with format, key, locale, and value.

```
php artisan translation-handler:find {from?} {key?} {locale?} {--from-path=}
```

### `translation-handler:get`

[](#translation-handlerget)

Get the raw value of a single translation.

```
php artisan translation-handler:get {from?} {key?} {locale?} {--from-path=}
```

### `translation-handler:set`

[](#translation-handlerset)

Set a single translation value.

```
php artisan translation-handler:set {to?} {key?} {locale?} {value?} {--to-path=} {--force}
```

### `translation-handler:delete`

[](#translation-handlerdelete)

Delete a translation key from a storage format. Omit `--locale` to delete all locales for the key.

```
php artisan translation-handler:delete {from?} {key?} {--locale=} {--from-path=}
```

### `translation-handler:delete-group`

[](#translation-handlerdelete-group)

Delete all translation keys under a group prefix from a storage format.

```
php artisan translation-handler:delete-group {from?} {group?} {--from-path=}
```

### `translation-handler:sort`

[](#translation-handlersort)

Sort translation keys alphabetically. Works on `php_file`, `json_file`, and `csv_file` only.

```
php artisan translation-handler:sort {from?} {--from-path=} {--locale=*} {--group=*}
```

OptionDescription`--locale`Restrict sorting to this locale (repeatable: `--locale=en --locale=it`)`--group`Restrict sorting to this key group prefix (repeatable)### `translation-handler:check`

[](#translation-handlercheck)

Scan the application's backend PHP and frontend JS/TS source for translation usages (`__()`, `trans()`, `trans_choice()`, `Lang::get()`, `@lang`, and `t()` / `i18next.t()`) and report keys that are referenced in code but not defined per locale. A non-zero exit code is returned when any key is missing, so it doubles as a CI gate.

```
php artisan translation-handler:check {from?} {--from-path=} {--locale=*} {--side=} {--show-keys} {--orphans}
```

OptionDescription`--locale`Restrict the report to one or more locales (repeatable). Defaults to the configured `locales`.`--side`Limit scanning to a single configured side (`backend` / `frontend` by default). Defaults to all sides.`--show-keys`Print each missing (or orphan) key.`--orphans`Also list keys that are defined but never referenced in code (informational — does not affect the exit code).Defined keys are read from the chosen `from` format and scoped to the configured `fileNames`. The directories and extensions scanned per side are configurable via the `check` config entry:

```
'check' => [
    'backend' => [
        'paths' => ['app', 'resources/views', 'routes', 'database'],
        'extensions' => ['php'],
    ],
    'frontend' => [
        'paths' => ['resources/js'],
        'extensions' => ['ts', 'tsx', 'js', 'jsx'],
    ],
],
```

Because defined keys are scoped to the configured `fileNames`, the check reflects exactly the translations the package manages. References to keys outside those groups (e.g. Laravel's own `auth.*` / `validation.*`) are reported as missing unless you add their groups to `fileNames` — or set [`checkIncludeFrameworkKeys`](#check) to `true` to treat Laravel's bundled lang keys as defined.

Facade API
----------

[](#facade-api)

```
use BrunosCode\TranslationHandler\Facades\TranslationHandler;
```

### sync

[](#sync)

Copies translations from one format to another. Unlike `import`/`export`, `from` and `to` are required — no config defaults are used.

With `force: false` (default) this is a **non-destructive merge** — keys missing in the destination are added, existing keys keep their value. With `force: true` existing values are overwritten by the source.

Returns `false` if the source has no translations to read; otherwise returns the number of translations changed in the destination (`0` means already in sync).

```
TranslationHandler::sync(
    from: string,      // source format
    to: string,        // destination format
    force: bool,       // overwrite existing (default: false)
    fromPath: ?string, // custom source path (default: null)
    toPath: ?string,   // custom destination path (default: null)
): false|int;
```

### import / export

[](#import--export)

Both methods share the same signature and the same return semantics as `sync`. `from` and `to` fall back to config defaults (`defaultImportFrom`/`defaultImportTo` and `defaultExportFrom`/`defaultExportTo`) when omitted.

```
TranslationHandler::import(
    from: ?string,     // source format (default: config value)
    to: ?string,       // destination format (default: config value)
    force: bool,       // overwrite existing (default: false)
    fromPath: ?string, // custom source path (default: null)
    toPath: ?string,   // custom destination path (default: null)
): false|int;

TranslationHandler::export(/* same signature */): false|int;
```

### find

[](#find)

Finds a single translation by key and locale. Returns `null` if not found.

```
$translation = TranslationHandler::find(
    from: string,      // source format
    key: string,       // dot-delimited key
    locale: string,    // locale to look up
    path: ?string,     // custom path (default: null)
): ?Translation;
```

### listTranslations

[](#listtranslations)

Returns a filtered `TranslationCollection`. Applies locale and/or group prefix filters on top of `get()`.

```
$translations = TranslationHandler::listTranslations(
    from: string,      // source format
    path: ?string,     // custom path (default: null)
    locale: ?string,   // filter by locale (default: null = all)
    group: ?string,    // filter by key group prefix (default: null = all)
): TranslationCollection;
```

### listGroups

[](#listgroups)

Returns a sorted `Collection` of unique key group names at a given depth level.

```
$groups = TranslationHandler::listGroups(
    from: string,      // source format
    path: ?string,     // custom path (default: null)
    level: int,        // 0 = top-level groups, 1 = second-level, … (default: 0)
    search: ?string,   // case-insensitive filter on group names (default: null)
): Collection;
```

### get

[](#get)

```
$translations = TranslationHandler::get(
    from: string,      // source format
    path: ?string,     // custom path (default: null)
): TranslationCollection;
```

### set

[](#set)

Returns the number of translations actually changed (added, modified, or removed) in the destination — `0` if the destination already matches the desired state.

```
$count = TranslationHandler::set(
    translations: TranslationCollection,
    to: string,        // destination format
    path: ?string,     // custom path (default: null)
    force: bool,       // overwrite existing (default: false)
): int;
```

Example:

```
use BrunosCode\TranslationHandler\Collections\TranslationCollection;
use BrunosCode\TranslationHandler\Data\Translation;
use BrunosCode\TranslationHandler\Data\TranslationOptions;

$translation = new Translation('welcome', 'en', 'Welcome!');
$collection = new TranslationCollection([$translation]);

TranslationHandler::set($collection, TranslationOptions::JSON);
```

### deleteKey

[](#deletekey)

Deletes a specific translation key from a format. Pass `locale` to target a single locale; omit to delete all locales.

```
$count = TranslationHandler::deleteKey(
    from: string,      // format to delete from
    key: string,       // dot-delimited key
    locale: ?string,   // locale to delete (default: null = all locales)
    path: ?string,     // custom path (default: null)
): int;
```

### deleteGroup

[](#deletegroup)

Deletes all keys whose name starts with the given group prefix.

```
$count = TranslationHandler::deleteGroup(
    from: string,      // format to delete from
    group: string,     // group prefix (e.g. "auth" removes all "auth.*" keys)
    path: ?string,     // custom path (default: null)
): int;
```

### sortKeys

[](#sortkeys)

Sorts translation keys alphabetically within a format. Supports `php_file`, `json_file`, and `csv_file`. Optionally restrict by locale and/or group.

```
$count = TranslationHandler::sortKeys(
    from: string,      // format to sort (php_file, json_file, csv_file)
    locales: array,    // restrict to these locales (default: [] = all)
    groups: array,     // restrict to these group prefixes (default: [] = all)
    path: ?string,     // custom path (default: null)
): int;
```

### delete

[](#delete)

```
$count = TranslationHandler::delete(
    from: string,      // format to delete from
    path: ?string,     // custom path (default: null)
): int;
```

### Options Management

[](#options-management)

```
// Get/set individual options
TranslationHandler::setOption('keyDelimiter', '_');
$value = TranslationHandler::getOption('keyDelimiter');

// Replace all options
TranslationHandler::setOptions(new TranslationOptions([...]));

// Reset to defaults
TranslationHandler::resetOptions();
```

Linter-friendly Writes
----------------------

[](#linter-friendly-writes)

File-based formats (PHP, JSON, CSV) skip the write entirely when the resulting content would be identical to what's already on disk — including key order. This avoids churn from your code formatter (Pint, PHP-CS-Fixer, Prettier, …): a file already formatted by the linter is left untouched as long as its translations and ordering match the new state.

- Comparison is **strict and includes key order** — a re-sort still triggers a rewrite (intended, since `sort` is an explicit operation).
- Counts returned by `set`, `sync`, `import`, `export` reflect the number of translations actually **changed** (added, modified, removed), not the total in the collection. A no-op write returns `0`.
- `sync` / `import` / `export` return `false` only when there are no source translations to read; `0` is a successful no-op.

### Formatting PHP files with Pint

[](#formatting-php-files-with-pint)

Set `phpPint` to `true` to run [Pint](https://github.com/laravel/pint) on the PHP files written during a write operation, so generated translation files match your project's own code style and stay diff-stable across runs. The binary is resolved from your project first (`vendor/bin/pint`), then from this package's own vendor (only when developing the package itself). If no Pint binary is found the step is skipped silently and the files keep their raw `phpFormat` output — so enabling `phpPint` is a no-op unless `laravel/pint` is installed.

AI Translation Management with Laravel Boost
--------------------------------------------

[](#ai-translation-management-with-laravel-boost)

When [Laravel Boost](https://github.com/laravel/boost) **v2** is installed, this package auto-registers **12 MCP tools** into Boost's MCP server — no configuration. Any MCP-compatible agent (Claude, Cursor, GitHub Copilot, …) can then browse, add, update, translate, sync, delete, sort, and audit your translations directly.

```
composer require laravel/boost:^2.0
```

Two Boost skills ship with the package and guide the agent — the README only sketches the tools; the skills (and the MCP server's own schemas) hold the detail:

- **`translation-handler-mcp`** — the agent workflow: the recommended `db`-then-`sync` pattern, group and all-locale writes, and missing-key checks.
- **`translation-handler-development`** — writing custom PHP against the package (facade, collection, extending handlers / the checker).

### Tools at a glance

[](#tools-at-a-glance)

All formats accept `php_file`, `json_file`, `csv_file`, `db`.

- **Read** — `get-translation-config-tool` (locales, paths, defaults), `list-translation-groups-tool` (browse keys by depth), `list-translations-tool` (filter by locale/group), `find-translation-tool` (one key + locale).
- **Write** — `set-translation-tool` (one key + locale), `set-all-locales-translation-tool` (one key, every locale), `set-translation-group-tool` (a whole group in one call), `sync-translations-tool` (copy between formats), `delete-translation-tool`, `delete-translation-group-tool`.
- **Maintenance** — `sort-translations-tool` (alphabetical; file formats only), `check-translations-tool` (keys used in code but missing per locale).

### Recommended workflow for editing translations

[](#recommended-workflow-for-editing-translations)

**Use `db` as the working format for all writes, then sync to files at the end.**

File-based formats (PHP, JSON, CSV) rewrite the entire file on every write operation. The database format writes only the affected rows, making each change significantly faster. Once all edits are done, a single sync pushes everything to the target file format.

```
1. Read/browse   → db (or any format for read-only queries)
2. Write keys    → always db
3. Finalise      → sync-translations-tool  from: db  to:
4. Verify        → check-translations-tool  (or translation-handler:check)

```

When no database is configured, write directly to the file format but batch all locales for a key into a single `set-all-locales-translation-tool` call rather than one call per locale. End the work with a `check` run to confirm no referenced key is missing.

### Example AI workflow

[](#example-ai-workflow)

> **You:** "Add a `auth.too_many_attempts` key in English and Italian to the JSON files."

The AI will:

1. Call `get-translation-config-tool` to confirm the locales and format
2. Call `set-all-locales-translation-tool` with `{"en": "Too many attempts. Please try again later.", "it": "Troppi tentativi. Riprova più tardi."}` targeting `json_file`

> **You:** "Translate the entire `auth` group into English, Italian, and Spanish."

The AI will call `set-translation-group-tool` with `format: db`, `group: auth`, and a `translations` object containing every auth subkey mapped to all three locales — in a single DB transaction — then sync `db` → `json_file`.

Configuration
-------------

[](#configuration)

The `config/translation-handler.php` file contains:

### General

[](#general)

OptionDefaultDescription`keyDelimiter``.`Delimiter used in translation keys`fileNames``['translation-handler']`Translation file names to process`locales``['en']`Supported locales### Default Formats

[](#default-formats)

OptionDefaultDescription`defaultImportFrom``php_file`Default source format for import`defaultImportTo``json_file`Default destination format for import`defaultExportFrom``json_file`Default source format for export`defaultExportTo``php_file`Default destination format for export### PHP

[](#php)

OptionDefaultDescription`phpPath``lang_path()`Path to PHP translation files`phpFormat``false`Convert exported arrays to short syntax (`[]` instead of `array()`)`phpPint``false`Format exported PHP files with Pint after writing (see [Linter-friendly Writes](#linter-friendly-writes))`phpHandlerClass``PhpFileHandler::class`Handler class### JSON

[](#json)

OptionDefaultDescription`jsonPath``lang_path()`Path to JSON translation files`jsonFileName``''`File name (empty = use locale as filename, set = use locale as folder)`jsonNested``false`Nest output like PHP files`jsonFormat``true`Pretty-print JSON output`jsonHandlerClass``JsonFileHandler::class`Handler class### CSV

[](#csv)

OptionDefaultDescription`csvPath``storage_path('lang')`Path to CSV files`csvFileName``translations`CSV file name`csvDelimiter``;`CSV delimiter (must differ from `keyDelimiter`)`csvHandlerClass``CsvFileHandler::class`Handler class### Database

[](#database)

OptionDefaultDescription`dbHandlerClass``DatabaseHandler::class`Handler class### Check

[](#check)

Used by `translation-handler:check` and `check-translations-tool` to locate source files. Paths are relative to the application base path (absolute paths allowed).

The keys of `check` define the **sides** to scan — `backend` and `frontend` by default, but you can rename, remove, or add sides freely. Each side must provide a `paths` array and an `extensions` array (the structure is validated).

Each side may also declare a `patterns` entry to override the extraction regexes — `static` patterns must capture a full key in group 1, `dynamic` patterns a key prefix. Every pattern is validated to be a compilable regex. When omitted, the bundled defaults are used (PHP patterns for the `backend` side, JS/TS patterns for any other side). For example, to recognise a custom helper:

```
'check' => [
    'backend' => [
        'paths' => ['app', 'resources/views'],
        'extensions' => ['php'],
        'patterns' => [
            'static' => ["/(?:__|myTrans)\\(\\s*'([^'\\\\]+)'/"],
            'dynamic' => [],
        ],
    ],
],
```

Set `checkIncludeFrameworkKeys` to `true` to treat the keys shipped with Laravel's own bundled lang files (`auth`, `pagination`, `passwords`, `validation`) as defined. Laravel's translator falls back to those files even when your project never publishes them, so references like `__('auth.failed')` are valid at runtime; with this option enabled they are no longer reported as missing. The keys are read straight from `vendor/laravel/framework` (the bundled `en` locale) and flattened to your `keyDelimiter`, independent of `fileNames` — so it covers framework groups you don't publish too. It removes the need for a custom `checkerClass` subclass just to whitelist framework keys.

For customisation that can't be expressed as static patterns (programmatic generation, custom defined-key resolution), extend `TranslationChecker` and override `patternsFor()`, then point `checkerClass` at your subclass.

OptionDefaultDescription`check.backend.paths``['app', 'resources/views', 'routes', 'database']`Backend directories to scan`check.backend.extensions``['php']`Backend file extensions`check.frontend.paths``['resources/js']`Frontend directories to scan`check.frontend.extensions``['ts', 'tsx', 'js', 'jsx']`Frontend file extensions`checkIncludeFrameworkKeys``false`Count Laravel's bundled lang keys (`auth`, `pagination`, `passwords`, `validation`) as defined, so the framework's own fallback keys are not reported as missing`checkerClass``TranslationChecker::class`Checker implementation. Extend `TranslationChecker` and override `patternsFor()` to customise the scanning regexes (e.g. for custom helpers or frameworks).Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG.md](CHANGELOG.md) for what has changed recently.

Credits
-------

[](#credits)

- [BrunosCode](https://github.com/BrunosCode)
- [All Contributors](https://github.com/BrunosCode/LaravelTranslationHandler/graphs/contributors)

Contributing
------------

[](#contributing)

Contributions are welcome! Please submit a pull request or open an issue to discuss what you would like to change.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance97

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 86.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~23 days

Recently: every ~3 days

Total

22

Last Release

17d ago

Major Versions

v0.1.7 → v1.02026-03-18

v1.0 → v2.02026-03-18

PHP version history (2 changes)v0.1PHP ^8.1

v1.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/a76a0e4fa1309d69450b1e860c42a4cc7973277bda7a3b8aac15b14a1f78e408?d=identicon)[BrunosCode](/maintainers/BrunosCode)

---

Top Contributors

[![BrunosCode](https://avatars.githubusercontent.com/u/78606186?v=4)](https://github.com/BrunosCode "BrunosCode (137 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (13 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (8 commits)")

---

Tags

laravellaravel-packagelaravel-translation-managerlaravel-translationsmcp-toolslaravelBrunosCodelaravel-translation-handler

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/brunoscode-laravel-translation-handler/health.svg)

```
[![Health](https://phpackages.com/badges/brunoscode-laravel-translation-handler/health.svg)](https://phpackages.com/packages/brunoscode-laravel-translation-handler)
```

###  Alternatives

[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M47](/packages/spatie-laravel-pdf)[bezhansalleh/filament-language-switch

Zero config Language Switch(Changer/Localizer) plugin for filamentphp admin

3581.3M28](/packages/bezhansalleh-filament-language-switch)[askdkc/breezejp

Laravel Starter Kit (Livewire+Breeze+Laravel UI+Jetstream)や標準のバリデーションメッセージを全て一瞬で日本語化し、言語切替機能も提供するパッケージです / This package provides all-in-one Japanese translation for Laravel StarterKit (Livewire StarterKit, Breeze, Laravel UI and Jetstream) packages and validation messages with language switching feature.

593277.6k1](/packages/askdkc-breezejp)[elegantly/laravel-translator

All on one translations management for Laravel

6333.1k](/packages/elegantly-laravel-translator)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[osama-98/laravel-enum-translatable

A Laravel package that provides translatable enum functionality with easy-to-use methods for working with enum values and their translations

561.2k](/packages/osama-98-laravel-enum-translatable)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
