Skip to content

Commit a59e22d

Browse files
author
AlexVakhovski
committed
Add example, upd Readme
1 parent eede461 commit a59e22d

File tree

5 files changed

+204
-54
lines changed

5 files changed

+204
-54
lines changed

README.md

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,23 @@ Simple and lightweight package to localize your Laravel routes.
1616
- Redirects `/fallback_locale/...` to `/...` with 301 if needed
1717
- Works with Laravel 10, 11, and 12
1818

19-
## Installation
19+
## 📚 Installation
2020

2121
Install the package via Composer:
2222

2323
```bash
2424
composer require alexwaha/laravel-multilang-routes
2525
```
2626

27-
Publish package config file:
27+
Publish the configuration file:
28+
2829
```bash
29-
php artisan vendor:publish --tag=multilang-localize-config
30+
php artisan vendor:publish --tag=multilang-routes-config
3031
```
3132

32-
This will publish the config file to `config/multilang-routes.php`:
33-
34-
You can customize the list of supported languages and their URL slugs.
33+
This will create `config/multilang-routes.php`.
3534

36-
## Usage
35+
## 🚀 Usage
3736

3837
Define your routes using the `localizedRoutes` macro.
3938

@@ -65,22 +64,24 @@ Route::localizedRoutes(function () {
6564
}, ['web']);
6665
```
6766

68-
### Checking if Route is Already Localized
69-
You can easily check if your route name is already localized before generating or using it.
70-
```php
71-
@if (Route::isLocalized($name))
72-
// It returns TRUE if The route name is already localized (e.g., "en.blog.index")
73-
@endif
74-
```
75-
7667
This automatically generates localized routes like:
7768

78-
- `/en/about`
79-
- `/es/about`
80-
- `/de/about`
69+
- `/en/blog`
70+
- `/es/blog`
71+
- `/de/blog`
8172

8273
>The slug in the URL is required for the `setLocale` middleware, which changes the application language based on the `locale` slug.
8374
75+
76+
## 🧩 Checking if Route is Localized
77+
You can easily check if your route name is already localized:
78+
79+
```php
80+
@if (Route::isLocalized($name))
81+
// The route name is already localized (e.g., "en.blog.index")
82+
@endif
83+
```
84+
8485
### Blade usage
8586

8687
Generate a localized URL in Blade templates using `Route::localize()` method:
@@ -95,7 +96,8 @@ Or generate URLs with parameters:
9596
<a href="{{ Route::localize('blog.show', ['post' => $post]) }}">View Post</a>
9697
```
9798

98-
### Middleware: `SetLocaleMiddleware`
99+
## 🛡️ Middleware
100+
### 🧩 `localize.setLocale`
99101
Middleware to automatically detect and set the application locale based on the first segment of the URL.
100102

