PHPackages                             mindtwo/laravel-auto-translatable - 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. mindtwo/laravel-auto-translatable

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

mindtwo/laravel-auto-translatable
=================================

AI-powered translation package for Laravel with smart markdown chunking and extensible adapters

0.7.0(2w ago)00MITPHPPHP ^8.3

Since Jan 2Pushed 2w agoCompare

[ Source](https://github.com/mindtwo/laravel-auto-translatable)[ Packagist](https://packagist.org/packages/mindtwo/laravel-auto-translatable)[ RSS](/packages/mindtwo-laravel-auto-translatable/feed)WikiDiscussions main Synced today

READMEChangelog (5)Dependencies (60)Versions (16)Used By (0)

[![mindtwo GmbH](https://camo.githubusercontent.com/e6886afd538992ffea88b46c2b2abac75261fde5d9c4444b22d6699f1e222c5d/68747470733a2f2f7777772e6d696e6474776f2e64652f646f776e6c6f6164732f646f6f646c65732f6769746875622f7265706f7369746f72792d6865616465722e706e67)](https://www.mindtwo.de/)

 [![](https://camo.githubusercontent.com/a19160e8bc0d1c292e6618ce228a499968bf0eb353ebf403497df4b74f2bf543/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636865636b2d72756e732f6d696e6474776f2f6c61726176656c2d6175746f2d7472616e736c617461626c652f6d61696e)](https://camo.githubusercontent.com/a19160e8bc0d1c292e6618ce228a499968bf0eb353ebf403497df4b74f2bf543/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636865636b2d72756e732f6d696e6474776f2f6c61726176656c2d6175746f2d7472616e736c617461626c652f6d61696e) [![](https://camo.githubusercontent.com/ec21f169d70b69344c67d6f18fa1a24d20476d2f0cd680e8c4a1534c22f34e5f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e322d3838393242462e737667)](https://camo.githubusercontent.com/ec21f169d70b69344c67d6f18fa1a24d20476d2f0cd680e8c4a1534c22f34e5f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e322d3838393242462e737667) [![](https://camo.githubusercontent.com/5a05d3c9e420ab83f0af27d4cb7896ba703a8a6a7f0ad26ef6af052c8517b152/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d3131253230253743253230313225323025374325323031332d4646324432302e737667)](https://camo.githubusercontent.com/5a05d3c9e420ab83f0af27d4cb7896ba703a8a6a7f0ad26ef6af052c8517b152/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d3131253230253743253230313225323025374325323031332d4646324432302e737667)

 **Laravel Auto-Translatable
-------------------------

[](#laravel-auto-translatable)**  AI-powered translation package for Laravel with smart content chunking, extensible adapters, and automatic link replacement.

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

[](#table-of-contents)

- [Features](#features)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Token Configuration](#token-configuration)
    - [Available Configuration Options](#available-configuration-options)
- [Usage](#usage)
    - [Direct Translation](#direct-translation)
    - [Model Translation](#model-translation)
    - [Chunking Strategies](#chunking-strategies)
    - [Batch Translation (Structured Output)](#batch-translation-structured-output)
    - [Custom Post-Processors](#custom-post-processors)
- [Link Replacement](#link-replacement)
- [Events](#events)
- [Advanced Usage](#advanced-usage)
    - [Custom Adapters](#custom-adapters)
    - [Translation Status Tracking](#translation-status-tracking)
    - [Error Handling](#error-handling)
- [Testing](#testing)
- [License](#license)

Features
--------

[](#features)

- **AI-Powered Translations** - Uses any [laravel/ai](https://github.com/laravel/ai)-supported provider (Anthropic, OpenAI, Gemini, etc.)
- **Smart Content Chunking** - Intelligent chunking for long content:
    - **Markdown**: Respects document structure, never breaks mid-section
    - **Plain Text**: Chunks at paragraph, sentence, or word boundaries
    - **Configurable**: Set custom strategies per field
- **Batch Translation** - Translate many short fields in a single structured-output request instead of one request per field, with automatic per-field fallback
- **Automatic Link Replacement** - Localize internal links in markdown content
- **Extensible Adapter System** - Built-in support for popular i18n packages:
    - `spatie/laravel-translatable`
    - `mindtwo/laravel-translatable`
    - Custom adapters supported

Installation
------------

[](#installation)

Install via Composer:

```
composer require mindtwo/laravel-auto-translatable
```

Publish configuration and migrations:

```
php artisan vendor:publish --tag=auto-translatable-config
php artisan vendor:publish --tag=auto-translatable-migrations
php artisan migrate
```

### AI Provider Credentials

[](#ai-provider-credentials)

Translations are performed through [laravel/ai](https://github.com/laravel/ai). Configure your provider credentials in its `config/ai.php` (publish it with `php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"`) or simply set the relevant API key in your environment, e.g.:

```
ANTHROPIC_API_KEY=
```

This package's `provider` / `model` settings (below) select which configured laravel/ai provider and model to use.

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

[](#configuration)

Configure the package in `config/auto-translatable.php`:

```
return [
    /*
    |--------------------------------------------------------------------------
    | AI Provider Configuration
    |--------------------------------------------------------------------------
    */
    'provider' => env('AUTO_TRANSLATABLE_PROVIDER', 'anthropic'),
    'model' => env('AUTO_TRANSLATABLE_MODEL', 'claude-3-5-sonnet-20241022'),
    'request_timeout' => env('AUTO_TRANSLATABLE_REQUEST_TIMEOUT', 500), // seconds per request

    /*
    |--------------------------------------------------------------------------
    | Token Configuration
    |--------------------------------------------------------------------------
    */
    'chunk_size' => env('AUTO_TRANSLATABLE_CHUNK_SIZE', 80000),
    'output_tokens' => env('AUTO_TRANSLATABLE_OUTPUT_TOKENS', 100000),

    /*
    |--------------------------------------------------------------------------
    | Batch Translation (Structured Output)
    |--------------------------------------------------------------------------
    */
    'batch_fields' => env('AUTO_TRANSLATABLE_BATCH_ENABLED', false),
    'batch_max_tokens' => env('AUTO_TRANSLATABLE_BATCH_MAX_TOKENS', 1500), // max tokens for a field to be batched
    'batch_max_fields' => env('AUTO_TRANSLATABLE_BATCH_MAX_FIELDS', 50),   // max fields per structured request

    /*
    |--------------------------------------------------------------------------
    | Locales
    |--------------------------------------------------------------------------
    */
    'default_source_locale' => env('AUTO_TRANSLATABLE_SOURCE_LOCALE', 'en'),
    'available_locales' => ['de', 'en', 'fr', 'es', 'it', 'pt', 'nl', 'pl'],

    /*
    |--------------------------------------------------------------------------
    | Queue Configuration
    |--------------------------------------------------------------------------
    */
    'queue_translations' => env('AUTO_TRANSLATABLE_QUEUE_ENABLED', true),
    'queue_connection' => env('AUTO_TRANSLATABLE_QUEUE_CONNECTION'),
    'queue_name' => env('AUTO_TRANSLATABLE_QUEUE_NAME', 'translations'),

    /*
    |--------------------------------------------------------------------------
    | Link Replacement
    |--------------------------------------------------------------------------
    */
    'link_replacement' => [
        'enabled' => false,
        'resolver' => null, // Class implementing LinkMappingResolver
        'internal_hosts' => [],
        'unmapped_links' => 'remove', // 'remove', 'keep', or 'warn'
    ],

    /*
    |--------------------------------------------------------------------------
    | Adapter & Auto-Apply
    |--------------------------------------------------------------------------
    */
    'adapter' => \Mindtwo\AutoTranslatable\Adapters\SpatieTranslatableAdapter::class,
    'auto_apply' => env('AUTO_TRANSLATABLE_AUTO_APPLY', false),
];
```

### Token Configuration

[](#token-configuration)

The `chunk_size` and `output_tokens` configuration is critical for handling long content correctly:

- **chunk\_size**: Maximum input tokens per chunk (30-50% of model context window)
- **output\_tokens**: Maximum tokens for model generation
- **Rule**: `chunk_size + output_tokens ≤ model_context_window`

**Examples for different scenarios:**

```
// Conservative (handles Chinese→German expansion ~2x)
// Context window: 200,000 tokens
['chunk_size' => 60000, 'output_tokens' => 120000]

// Balanced (most European language pairs)
// Context window: 200,000 tokens
['chunk_size' => 80000, 'output_tokens' => 100000]

// Aggressive (German→English, content shrinks ~20%)
// Context window: 200,000 tokens
['chunk_size' => 100000, 'output_tokens' => 80000]
```

Usage
-----

[](#usage)

### Direct Translation

[](#direct-translation)

Translate any string directly using the `TranslationService`:

```
use Mindtwo\AutoTranslatable\Services\TranslationService;

class MyService
{
    public function __construct(
        private readonly TranslationService $translator,
    ) {}

    public function translateContent(): void
    {
        // Simple translation
        $result = $this->translator->translate(
            content: 'Hello World',
            sourceLocale: 'en',
            targetLocale: 'de'
        );

        echo $result->translated_content; // "Hallo Welt"
        echo $result->status; // TranslationStatus::COMPLETED
        echo $result->chunks_count; // 1
    }

    public function translateLongContent(): void
    {
        $longMarkdown = file_get_contents('article.md');

        // Automatically chunks large content
        $result = $this->translator->translate(
            content: $longMarkdown,
            sourceLocale: 'en',
            targetLocale: 'de',
            options: [
                'chunking_strategy' => 'markdown', // or 'plain', 'none', 'auto'
                'chunk_size' => 50000, // Override default
            ]
        );

        echo $result->chunks_count; // e.g., 3
        echo $result->translated_content; // Full translated content
    }
}
```

### Model Translation

[](#model-translation)

Translate Eloquent models automatically using the `HasAutoTranslations` trait.

#### 1. Add Trait to Your Model

[](#1-add-trait-to-your-model)

```
use Illuminate\Database\Eloquent\Model;
use Mindtwo\AutoTranslatable\Concerns\HasAutoTranslations;
use Spatie\Translatable\HasTranslations;

class Post extends Model
{
    use HasTranslations;      // From spatie/laravel-translatable
    use HasAutoTranslations;  // From this package

    public array $translatable = ['title', 'body', 'excerpt'];

    /**
     * Define which fields should be auto-translated.
     */
    public function autoTranslatableFields(): array
    {
        return ['title', 'body', 'excerpt'];
    }

    /**
     * Optional: Define chunking strategies per field.
     */
    public function chunkingStrategies(): array
    {
        return [
            'title' => 'none',      // Don't chunk titles
            'body' => 'markdown',   // Smart markdown chunking
            'excerpt' => 'plain',   // Plain text chunking
        ];
    }
}
```

#### 2. Configure Adapter

[](#2-configure-adapter)

Choose the appropriate adapter in your config:

```
// For spatie/laravel-translatable
'adapter' => \Mindtwo\AutoTranslatable\Adapters\SpatieTranslatableAdapter::class,

// For mindtwo/laravel-translatable
'adapter' => \Mindtwo\AutoTranslatable\Adapters\MindtwoTranslatableAdapter::class,
```

#### 3. Translate Your Model

[](#3-translate-your-model)

```
// Translate to all configured locales
$post->autoTranslate();

// Or translate into an explicit subset of locales (the source locale is always
// excluded). Useful for on-demand / user-triggered translation, retrying a
// single failed locale, or incrementally adding a locale.
$post->autoTranslate(['locales' => ['fr', 'nl']]);

// Translations are queued by default
// Set 'queue_translations' => false in config for synchronous translation

// Later, retrieve translations:
$post->getTranslation('title', 'de');    // "Deutscher Titel"
$post->getTranslation('body', 'fr');     // "Corps français"

// Access translation results
$results = $post->translationResults()
    ->where('status', TranslationStatus::COMPLETED)
    ->get();

foreach ($results as $result) {
    echo "{$result->field_name}: {$result->target_locale} - {$result->status}";
}
```

### Chunking Strategies

[](#chunking-strategies)

The package provides three chunking strategies:

#### 1. **Markdown Chunking** (`markdown`)

[](#1-markdown-chunking-markdown)

Smart chunking that preserves document structure:

```
$result = $translator->translate(
    content: '# Heading\n\nParagraph...',
    sourceLocale: 'en',
    targetLocale: 'de',
    options: ['chunking_strategy' => 'markdown']
);

// Features:
// - Respects heading boundaries
// - Never breaks mid-paragraph
// - Preserves code blocks
// - Greedy packing of sections that fit together
```

#### 2. **Plain Text Chunking** (`plain`)

[](#2-plain-text-chunking-plain)

Intelligent text chunking with fallback levels:

```
$result = $translator->translate(
    content: 'Long plain text...',
    sourceLocale: 'en',
    targetLocale: 'de',
    options: ['chunking_strategy' => 'plain']
);

// Chunking hierarchy:
// 1. Try paragraph boundaries (double newlines)
// 2. Fall back to sentence boundaries (. ! ?)
// 3. Last resort: word boundaries
```

#### 3. **No Chunking** (`none`)

[](#3-no-chunking-none)

Pass content as-is without chunking:

```
$result = $translator->translate(
    content: 'Short title',
    sourceLocale: 'en',
    targetLocale: 'de',
    options: ['chunking_strategy' => 'none']
);
```

### Batch Translation (Structured Output)

[](#batch-translation-structured-output)

The default flow issues one AI request per field, per locale. That is ideal for a blog post with a long body, but inefficient for models with many short attributes — a product with 10 attributes × 5 locales would make 50 sequential requests.

Batch translation collapses all *small* fields of a record into a **single structured-output request per locale**, decoding the response straight back into the individual fields. Fewer round-trips means faster translation, and translating the fields together keeps terminology consistent across them.

Enable it in config (opt-in, off by default):

```
'batch_fields' => true,
'batch_max_tokens' => 1500, // only fields at or below this token count are batched
'batch_max_fields' => 50,   // larger sets are split across multiple requests
```

Then translate as usual — no model changes required:

```
$product->autoTranslate();
```

**How fields are routed**

- Fields with a token count at or below `batch_max_tokens` are translated together in one structured request.
- Larger fields keep using the per-field [chunking](#chunking-strategies) path, so long markdown still chunks correctly. Batching and chunking are mutually exclusive per field.
- If only one field is eligible, it uses the normal per-field path (a one-field batch saves nothing and loses error isolation).

**Resilient by design**

If a batched request fails, or the model omits a field from its structured response, those fields are automatically retried individually. A partial or failed batch never loses data — it only costs the affected fields an extra request.

Each field is still tracked by its own `TranslationResult` (with `metadata.batched = true`) and still fires `TranslationCompleted` / `ModelTranslationCompleted`, so events, status tracking, and adapters behave exactly as with per-field translation.

#### Direct batch translation

[](#direct-batch-translation)

`TranslationService::translateMany()` batches an arbitrary keyed set of strings without a model. It always batches (independent of the `batch_fields` config) and returns a collection keyed by your input keys:

```
$results = $translator->translateMany(
    strings: [
        'name' => 'Red Chair',
        'subtitle' => 'Comfortable and durable',
        'cta' => 'Add to cart',
    ],
    sourceLocale: 'en',
    targetLocale: 'de',
);

echo $results['name']->translated_content; // "Roter Stuhl"
```

Keys missing from the structured response are recovered with individual requests, mirroring the model batch behavior.

### Custom Post-Processors

[](#custom-post-processors)

Add custom post-processing logic:

```
use Mindtwo\AutoTranslatable\Contracts\PostProcessor;
use Mindtwo\AutoTranslatable\Models\TranslationResult;

class CustomPostProcessor implements PostProcessor
{
    public function process(string $content, TranslationResult $result, array $context = []): string
    {
        // Your custom logic
        return str_replace('old', 'new', $content);
    }
}

// Use it
$result = $translator->translate(
    content: 'Some content',
    sourceLocale: 'en',
    targetLocale: 'de',
    options: [
        'post_processors' => [
            new CustomPostProcessor(),
        ],
    ]
);
```

Link Replacement
----------------

[](#link-replacement)

Automatically localize internal links in markdown content.

### 1. Create a Link Mapping Resolver

[](#1-create-a-link-mapping-resolver)

```
namespace App\Services;

use Mindtwo\AutoTranslatable\Contracts\LinkMappingResolver;

class BlogLinkResolver implements LinkMappingResolver
{
    /**
     * Provide static URL mappings.
     */
    public function getMapping(string $sourceLocale, string $targetLocale): array
    {
        return [
            '/blog/getting-started' => '/blog/erste-schritte',
            '/contact' => '/kontakt',
            '/about' => '/ueber-uns',
        ];
    }

    /**
     * Dynamic resolution for URLs not in static mapping.
     */
    public function resolve(string $url, string $sourceLocale, string $targetLocale): ?string
    {
        // Example: Fetch from database
        $post = Post::query()->where('slug', ltrim($url, '/'))->first();

        if ($post) {
            return '/' . $post->getTranslation('slug', $targetLocale);
        }

        return null;
    }
}
```

### 2. Configure Link Replacement

[](#2-configure-link-replacement)

```
'link_replacement' => [
    'enabled' => true,
    'resolver' => \App\Services\BlogLinkResolver::class,
    'internal_hosts' => [
        'https://example.com',
        'https://www.example.com',
    ],
    'unmapped_links' => 'remove', // Options: 'remove', 'keep', 'warn'
],
```

### 3. Example

[](#3-example)

**Input (English):**

```
Read our [getting started guide](/blog/getting-started) and [contact us](/contact).
Also check out [this untranslated post](/blog/new-post).
Visit [Google](https://google.com) for more info.
```

**Output (German):**

```
Read our [getting started guide](/blog/erste-schritte) and [contact us](/kontakt).
Also check out this untranslated post.
Visit [Google](https://google.com) for more info.
```

Events
------

[](#events)

The package dispatches events throughout the translation lifecycle:

### TranslationCompleted

[](#translationcompleted)

Fired when a single field translation completes successfully.

```
use Mindtwo\AutoTranslatable\Events\TranslationCompleted;

Event::listen(TranslationCompleted::class, function (TranslationCompleted $event) {
    // $event->result - TranslationResult instance
    // $event->model - Model that was translated (if applicable)
    // $event->field - Field name that was translated

    Log::info("Translation completed: {$event->field} -> {$event->result->target_locale}");
});
```

### TranslationFailed

[](#translationfailed)

Fired when a translation fails.

```
use Mindtwo\AutoTranslatable\Events\TranslationFailed;

Event::listen(TranslationFailed::class, function (TranslationFailed $event) {
    // $event->result - TranslationResult instance
    // $event->error - Error message
    // $event->model - Model that failed translation
    // $event->field - Field name that failed

    Log::error("Translation failed: {$event->field} - {$event->error}");

    // Optionally notify administrators
    Mail::to('admin@example.com')->send(new TranslationFailedNotification($event));
});
```

### ModelTranslationCompleted

[](#modeltranslationcompleted)

Fired when all fields of a model have been processed (some may have failed).

```
use Mindtwo\AutoTranslatable\Events\ModelTranslationCompleted;

Event::listen(ModelTranslationCompleted::class, function (ModelTranslationCompleted $event) {
    // $event->model - The translated model
    // $event->results - Collection of TranslationResult instances
    // $event->fields - Array of field names that were translated

    $successful = $event->results->where('status', TranslationStatus::COMPLETED)->count();
    $failed = $event->results->where('status', TranslationStatus::FAILED)->count();

    Log::info("Model translation completed: {$successful} successful, {$failed} failed");
});
```

### Manual Translation Application

[](#manual-translation-application)

Listen to events and apply translations manually:

First, disable auto applying:

```
AUTO_TRANSLATABLE_AUTO_APPLY=false

```

```
use Mindtwo\AutoTranslatable\Events\ModelTranslationCompleted;
use Mindtwo\AutoTranslatable\Contracts\TranslatableAdapter;
use Mindtwo\AutoTranslatable\Adapters\SpatieTranslatableAdapter;

Event::listen(ModelTranslationCompleted::class, function (ModelTranslationCompleted $event) {
    // Review changes manually, e.g. through an admin interface, then:
    resolve(SpatieTranslatableAdapter::class)->applyTranslations($event->model, $event->results);
});
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom Adapters

[](#custom-adapters)

Create a custom adapter for your i18n package:

```
namespace App\Services;

use Illuminate\Database\Eloquent\Model;
use Mindtwo\AutoTranslatable\Contracts\TranslatableAdapter;

class MyCustomAdapter implements TranslatableAdapter
{
    public function supports(Model $model): bool
    {
        return $model instanceof MyTranslatableModel;
    }

    public function getAvailableLocales(Model $model): array
    {
        return config('app.locales');
    }

    public function getSourceLocale(Model $model): string
    {
        return $model->source_locale ?? config('app.locale');
    }

    public function getFieldValue(Model $model, string $field, string $locale): ?string
    {
        return $model->translate($field, $locale);
    }

    public function applyTranslations(Model $model, string $locale, array $translations): void
    {
        foreach ($translations as $field => $value) {
            $model->setTranslation($field, $locale, $value);
        }
        $model->save();
    }
}
```

Register your adapter:

```
'adapter' => \App\Services\MyCustomAdapter::class,
```

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

Credits
-------

[](#credits)

Created by [mindtwo GmbH](https://mindtwo.de)

Support
-------

[](#support)

- **Issues**: [GitHub Issues](https://github.com/mindtwo/laravel-auto-translatable/issues)
- **Documentation**: [GitHub Repository](https://github.com/mindtwo/laravel-auto-translatable)
- **Email**:

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance97

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.4% 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 ~16 days

Recently: every ~4 days

Total

11

Last Release

15d ago

PHP version history (2 changes)0.1.0PHP ^8.2

0.3.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/4cc86fe6179314d204b14d1c81eb09a87ef84b0bcf2360dcd981171d1346c077?d=identicon)[mindtwo](/maintainers/mindtwo)

---

Top Contributors

[![chiiya](https://avatars.githubusercontent.com/u/15029301?v=4)](https://github.com/chiiya "chiiya (19 commits)")[![jonasemde](https://avatars.githubusercontent.com/u/5083193?v=4)](https://github.com/jonasemde "jonasemde (3 commits)")

###  Code Quality

TestsPest

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mindtwo-laravel-auto-translatable/health.svg)

```
[![Health](https://phpackages.com/badges/mindtwo-laravel-auto-translatable/health.svg)](https://phpackages.com/packages/mindtwo-laravel-auto-translatable)
```

###  Alternatives

[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M194](/packages/laravel-ai)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.6k3](/packages/defstudio-telegraph)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M345](/packages/psalm-plugin-laravel)[elegantly/laravel-translator

All on one translations management for Laravel

6333.1k](/packages/elegantly-laravel-translator)[illuminate/mail

The Illuminate Mail package.

5910.6M498](/packages/illuminate-mail)[spatie/laravel-health

Monitor the health of a Laravel application

87512.0M164](/packages/spatie-laravel-health)

PHPackages © 2026

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