misaf / vendra-language
Multi-language support system with tenant-aware languages and translation lines
Requires
- php: ^8.3
- bezhansalleh/filament-language-switch: ^4.3
- misaf/vendra-support: v1.7.1
- spatie/eloquent-sortable: ^5.0.1
- spatie/laravel-package-tools: ^1.93.1
- spatie/laravel-translation-loader: ^2.8.3
Requires (Dev)
- fakerphp/faker: ^1.24.1
- larastan/larastan: ^3.10.0
- laravel/boost: ^2.4.12
- laravel/pint: ^1.29.3
- misaf/vendra-localization: v1.7.1
- misaf/vendra-testing: v1.7.1
- mockery/mockery: ^1.6.12
- nunomaduro/collision: ^8.9.4
- orchestra/testbench: ^11.1
- pestphp/pest: ^4.7.5
- pestphp/pest-plugin-arch: ^4.0.2
- pestphp/pest-plugin-laravel: ^4.1
- pestphp/pest-plugin-profanity: ^4.2.1
- pestphp/pest-plugin-type-coverage: ^4.0.4
- phpstan/extension-installer: ^1.4.3
Suggests
- misaf/vendra-localization: Bridges the tenant's enabled languages into request locale resolution (adds a tenant-default resolver and feeds the supported locales).
README
Tenant-aware language catalogs and database-backed translation lines for Vendra applications.
Features
- A platform locale catalog backed by Symfony Intl and ICU
- Per-tenant enabled languages with exactly one default and sortable display order
- Locale-specific database overrides powered by
spatie/laravel-translation-loader - A global Filament language switcher
- An optional bridge to
misaf/vendra-localization
Requirements
- PHP 8.3+
- Laravel 13
- Filament 5
misaf/vendra-supportsymfony/intl
Installation
composer require misaf/vendra-language php artisan vendor:publish --tag=vendra-language-migrations php artisan migrate
Optionally publish the configuration and translations:
php artisan vendor:publish --tag=vendra-language-config php artisan vendor:publish --tag=vendra-language-translations
The service provider and Filament plugin are discovered automatically.
Locale catalog
Every locale exposed by Symfony Intl may be installed for a tenant from the searchable Languages resource. The preferred locale subset for host integrations may still be configured in config/vendra-language.php:
'locales' => ['en', 'de', 'fa', 'pt-BR'],
Values use canonical web/BCP-47 tags and must exist in the ICU locale catalog. This preferred subset does not limit which locales may be installed. Tenant language records store the locale, active state, default flag, and display position; localized names are derived from ICU.
Usage
Enable a language for the current tenant:
use Misaf\VendraLanguage\Models\Language; $language = Language::query()->create([ 'locale' => 'en', 'active' => true, 'is_default' => true, 'position' => 1, ]);
The first enabled language becomes the default automatically. Setting another language as default clears the previous default for the current tenant, and deleting the default promotes the first remaining language in display order.
Create a translation line and read it through Laravel's translator:
use Misaf\VendraLanguage\Models\LanguageLine; LanguageLine::query()->create([ 'group' => 'navigation', 'key' => 'dashboard', 'text' => [ 'en' => 'Dashboard', 'de' => 'Übersicht', 'fa' => 'داشبورد', ], ]); __('navigation.dashboard');
To override a package translation, store the package translation namespace separately from the translation file group:
LanguageLine::query()->create([ 'namespace' => 'vendra-product', 'group' => 'attributes', 'key' => 'name', 'text' => ['en' => 'Product name'], ]); __('vendra-product::attributes.name');
Leave namespace empty for application translations. In Laravel's namespace::group.key syntax, the package name is the namespace and the translation file name is the group.
Database values override only the locale for which a non-blank value is stored. Missing and blank values leave that locale's file translation intact, allowing Laravel's normal fallback behavior to run afterward.
Applications that replace translation-loader.model may implement Misaf\VendraLanguage\Contracts\NamespacedLanguageLine to receive package namespaces. Models without the contract continue to support application translations, while explicit custom loaders and translation managers remain authoritative.
Load the current tenant's enabled languages in display order:
$languages = Language::query()->ordered()->get();
Optional localization bridge
When misaf/vendra-localization is installed, this package supplies its supported locale catalog and appends the tenant-default resolver at the end of the resolver chain. Explicit user, route, query, and header preferences therefore retain priority.
Filament
The configured panels expose Languages and Language Lines within the Localization cluster. Language lines can override keys discovered in application and Vendra package translation files. Their form displays all enabled tenant locales together and retains stored values for locales that are later disabled. Installed languages can be temporarily disabled from the Languages table without deleting them. The Languages table reports override coverage per locale, while the Language Lines table reports enabled-locale completion and identifies missing locales.
The global language switcher uses the current tenant's enabled languages in display order and falls back to config('app.fallback_locale') when none are enabled.
Testing
Run the package checks from the package directory:
composer test
composer analyse
License
MIT. See LICENSE.