simonjolsen89's avatar

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?

0 likes
45 replies
simonjolsen89's avatar

@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).

sr57's avatar

Any error in your logs?

config/app.php has the good rights?

rename it to be sure it is called ...

simonjolsen89's avatar

@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.

sr57's avatar

@simonjolsen

Did you publish the config?

In order to edit the default configuration you may execute:

php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"

sr57's avatar

@simonjolsen

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?

simonjolsen89's avatar

@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.

sr57's avatar

@simonjolsen

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 ...

simonjolsen89's avatar

@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?

sr57's avatar

@simonjolsen

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 **/
   ...
});
simonjolsen89's avatar

@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.

simonjolsen89's avatar

@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

sr57's avatar

@simonjolsen

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)

simonjolsen89's avatar

@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

simonjolsen89's avatar

@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?

sr57's avatar

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
simonjolsen89's avatar

@sr57 My results:

test -> Test locale=test 
en/test -> Test locale=en
xx/test -> 404
sr57's avatar

@simonjolsen

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

simonjolsen89's avatar

@sr57

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 
simonjolsen89's avatar

@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

simonjolsen89's avatar

@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.

simonjolsen89's avatar

@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).

sr57's avatar

@simonjolsen

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.

simonjolsen89's avatar

@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.

sr57's avatar

@simonjolsen

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'],
];
simonjolsen89's avatar

@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.

sr57's avatar

@simonjolsen

So my new web.php

	Route::get('test',function(){
		return("Test locale=".App::currentLocale());
	});

and my result

test -> Test locale=en
en/test -> 404
simonjolsen89's avatar

@sr57 with the same web.php

My results are

test -> Test locale=test
en/test -> 404
sr57's avatar

@simonjolsen

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

simonjolsen89's avatar

@sr57

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.

sr57's avatar

@simonjolsen

OK, we are on the way, I have to leave until evening ... try to figure our why this 2 more calls

simonjolsen89's avatar

@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.

sr57's avatar
sr57
Best Answer
Level 39

@simonjolsen

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 ...

Please or to participate in this conversation.