101103
Registered alias as `localize.setLocale`
@@ -140,13 +142,14 @@ Route::localizedRoutes(function () {
140142
```
141143
This is a simpler and more compact approach, especially useful for smaller projects.
142144

143-
### Middleware: `PaginatedMiddleware`
145+
### 🧩 `PaginatedMiddleware`
144146
Middleware that transforms paginated URLs by cleaning query parameters.
145147

146148
Registered alias as `localize.paginated`.
147149

148150
When a paginated route like `/page/{page?}` is used:
149151

152+
🛠 **Note**:
150153
* It ensures that the first page `blog/page/1` does not have a query string or URL segment like `/page/1`.
151154
* Instead, the first page URL is clean, such as `/blog`, improving SEO and URL readability.
152155
* If the user accesses `blog/page/2`, `blog/page/3`, etc., the page number remains in the URL.
@@ -172,7 +175,7 @@ If a user visits a URL with the default fallback locale (e.g., `/en/about` when
172175
This ensures clean URLs for your default language.
173176

174177

175-
### Configuration
178+
## ⚙️ Configuration
176179

177180
You can configure which languages are available and their corresponding URL slugs inside the `config/multilang-routes.php` file.
178181

@@ -225,43 +228,26 @@ interface LanguageProviderInterface
225228
```
226229
This gives you the flexibility to load languages from the database, API, or any other source.
227230

228-
Example of `app/Providers/DatabaseLanguageProvider.php`
231+
---
229232

230-
```php
231-
<?php
233+
## 📂 Examples
232234

233-
namespace App\Providers;
235+
You can find practical examples inside the [examples](./examples) folder:
234236

235-
use App\Contracts\LanguageProviderInterface;
236-
use App\Contracts\LanguageInterface;
237-
use App\Models\Language;
237+
- [ExampleController.php](examples/ExampleController.php)
238+
Simple controller with paginated navigation.
239+
240+
- [DatabaseLanguageProvider.php](examples/DatabaseLanguageProvider.php)
241+
Custom Language Provider loading languages from database.
242+
243+
- [RoutesExample.php](examples/RoutesExample.php)
244+
Localized routes registration example.
245+
246+
- [pagination.blade.php](examples/pagination.blade.php)
247+
Blade pagination rendering.
248+
249+
---
238250

239-
class DatabaseLanguageProvider implements LanguageProviderInterface
240-
{
241-
/**
242-
* @return array<LanguageInterface>
243-
*/
244-
public function getLanguages(): array
245-
{
246-
$languages = Language::all();
247-
248-
return array_map(function (Language $language) {
249-
return new \Alexwaha\Localize\Language(
250-
$language->locale,
251-
$language->slug,
252-
$language->is_default
253-
);
254-
}, $languages->all());
255-
}
256-
257-
public function getLocaleBySegment(?string $segment = null): string
258-
{
259-
$language = Language::where('slug', $segment)->first();
260-
261-
return $language?->locale ?? config('app.fallback_locale');
262-
}
263-
}
264-
```
265251

266252
## Requirements
267253

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* @author Alexander Vakhovski (AlexWaha)
4+
* @link https://alexwaha.com
5+
* @email support@alexwaha.com
6+
* @license MIT
7+
*/
8+
9+
namespace App\Providers;
10+
11+
use Alexwaha\Localize\Contracts\LanguageProviderInterface;
12+
use Alexwaha\Localize\Contracts\LanguageInterface;
13+
use App\Models\Language;
14+
15+
class DatabaseLanguageProvider implements LanguageProviderInterface
16+
{
17+
/**
18+
* @return array<LanguageInterface>
19+
*/
20+
public function getLanguages(): array
21+
{
22+
$languages = Language::all();
23+
24+
return array_map(function (Language $language) {
25+
return new \Alexwaha\Localize\Language(
26+
$language->locale,
27+
$language->slug,
28+
$language->is_default
29+
);
30+
}, $languages->all());
31+
}
32+
33+
/**
34+
* @param string|null $segment
35+
* @return string
36+
*/
37+
public function getLocaleBySegment(?string $segment = null): string
38+
{
39+
$language = Language::where('slug', $segment)->first();
40+
41+
return $language?->locale ?? config('app.fallback_locale');
42+
}
43+
}

examples/ExampleController.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* @author Alexander Vakhovski (AlexWaha)
4+
* @link https://alexwaha.com
5+
* @email support@alexwaha.com
6+
* @license MIT
7+
*/
8+
9+
namespace App\Http\Controllers;
10+
11+
use App\Models\Example;
12+
use Illuminate\Http\Request;
13+
14+
class ExampleController extends Controller
15+
{
16+
public function index(Request $request, int $page = 1)
17+
{
18+
$validated = $request->validate([
19+
'page' => ['nullable', 'integer', 'min:1'],
20+
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
21+
]);
22+
23+
$perPage = $validated['per_page'] ?? 15;
24+
25+
$results = Example::query()
26+
->paginate($perPage, ['*'], 'page', $page)
27+
->withQueryString();
28+
29+
return view('list', compact('results'));
30+
}
31+
}

examples/RoutesExample.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* @author Alexander Vakhovski (AlexWaha)
4+
* @link https://alexwaha.com
5+
* @email support@alexwaha.com
6+
* @license MIT
7+
*/
8+
9+
use Illuminate\Support\Facades\Route;
10+
11+
12+
Route::post('admin', [AdminController::class, 'index'])->name('admin');
13+
14+
Route::localizedRoutes(function () {
15+
Route::get('/', [HomeController::class, 'index'])->name('home');
16+
Route::get('about', [AboutController::class, 'index'])->name('about');
17+
18+
Route::name('blog.')->prefix('/blog')->group(function () {
19+
Route::get('', [BlogController::class, 'index'])->name('index');
20+
Route::get('/page/{page?}', [BlogController::class, 'index'])->name('paginated');
21+
Route::get('/{post}', [BlogController::class, 'show'])->name('show');
22+
});
23+
}, ['web', 'localize.setLocale', 'localize.paginated']);
24+

examples/pagination.blade.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
@if ($paginator->hasPages())
2+
<nav class="page-nav">
3+
<ul class="page-nav-list">
4+
@if ($paginator->currentPage() > 2)
5+
<li class="page-nav-item">
6+
<a class="page-nav-link"
7+
href="{{ Route::localize(request()->route()->getName(), ['page' => 1] + request()->except(['page'])) }}"
8+
aria-label="First">&laquo;</a>
9+
</li>
10+
@endif
11+
@if ($paginator->onFirstPage())
12+
<li class="page-nav-item page-nav-disabled" aria-disabled="true" aria-label="Prev">
13+
<span class="page-nav-link" aria-hidden="true">&lsaquo;</span>
14+
</li>
15+
@else
16+
<li class="page-nav-item">
17+
<a class="page-nav-link"
18+
href="{{ Route::localize(request()->route()->getName(), ['page' => $paginator->currentPage() - 1] + request()->except(['page'])) }}"
19+
rel="prev" aria-label="Prev">&lsaquo;</a>
20+
</li>
21+
@endif
22+
@foreach ($elements as $element)
23+
@if (is_string($element))
24+
<li class="page-nav-item page-nav-disabled" aria-disabled="true">
25+
<span class="page-nav-link">{{ $element }}</span>
26+
</li>
27+
@endif
28+
@if (is_array($element))
29+
@foreach ($element as $page => $url)
30+
@if ($page == $paginator->currentPage())
31+
<li class="page-nav-item page-nav-current" aria-current="page">
32+
<span class="page-nav-link">{{ $page }}</span>
33+
</li>
34+
@else
35+
<li class="page-nav-item">
36+
<a class="page-nav-link"
37+
href="{{ Route::localize(request()->route()->getName(), ['page' => $page] + request()->except(['page'])) }}">
38+
{{ $page }}
39+
</a>
40+
</li>
41+
@endif
42+
@endforeach
43+
@endif
44+
@endforeach
45+
@if ($paginator->hasMorePages())
46+
<li class="page-nav-item">
47+
<a class="page-nav-link"
48+
href="{{ Route::localize(request()->route()->getName(), ['page' => $paginator->currentPage() + 1] + request()->except(['page'])) }}"
49+
rel="next" aria-label="Next">&rsaquo;</a>
50+
</li>
51+
@else
52+
<li class="page-nav-item page-nav-disabled" aria-disabled="true" aria-label="Next">
53+
<span class="page-nav-link" aria-hidden="true">&rsaquo;</span>
54+
</li>
55+
@endif
56+
@php $lastPage = $paginator->lastPage(); @endphp
57+
@if ($paginator->currentPage() < $lastPage - 1)
58+
<li class="page-nav-item">
59+
<a class="page-nav-link"
60+
href="{{ Route::localize(request()->route()->getName(), ['page' => $lastPage] + request()->except(['page'])) }}"
61+
aria-label="Last">&raquo;</a>
62+
</li>
63+
@endif
64+
</ul>
65+
</nav>
66+
@endif

0 commit comments

Comments
 (0)