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
translation-handler-development
brunoscode/laravel-translation-handler
claude-code
laravel
BrunosCode
laravel-translation-handler

Develop with brunoscode/laravel-translation-handler in PHP — write custom translation flows on the TranslationHandler facade and TranslationCollection, or extend the package itself (custom file/database handlers, a TranslationChecker subclass, the data objects). Use for code; for agent/MCP-driven translation editing see translation-handler-mcp.

Install
php artisan boost:add-skill brunoscode/laravel-translation-handler

Save this content to: .claude/skills/translation-handler-development/SKILL.md

# Translation Handler — Development

For driving translations from PHP: the facade, collections, data objects, and extension points.
For agent-driven editing via Boost MCP tools, use the `translation-handler-mcp` skill instead.

## Formats

Four interchangeable storage formats, referenced by constants on `TranslationOptions`:

| Constant | String value | Notes |
|----------|-------------|-------|
| `TranslationOptions::PHP`  | `php_file`  | Standard Laravel PHP arrays |
| `TranslationOptions::JSON` | `json_file` | JSON files |
| `TranslationOptions::CSV`  | `csv_file`  | CSV files |
| `TranslationOptions::DB`   | `db`        | Database rows (run migrations first) |

File formats rewrite the **entire file** on every write; `db` writes only affected rows. For bulk programmatic edits, work in `db` then `sync` to the file format once at the end.

## Data objects

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

$t = new Translation(key: 'auth.welcome', locale: 'en', value: 'Welcome!'); // value nullable
$collection = new TranslationCollection([$t]);
```

`TranslationOptions` is the config snapshot — read from config by default; construct manually only to override.

## Facade

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

| Method | Signature (key args) | Returns |
|--------|----------------------|---------|
| `import` / `export` | `(from, to, force=false, fromPath=null, toPath=null)` | `bool` |
| `sync`        | `(from, to, force=false, fromPath=null, toPath=null)` | `bool` |
| `get`         | `(from, path=null)` | `TranslationCollection` |
| `set`         | `(translations, to, path=null, force=false)` | `int` (count) |
| `find`        | `(from, key, locale, path=null)` | `?Translation` |
| `listTranslations` | `(from, path=null, locale=null, group=null)` | `TranslationCollection` |
| `listGroups`  | `(from, path=null, level=0, search=null)` | `Collection` |
| `deleteKey`   | `(from, key, locale=null, path=null)` | `int` |
| `deleteGroup` | `(from, group, path=null)` | `int` |
| `sortKeys`    | `(from, locales=[], groups=[], path=null)` | `int` — PHP/JSON/CSV only |
| `delete`      | `(from, path=null)` | `int` — wipes the whole format |

`null` path means the config default. `locale=null` / empty arrays mean "all".

Options at runtime: `setOption($k, $v)`, `getOption($k)`, `setOptions(new TranslationOptions([...]))`, `resetOptions()`.

## TranslationCollection

```php
// Filter (each returns a new filtered collection)
$c->whereLocale('en');   $c->whereLocaleIn(['en','it']);
$c->whereKey('auth.welcome'); $c->whereKeyIn([...]);
$c->whereGroup('auth');  $c->whereGroupIn(['auth','validation']); // 'auth' matches auth.*
$c->whereValue('Welcome!'); $c->whereValueContains('Welc'); $c->whereValueIn([...]);

// Add / replace
$c->addTranslation($t);          // skip if key+locale exists
$c->replaceTranslation($t);      // overwrite if key+locale exists
$c->addTranslations($other);     $c->replaceTranslations($other);

// Utilities
$c->searchTranslation($t);  $c->sortTranslations();  $c->clone();
```

## Common patterns

```php
// Migrate PHP → JSON
TranslationHandler::import(TranslationOptions::PHP, TranslationOptions::JSON, force: true);

// Read, modify, write back
$c = TranslationHandler::get(TranslationOptions::JSON);
$c->addTranslation(new Translation('auth.welcome', 'it', 'Benvenuto!'));
TranslationHandler::set($c, TranslationOptions::JSON, force: true);

// Merge two sources (DB keys not already present are added)
$base = TranslationHandler::get(TranslationOptions::PHP);
$base->addTranslations(TranslationHandler::get(TranslationOptions::DB));
TranslationHandler::set($base, TranslationOptions::JSON, force: true);

