Welcome Guest, Not a member yet? Register   Sign In
setLocale() doesn't change the language set by browser
#1
Question 
(This post was last modified: 04-07-2020, 06:02 AM by blackrabbit.)

Hello everybody



I'm new to CI and to any framework and it's just awesome! Heart 
I'm not used to write in forums as I'm usualy allways able to find a solution already posted somewhere so it's my first time in 20 years of IT. Big Grin So I hope my english is ok as the rules say "proper english only" and I correctly explain my problem.



So to my problem:

I'm making a bilingual site french/german with CMS features so I use bilingual db's and the CI locale feature.



The language recognition of browsers works fine but I'm unable to change the language through



$this->request->setLocale($language);

or

setlocale(LC_ALL, $language);



when I control it with getLocale() I can see that setLocale() works but there is no change in the views...



in Config/App.php

public $defaultLocale = 'de';

public $negotiateLocale = true;

public $supportedLocales = ['de-CH','de-DE','de-AT','fr-CH','fr-FR','fr-CA','fr-BE','fr','de'];      ( tryed also ['de','fr'] )



my switchlanguage-button calls Language.php Controller with:

PHP Code:
<?php namespace App\Controllers;
use 
CodeIgniter\HTTP\IncomingRequest;

class 
Language extends BaseController
{
    public function 
setLanguage($language)
    {
        
$session = \Config\Services::session();
        
$session->set('language',$language);
        
$this->request->setLocale($language);
        
$session->set('locale',$this->request->getLocale());
        
/*setlocale(LC_ALL, $language);*/
        
return redirect()->back();
    }



I'm using session('language') to select the right columns in the db's and the locale for all the titles, bottons, validation errors and more...




in BaseController.php I got:

PHP Code:
$session = \Config\Services::session();
if (
session('language') == null) {
    
$locale $this->request->getLocale();
    
$language substr($locale02);
    
$session->set('language',$language);
    
$session->set('locale',$locale); /*<-this only for debuging*/



Can you see where I'm wrong? I can't find a solution. CI locale strictly follows the Browsers properties and I can't change it...
I'm sure it's something stupid Wink


thank you
Reply
#2
Tongue 

I still don't know if setlocal() should change the selected language used by the language files or if it was just my immagination...

So I finaly did manualy insert the language variable in all the lang() functions like that:
Code:
<?= lang('Titles.titleStundenplan', [],$language)?>

The only problem now is for the validation error language who strictly follows the user properties set in browser. I don't know how to change that manualy.

any help would be apreciated...
Reply
#3

(This post was last modified: 04-26-2020, 10:50 AM by thingNumber1.)

To set the language you need to do this:

PHP Code:
$language = \Config\Services::language();
$language->setLocale($real_language); 

That way you won't need to set the language every single time. Also, I think that this function would do the validation for you.
Reply
#4

Thank you but it's still not working.....
Checking with $language->getLocale() I see it's changing but in the lang() function it doesn't nor for validation...

PHP Code:
public function setLanguage($real_language)
 {
    $language = \Config\Services::language();
    $language->setLocale($real_language); 

    /*just for debuging*/
    $session = \Config\Services::session();
    $session->set('language',$real_language);
    $session->set('locale',$language->getLocale());

return 
redirect()->back();

Reply
#5

Hello,

I know this thread is a little bit old but have faced the same problem in CI4, i'm not an expert, solved it this way

Have created a filter in App\Filters\Locale.php
PHP Code:
<?php namespace App\Filters;

use 
CodeIgniter\HTTP\RequestInterface;
use 
CodeIgniter\HTTP\ResponseInterface;
use 
CodeIgniter\Filters\FilterInterface;

class 
Locale implements FilterInterface
{
    public function before(RequestInterface $request$arguments null)
    {
        if (session()->has('locale'))
        {
            // Set site language to session locale value
            service('language')->setLocale(session('locale'));
        }
        else
        {
            // Save locale to session
            session()->set('locale'service('language')->getLocale());
        }
    }

    //--------------------------------------------------------------------

    public function after(RequestInterface $requestResponseInterface $response$arguments null)
    {
        // Do something here
    }


Activate the filter for every request in Config\Filters
PHP Code:
    // Makes reading things below nicer,
    // and simpler to change out script that's used.
    
public $aliases = [
        
'csrf'     => \CodeIgniter\Filters\CSRF::class,
        
'toolbar'  => \CodeIgniter\Filters\DebugToolbar::class,
        
'honeypot' => \CodeIgniter\Filters\Honeypot::class,
        
'locale'   => \App\Filters\Locale::class
    ];

    
// Always applied before every request
    
public $globals = [
        
'before' => [
            
'honeypot',
            
'csrf',
            
'locale',
        ],
        
'after'  => [
            
'toolbar',
            
'honeypot'
        
],
    ]; 

A controller to allow user to change language
PHP Code:
<?php namespace App\Controllers;

use 
CodeIgniter\Controller;

/**
 * Change site locale to requested one
 */
class Locale extends Controller
{
    // Set application wide locale
    public function setstring $locale )
    {
        
// Check requested language exist in \Config\App
        
if ( in_array($localeconfig('App')->supportedLocales) )
        {
            
// Save requested locale in session, will be set by filter
            
session()->set('locale'$locale);

            
// Reload page
            
return redirect()->back();
        }
        else
        {
            throw new \CodeIgniter\Exceptions\PageNotFoundExceptionesc($locale) ." is not a supported language" );
        }
    }


Controller route
Code:
$routes->get('locale/(:segment)', 'Locale::set/$1');


My Config\App

PHP Code:
    public $defaultLocale 'fr';

    
/*
    |--------------------------------------------------------------------------
    | Negotiate Locale
    |--------------------------------------------------------------------------
    |
    | If true, the current Request object will automatically determine the
    | language to use based on the value of the Accept-Language header.
    |
    | If false, no automatic detection will be performed.
    |
    */
    
public $negotiateLocale true;

    
/*
    |--------------------------------------------------------------------------
    | Supported Locales
    |--------------------------------------------------------------------------
    |
    | If $negotiateLocale is true, this array lists the locales supported
    | by the application in descending order of priority. If no match is
    | found, the first locale will be used.
    |
    */
    
public $supportedLocales = ['fr','en']; 

This way Codeigniter set locale to defined browser language automatically and user can use the controller to set another language.

View example to change language, with selected language flag auto update
Code:
<!-- Language dropdown -->
<div class="navbar-tool dropdown">
    <a class="topbar-link" data-toggle="dropdown" aria-expanded="false">
        <img width="20" src="/assets/img/flags/<?= session('locale') ?>.png" />
    </a>
    <ul class="dropdown-menu">
        <li>
            <a class="dropdown-item" href="/locale/en"><img width="20" src="/assets/img/flags/en.png" alt="English" />English</a>
        </li>
        <li>
            <a class="dropdown-item" href="/locale/fr"><img width="20" src="/assets/img/flags/fr.png" alt="Français" />Français</a>
        </li>
    </ul>
</div>

If anyone know a better way, any advises welcome  Wink
Reply
#6

Thank your eelisland!
I was calling service('language')->setLocale('currentLocale) just before calling the views, but that didn't work when the view has a link to another page. Your solution is much more elegant works all the time!
My only concern with your solution is that I am setting the locale at each method call, which is not necessary most of the time...
I just do not understand why there is not a way to set the current locale once for all, and why it gets reset all the time to the default or negotiated one.
I used to work with CakePHP and setting it once was enough.
Reply
#7

(07-27-2024, 09:02 AM)PhilInLoco Wrote: Thank your eelisland!
I was calling service('language')->setLocale('currentLocale) just before calling the views, but that didn't work when the view has a link to another page. Your solution is much more elegant works all the time!
My only concern with your solution is that I am setting the locale at each method call, which is not necessary most of the time...
I just do not understand why there is not a way to set the current locale once for all, and why it gets reset all the time to the default or negotiated one.
I used to work with CakePHP and setting it once was enough.

@PhilInLoco Glad you find my post usefull.

The question in my previous post still remain, maybe some CI guru here could help  Wink

"If anyone know a better way, please advises".
Reply
#8

PHP shares nothing between requests.
So if you keep something, you need to persist it with something like Session, Database, ....
So if you want to change the locale from the default one, you need to set it in every request.

service('language') gets the locale from the IncommingRequest instance.
So if you change the locale in IncommingRequest before the first call for service('language'),
the request locale is set.
Reply
#9

@eelisland I think you can move the following code to Event pre_system.
https://codeigniter.com/user_guide/exten...ent-points

PHP Code:
        if (session()->has('locale'))
        {
            // Set site language to session locale value
            service('language')->setLocale(session('locale'));
        }
        else
        {
            // Save locale to session
            session()->set('locale'service('language')->getLocale());
        
Reply
#10

(07-27-2024, 06:53 PM)kenjis Wrote: @eelisland I think you can move the following code to Event pre_system.
https://codeigniter.com/user_guide/exten...ent-points

PHP Code:
        if (session()->has('locale'))
        {
            // Set site language to session locale value
            service('language')->setLocale(session('locale'));
        }
        else
        {
            // Save locale to session
            session()->set('locale'service('language')->getLocale());
        

@kenjis Thank you, just tested it and it works.

I realise, i have this in my app/Config/Events.php to maintain locale when user logout.

PHP Code:
/*
 * --------------------------------------------------------------------
 * Auth logout
 * --------------------------------------------------------------------
 * Maintain locale variable in session after logout 
 */
Events::on('logout', function ()
{
 
    session()->set('locale'service('language')->getLocale());
}); 
Reply




Theme © iAndrew 2016 - Forum software by © MyBB