rdcstarr/laravel-locale
laravel-locale
Database-driven language and country management for Laravel 13.
- Languages — ISO 639-1, enabled/default flags
- Countries — ISO 3166-1 alpha-2, flag emoji, timezone, E.164 calling code, primary language
- Octane-safe — stateless singleton service, current locale read dynamically per request
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.3 |
| Laravel | ^13.0 |
Installation
composer require rdcstarr/laravel-locale
Run the install command to publish and run migrations, then seed languages, countries and their relationships:
php artisan locale:install
Manual installation
If you prefer to control the process yourself, publish the migrations without running the install command:
php artisan vendor:publish --tag=laravel-locale-migrations
Then run the migrations and seed the reference data:
php artisan migrate
php artisan db:seed --class="Rdcstarr\Locale\Database\Seeders\LanguagesSeeder"
php artisan db:seed --class="Rdcstarr\Locale\Database\Seeders\CountriesSeeder"
php artisan db:seed --class="Rdcstarr\Locale\Database\Seeders\CountryLanguageSeeder"
Note: Migrations run automatically without publishing — skip
vendor:publishif you do not need to modify the migration files.
Languages
use Locale;
// All enabled languages
Locale::enabledLanguages();
// Default language
Locale::defaultLanguage();
// Find by ISO 639-1 code
Locale::languageByCode('ro');
// code → id map (useful for seeding)
Locale::enabledLanguageCodeToId();
// Raw query builder
Locale::languages()->where('enabled', true)->get();
Countries
use Locale;
// Find by ISO 3166-1 alpha-2 code
Locale::countryByCode('RO');
// Phone prefix (ITU-T E.164, e.g. "+40")
Locale::callingCodeByCode('RO'); // → "+40"
country_calling_code('RO'); // → "+40" (global helper)
Locale::countryByCode('RO')->calling_code; // direct model access
// All countries sharing a calling code (e.g. NANP "+1")
Locale::countries()->byCallingCode('+1')->get();
// All countries that use a given language
Locale::countriesForLanguage('ro');
// code → id map (useful for seeding)
Locale::countryCodeToId();
// Raw query builder
Locale::countries()->with('primaryLanguage')->get();
Models
Language
| Column | Type | Notes |
|---|---|---|
id |
bigint | |
name |
string | e.g. Romanian |
code |
string(5) | ISO 639-1, e.g. ro |
enabled |
boolean | default true |
default |
boolean | default false |
Country
| Column | Type | Notes |
|---|---|---|
id |
bigint | |
name |
string | e.g. Romania |
code |
string(2) | ISO 3166-1 alpha-2, e.g. RO |
flag |
string | URL or path |
flag_emoji |
string | e.g. 🇷🇴 |
timezone |
string | e.g. Europe/Bucharest |
calling_code |
string(10) | ITU-T E.164, e.g. +40, +1 |
primary_language_id |
FK → languages |
The country_language pivot table stores all official languages per country with an is_official boolean.
Octane compatibility
LocaleService is registered as a singleton but stores no request-scoped state — the current locale is always read dynamically via app()->getLocale(), so it is safe to reuse across requests on a long-lived worker.
Related Packages
Type-safe internationalization value objects and validation rules for Laravel ap...
Automatically detect and set an app locale that matches your visitor's preferenc...
Detect the language for your application using browser preferences, subdomains o...