// Export one locale to CSV
$it = TranslationHandler::get(TranslationOptions::PHP)->whereLocale('it');
TranslationHandler::set($it, TranslationOptions::CSV, force: true);

// Delete a key everywhere / for one locale / a whole group
TranslationHandler::deleteKey(TranslationOptions::PHP, 'auth.old_key');
TranslationHandler::deleteKey(TranslationOptions::PHP, 'auth.welcome', locale: 'fr');
TranslationHandler::deleteGroup(TranslationOptions::PHP, 'legacy');
```

## Extending the package

All handler classes and the checker are swappable via config (`config/translation-handler.php`) or `setOption()`:

```php
'phpHandlerClass'  => \App\Translations\MyPhpHandler::class,   // implements FileHandlerInterface
'jsonHandlerClass' => ...,
'csvHandlerClass'  => ...,
'dbHandlerClass'   => \App\Translations\MyDbHandler::class,    // implements DatabaseHandlerInterface
'checkerClass'     => \App\Translations\MyChecker::class,      // extends TranslationChecker
```

**Custom file handler** — implement `FileHandlerInterface`:

```php
public function __construct(TranslationOptions $options);
public function get(?string $path = null): TranslationCollection;
public function put(TranslationCollection $translations, ?string $path = null): int;
public function delete(?string $path = null): int;
```

**Custom database handler** — implement `DatabaseHandlerInterface` (same shape, `?string $connection` instead of `$path`, and `delete(?string $connection = null, bool $hardDelete = false)`).

**Custom key extraction for `check`** — extend `TranslationChecker` and override `patternsFor(string $side): array`. It returns `['static' => [...regex], 'dynamic' => [...regex]]`; group 1 of each regex must capture the key (static) or prefix (dynamic). The scanned paths/extensions per side come from the `check` config entry.

## Configuration

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

```php
'keyDelimiter' => '.',          'fileNames' => ['translation-handler'], 'locales' => ['en'],
'defaultImportFrom' => 'php_file', 'defaultImportTo' => 'json_file',
'defaultExportFrom' => 'json_file','defaultExportTo' => 'php_file',
'phpPath' => lang_path(),  'phpFormat' => false,
'jsonPath' => lang_path(), 'jsonFileName' => '', 'jsonNested' => false, 'jsonFormat' => true,
'csvPath' => storage_path('lang'), 'csvFileName' => 'translations', 'csvDelimiter' => ';', // ≠ keyDelimiter
'check' => [
    'backend'  => ['paths' => ['app','resources/views','routes','database'], 'extensions' => ['php']],
    'frontend' => ['paths' => ['resources/js'], 'extensions' => ['ts','tsx','js','jsx']],
    // optional per-side 'patterns' => ['static' => [...], 'dynamic' => [...]] overrides the regexes
],
```

Translation Handler — Development

For driving translations from PHP: the facade, collections, data objects, and extension points. For agent-driven editing via Boost MCP tools, use the translation-handler-mcp skill instead.

Formats

Four interchangeable storage formats, referenced by constants on TranslationOptions:

Constant String value Notes
TranslationOptions::PHP php_file Standard Laravel PHP arrays
TranslationOptions::JSON json_file JSON files
TranslationOptions::CSV csv_file CSV files
TranslationOptions::DB db Database rows (run migrations first)

File formats rewrite the entire file on every write; db writes only affected rows. For bulk programmatic edits, work in db then sync to the file format once at the end.

Data objects

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

$t = new Translation(key: 'auth.welcome', locale: 'en', value: 'Welcome!'); // value nullable
$collection = new TranslationCollection([$t]);

TranslationOptions is the config snapshot — read from config by default; construct manually only to override.

Facade

use BrunosCode\TranslationHandler\Facades\TranslationHandler;
use BrunosCode\TranslationHandler\Data\TranslationOptions;
Method Signature (key args) Returns
import / export (from, to, force=false, fromPath=null, toPath=null) bool
sync (from, to, force=false, fromPath=null, toPath=null) bool
get (from, path=null) TranslationCollection
set (translations, to, path=null, force=false) int (count)
find (from, key, locale, path=null) ?Translation
listTranslations (from, path=null, locale=null, group=null) TranslationCollection
listGroups (from, path=null, level=0, search=null) Collection
deleteKey (from, key, locale=null, path=null) int
deleteGroup (from, group, path=null) int
sortKeys (from, locales=[], groups=[], path=null) int — PHP/JSON/CSV only
delete (from, path=null) int — wipes the whole format

null path means the config default. locale=null / empty arrays mean "all".

Options at runtime: setOption($k, $v), getOption($k), setOptions(new TranslationOptions([...])), resetOptions().

TranslationCollection

// Filter (each returns a new filtered collection)
$c->whereLocale('en');   $c->whereLocaleIn(['en','it']);
$c->whereKey('auth.welcome'); $c->whereKeyIn([...]);
$c->whereGroup('auth');  $c->whereGroupIn(['auth','validation']); // 'auth' matches auth.*
$c->whereValue('Welcome!'); $c->whereValueContains('Welc'); $c->whereValueIn([...]);

// Add / replace
$c->addTranslation($t);          // skip if key+locale exists
$c->replaceTranslation($t);      // overwrite if key+locale exists
$c->addTranslations($other);     $c->replaceTranslations($other);

// Utilities
$c->searchTranslation($t);  $c->sortTranslations();  $c->clone();

Common patterns

// Migrate PHP → JSON
TranslationHandler::import(TranslationOptions::PHP, TranslationOptions::JSON, force: true);

// Read, modify, write back
$c = TranslationHandler::get(TranslationOptions::JSON);
$c->addTranslation(new Translation('auth.welcome', 'it', 'Benvenuto!'));
TranslationHandler::set($c, TranslationOptions::JSON, force: true);

// Merge two sources (DB keys not already present are added)
$base = TranslationHandler::get(TranslationOptions::PHP);
$base->addTranslations(TranslationHandler::get(TranslationOptions::DB));
TranslationHandler::set($base, TranslationOptions::JSON, force: true);

// Export one locale to CSV
$it = TranslationHandler::get(TranslationOptions::PHP)->whereLocale('it');
TranslationHandler::set($it, TranslationOptions::CSV, force: true);

// Delete a key everywhere / for one locale / a whole group
TranslationHandler::deleteKey(TranslationOptions::PHP, 'auth.old_key');
TranslationHandler::deleteKey(TranslationOptions::PHP, 'auth.welcome', locale: 'fr');
TranslationHandler::deleteGroup(TranslationOptions::PHP, 'legacy');

Extending the package

All handler classes and the checker are swappable via config (config/translation-handler.php) or setOption():

'phpHandlerClass'  => \App\Translations\MyPhpHandler::class,   // implements FileHandlerInterface
'jsonHandlerClass' => ...,
'csvHandlerClass'  => ...,
'dbHandlerClass'   => \App\Translations\MyDbHandler::class,    // implements DatabaseHandlerInterface
'checkerClass'     => \App\Translations\MyChecker::class,      // extends TranslationChecker

Custom file handler — implement FileHandlerInterface:

public function __construct(TranslationOptions $options);
public function get(?string $path = null): TranslationCollection;
public function put(TranslationCollection $translations, ?string $path = null): int;
public function delete(?string $path = null): int;

Custom database handler — implement DatabaseHandlerInterface (same shape, ?string $connection instead of $path, and delete(?string $connection = null, bool $hardDelete = false)).

Custom key extraction for check — extend TranslationChecker and override patternsFor(string $side): array. It returns ['static' => [...regex], 'dynamic' => [...regex]]; group 1 of each regex must capture the key (static) or prefix (dynamic). The scanned paths/extensions per side come from the check config entry.

Configuration

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

'keyDelimiter' => '.',          'fileNames' => ['translation-handler'], 'locales' => ['en'],
'defaultImportFrom' => 'php_file', 'defaultImportTo' => 'json_file',
'defaultExportFrom' => 'json_file','defaultExportTo' => 'php_file',
'phpPath' => lang_path(),  'phpFormat' => false,
'jsonPath' => lang_path(), 'jsonFileName' => '', 'jsonNested' => false, 'jsonFormat' => true,
'csvPath' => storage_path('lang'), 'csvFileName' => 'translations', 'csvDelimiter' => ';', // ≠ keyDelimiter
'check' => [
    'backend'  => ['paths' => ['app','resources/views','routes','database'], 'extensions' => ['php']],
    'frontend' => ['paths' => ['resources/js'], 'extensions' => ['ts','tsx','js','jsx']],
    // optional per-side 'patterns' => ['static' => [...], 'dynamic' => [...]] overrides the regexes
],
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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk