Package Data | |
---|---|
Maintainer Username: | pmochine |
Maintainer Contact: | mail@philippmochine.com (Philipp Mochine) |
Package Create Date: | 2018-07-14 |
Package Last Update: | 2023-03-10 |
Language: | PHP |
License: | MIT |
Last Refreshed: | 2024-11-19 03:18:31 |
Package Statistics | |
---|---|
Total Downloads: | 58,294 |
Monthly Downloads: | 45 |
Daily Downloads: | 0 |
Total Stars: | 40 |
Total Watchers: | 7 |
Total Forks: | 7 |
Total Open Issues: | 8 |
If you are looking for an easy package for subdomain multilingual urls, this package is for you. π
Old Way: https://example.com/de
, https://example.com/fr
etc.
New Way: https://de.example.com
, https://fr.example.com
etc.
*Prerequisites: PHP >=7.0 and at least 5.4 <= Laravel <=5.8
composer require pmochine/laravel-tongue
php artisan vendor:publish --provider="Pmochine\LaravelTongue\ServiceProvider" --tag="config"
Laravel Tongue comes with a middleware that can be used to enforce the use of a language subdomain. For example: the user calls example.com it goes directly to fr.example.com.
If you want to use it, open app/Http/kernel.php
and register this route middleware by adding it to the routeMiddleware
(down below) array:
...
'speaks-tongue' => \Pmochine\LaravelTongue\Middleware\TongueSpeaksLocale::class,
...
APP_DOMAIN=yourdomain.com #Only important for domains with many dots like: '155ad73e.eu.ngrok.io'
SESSION_DOMAIN=.yourdomain.com #Read down below why
Important! Note the dot before the domain name. Now the session is availabe in every subdomain π. This is important, because you want to save all your cookie πͺ data in one place and not in many other.
*Note! π This step is optional if you use laravel>=5.5 with package auto discovery feature. Add service provider to
config/app.php
inproviders
sectionPmochine\LaravelTongue\ServiceProvider::class,
Open app/Providers/RouteServiceProvider.php
and add this
public function boot()
{
// This will guess a locale from the current HTTP request
// and set the application locale.
tongue()->detect();
//If you use Carbon you can set the Locale right here.
\Carbon\Carbon::setLocale(tongue()->current());
parent::boot();
}
...
Once you have done this, there is nothing more that you MUST do. Laravel application locale has been set and you can use other locale-dependant Laravel components (e.g. Translation) as you normally do.
If you want to enforce the use of a language subdomain for some routes, you can simply assign the middleware provided, for example as follows in routes/web.php
:
// Without the localize middleware, this route can be reached with or without language subdomain
Route::get('logout', 'AuthController@logout');
// With the localize middleware, this route cannot be reached without language subdomain
Route::group([ 'middleware' => [ 'speaks-tongue' ]], function() {
Route::get('welcome', 'WelcomeController@index');
});
For more information about Middleware, please refer to Laravel docs.
<!doctype html>
<html lang="{{tongue()->current()}}" dir="{{tongue()->leftOrRight()}}">
<head>
@include('layouts.head')
</head>
<body>
...
The above <html>
tag will always have a supported locale and directionality (βltrβ or βrtlβ). The latter is important for right-to-left languages like Arabic and Hebrew, since the whole page layout will change for those.
Once you have imported the config file, you will find it at config/localization.php
.
domain
(default: null
)You don't need to worry about this, only when you are using domains with multiple dots, like: 155ad73e.eu.ngrok.io
. Without it, we cannot check what your subdomain is.
beautify_url
(default: true
)Makes the URL BEAUTIFUL πββοΈ. ( Use to set fallback language to mydomain.com and not to en.mydomain.com). That is why I even created this package. I just could not find this! π
subdomains
(default: []
)Sometimes you would like to have your admin panel as a subdomain url. Here you can whitelist those subdomains (only important if those urls are using the middleware).
aliases
(default: []
)
Sometimes you would like to specify aliases to use custom subdomains instead of locale codes. For example: gewinnen.domain.com --> "de"
gagner.domain.com --> "fr",
acceptLanguage
(default: true
)Use this option to enable or disable the use of the browser π» settings during the locale detection.
cookie_localization
(default: true
)Use this option to enable or disable the use of cookies πͺ during the locale detection.
prevent_redirect
(default: false
)Important for debugging, when you want to deactivate the middelware speaks-tongue
.
supportedLocales
(default: π¬π§π©πͺπͺπΈπ«π·ππΊ
)Don't say anyone that I copied it from mcamara π€«
If you want to use translated routes (en.yourdomain.com/welcome, fr.yourdomain.com/bienvenue), proceed as follows:
First, create language files for the languages that you support:
resources/lang/en/routes.php
:
return [
// route name => route translation
'welcome' => 'welcome',
'user_profile' => 'user/{username}',
];
resources/lang/fr/routes.php
:
return [
// route name => route translation
'welcome' => 'bienvenue',
'user_profile' => 'utilisateur/{username}',
];
Then, here is how you define translated routes in routes/web.php
:
Route::group([ 'middleware' => [ 'speaks-tongue' ]], function() {
Route::get(dialect()->interpret('routes.welcome'), 'WelcomeController@index');
});
You can of course name the language files as you wish, and pass the proper prefix (routes. in the example) to the interpret() method.
This package provides useful helper functions that you can use - for example - in your views:
<a href="{{ dialect()->current('fr') }}">See the french version</a>
@foreach (dialect()->translateAll() as $locale => $url)
<a href="{{ $url }}">{{ $locale }}</a>
@endforeach
You can pass false
as parameter so it won't explude the current URL.
<a href="{{ dialect()->translate('user_profile', [ 'username' => 'JohnDoe' ], 'fr') }}">See JohnDoe's profile</a>
Use dialect()->translate($routeName, $routeAttributes = null, $locale = null)
to generate an alternate version of the given route. This will return an url with the proper subdomain and also translate the uri if necessary.
You can pass route parameters if necessary. If you don't give a specific locale, it will use the current locale βΊοΈ.
$collection = tongue()->speaking(); //returns collection
Remember it returns a collection. You can add methods to it (see available methods) Examples:
$keys = tongue()->speaking()->keys()->all(); //['en','de',..]
$sorted = tongue()->speaking()->sort()->all(); //['de','en',..]
Additionally, you can even get some addtional information:
tongue()->speaking('BCP47', 'en'); // en-GB
tongue()->speaking('subdomains'); // ['admin']
tongue()->speaking('subdomains', 'admin'); // true
tongue()->speaking('aliases'); // ['gewinnen' => 'de', 'gagner' => 'fr]
tongue()->speaking('aliases', 'gewinnen'); //' de'
$locale = tongue()->current(); //de
Or if you like you can get the full name, the alphabet script, the native name of the language & the regional code.
$name = tongue()->current('name'); //German
$script = tongue()->current('script'); //Latn
$native = tongue()->current('native'); //Deutsch
$regional = tongue()->current('regional'); //de_DE
For example with a selector:
<ul>
@foreach(tongue()->speaking()->all() as $localeCode => $properties)
<li>
<a rel="alternate" hreflang="{{ $localeCode }}" href="dialect()->current($localeCode)">
{{ $properties['native'] }}
</a>
</li>
@endforeach
</ul>
Or in a controller far far away...
/**
* Sets the locale in the app
* @return redirect to previous url
*/
public function store()
{
$locale = request()->validate([
'locale' => 'required|string|size:2'
])['locale'];
return tongue()->speaks($locale)->back();
}
There are little changes that might be important for you.
domain
and aliases
. Add these like here.APP_DOMAIN
in your .env if you have a complicated domain, like: 155ad73e.eu.ngrok.io
gewinnen.domain.com --> "de"
If you discover any security related issues, please don't email me. I'm afraid π±. avidofood@protonmail.com
Now comes the best part! π This package is based on
Oh come on. You read everything?? If you liked it so far, hit the βοΈ button to give me a π€© face.