├── .github ├── FUNDING.yml ├── SECURITY.md └── workflows │ └── run-tests.yml ├── LICENSE.md ├── README.md ├── UPGRADE.md ├── composer.json ├── config └── localizer.php └── src ├── Detectors ├── AppDetector.php ├── BrowserDetector.php ├── CookieDetector.php ├── Detector.php ├── OmittedLocaleDetector.php ├── RouteActionDetector.php ├── SessionDetector.php ├── UrlDetector.php └── UserDetector.php ├── Localizer.php ├── LocalizerServiceProvider.php ├── Middleware └── SetLocale.php └── Stores ├── AppStore.php ├── CookieStore.php ├── SessionStore.php └── Store.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: ivanvermeyen 2 | custom: https://paypal.me/ivanvermeyen 3 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | If you discover any security related issues, please email ivan@codezero.be instead of using the issue tracker. 4 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | fail-fast: true 10 | matrix: 11 | php: [ 8.1, 8.2, 8.3 ] 12 | laravel: [ 10.*, 11.* ] 13 | dependency-version: [ prefer-stable ] 14 | exclude: 15 | - laravel: 11.* 16 | php: 8.1 17 | include: 18 | - laravel: 10.* 19 | testbench: 8.* 20 | - laravel: 11.* 21 | testbench: 9.* 22 | 23 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} 24 | 25 | steps: 26 | - name: Checkout code 27 | uses: actions/checkout@v2 28 | 29 | - name: Cache dependencies 30 | uses: actions/cache@v2 31 | with: 32 | path: ~/.composer/cache/files 33 | key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} 34 | 35 | - name: Setup PHP 36 | uses: shivammathur/setup-php@v2 37 | with: 38 | php-version: ${{ matrix.php }} 39 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick 40 | coverage: xdebug 41 | 42 | - name: Install dependencies 43 | run: composer update --with="illuminate/support:${{ matrix.laravel }}" --with="orchestra/testbench:${{ matrix.testbench }}" --prefer-dist --no-interaction --no-progress 44 | 45 | - name: Execute tests 46 | run: vendor/bin/phpunit --coverage-clover=coverage.xml 47 | 48 | - if: github.event_name == 'push' 49 | name: Run Codacy Coverage Reporter 50 | uses: codacy/codacy-coverage-reporter-action@master 51 | with: 52 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 53 | coverage-reports: coverage.xml 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Ivan Vermeyen (ivan@codezero.be) 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Localizer 2 | 3 | [![GitHub release](https://img.shields.io/github/release/codezero-be/laravel-localizer.svg?style=flat-square)](https://github.com/codezero-be/laravel-localizer/releases) 4 | [![Laravel](https://img.shields.io/badge/laravel-11-red?style=flat-square&logo=laravel&logoColor=white)](https://laravel.com) 5 | [![License](https://img.shields.io/packagist/l/codezero/laravel-localizer.svg?style=flat-square)](LICENSE.md) 6 | [![Build Status](https://img.shields.io/github/actions/workflow/status/codezero-be/laravel-localizer/run-tests.yml?style=flat-square&logo=github&logoColor=white&label=tests)](https://github.com/codezero-be/laravel-localizer/actions) 7 | [![Code Coverage](https://img.shields.io/codacy/coverage/ad6fcea152b449d380a187a375d0f7d7/master?style=flat-square)](https://app.codacy.com/gh/codezero-be/laravel-localizer) 8 | [![Code Quality](https://img.shields.io/codacy/grade/ad6fcea152b449d380a187a375d0f7d7/master?style=flat-square)](https://app.codacy.com/gh/codezero-be/laravel-localizer) 9 | [![Total Downloads](https://img.shields.io/packagist/dt/codezero/laravel-localizer.svg?style=flat-square)](https://packagist.org/packages/codezero/laravel-localizer) 10 | 11 | [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R3UQ8V) 12 | 13 | Automatically detect and set an app locale that matches your visitor's preference. 14 | 15 | - Define your supported locales and match your visitor's preference 16 | - Uses the most common locale [detectors](#-detectors) by default 17 | - Uses the most common locale [stores](#-stores) by default 18 | - Easily create and add your own detectors and stores 19 | 20 | ## ✅ Requirements 21 | 22 | - PHP >= 8.1 23 | - Laravel >= 10.0 24 | 25 | ## ⬆ Upgrade 26 | 27 | Upgrading to a new major version? 28 | Check our [upgrade guide](UPGRADE.md) for instructions. 29 | 30 | ## 📦 Install 31 | 32 | Install this package with Composer: 33 | 34 | ```bash 35 | composer require codezero/laravel-localizer 36 | ``` 37 | 38 | Laravel will automatically register the ServiceProvider. 39 | 40 | ## 🧩 Add Middleware 41 | 42 | By default, the app locale will always be what you configured in `config/app.php`. 43 | To automatically update the app locale, you need to register the middleware in the `web` middleware group. 44 | Make sure to add it after `StartSession` and before `SubstituteBindings`. 45 | 46 | The order of the middleware is important if you are using localized route keys (translated slugs)! 47 | The session needs to be active when setting the locale, and the locale needs to be set when substituting the route bindings. 48 | 49 | ### Laravel 11 and newer: 50 | 51 | Add the middleware to the `web` middleware group in `bootstrap/app.php`. 52 | 53 | ```php 54 | // bootstrap/app.php 55 | ->withMiddleware(function (Middleware $middleware) { 56 | $middleware->web(remove: [ 57 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 58 | ]); 59 | $middleware->web(append: [ 60 | \CodeZero\Localizer\Middleware\SetLocale::class, 61 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 62 | ]); 63 | }) 64 | ``` 65 | 66 | ### Laravel 10: 67 | 68 | Add the middleware to the `web` middleware group in `app/Http/Kernel.php`. 69 | 70 | ```php 71 | // app/Http/Kernel.php 72 | protected $middlewareGroups = [ 73 | 'web' => [ 74 | //... 75 | \Illuminate\Session\Middleware\StartSession::class, // <= after this 76 | //... 77 | \CodeZero\Localizer\Middleware\SetLocale::class, 78 | \Illuminate\Routing\Middleware\SubstituteBindings::class, // <= before this 79 | ], 80 | ]; 81 | ``` 82 | 83 | ## ⚙ Configure 84 | 85 | ### Publish Configuration File 86 | 87 | ```bash 88 | php artisan vendor:publish --provider="CodeZero\Localizer\LocalizerServiceProvider" --tag="config" 89 | ``` 90 | 91 | You will now find a `localizer.php` file in the `config` folder. 92 | 93 | ### Configure Supported Locales 94 | 95 | Add any locales you wish to support to your published `config/localizer.php` file: 96 | 97 | ```php 98 | 'supported_locales' => ['en', 'nl']; 99 | ``` 100 | 101 | By default, the `UrlDetector` will look for these locales in the URL. 102 | 103 | You can also use one or more custom slugs for a locale: 104 | 105 | ```php 106 | 'supported_locales' => [ 107 | 'en' => 'english-slug', 108 | 'nl' => ['dutch-slug', 'nederlandse-slug'], 109 | ]; 110 | ``` 111 | 112 | Or you can use one or more custom domains for a locale: 113 | 114 | ```php 115 | 'supported_locales' => [ 116 | 'en' => 'english-domain.test', 117 | 'nl' => ['dutch-domain.test', 'nederlands-domain.test'], 118 | ]; 119 | ``` 120 | 121 | ## 🔍 Detectors 122 | 123 | By default, the middleware will use the following detectors to check for a supported locale in: 124 | 125 | | # | Detector | Description | 126 | |:---:|-------------------------|------------------------------------------------------------------------| 127 | | 1. | `RouteActionDetector` | Checks for a locale in a custom route action. | 128 | | 2. | `UrlDetector` | Tries to find a locale based on the URL slugs or domain. | 129 | | 3. | `OmittedLocaleDetector` | Required if an omitted locale is configured. This will always be used. | 130 | | 4. | `UserDetector` | Checks a configurable `locale` attribute on the authenticated user. | 131 | | 5. | `SessionDetector` | Checks the session for a previously stored locale. | 132 | | 6. | `CookieDetector` | Checks a cookie for a previously stored locale. | 133 | | 7. | `BrowserDetector` | Checks the preferred language settings of the visitor's browser. | 134 | | 8. | `AppDetector` | Checks the default app locale as a last resort. | 135 | 136 | Update the `detectors` array in the config file to choose which detectors to run and in what order. 137 | 138 | > You can create your own detector by implementing the `CodeZero\Localizer\Detectors\Detector` interface 139 | > and add a reference to it in the config file. The detectors are resolved from Laravel's IOC container, 140 | > so you can add any dependencies to your constructor. 141 | 142 | ## 💾 Stores 143 | 144 | The first supported locale that is returned by a detector will automatically be stored in: 145 | 146 | | # | Store | Description | 147 | |:---:|----------------|-------------------------------------------| 148 | | 1. | `SessionStore` | Stores the locale in the session. | 149 | | 2. | `CookieStore` | Stores the locale in a cookie. | 150 | | 3. | `AppStore` | Sets the locale as the active app locale. | 151 | 152 | Update the `stores` array in the config file to choose which stores to use. 153 | 154 | > You can create your own store by implementing the `CodeZero\Localizer\Stores\Store` interface 155 | > and add a reference to it in the config file. The stores are resolved from Laravel's IOC container, 156 | > so you can add any dependencies to your constructor. 157 | 158 | ## 🛠 More Configuration 159 | 160 | ### ☑ `omitted_locale` 161 | 162 | If you don't want your main locale to have a slug, you can set it as the `omitted_locale` (not the custom slug). 163 | 164 | If you do this, no additional detectors will run after the `UrlDetector` and `OmittedLocaleDetector`. 165 | This makes sense, because the locale will always be determined by those two in this scenario. 166 | 167 | Example: 168 | 169 | ```php 170 | 'omitted_locale' => 'en', 171 | ``` 172 | 173 | Result: 174 | 175 | - /example-route (English without slug) 176 | - /nl/example-route (Other locales with slug) 177 | 178 | Default: `null` 179 | 180 | ### ☑ `trusted_detectors` 181 | 182 | Add any detector class name to this array to make it trusted. (do not remove it from the `detectors` array) 183 | When a trusted detector returns a locale, it will be used as the app locale, regardless if it's a supported locale or not. 184 | 185 | Default: `[]` 186 | 187 | ### ☑ `url_segment` 188 | 189 | The index of the URL segment that has the locale, when using the `UrlDetector`. 190 | 191 | Default: `1` 192 | 193 | ### ☑ `route_action` 194 | 195 | The custom route action that holds the locale, when using the `RouteActionDetector`. 196 | 197 | Default: `locale` 198 | 199 | To use the custom route action `locale`, you register a route like this: 200 | 201 | ```php 202 | Route::group(['locale' => 'nl'], function () { 203 | //Route::get(...); 204 | }); 205 | ``` 206 | 207 | ### ☑ `user_attribute` 208 | 209 | The attribute on the user model that holds the locale, when using the `UserDetector`. 210 | If the user model does not have this attribute, this detector check will be skipped. 211 | 212 | Default: `locale` 213 | 214 | ### ☑ `session_key` 215 | 216 | The session key that holds the locale, when using the `SessionDetector` and `SessionStore`. 217 | 218 | Default: `locale` 219 | 220 | ### ☑ `cookie_name` 221 | 222 | The name of the cookie that holds the locale, when using the `CookieDetector` and `CookieStore`. 223 | 224 | Default: `locale` 225 | 226 | ### ☑ `cookie_minutes` 227 | 228 | The lifetime of the cookie that holds the locale, when using the `CookieStore`. 229 | 230 | Default: `60 * 24 * 365` (1 year) 231 | 232 | ## 🚧 Testing 233 | 234 | ```bash 235 | composer test 236 | ``` 237 | 238 | ## ☕ Credits 239 | 240 | - [Ivan Vermeyen](https://github.com/ivanvermeyen) 241 | - [All contributors](https://github.com/codezero-be/laravel-localizer/contributors) 242 | 243 | ## 🔒 Security 244 | 245 | If you discover any security related issues, please [e-mail me](mailto:ivan@codezero.be) instead of using the issue tracker. 246 | 247 | ## 📑 Changelog 248 | 249 | A complete list of all notable changes to this package can be found on the 250 | [releases page](https://github.com/codezero-be/laravel-localizer/releases). 251 | 252 | ## 📜 License 253 | 254 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 255 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guide 2 | 3 | ## Upgrading To 3.0 From 2.x 4 | 5 | ### ➡ Minimum Requirements Updated 6 | 7 | Due to PHP and PHPUnit version constraints with Laravel 11, we dropped support for Laravel 7.x, 8.x and 9.x. 8 | 9 | - The minimum PHP version required is now 8.1 10 | - The minimum Laravel version required is now 10.0 11 | 12 | --- 13 | 14 | ### ➡ Re-register Middleware 15 | 16 | Laravel 11 no longer has a `app/Http/Kernel.php` to register middleware. 17 | This is now handled in `bootstrap/app.php`. 18 | 19 | 🔸 **Actions Required** 20 | 21 | If you use Laravel 11, register the middleware in `bootstrap/app.php` as described in the README. 22 | 23 | ## Upgrading To 2.0 From 1.x 24 | 25 | ### ➡ Minimum Requirements Updated 26 | 27 | We dropped support for Laravel 5.6, 5.7, 5.8 and 6.x. 28 | 29 | - The minimum PHP version required is now 7.2.5 30 | - The minimum Laravel version required is now 7.0 31 | 32 | --- 33 | 34 | ### ➡ Names of Config Options Updated 35 | 36 | Every config option that contained a `-` (dash) in its name has been updated and the dash is replaced by an `_` (underscore). 37 | This is done mainly for consistency across other packages. 38 | 39 | 🔸 **Actions Required** 40 | 41 | - Review and update your published config file accordingly. 42 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codezero/laravel-localizer", 3 | "description": "Automatically detect and set an app locale that matches your visitor's preference.", 4 | "keywords": [ 5 | "php", 6 | "laravel", 7 | "browser", 8 | "cookie", 9 | "session", 10 | "locale", 11 | "language", 12 | "country", 13 | "localization", 14 | "detect" 15 | ], 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "Ivan Vermeyen", 20 | "email": "ivan@codezero.be" 21 | } 22 | ], 23 | "require": { 24 | "php": "^8.1", 25 | "codezero/browser-locale": "^3.0", 26 | "illuminate/support": "^10.0|^11.0" 27 | }, 28 | "require-dev": { 29 | "mockery/mockery": "^1.3.3", 30 | "orchestra/testbench": "^8.0|^9.0", 31 | "phpunit/phpunit": "^10.5" 32 | }, 33 | "scripts": { 34 | "test": "phpunit" 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "CodeZero\\Localizer\\": "src" 39 | } 40 | }, 41 | "autoload-dev": { 42 | "psr-4": { 43 | "CodeZero\\Localizer\\Tests\\": "tests" 44 | } 45 | }, 46 | "extra": { 47 | "laravel": { 48 | "providers": [ 49 | "CodeZero\\Localizer\\LocalizerServiceProvider" 50 | ] 51 | } 52 | }, 53 | "config": { 54 | "preferred-install": "dist", 55 | "sort-packages": true, 56 | "optimize-autoloader": true 57 | }, 58 | "minimum-stability": "dev", 59 | "prefer-stable": true 60 | } 61 | -------------------------------------------------------------------------------- /config/localizer.php: -------------------------------------------------------------------------------- 1 | [], 9 | 10 | /** 11 | * If your main locale is omitted from the URL, set it here. 12 | * It will always be used if no supported locale is found in the URL. 13 | * Note that no other detectors will run after the OmittedLocaleDetector! 14 | * Setting this option to `null` will disable this detector. 15 | */ 16 | 'omitted_locale' => null, 17 | 18 | /** 19 | * The detectors to use to find a matching locale. 20 | * These will be executed in the order that they are added to the array! 21 | */ 22 | 'detectors' => [ 23 | CodeZero\Localizer\Detectors\RouteActionDetector::class, 24 | CodeZero\Localizer\Detectors\UrlDetector::class, 25 | CodeZero\Localizer\Detectors\OmittedLocaleDetector::class, 26 | CodeZero\Localizer\Detectors\UserDetector::class, 27 | CodeZero\Localizer\Detectors\SessionDetector::class, 28 | CodeZero\Localizer\Detectors\CookieDetector::class, 29 | CodeZero\Localizer\Detectors\BrowserDetector::class, 30 | CodeZero\Localizer\Detectors\AppDetector::class, 31 | ], 32 | 33 | /** 34 | * Add any of the above detector class names here to make it trusted. 35 | * When a trusted detector returns a locale, it will be used 36 | * as the app locale, regardless if it's a supported locale or not. 37 | */ 38 | 'trusted_detectors' => [ 39 | // 40 | ], 41 | 42 | /** 43 | * The stores to store the first matching locale in. 44 | */ 45 | 'stores' => [ 46 | CodeZero\Localizer\Stores\SessionStore::class, 47 | CodeZero\Localizer\Stores\CookieStore::class, 48 | CodeZero\Localizer\Stores\AppStore::class, 49 | ], 50 | 51 | /** 52 | * The index of the segment that has the locale, 53 | * when using the UrlDetector. 54 | */ 55 | 'url_segment' => 1, 56 | 57 | /** 58 | * The attribute or "action" on the route that holds the locale, 59 | * when using the RouteActionDetector. 60 | */ 61 | 'route_action' => 'locale', 62 | 63 | /** 64 | * The attribute on the user model that holds the locale, 65 | * when using the UserDetector. 66 | */ 67 | 'user_attribute' => 'locale', 68 | 69 | /** 70 | * The session key that holds the locale, 71 | * when using the SessionDetector and SessionStore. 72 | */ 73 | 'session_key' => 'locale', 74 | 75 | /** 76 | * The name of the cookie that holds the locale, 77 | * when using the CookieDetector and CookieStore. 78 | */ 79 | 'cookie_name' => 'locale', 80 | 81 | /** 82 | * The lifetime of the cookie that holds the locale, 83 | * when using the CookieStore. 84 | */ 85 | 'cookie_minutes' => 60 * 24 * 365, // 1 year 86 | 87 | ]; 88 | -------------------------------------------------------------------------------- /src/Detectors/AppDetector.php: -------------------------------------------------------------------------------- 1 | filter(new CombinedFilter); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Detectors/CookieDetector.php: -------------------------------------------------------------------------------- 1 | getAction($action); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Detectors/SessionDetector.php: -------------------------------------------------------------------------------- 1 | flipLocalesArray($locales); 32 | $locale = $locales[$domain] ?? $locales[$slug] ?? $slug; 33 | 34 | return $locale; 35 | } 36 | 37 | /** 38 | * Flip the locales array so the custom domain or slug 39 | * become the key and the locale becomes te value. 40 | * 41 | * @param array $locales 42 | * 43 | * @return array 44 | */ 45 | protected function flipLocalesArray($locales) 46 | { 47 | $flipped = []; 48 | 49 | foreach ($locales as $locale => $values) { 50 | $values = is_array($values) ? $values : [$values]; 51 | 52 | foreach ($values as $value) { 53 | $flipped[$value] = $locale; 54 | } 55 | } 56 | 57 | return $flipped; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Detectors/UserDetector.php: -------------------------------------------------------------------------------- 1 | getAttributeValue($attribute); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Localizer.php: -------------------------------------------------------------------------------- 1 | setSupportedLocales($locales); 48 | $this->detectors = $detectors; 49 | $this->stores = $stores; 50 | $this->trustedDetectors = $trustedDetectors; 51 | } 52 | 53 | /** 54 | * Detect any supported locale and return the first match. 55 | * 56 | * @return string|false 57 | */ 58 | public function detect() 59 | { 60 | foreach ($this->detectors as $detector) { 61 | $locales = (array) $this->getInstance($detector)->detect(); 62 | 63 | foreach ($locales as $locale) { 64 | if ($locale && ($this->isSupportedLocale($locale) || $this->isTrustedDetector($detector))) { 65 | return $locale; 66 | } 67 | } 68 | } 69 | 70 | return false; 71 | } 72 | 73 | /** 74 | * Store the given locale. 75 | * 76 | * @param string $locale 77 | * 78 | * @return void 79 | */ 80 | public function store($locale) 81 | { 82 | foreach ($this->stores as $store) { 83 | $this->getInstance($store)->store($locale); 84 | } 85 | } 86 | 87 | /** 88 | * Set the supported locales. 89 | * 90 | * @param array $locales 91 | * 92 | * @return \CodeZero\Localizer\Localizer 93 | */ 94 | public function setSupportedLocales(array $locales) 95 | { 96 | if ( ! array_key_exists(0, $locales)) { 97 | $locales = array_keys($locales); 98 | } 99 | 100 | $this->locales = $locales; 101 | 102 | return $this; 103 | } 104 | 105 | /** 106 | * Check if the given locale is supported. 107 | * 108 | * @param mixed $locale 109 | * 110 | * @return bool 111 | */ 112 | protected function isSupportedLocale($locale) 113 | { 114 | return in_array($locale, $this->locales); 115 | } 116 | 117 | /** 118 | * Check if the given Detector class is trusted. 119 | * 120 | * @param \CodeZero\Localizer\Detectors\Detector|string $detector 121 | * 122 | * @return bool 123 | */ 124 | protected function isTrustedDetector($detector) 125 | { 126 | if (is_string($detector)) { 127 | return in_array($detector, $this->trustedDetectors); 128 | } 129 | 130 | foreach ($this->trustedDetectors as $trustedDetector) { 131 | if ($detector instanceof $trustedDetector) { 132 | return true; 133 | } 134 | } 135 | 136 | return false; 137 | } 138 | 139 | /** 140 | * Get the class from Laravel's IOC container if it is a string. 141 | * 142 | * @param mixed $class 143 | * 144 | * @return mixed 145 | */ 146 | protected function getInstance($class) 147 | { 148 | if (is_string($class)) { 149 | return App::make($class); 150 | } 151 | 152 | return $class; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/LocalizerServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerPublishableFiles(); 25 | } 26 | 27 | /** 28 | * Register any application services. 29 | * 30 | * @return void 31 | */ 32 | public function register() 33 | { 34 | $this->mergeConfig(); 35 | $this->registerLocalizer(); 36 | $this->registerProviders(); 37 | } 38 | 39 | /** 40 | * Register the publishable files. 41 | * 42 | * @return void 43 | */ 44 | protected function registerPublishableFiles() 45 | { 46 | $this->publishes([ 47 | __DIR__."/../config/{$this->name}.php" => config_path("{$this->name}.php"), 48 | ], 'config'); 49 | } 50 | 51 | /** 52 | * Merge published configuration file with 53 | * the original package configuration file. 54 | * 55 | * @return void 56 | */ 57 | protected function mergeConfig() 58 | { 59 | $this->mergeConfigFrom(__DIR__."/../config/{$this->name}.php", $this->name); 60 | } 61 | 62 | /** 63 | * Register Localizer. 64 | * 65 | * @return void 66 | */ 67 | protected function registerLocalizer() 68 | { 69 | $this->app->bind(Localizer::class, function ($app) { 70 | $locales = $app['config']->get("{$this->name}.supported_locales"); 71 | $detectors = $app['config']->get("{$this->name}.detectors"); 72 | $stores = $app['config']->get("{$this->name}.stores"); 73 | $trustedDetectors = $app['config']->get("{$this->name}.trusted_detectors"); 74 | 75 | return new Localizer($locales, $detectors, $stores, $trustedDetectors); 76 | }); 77 | } 78 | 79 | /** 80 | * Registers the package dependencies 81 | * 82 | * @return void 83 | */ 84 | protected function registerProviders() 85 | { 86 | $this->app->register(BrowserLocaleServiceProvider::class); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Middleware/SetLocale.php: -------------------------------------------------------------------------------- 1 | localizer = $localizer; 25 | } 26 | 27 | /** 28 | * Handle an incoming request. 29 | * 30 | * @param \Illuminate\Http\Request $request 31 | * @param \Closure $next 32 | * 33 | * @return mixed 34 | */ 35 | public function handle($request, Closure $next) 36 | { 37 | $locale = $this->localizer->detect(); 38 | 39 | if ($locale) { 40 | $this->localizer->store($locale); 41 | } 42 | 43 | return $next($request); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Stores/AppStore.php: -------------------------------------------------------------------------------- 1 |