A professional Laravel package for automatic locale detection from HTTP headers and translation key extraction from your codebase.
- Features
- Requirements
- Installation
- Configuration
- Usage
- Translation Key Extraction
- Translatable Models
- Advanced Usage
- Testing
- License
- ✅ Automatic Locale Detection - Automatically detects user's preferred language from
Accept-Languageheader - ✅ Translation Key Extraction - Extract all translation keys from your codebase
- ✅ Multiple Detection Methods - Supports Laravel's
getPreferredLanguage()and direct header parsing - ✅ Configurable Supported Locales - Define which locales your application supports
- ✅ Global Middleware - Automatically registered middleware for seamless integration
- ✅ Multiple Output Formats - Export translation keys as JSON, PHP, or array format
- ✅ Namespace Filtering - Filter translation keys by namespace
- ✅ Exclude Paths - Exclude specific directories from key extraction
- ✅ Translation Key Synchronization - Sync translation keys to language files automatically
- ✅ 40+ Language Files - Includes translation files for auth, pagination, passwords, and validation in 40+ languages
- ✅ Translatable Models - Wrapper for Astrotomic Translatable with additional helper methods
- ✅ Database Migrations - Helper traits and classes for creating translation tables
- ✅ Translation Format Converter - Convert between attribute-based and locale-based translation formats
- PHP 8.2 or higher
- Laravel 11.0+ or Laravel 12.0+
composer require rawnoq/laravel-locale-detectorThe package will be automatically discovered and registered by Laravel.
php artisan vendor:publish --tag=locale-detector-configThis will publish the configuration file to config/locale-detector.php.
php artisan vendor:publish --tag=locale-detector-langThis will publish language files to lang/ directory. The package includes translation files for 40+ languages (auth, pagination, passwords, validation).
The configuration file is located at config/locale-detector.php:
return [
/*
|--------------------------------------------------------------------------
| Auto Detect Locale
|--------------------------------------------------------------------------
|
| Enable automatic locale detection from Accept-Language header.
|
*/
'auto_detect_locale' => env('AUTO_DETECT_LOCALE', true),
/*
|--------------------------------------------------------------------------
| Auto Detect Preferred Language
|--------------------------------------------------------------------------
|
| Use Laravel's getPreferredLanguage() method for locale detection.
| If false, uses the Accept-Language header directly.
|
*/
'auto_detect_preferred_language' => env('AUTO_DETECT_PREFERRED_LANGUAGE', true),
/*
|--------------------------------------------------------------------------
| Supported Locales
|--------------------------------------------------------------------------
|
| List of supported locales for automatic detection.
|
*/
'supported_locales' => env('SUPPORTED_LOCALES', 'en,ar')
? explode(',', env('SUPPORTED_LOCALES', 'en,ar'))
: ['en', 'ar'],
];You can configure the package using environment variables in your .env file:
AUTO_DETECT_LOCALE=true
AUTO_DETECT_PREFERRED_LANGUAGE=true
SUPPORTED_LOCALES=en,ar,fr,esThe middleware automatically detects the user's preferred language from the Accept-Language header and sets the application locale accordingly.
No additional code required! The middleware is automatically registered and works out of the box.
You can still manually set the locale in your code:
app()->setLocale('ar');$locale = app()->getLocale();The package provides a powerful command to extract all translation keys from your codebase.
# Extract all translation keys from the entire codebase
php artisan locale:extract-keys
# Extract keys from a specific path
php artisan locale:extract-keys --path=app
# Extract keys and save to a file
php artisan locale:extract-keys --output=translation-keys.json
# Extract keys in PHP format
php artisan locale:extract-keys --format=php --output=keys.php
# Extract keys in array format
php artisan locale:extract-keys --format=array
# Extract keys with file path and line number
php artisan locale:extract-keys --with-location
# Extract keys with location and save to JSON file
php artisan locale:extract-keys --with-location --output=translation-keys.json| Option | Description | Default |
|---|---|---|
--path |
The path to search for translation keys | base_path() |
--output |
The output file path for extracted keys | Display in console |
--format |
Output format (json, php, array) | json |
--exclude |
Comma-separated paths to exclude | None |
--namespace |
Filter keys by namespace | None |
--with-location |
Include file path and line number for each key | false |
php artisan locale:extract-keys --path=appphp artisan locale:extract-keys --output=storage/app/translation-keys.jsonphp artisan locale:extract-keys --format=php --output=config/translation-keys.phpphp artisan locale:extract-keys --exclude=vendor,storagephp artisan locale:extract-keys --namespace=blogThis will only extract keys that start with blog::.
php artisan locale:extract-keys --with-location --output=translation-keys.jsonThis will extract keys with file path and line number information. The output will include:
key: The translation keyfile: The relative file pathline: The line number where the key was foundlocation: A formatted string likefile:linelocations: An array of all locations where the key appears (if the same key appears multiple times)
Example output:
[
{
"key": "welcome",
"file": "app/Http/Controllers/TestController.php",
"line": 11,
"location": "app/Http/Controllers/TestController.php:11",
"locations": [
"app/Http/Controllers/TestController.php:11",
"app/Http/Controllers/TestController.php:12"
]
}
]The command extracts keys from the following patterns:
__('key')- Laravel's translation helpertrans('key')- Translation function@lang('key')- Blade directiveLang::get('key')- Lang facade methodLang::trans('key')- Lang facade trans methodtrans_choice('key', ...)- Translation choice function__('namespace::key')- Namespaced translationstrans('namespace::key')- Namespaced translations
[
"validation.required",
"validation.email",
"messages.welcome",
"blog::post.title"
]<?php
return [
'validation.required',
'validation.email',
'messages.welcome',
'blog::post.title',
];[
'validation.required',
'validation.email',
'messages.welcome',
'blog::post.title',
]
The package provides a wrapper for Astrotomic Translatable with additional helper methods and utilities.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Rawnoq\LocaleDetector\Concerns\Translatable;
class Post extends Model
{
use Translatable;
public $translatedAttributes = ['title', 'content'];
protected $fillable = ['author', 'title', 'content'];
}// Using locale-based format (Astrotomic standard)
$post = Post::create([
'author' => 'John Doe',
'en' => [
'title' => 'My First Post',
'content' => 'This is the content.'
],
'ar' => [
'title' => 'منشوري الأول',
'content' => 'هذا المحتوى.'
]
]);
// Accessing translations
echo $post->translate('en')->title; // My First Post
echo $post->translate('ar')->title; // منشوري الأول
App::setLocale('ar');
echo $post->title; // منشوري الأولThe package provides helper functions to convert between different translation formats:
// Convert from attribute-based to locale-based format
$data = [
'author' => 'John',
'title' => [
'en' => 'My Post',
'ar' => 'منشوري'
],
'content' => [
'en' => 'Content',
'ar' => 'المحتوى'
]
];
$converted = to_locale_based($data, ['title', 'content']);
// Result:
// [
// 'author' => 'John',
// 'en' => ['title' => 'My Post', 'content' => 'Content'],
// 'ar' => ['title' => 'منشوري', 'content' => 'المحتوى']
// ]
// Convert back to attribute-based format
$original = to_attribute_based($converted, ['title', 'content']);// Using the model's static methods
$converted = Post::convertToLocaleBased($data);
$original = Post::convertToAttributeBased($converted);The package provides helper traits and classes for creating translation tables:
<?php
use Rawnoq\LocaleDetector\Database\Migrations\MigrationWithTranslations;
use Illuminate\Database\Schema\Blueprint;
class CreatePostsTable extends MigrationWithTranslations
{
public function up(): void
{
$this->createTableWithTranslations(
'posts',
function (Blueprint $table) {
$table->id();
$table->string('author');
$table->boolean('is_published')->default(false);
$table->timestamps();
},
function (Blueprint $table) {
$table->string('title');
$table->text('content');
$table->string('slug')->unique();
}
);
}
public function down(): void
{
$this->dropIfExistsWithTranslations('posts');
}
}<?php
use Illuminate\Database\Migrations\Migration;
use Rawnoq\LocaleDetector\Concerns\CreateTableWithTranslations;
use Illuminate\Database\Schema\Blueprint;
class CreatePostsTable extends Migration
{
use CreateTableWithTranslations;
public function up(): void
{
$this->createTableWithTranslations(/* ... */);
}
}$this->createTableWithTranslations(
'posts',
function (Blueprint $table) {
$table->uuid('id')->primary();
// ...
},
function (Blueprint $table) {
// ...
},
true // useUuid = true
);You can customize the locale detection logic by modifying the middleware or creating your own:
// In your custom middleware
if (config('locale-detector.auto_detect_locale')) {
$locale = $request->header('Accept-Language');
// Your custom logic here
app()->setLocale($locale);
}If you're using the rawnoq/laravel-hmvc package, you can extract translation keys from modules:
# Extract keys from all modules
php artisan locale:extract-keys --path=modules
# Extract keys from a specific module
php artisan locale:extract-keys --path=modules/Blog --namespace=blogYou can create a script to automatically extract and update translation files:
#!/bin/bash
# Extract keys and save to a file
php artisan locale:extract-keys --output=storage/app/keys.json
# Process the keys and update translation files
# Your custom script hereIf locale detection is not working:
- Check if middleware is registered:
php artisan route:list - Verify configuration:
php artisan config:show locale-detector - Check
Accept-Languageheader in requests - Ensure supported locales are configured correctly
If the extraction command finds no keys:
- Verify the path contains PHP files
- Check if translation functions are used correctly
- Ensure files are readable
- Check excluded paths
If locale:extract-keys command is not found:
- Run
php artisan package:discover - Clear cache:
php artisan optimize:clear - Verify Service Provider is registered
php artisan locale:extract-keysphp artisan locale:extract-keys --path=app/Http/Controllersphp artisan locale:extract-keys --output=storage/app/translation-keys.json --format=jsonphp artisan locale:extract-keys --exclude=vendor,storage,node_modulesphp artisan locale:extract-keys --namespace=blogContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
The package comes with a comprehensive test suite:
# Run tests
composer test
# Run tests with coverage
composer test-coverageThe test suite includes:
- ✅ Middleware locale detection tests
- ✅ ServiceProvider registration tests
- ✅ Translation key extraction command tests
- ✅ Configuration tests
- ✅ Translation format converter tests
- ✅ Helper functions tests
- ✅ Edge cases and error handling
This package is open-sourced software licensed under the MIT license.
- Author: Rawnoq
- Package: rawnoq/laravel-locale-detector
- Version: 1.0.0
Made with ❤️ for the Laravel community