alex-no / language-detector
Framework-agnostic language detector with Yii2 and Laravel adapters
Installs: 14
Dependents: 0
Suggesters: 1
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/alex-no/language-detector
Requires
- php: >=8.0
- psr/simple-cache: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- phpunit/phpunit: ^9.5 || ^10.0
- squizlabs/php_codesniffer: ^3.0
README
A framework-agnostic language detection library for PHP 8.0+
with adapters for Yii 2 and Laravel.
✨ Features
- Detects language from multiple sources:
- POST/- GETparameters
- 'Path' - URL path request
- Authenticated user profile
- Session / Cookies
- Accept-Languageheader
 
- Caches allowed languages from the database
- Can persist language to session, cookie, and user profile
- Works in both web and API contexts
- Easily extensible for any framework via adapters
⚙️ Installation
Install via Composer:
composer require alex-no/language-detector
🚀 Usage in Yii 2
Register the "component" and the "bootstrap" in config/web.php:
'bootstrap' => [ 'languageBootstrap', ], 'components' => [ 'languageBootstrap' => [ 'class' => \LanguageDetector\Adapters\Yii2\Bootstrap::class, 'paramName' => 'lang', 'default' => 'en', 'userAttribute' => 'language_code', 'tableName' => 'language', 'codeField' => 'code', 'enabledField' => 'is_enabled', 'pathSegmentIndex' => 1, ], ],
The component will:
- Checks for a lang parameter in URL or POST data.
- If not found, reads language from the authenticated user profile.
- If still not found, reads from session or cookie.
- Falls back to browser’s Accept-Language.
- Updates Yii::$app->language accordingly.
You can also call it manually:
Yii::$app->languageBootstrap->apply();
🚀 Usage in Laravel
Register the Service Provider Add this line to the providers array in config/app.php (if not auto-discovered):
'providers' => [ LanguageDetector\Adapters\Laravel\LaravelServiceProvider::class, ],
Register the Middleware
Add to app/Http/Kernel.php:
protected $middlewareGroups = [ 'web' => [ // ... \LanguageDetector\Adapters\Laravel\LaravelMiddleware::class, ], ];
Example configuration (config/language.php)
return [ 'paramName' => 'lang', 'default' => 'en', 'userAttribute' => 'language_code', 'tableName' => 'language', 'codeField' => 'code', 'enabledField' => 'is_enabled', ];
Example usage in controller
public function index(LanguageDetector $detector) { $lang = $detector->detect(); App::setLocale($lang); return view('welcome', ['lang' => $lang]); }
How it works
- Intercepts incoming requests.
- Detects preferred language based on request or session.
- Applies it globally using App::setLocale().
⚙️ Configuration Options
| Option | Description | Default | 
|---|---|---|
| paramName | Request parameter name for language | lang | 
| default | Fallback language code | en | 
| userAttribute | User model attribute used to store language | language_code | 
| tableName | Database table name containing languages | language | 
| codeField | Field name containing language code | code | 
| enabledField | Field name for active/enabled flag | is_enabled | 
| orderField | Field used for sorting languages | order | 
| pathSegmentIndex | Segment Index of Url Path if get language by URL | 0 | 
🗃️ Example Language Table
CREATE TABLE `language` ( `code` VARCHAR(5) NOT NULL, `short_name` VARCHAR(3) NOT NULL, `full_name` VARCHAR(32) NOT NULL, `is_enabled` TINYINT(1) NOT NULL DEFAULT '1', `order` TINYINT NOT NULL, PRIMARY KEY (`code`)) ENGINE = InnoDB
Sample data:
INSERT INTO language (code, is_enabled, `order`) VALUES ('en', 1, 1), ('uk', 1, 2), ('ru', 0, 3);
🧪 Running Tests
Install PHPUnit as a dev dependency:
composer require --dev phpunit/phpunit
Run the test suite:
./vendor/bin/phpunit -c phpunit.xml.dist
Or define a shortcut in composer.json:
"scripts": { "test": "phpunit -c phpunit.xml.dist" }
Then simply run:
composer test
🧱 Directory Structure
language-detector/ ├── src/ │ ├── Core/ │ │ ├── LanguageDetector.php │ │ ├── Contracts/ │ │ │ ├── LanguageRepositoryInterface.php │ │ │ ├── RequestInterface.php │ │ │ ├── ResponseInterface.php │ │ │ ├── UserInterface.php │ │ │ └── AuthenticatorInterface.php │ │ └── Extractor.php │ └── Adapters/ │ ├── Yii2/ │ │ ├── Bootstrap.php │ │ ├── YiiCacheAdapter.php │ │ ├── YiiLanguageRepository.php │ │ ├── YiiRequestAdapter.php │ │ ├── YiiResponseAdapter.php │ │ ├── YiiUserAdapter.php │ └── Laravel/ │ ├── LanguageServiceProvider.php │ ├── EloquentLanguageRepository.php │ ├── LaravelCacheAdapter.php │ ├── LaravelLanguageRepository.php │ ├── LaravelMiddleware.php │ ├── LaravelRequestAdapter.php │ ├── LaravelResponseAdapter.php │ └── LaravelUserAdapter.php ├──tests/ │ └── LanguageDetectorTest.php composer test composer.json phpunit.xml.dist LICENSE
🧰 Example test
A minimal test file tests/LanguageDetectorTest.php:
<?php declare(strict_types=1); use PHPUnit\Framework\TestCase; use LanguageDetector\LanguageDetector; final class LanguageDetectorTest extends TestCase { public function testDefaultLanguage(): void { $detector = new LanguageDetector(['default' => 'en']); $this->assertSame('en', $detector->detect()); } }
📄 License
Released under the MIT License © 2025 Oleksandr Nosov