Did you do a php artisan config:cache ?
app->getLocale() returns empty
Hello,
I'm currently adding localization and translations to my app.
Using mcamara/laravel-localization package, I'm adding a prefix to all my routes that set the locale, so it should work something like this:
myappurl.com/{locale}/something
If they for some reason come without the prefix, I would like to use the default locale variable, so I'm trying something like this in my web.php
Route::get('/', function(){
return redirect(app()->getLocale());
});
However, my app()->getLocale() doesn't return anything. My config/app.php contains this:
'locale' => 'no',
'fallback_locale' => 'no',
What am I missing here?
@vincent15000 So I've actually getting errors when I'm trying to do that.
"Laravel default locale is not in the supportedLocales array. {"exception":"[object] (Mcamara\LaravelLocalization\Exceptions\UnsupportedLocaleException(code: 0)"
Looks like a related issue. Since I'm not getting locale or fallback_locale from the config, the LaravelLocalization package throws an error, because default locale returns empty as well (and that's not a supportedLocale).
Any error in your logs?
config/app.php has the good rights?
rename it to be sure it is called ...
@sr57 Renaming config/app.php gives me a new error. "Fatal error: Uncaught RuntimeException: A facade root has not been set" So it looks like it's reading from the file.
The error I'm getting in my logs are:
"Laravel default locale is not in the supportedLocales array. {"exception":"[object] (Mcamara\LaravelLocalization\Exceptions\UnsupportedLocaleException(code: 0)"
Basically fallback_locale and locale return empty when I go to myapprurl.com/
If I add myapprurl.com/{locale} They return the locale value.
https://github.com/mcamara/laravel-localization#usage
The package sets your application locale App::getLocale() according to your url.
You've got the cause.
@sr57 but shouldn't App::getLocale() be my default locale (fallback) when url doesn't contain locale?
readme says, // Set application language to English or Spanish (depending on browsers default locales) // if nothing found set to default locale http://url-to-laravel http://url-to-laravel/test
Did you publish the config?
In order to edit the default configuration you may execute:
php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"
@sr57 Yes, I have published the config for the package.
Strange ... I did a test, can you do the same
in config/app.php : locale & fallback_local = en
app()->getLocale()
// en
in config/config/laravellocalization.php I comment en , ie just let es
app()->getLocale()
gives me this error " Laravel default locale is not in the supportedLocales array."
Same for you?
@sr57 Yes, if my locale and fallback_locale is set to en in config/app.php, and in config/laravellocalization.php I comment out en and keep es, I get the same error if my URL does not contain a locale.
Ok, good.
It should be a config of your routes, default route(s) are chosen except if they not defined by themselves.
In your web.php comment out all your routes except the "localized" and test ...
@sr57 So for testing, this is my entire web.php atm
<?php
use App\Http\Controllers\StoreController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::group([
'prefix' => LaravelLocalization::setLocale(),
'middleware' => [ 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath' ]], function () {
Route::get('/', [StoreController::class, 'getIndex'])->name('home');
});
myappurl.com/en shows the page in english, myappurl.com/no shows the page in norwegian, however, myappurl.com/ still gives me
Laravel default locale is not in the supportedLocales array.
I want it to redirect to my default locale. Am I just reading the documentation of this package wrong?
Am I just reading the documentation of this package wrong?
It works well here.
You default locale are 'en' or 'no' in config/app.php ?
and from the doc your routes should be
Route::group(['prefix' => LaravelLocalization::setLocale()], function()
{
/** ADD ALL LOCALIZED ROUTES INSIDE THIS GROUP **/
...
});
@sr57 This is from my config/app.php
'locale' => 'en',
'locales' => [
'en' => 'English',
'se' => 'Swedish',
'no' => 'Norwegian',
'dk' => 'Danish',
'is' => 'Icelandic',
],
/**
* Let's also add a all_langs array
*/
'all_langs' => ['en', 'se', 'no', 'dk', 'is'],
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'fallback_locale' => 'en',
If it works well for you, then I have a feeling there might be some other middleware or package messing with my apps default locale.
Maybe but you should find the cause.
Have test to code the routes exactly as the doc?
you can test on fresh install of Laravel
you can check how the default route is (or is not) created but the framework. Using dump and the package https://github.com/beyondcode/laravel-dump-server is not difficult and educational.
@sr57 I've tried to set up the routes just as the docs, yes.
What's a little bit strange is, if I go into vendor/mcamara/laravel-localization/mcmara/laravelLocalization/LaravelLocalization.php and add a bit of debugging to the contstuct like this
/**
* Creates new instance.
*
* @throws UnsupportedLocaleException
*/
public function __construct()
{
$this->app = app();
$this->configRepository = $this->app['config'];
$this->view = $this->app['view'];
$this->translator = $this->app['translator'];
$this->router = $this->app['router'];
$this->request = $this->app['request'];
$this->url = $this->app['url'];
// set default locale
$this->defaultLocale = $this->configRepository->get('app.locale');
$this->fallbackLocale = $this->configRepository->get('app.fallback_locale');
$supportedLocales = $this->getSupportedLocales();
//dd($supportedLocales);
Log::debug("Default Locale: " . $this->defaultLocale);
Log::debug("fallback_locale: " . $this->fallbackLocale);
if (empty($supportedLocales[$this->defaultLocale])) {
throw new UnsupportedLocaleException('Laravel default locale is not in the supportedLocales array.');
}
}
My laravel.log gets this
[2022-04-06 13:07:15] local.DEBUG: Default Locale:
[2022-04-06 13:07:15] local.DEBUG: fallback_locale: en
So it's able to read the fallback_locale from the config file, but my locale is just empty. I'll test the dump-server package you are recommending and see if I can figure out what's going on
For you information I have no file vendor/mcamara/laravel-localization/mcmara/laravelLocalization/LaravelLocalization.php
but : vendor/mcamara/laravel-localization/src/Mcamara/LaravelLocalization/LaravelLocalization.php
Which version of Laravel do you use?
Can you share your composer.json?
Have you run composer update? (dev app)
@sr57 my file is the same location as you mentioned. I manually typed it, and just mistyped.
I'm on Laravel 9.5. This was originally an app running an older version of Laravel (4.5 I think) and I used Laravel Shift to upgrade it to the latest. Maybe some of the automation steps did something strange. Not sure.
Here's my composer.json
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"type": "project",
"require": {
"laravel/framework": "^9.5",
"laravel/tinker": "^2.7",
"intervention/image": "dev-master",
"laravelcollective/html": "^6.3",
"guzzlehttp/guzzle": "^7.2",
"predis/predis": "^1.1",
"cviebrock/eloquent-sluggable": "^9.0",
"picqer/php-barcode-generator": "^2.2",
"php": "^7.3|^8.0",
"laravel/ui": "^3.4",
"league/flysystem-aws-s3-v3": "^3.0",
"barryvdh/laravel-translation-manager": "^0.6.3",
"mcamara/laravel-localization": "^1.7"
},
"require-dev": {
"mockery/mockery": "^1.4.4",
"phpunit/phpunit": "^9.5.10",
"nunomaduro/collision": "^6.1",
"fakerphp/faker": "^1.9.1",
"spatie/laravel-ignition": "^1.0",
"beyondcode/laravel-dump-server": "^1.8"
},
"autoload": {
"classmap": [
"app/models",
"app/Http/Controllers"
],
"psr-4": {
"App\": "app/",
"Database\Factories\": "database/factories/",
"Database\Seeders\": "database/seeders/"
}
},
"autoload-dev": {
"classmap": [
"tests/TestCase.php"
]
},
"scripts": {
"post-install-cmd": [
"@php artisan clear-compiled",
"@php artisan optimize"
],
"post-update-cmd": [
"@php artisan clear-compiled",
"@php artisan optimize",
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-create-project-cmd": [
"@php -r \"copy('.env.example', '.env');\"",
"@php artisan key:generate --ansi"
],
"post-autoload-dump": [
"Illuminate\Foundation\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
]
},
"config": {
"preferred-install": "dist",
"optimize-autoloader": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"laravel": {
"dont-discover": []
}
}
}
yes, I have ran composer update
I did the test on Laravel 8.82
@sr57 So I put this issue on hold for a bit (since I was stuck, and couldn't figure out what was going on), but started debugging a bit yesterday again.
Now, I actually don't think it has anything to do with the laravel-localization package.
I created a very simple web.php file:
<?php
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
$this->app = app();
Log::debug("Current Locale: " . App::currentLocale());
dd($this->app['config']);
});
Route::get('/no', function () {
$this->app = app();
Log::debug("Current Locale: " . App::currentLocale());
dd($this->app['config']);
});
Route::get('/checkout', function () {
$this->app = app();
Log::debug("Current Locale: " . App::currentLocale());
dd($this->app['config']);
});
Here I'm not using any custom middleware, but the local variable is still being set to the first segment of the url.
[2022-04-12 01:46:31] local.DEBUG: Current Locale:
[2022-04-12 01:47:14] local.DEBUG: Current Locale: no
[2022-04-12 01:48:34] local.DEBUG: Current Locale: checkout
This is my Kernel.php file
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'admin' => \App\Http\Middleware\Admin::class,
'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
];
}
Is there a good method to figure out what is changing my app.config.locale value?
Hello @simonjolsen
I suggest to make the exact same tests and try to figure out what is the cause.
Let's begin by this web.php
Route::group(['prefix' => LaravelLocalization::setLocale()], function()
{
Route::get('test',function(){
return("Test locale=".App::currentLocale());
});
});
and my results
test -> Test locale=en
en/test -> Test locale=en
xx -> 404
xx/test -> 404
@sr57 My results:
test -> Test locale=test
en/test -> Test locale=en
xx/test -> 404
OK, your pb is well defined (as it was before)
config the same app.php then me for locale
cat config/app.php | grep locale
| The application locale determines the default locale that will be used
| to any of the locales which will be supported by the application.
'locale' => 'en',
| The fallback locale determines the locale to use when the current one
'fallback_locale' => 'en',
| This locale will be used by the Faker PHP library when generating fake
'faker_locale' => 'en_US',
and redo the tests
Updated my config, so this is what I get when grep
| The application locale determines the default locale that will be used
| to any of the locales which will be supported by the application.
'locale' => 'en',
'locales' => [
| The fallback locale determines the locale to use when the current one
'fallback_locale' => 'en',
then ran
php artisan config:cache
But I'm still getting the same results.
test -> Test locale=test
en/test -> Test locale=en
xx/test -> 404
@sr57 Updated my app.config to match. This is my grep
| The application locale determines the default locale that will be used
| to any of the locales which will be supported by the application.
'locale' => 'en',
| The fallback locale determines the locale to use when the current one
'fallback_locale' => 'en',
'faker_locale' => 'en_US',
Still, same results
Read the documentation of that package one more time!
https://github.com/mcamara/laravel-localization#recommendations
@MichalOravec What am I missing? My Route group looks like this.
Route::group([
'prefix' => LaravelLocalization::setLocale(),
'middleware' => [ 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath' ]], function () {...
LocaleSessionRedirect Whenever a locale is present in the url, it will be stored in the session by this middleware. In there is no locale present in the url, then this middleware will check the following
If no locale is saved in session and useAcceptLanguageHeader is set to true, compute locale from browser and redirect to url with locale.
If a locale is saved in session redirect to url with locale, unless its the default locale and hideDefaultLocaleInURL is set to true.
For example, if a user navigates to http://url-to-laravel/test and en is the current locale, it would redirect him automatically to http://url-to-laravel/en/test.
In my config/laravellocalization.php hideDefaultLocaleInURL is set to false, and useAcceptLanguageHeader is set to true.
https://github.com/mcamara/laravel-localization#register-middleware
and this
Route::prefix(LaravelLocalization::setLocale())->middleware(['localize', 'localeSessionRedirect', 'localizationRedirect'])->group(function () {
Route::get('/', function() {
return views('home'); // just an example
});
// other routes
});
@MichalOravec I had this in my Route::group
Route::get(trans('routes.home'), [StoreController::class, 'getIndex'])->name('home');
So I thought that was the same thing?
Route::prefix(LaravelLocalization::setLocale())->middleware(['localize', 'localeSessionRedirect', 'localizationRedirect'])->group(function () {
Route::get('/', [StoreController::class, 'getIndex'])->name('home');
});
This still doesn't redirect to my default locale (I'm getting the same error).
@simonjolsen Read the documentation of that package!
Bye!
Put my answer at the end of this thread to be easier to follow
What's this line "'faker_locale' => 'en_US'," that appeared ! ?
A typo? Please remove it and redo the tests.
@sr57 I just added it to match your file.
Removed it, and this it my result from cat config/app.php | grep locale
| The application locale determines the default locale that will be used
| to any of the locales which will be supported by the application.
'locale' => 'en',
| The fallback locale determines the locale to use when the current one
'fallback_locale' => 'en',
When I redo the test, I get the same results as before.
SORRY, I did not noticed this line in my file! I remove it also.
cat config/laravellocalization.php | grep -v "//"
<?php
return [
'supportedLocales' => [
'en' => ['name' => 'English', 'script' => 'Latn', 'native' => 'English', 'regional' => 'en_GB'],
'es' => ['name' => 'Spanish', 'script' => 'Latn', 'native' => 'español', 'regional' => 'es_ES'],
],
'useAcceptLanguageHeader' => true,
'hideDefaultLocaleInURL' => false,
'localesOrder' => [],
'localesMapping' => [],
'utf8suffix' => env('LARAVELLOCALIZATION_UTF8SUFFIX', '.UTF-8'),
'urlsIgnored' => ['/skipped'],
'httpMethodsIgnored' => ['POST', 'PUT', 'PATCH', 'DELETE'],
];
@sr57 Yes I have the same.
But like I mentioned earlier, I'm pretty sure this is nothing with the laravel-localization package.
Even if I remove it, and run an extremely basic web.php with no prefix or middleware, my apps default locale is being set by the first segment of the url. I'm having trouble figuring out what's currently changing the app.config.locale value.
Yes, I read it , I just wanted to be sure we have the same config.
So my new web.php
Route::get('test',function(){
return("Test locale=".App::currentLocale());
});
and my result
test -> Test locale=en
en/test -> 404
in vendor/laravel/framework/src/Illuminate/Foundation/Application.php getLocale
dump($this['config']['app']['locale']);
// -> en for me
with dump-server or use your debug logs
So when I reload myapp.test/test
from my debug log, it seems like getLocale is called 3 times, because I get this:
[2022-04-12 11:51:55] local.DEBUG: getLocale in Foundation en
[2022-04-12 11:51:55] local.DEBUG: getLocale in Foundation test
[2022-04-12 11:51:55] local.DEBUG: getLocale in Foundation test
So it starts out correct, and something is changing it afterwards.
OK, we are on the way, I have to leave until evening ... try to figure our why this 2 more calls
@sr57 Well, one of the extra get calls was from the route (App::currentLocale())
But I'm pretty sure I found the culprit. After some more debugging, I found this in my AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(Request $request)
{
app()->setLocale($request->segment(1));
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
This is an old app, that used to be Laravel 4.2, and I used Laravel Shift to get it to the latest version. Not sure when or why that was added, but I'm pretty sure this is what was messing with my app.
my AppServiceProvider (Laravel 8)
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
seems you got it ...
Thanks to Laravel as open source project by Taylor Otwell
Please or to participate in this conversation.