rdcstarr / laravel-multilanguage
A simple multilanguage package for Laravel with metadata support.
v1.1.6
2025-09-26 06:00 UTC
Requires
- php: ^8.0
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
README
Elegant package for managing multilanguage locale data in Laravel — with intelligent per‑language caching and a fluent API.
✨ Features
- 🌍 Multiple languages – easily switch & manage localized content
- 🔑 Key-value locale data – structured, namespaced keys per language
- ⚡ Smart cache – per-language forever cache with auto invalidation
- 📦 Batch operations – set or fetch many keys at once
- 🔄 Fluent API – expressive chaining (
localedata()->lang('en')->set(...)
) - 🧩 Blade directives – simple templating helpers & conditionals
- 🗄️ Clean schema – normalized tables with FK constraints
📦 Installation
Install via Composer:
composer require rdcstarr/laravel-multilanguage
- (Optional) Publish migration files:
php artisan vendor:publish --provider="Rdcstarr\Multilanguage\MultilanguageServiceProvider"
- Run migrations:
php artisan migrate
- (Recommended) Use the install command (runs migrations & seeds default languages):
php artisan multilanguage:install
Default seeded languages: English (en), Romanian (ro), French (fr).
🛠️ Artisan Commands
Install package (migrations + seed languages)
php artisan multilanguage:install [--force]
- --force : Skip interactive confirmation.
🔑 Usage
Set Values
// Single key per language localedata()->lang('en')->set('site.title', 'Welcome to our website'); localedata()->lang('ro')->set('site.title', 'Bine ai venit pe site-ul nostru'); // Batch (multiple keys) localedata()->lang('en')->setMany([ 'nav.home' => 'Home', 'nav.about' => 'About', 'nav.contact' => 'Contact', 'site.description'=> 'Best website ever', ]);
Get Values
$title = localedata()->lang('en')->get('site.title'); $titleWithDefault = localedata()->lang('es')->get('site.title', 'Default Title'); // Multiple $navigation = localedata()->lang('en')->getMany(['nav.home', 'nav.about', 'nav.contact']); // All for a language $allEnglish = localedata()->lang('en')->all(); // Current app locale (app()->getLocale()) $localized = localedata()->get('site.title', 'Fallback');
Working with Languages
use Rdcstarr\Multilanguage\Models\Language; // Create a language Language::create([ 'name' => 'Spanish', 'code' => 'es', 'flag' => '🇪🇸' ]); // Retrieve $languages = Language::all(); $english = Language::where('code', 'en')->first(); // Seed multiple values dynamically foreach (['en','ro','fr','es'] as $lang) { localedata()->lang($lang)->set("demo.message", "Message for {$lang}"); }
Facade
use Rdcstarr\Multilanguage\Facades\LocaleData; LocaleData::lang('en')->set('app.name', 'My App'); LocaleData::lang('ro')->set('app.name', 'Aplicația Mea'); $appName = LocaleData::lang('en')->get('app.name');
Helper
// Manager instance localedata(); // same as app('localedata') // Direct access (current locale) $title = localedata('site.title', 'Default Title');
Extra Operations
localedata()->lang('en')->has('site.title'); // existence localedata()->lang('en')->forget('old.unused.key'); // delete one localedata()->lang('en')->flushCache(); // clear cache for one language localedata()->flushAllCache(); // clear cache for all languages
🎨 Blade Directives
{{-- Current locale value (with optional default) --}} @localedata('site.title', 'Default Title') {{-- Specific language --}} @localedataForLang('"en"', '"site.title"', '"Default"') {{-- Conditional (current locale) --}} @hasLocaledata('site.title') <h1>{{ localedata('site.title') }}</h1> @endhasLocaledata {{-- Conditional (specific language) --}} @hasLocaledataForLang('"ro"', '"site.title"') <h1>{{ localedata()->lang('ro')->get('site.title') }}</h1> @endhasLocaledataForLang
Placeholders
// welcome.user => "Hello :NAME, your :type_plural are ready! :message_limit"; $result = localedata()->get('welcome.user')->placeholders([ 'name' => 'john doe', 'type' => 'order', 'message' => 'This is a very long message that will be truncated at 50 characters automatically', ]); // Result: "Hello JOHN DOE, your orders are ready! This is a very long message that will be truncat..."
💡 Examples
Website Content
localedata()->lang('en')->setMany([ 'home.hero.title' => 'Welcome to Our Platform', 'home.hero.subtitle' => 'The best solution for your business', ]); localedata()->lang('ro')->setMany([ 'home.hero.title' => 'Bine ai venit pe Platforma Noastră', 'home.hero.subtitle' => 'Cea mai bună soluție pentru afacerea ta', ]);
SEO Meta
localedata()->lang('en')->setMany([ 'seo.home.title' => 'Home - Best Platform Ever', 'seo.home.description' => 'Discover our amazing platform features', ]); <title>{{ localedata()->get('seo.' . request()->route()->getName() . '.title', 'Default') }}</title>
User Personalization
$userId = auth()->id(); localedata()->lang('en')->setMany([ "user.{$userId}.welcome" => 'Welcome back!', ]); localedata()->lang('ro')->setMany([ "user.{$userId}.welcome" => 'Bine ai revenit!', ]);
Product Catalog
$productId = 123; localedata()->lang('en')->setMany([ "product.{$productId}.name" => 'Premium Laptop', "product.{$productId}.description" => 'High-performance laptop', ]);
⚡ Performance
- Per-language cache buckets
- Forever cache via rememberForever
- Automatic invalidation on writes / deletes
- Minimal queries (one load per language as needed)
- Batch write operations
🧪 Testing
composer test
📖 Resources
- Changelog for recent changes.
👥 Credits
📜 License
- License for more information.