Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,57 @@ return [

This section is currently under construction.


## Caching Routes
If you want to cache the routes in all languages, you will need to use special Artisan commands. **Using `artisan route:cache`** will not work correctly!

### Setup

For the route caching solution to work, it is required to make a minor adjustment to your application route provision.

In your App's `RouteServiceProvider`, use the `LoadsTranslatedCachedRoutes` trait:

```php
<?php
class RouteServiceProvider extends ServiceProvider
{
use \RichanFongdasen\I18n\Traits\LoadsTranslatedCachedRoutes;

```


### Usage

To cache your routes, use:

``` bash
php artisan route:trans:cache
```

... instead of the normal `route:cache` command.

To list the routes for a given locale, use

``` bash
php artisan route:trans:list {locale}
# for instance:
php artisan route:trans:list en
```

To clear cached routes for all locales, use

``` bash
php artisan route:trans:clear
```

#### Note

Using `route:clear` will also effectively unset the cache but not locale cache (at the minor cost of leaving some clutter in your bootstrap/cache directory).





## Credits

* [mcamara/laravel-localization](https://github.com/mcamara/laravel-localization) - Route localization concepts in this repository was inspired by this package.
Expand Down
138 changes: 138 additions & 0 deletions src/Commands/RouteTranslationsCacheCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php

namespace RichanFongdasen\I18n\Commands;

use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Routing\RouteCollection;
use RichanFongdasen\I18n\Traits\TranslatedRouteCommandContext;

class RouteTranslationsCacheCommand extends Command
{
use TranslatedRouteCommandContext;

/**
* @var string
*/
protected $name = 'route:trans:cache';

/**
* @var string
*/
protected $description = 'Create a route cache file for faster route registration for all locales';

/**
* The filesystem instance.
*
* @var Filesystem
*/
protected $files;

/**
* Create a new route command instance.
*
* @param Filesystem $files
*/
public function __construct(Filesystem $files)
{
parent::__construct();

$this->files = $files;
}

/**
* Execute the console command.
*/
public function handle()
{
$this->call('route:trans:clear');

$this->cacheRoutesPerLocale();

$this->info('Routes cached successfully for all locales!');
}

/**
* Cache the routes separately for each locale.
*/
protected function cacheRoutesPerLocale()
{
// Store the default routes cache,
// this way the Application will detect that routes are cached.
$allLocales = array_keys($this->getSupportedLocales());

array_push($allLocales, null);

foreach ($allLocales as $locale) {
$routes = $this->getFreshApplicationRoutes($locale);

if (count($routes) == 0) {
$this->error("Your application doesn't have any routes.");

return;
}

foreach ($routes as $route) {
$route->prepareForSerialization();
}

$this->files->put(
$this->makeLocaleRoutesPath($locale), $this->buildRouteCacheFile($routes)
);
}
}

/**
* Boot a fresh copy of the application and get the routes.
*
* @param string|null $locale
*
* @return \Illuminate\Routing\RouteCollection
*/
protected function getFreshApplicationRoutes($locale = null)
{
$key = $this->getLocaleEnvKey();
if (null !== $locale) {
putenv("{$key}={$locale}");
}
$app = require $this->getBootstrapPath().'/app.php';
$app->make(Kernel::class)->bootstrap();
$routes = $app['router']->getRoutes();
putenv("{$key}");

return $routes;
}

/**
* Build the route cache file.
*
* @param \Illuminate\Routing\RouteCollection $routes
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*
* @return string
*/
protected function buildRouteCacheFile(RouteCollection $routes)
{
$stub = $this->files->get(
realpath(
__DIR__
.DIRECTORY_SEPARATOR.'..'
.DIRECTORY_SEPARATOR.'..'
.DIRECTORY_SEPARATOR.'stubs'
.DIRECTORY_SEPARATOR.'routes.stub'
)
);

return str_replace(
[
'{{routes}}',
],
[
base64_encode(serialize($routes)),
],
$stub
);
}
}
61 changes: 61 additions & 0 deletions src/Commands/RouteTranslationsClearCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace RichanFongdasen\I18n\Commands;

use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use RichanFongdasen\I18n\Traits\TranslatedRouteCommandContext;

class RouteTranslationsClearCommand extends Command
{
use TranslatedRouteCommandContext;
/**
* The console command name.
*
* @var string
*/
protected $name = 'route:trans:clear';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Remove the translated route cache files for each locale';
/**
* The filesystem instance.
*
* @var \Illuminate\Filesystem\Filesystem
*/
protected $files;

/**
* Create a new route clear command instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
*/
public function __construct(Filesystem $files)
{
parent::__construct();
$this->files = $files;
}

/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
foreach ($this->getSupportedLocales() as $locale => $localeValue) {
$path = $this->makeLocaleRoutesPath($locale);
if ($this->files->exists($path)) {
$this->files->delete($path);
}
}
$path = $this->laravel->getCachedRoutesPath();
if ($this->files->exists($path)) {
$this->files->delete($path);
}
$this->info('Route caches for locales cleared!');
}
}
92 changes: 92 additions & 0 deletions src/Commands/RouteTranslationsListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace RichanFongdasen\I18n\Commands;

use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Console\RouteListCommand;
use RichanFongdasen\I18n\Traits\TranslatedRouteCommandContext;
use Symfony\Component\Console\Input\InputArgument;

class RouteTranslationsListCommand extends RouteListCommand
{
use TranslatedRouteCommandContext;

/**
* @var string
*/
protected $name = 'route:trans:list';

/**
* @var string
*/
protected $description = 'List all registered routes for specific locales';

/**
* Execute the console command.
*/
public function handle()
{
$locale = $this->argument('locale');

if (!$this->isSupportedLocale($locale)) {
return $this->error("Unsupported locale: '{$locale}'.");
}

$this->displayRoutes($this->getLocaleRoutes($locale));
}

/**
* Compile the locale routes into a displayable format.
*
* @return array
*/
protected function getLocaleRoutes($locale)
{
$routes = $this->getFreshApplicationRoutes($locale);

$routes = collect($routes)->map(function ($route) {
return $this->getRouteInformation($route);
})->filter()->all();

if ($sort = $this->option('sort')) {
$routes = $this->sortRoutes($sort, $routes);
}

if ($this->option('reverse')) {
$routes = array_reverse($routes);
}

return $this->pluckColumns($routes);
}

/**
* Boot a fresh copy of the application and get the routes.
*
* @param string $locale
*
* @return \Illuminate\Routing\RouteCollection
*/
protected function getFreshApplicationRoutes($locale)
{
$key = $this->getLocaleEnvKey();
putenv("{$key}={$locale}");
$app = require $this->getBootstrapPath().'/app.php';
$app->make(Kernel::class)->bootstrap();
$routes = $app['router']->getRoutes();
putenv("{$key}");

return $routes;
}

/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['locale', InputArgument::REQUIRED, 'The locale to list routes for.'],
];
}
}
7 changes: 6 additions & 1 deletion src/I18nService.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

class I18nService
{
/**
* The env key that the forced locale for routing is stored in.
*/
const ENV_ROUTE_KEY = 'I18N_ROUTING_LOCALE';

/**
* I18n configuration.
*
Expand Down Expand Up @@ -75,7 +80,7 @@ public function __construct(Request $request)
*/
public function defaultLocale()
{
$fallback = $this->getConfig('fallback_language');
$fallback = env(static::ENV_ROUTE_KEY, $this->getConfig('fallback_language'));
$locale = $this->getLocale($fallback);

if (!$locale instanceof Locale) {
Expand Down
Loading