{"id":46705275,"url":"https://github.com/josemontano1996/laravel-localization-suite","last_synced_at":"2026-03-09T08:09:08.337Z","repository":{"id":341369032,"uuid":"1125382569","full_name":"josemontano1996/laravel-localization-suite","owner":"josemontano1996","description":"A comprehensive, runtime-safe localization suite for Laravel 12+, with first-class support for Octane, Swoole and OpenSwoole concurrency hooks.","archived":false,"fork":false,"pushed_at":"2026-03-01T11:11:57.000Z","size":325,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-01T14:46:03.640Z","etag":null,"topics":["concurrency","concurrency-safe","fpm","i18n","laravel","laravel-octane","laravel-package","localization","octane","openswoole","php","php-library","state","swoole"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/josemontano1996.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-30T16:20:03.000Z","updated_at":"2026-03-01T11:09:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/josemontano1996/laravel-localization-suite","commit_stats":null,"previous_names":["josemontano1996/laravel-localization-suite"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/josemontano1996/laravel-localization-suite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josemontano1996%2Flaravel-localization-suite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josemontano1996%2Flaravel-localization-suite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josemontano1996%2Flaravel-localization-suite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josemontano1996%2Flaravel-localization-suite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/josemontano1996","download_url":"https://codeload.github.com/josemontano1996/laravel-localization-suite/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/josemontano1996%2Flaravel-localization-suite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30287462,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","concurrency-safe","fpm","i18n","laravel","laravel-octane","laravel-package","localization","octane","openswoole","php","php-library","state","swoole"],"created_at":"2026-03-09T08:09:03.650Z","updated_at":"2026-03-09T08:09:08.329Z","avatar_url":"https://github.com/josemontano1996.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Localization Suite\n\nA comprehensive, runtime safe, localization package for Laravel 12+ with first-class driver support for **Laravel Octane**, **Swoole** and **OpenSwoole** concurrency hooks.\n\nLocalize your laravel app without having to worry about the runtime your app will run on, FPM, Octane, or even Octane with Swoole or OpenSwoole asynchronous hooks, just change the localization driver and you will get a worry free localized app.\n\n[![PHP Version](https://img.shields.io/badge/php-%5E8.4-blue)](https://php.net)\n[![Laravel Version](https://img.shields.io/badge/laravel-12.x-red)](https://laravel.com)\n\n## ✨ Features\n\n- **Driver-based architecture** — Swap between Native, Context, Swoole, or OpenSwoole drivers depending on your needs.\n- **Octane-ready** — Octane-safe drivers grant locale isolation preventing cross-request bleed\n- **Concurrency safe drivers** — Swoole and OpenSwoole drivers are completely concurrency safe, meaning they support multiple concurrent requests per worker and they support all Swoole based HOOKS.\n- **Localized routing** — Simple locale-prefixed route groups with automatic detection\n- **Middlewares** - Useful middlewares for smart locale detection with metadata integration for best SEO practices\n- **Blade directives** — `@t`, `@route`, `@locale`, `@currency`, `@date` and more\n- **Macros** — `redirect()-\u003elocalized()`, `Route::localized()`, `URL::withLocale()`\n- **Validation** — Context-aware validation messages without touching global state\n\n---\n\n## 📦 Installation\n\n```bash\ncomposer require josemontano1996/laravel-localization-suite\n```\n\nPublish the configuration:\n\n```bash\nphp artisan vendor:publish --tag=localization-config\n```\n\n---\n\n## ⚙️ Configuration\n\n## Drivers\n\n### PHP Version Support Matrix\n\n| Driver | PHP 8.4 | PHP 8.5 | Per Worker Concurrency Safe |\n|--------|---------|---------|------------------|\n| `native` | ✅ | ✅ | ❌ |\n| `context` | ✅ | ✅ | ❌ |\n| `swoole` | ✅ | ❌ | ✅ |\n| `openswoole` | ✅ | ❌ | ✅ |\n\n\u003e **Note:** Swoole and OpenSwoole do not yet support PHP 8.5. Use `native` or `context` drivers for PHP 8.5 environments.\n\nFor a detailed explanation of all available drivers, their concurrency guarantees, and how to implement your own, see the [Drivers Documentation](docs/DRIVERS.md).\n\n### `config/localization.php`\n\n```php\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | Localization Driver\n    |--------------------------------------------------------------------------\n    |\n    | Built-in Drivers:\n    |  - \"native\": Standard Laravel behavior.\n    |  - \"context\": Laravel 11+ Context.\n    |  - \"swoole\": Swoole Coroutine Context (concurrency safe).\n    |  - \"openswoole\": OpenSwoole Coroutine Context (concurrency safe).\n    |\n    | Custom Drivers:\n    | You may provide a fully qualified class name implementing:\n    | \\Josemontano1996\\LaravelLocalizationSuite\\Contracts\\LocalizationDriverContract\n    |\n    */\n    'driver' =\u003e env('LOCALIZATION_DRIVER', 'native'),\n\n    // Route parameter name for the locale segment\n    'route_key' =\u003e 'locale',\n];\n```\n\n### Required Laravel Configuration\n\nAdd these to your `config/app.php`:\n\n```php\n'locale' =\u003e 'en',\n'fallback_locale' =\u003e 'en',\n'supported_locales' =\u003e ['en', 'es', 'fr', 'de'], // Required!\n```\n\n\u003e [!IMPORTANT]\n\u003e The `supported_locales` array **must** be populated with at least one locale.\n\n---\n\n## 🚀 Quick Start\n\n### 1. Define Localized Routes\n\n```php\n// routes/web.php\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::localized()\n    -\u003emiddleware('localization')\n    -\u003egroup(function () {\n        Route::get('/', fn () =\u003e view('home'))-\u003ename('home');\n        Route::get('/about', fn () =\u003e view('about'))-\u003ename('about');\n    });\n```\n\nThis creates routes like:\n\n- `/en/`, `/es/`, `/fr/`\n- `/en/about`, `/es/about`, `/fr/about`\n\n### 2. Use in Controllers\n\n```php\nuse Localization;\n\nclass HomeController extends Controller\n{\n    public function index()\n    {\n        // Get current locale\n        $locale = Localization::getCurrentLocale();\n\n        // Translate with context-aware locale\n        $greeting = Localization::t('messages.welcome');\n\n        // Generate localized route URL\n        $aboutUrl = Localization::route('about');\n\n        return view('home', compact('greeting', 'aboutUrl'));\n    }\n}\n```\n\n### 3. Use in Blade Templates\n\n```blade\n{{-- Current locale --}}\n\u003chtml lang=\"@locale\"\u003e\n\n{{-- Translations --}}\n\u003ch1\u003e@t('messages.welcome')\u003c/h1\u003e\n\u003cp\u003e@t('messages.greeting', ['name' =\u003e $user-\u003ename])\u003c/p\u003e\n\n{{-- Pluralization --}}\n\u003cp\u003e@tchoice('messages.items', $count)\u003c/p\u003e\n\n{{-- Localized routes --}}\n\u003ca href=\"@route('about')\"\u003e{{ t('nav.about') }}\u003c/a\u003e\n\u003ca href=\"@route('product.show', $product)\"\u003e{{ $product-\u003ename }}\u003c/a\u003e\n\n{{-- Formatting --}}\n\u003cspan\u003e@number(1234.56)\u003c/span\u003e          {{-- 1,234.56 or 1.234,56 depending on locale --}}\n\u003cspan\u003e@currency(99.99, 'EUR')\u003c/span\u003e   {{-- €99.99 or 99,99 € --}}\n\u003cspan\u003e@percent(0.15)\u003c/span\u003e            {{-- 15% --}}\n\n{{-- Dates --}}\n\u003ctime\u003e@date($post-\u003ecreated_at)\u003c/time\u003e           {{-- January 15, 2025 --}}\n\u003ctime\u003e@datetime($post-\u003ecreated_at)\u003c/time\u003e       {{-- January 15, 2025 at 3:45 PM --}}\n\u003ctime\u003e@date($post-\u003ecreated_at, 'MMMM YYYY')\u003c/time\u003e {{-- Custom format --}}\n\n{{-- Conditionals --}}\n@localeIs('en')\n    \u003cp\u003eEnglish-specific content\u003c/p\u003e\n@elselocaleIs('es')\n    \u003cp\u003eContenido en español\u003c/p\u003e\n@endlocaleIs\n\n{{-- Language switcher --}}\n\u003cnav\u003e\n    @locales($lang)\n        \u003ca href=\"{{ URL::withLocale($lang) }}\"\n           @if($lang === localization()-\u003egetCurrentLocale()) class=\"active\" @endif\u003e\n            {{ strtoupper($lang) }}\n        \u003c/a\u003e\n    @endlocales\n\u003c/nav\u003e\n```\n\n---\n\n## 🛣️ Routing\n\n### Localized Route Groups\n\n```php\nRoute::localized()\n    -\u003emiddleware('localization')\n    -\u003egroup(function () {\n        // All routes here will be prefixed with /{locale}/\n        Route::get('/', HomeController::class)-\u003ename('home');\n        Route::get('/products', [ProductController::class, 'index'])-\u003ename('products.index');\n    });\n```\n\n### Middleware\n\nThe package provides a `localization` middleware group that:\n\n1. **Detects locale from URL** — Reads the `{locale}` route parameter\n2. **Validates locale** — Redirects to best match if unsupported, falling back to smart request preferred locales.\n3. **Sets response headers** — Adds `Content-Language` header\n\n```php\n// Individual middleware aliases available:\nRoute::middleware('localization.from_route'); // Set locale from URL\nRoute::middleware('localization.headers');     // Add Content-Language header\nRoute::middleware('localization');             // Both combined\n```\n\n### Generate Localized URLs\n\n```php\n// Using the service\nlocalization()-\u003eroute('products.show', ['product' =\u003e $product]);\n\n// Using URL macro\nURL::localeRoute('products.show', ['product' =\u003e $product]);\n\n// Generate URL with a different locale\nURL::withLocale('es'); // Same page but in Spanish\n```\n\n---\n\n## 🔄 Redirects\n\nThe `redirect()-\u003elocalized()` macro ensures all redirects respect the current locale:\n\n```php\n// Redirect to a named route (locale is injected automatically)\nreturn redirect()-\u003elocalized()-\u003eroute('dashboard');\n\n// Redirect to a path (locale is prefixed automatically)\nreturn redirect()-\u003elocalized()-\u003eto('/profile');\n\n// Redirect back with locale fallback\nreturn redirect()-\u003elocalized()-\u003eback();\n\n// Redirect to intended URL after authentication\nreturn redirect()-\u003elocalized()-\u003eintended('/dashboard');\n\n// Localized signed routes\nreturn redirect()-\u003elocalized()-\u003esignedRoute('unsubscribe', ['user' =\u003e $user]);\n\n// Controller actions\nreturn redirect()-\u003elocalized()-\u003eaction([UserController::class, 'show'], ['id' =\u003e 1]);\n\n// External URLs (bypasses localization)\nreturn redirect()-\u003elocalized()-\u003eaway('https://google.com');\n```\n\n---\n\n## 🌐 Request Helpers\n\n```php\n// Get current locale\n$locale = request()-\u003elocale();\n\n// Get browser's accepted locales\n$accepted = request()-\u003eacceptedLocales(); // ['en' =\u003e 1.0, 'es' =\u003e 0.8, ...]\n\n// Get best matching locale from supported list\n$preferred = request()-\u003epreferredLocale(['en', 'es', 'fr']); // 'en'\n```\n\n---\n\n## 🔧 Drivers\n\n### Native Driver (Default)\n\nUses Laravel's built-in `App::setLocale()`. Safe for traditional FPM/mod_php.\n\n```env\nLOCALIZATION_DRIVER=native\n```\n\n### Context Driver\n\nUses Laravel 11+ `Context` facade for request-isolated state. This is safe for regular Octane environments.\n\n```env\nLOCALIZATION_DRIVER=context\n```\n\n### Swoole Driver\n\nUses Swoole's coroutine context. Required when enabling HOOKS_ALL flag for true per worker concurrency in **Laravel Octane with Swoole**.\n\n```env\nLOCALIZATION_DRIVER=swoole\n```\n\n### OpenSwoole Driver\n\nUses OpenSwoole's coroutine context. Required when enabling HOOKS_ALL flag for true per worker concurrency in **Laravel Octane with OpenSwoole**.\n\n```env\nLOCALIZATION_DRIVER=openswoole\n```\n\n### Custom Driver\n\nImplement `LocalizationDriverContract`:\n\n```php\nuse Josemontano1996\\LaravelLocalizationSuite\\Contracts\\LocalizationDriverContract;\n\nclass MyCustomDriver implements LocalizationDriverContract\n{\n    public function getCurrentLocale(): ?string\n    {\n        // Return stored locale or null\n    }\n\n    public function setCurrentLocale(string $locale): void\n    {\n        // Store the locale\n    }\n\n    public function isSafeToMutateGlobalState(): bool\n    {\n        // Return true if driver environment allows/desires the application to know if it's safe to mutate global state (App locale, Carbon, etc.)\n        return false;\n    }\n}\n```\n\n```php\n// config/localization.php\n'driver' =\u003e \\App\\Drivers\\MyCustomDriver::class,\n```\n\n---\n\n## 📚 API Reference\n\n### `localization()` Helper\n\n| Method                                              | Description                                      |\n| --------------------------------------------------- | ------------------------------------------------ |\n| `getCurrentLocale(): string`                        | Get the current request locale                   |\n| `setCurrentLocale(string $locale): void`            | Set the locale for the current request           |\n| `getConfigLocale(): string`                         | Get the configured default locale                |\n| `getSupportedLocales(): array`                      | Get list of supported locales                    |\n| `getRouteKey(): string`                             | Get the route parameter name (default: `locale`) |\n| `route($name, $params, $absolute): string`          | Generate localized route URL                     |\n| `t($key, $replace, $locale): string`                | Translate a string                               |\n| `tchoice($key, $number, $replace, $locale): string` | Pluralized translation                           |\n| `formatNumber($value, $style, $options): string`    | Format number/currency/percent                   |\n\n### Blade Directives\n\n| Directive                        | Usage                           |\n| -------------------------------- | ------------------------------- |\n| `@locale`                        | Output current locale           |\n| `@t('key')`                      | Translate string                |\n| `@t('key', ['name' =\u003e $value])`  | Translate with replacements     |\n| `@tchoice('key', $count)`        | Pluralized translation          |\n| `@route('name')`                 | Localized route URL             |\n| `@route('name', $params)`        | Localized route with parameters |\n| `@number($value)`                | Locale-formatted number         |\n| `@currency($value, 'USD')`       | Locale-formatted currency       |\n| `@percent($value)`               | Locale-formatted percentage     |\n| `@date($date)`                   | Locale-formatted date           |\n| `@date($date, 'MMMM YYYY')`      | Date with custom format         |\n| `@datetime($date)`               | Locale-formatted date and time  |\n| `@localeIs('en')`                | Conditional for locale          |\n| `@locales($var)` / `@endlocales` | Loop through supported locales  |\n\n### Facade\n\n```php\nuse Localization;\n\nLocalization::getCurrentLocale();\nLocalization::route('home');\nLocalization::t('messages.welcome');\n```\n\n---\n\n## 🧪 Testing\n\n```bash\ncomposer test       # Run tests\ncomposer lint       # Run PHP Pint\ncomposer analyse    # Run PHPStan\n```\n\n---\n\n## 📚 Detailed Documentation\n\n- [Drivers Documentation](docs/DRIVERS.md): In-depth guide to all available drivers, concurrency, and custom driver implementation.\n- [Middleware Documentation](docs/MIDDLEWARES.md): Learn about the provided middlewares and how to use them for locale detection and headers.\n- [Blade Directives Documentation](docs/BLADEDIRECTIVES.md): Learn about the blade directives.\n- [Macros Documentation](docs/MACROS.md): Learn about the package macros.\n\n---\n\n## 📄 License\n\nMIT License. See [LICENSE](LICENSE.md) for details.\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! See [CONTRIBUTING](CONTRIBUTING.md) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosemontano1996%2Flaravel-localization-suite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjosemontano1996%2Flaravel-localization-suite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosemontano1996%2Flaravel-localization-suite/lists"}