Translation - Changing language

Hello everyone,
I have setted up my config file to use translation like this ;
‘translator’ => [
‘locale’ => ‘en_US’,
‘translation_file_patterns’ => [
[
‘base_dir’ => DIR . ‘/…/…/…/data/translations’,
‘type’ => ‘ini’,
‘pattern’ => ‘%s.ini’,
]
],
],

And i have written a little code for the user to able to switch language.
How can I change th default language by the user’choice in my controller ?

It depends, for example how the current locale is stored. If use session or a route parameter then you can use a listener.

My suggestion would be here to use PHP’s Locale class to set the locale in the listener class:

Locale::setDefault('en_US');

laminas-i18n uses per default this option.


See also my other comment on this topic:

Thnaks @froschdesign for your answer. I use session because I choose the option to not show language in my URL. This his how I proceed :
I’m costumizing Laminas Skeleton and adding link (Fr|En) for translation. When clicking on the link I call an action wich add a variable (containing the selected language) in session and then reload the page to apply changes. The lanaguage variable in session is correctly set but when the page is reloaded it is removed and I do not know Why : Here is my module file :

<?php

/**
 * @see       https://github.com/laminas/laminas-mvc-skeleton for the canonical source repository
 * @copyright https://github.com/laminas/laminas-mvc-skeleton/blob/master/COPYRIGHT.md
 * @license   https://github.com/laminas/laminas-mvc-skeleton/blob/master/LICENSE.md New BSD License
 */

declare(strict_types=1);

namespace Application;

use Laminas\Mvc\MvcEvent;
use Laminas\Mvc\Controller\AbstractActionController;
use Application\Service\AuthManager;
use Application\Controller\AuthController;

use Laminas\Session\SessionManager;

class Module
{
    public function getConfig() : array
    {
        return include __DIR__ . '/../config/module.config.php';
    }
    
    
    public function onBootstrap(MvcEvent $event){
        // Au demarrage, on va initialiser tous nos hiahi truc pour chose ici 
        // Get event manager.
        $eventManager = $event->getApplication()->getEventManager();
        $sharedEventManager = $eventManager->getSharedManager();                
        
        // Register the event listener method. 
        $sharedEventManager->attach(AbstractActionController::class, 
                MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch'], 100);
        
        
        
        
        
        $serviceManager = $event->getApplication()->getServiceManager();
        $sessionManager = $serviceManager->get(SessionManager::class);   
        
        $this->forgetInvalidSession($sessionManager);
        
        
        // Get language settings from session.
        $container = $serviceManager->get('I18nSessionContainer');
        
        $languageId = 'en_US';
        if (isset($container->languageId)){
            $languageId = $container->languageId;            
        }
        
        //var_dump($container->languageId);
        
        \Locale::setDefault($languageId);
        
        $translator = $serviceManager->get('translator');
        $translator->addTranslationFile(
            'ini',                
            __DIR__ . '/../../../data/translations/'.$languageId.'.ini',
            'default',
            $languageId
        );
        
        
        $translator->addTranslationFilePattern(
            'ini',
            __DIR__ . '/../../../data/translations',
            '%s.ini',
            'default'
        );
        
        
       
    }
    
    protected function forgetInvalidSession($sessionManager) 
    {
    	try {
    		$sessionManager->start();                    
    		return;
    	} catch (\Exception $e) {
    	}
    	/**
    	 * Session validation failed: toast it and carry on.
    	 */
    	// @codeCoverageIgnoreStart
    	//session_unset();
    	// @codeCoverageIgnoreEnd
    }
    
    public function onDispatch(MvcEvent $event){       
        $controller = $event->getTarget();
        $controllerName = $event->getRouteMatch()->getParam('controller', null);       
        $actionName = $event->getRouteMatch()->getParam('action', null);        
        
        // Convert dash-style action name to camel-case. Je pense pas avoir besoin de celui la.
        $actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));  
        
        
        
        // Get the instance of AuthManager service.
        $authManager = $event->getApplication()->getServiceManager()->get(AuthManager::class);
        
        // Execute the access filter on every controller except AuthController
        // (to avoid infinite redirect).       
        if ($controllerName!=AuthController::class && !$authManager->filterAccess($controllerName, $actionName)) {            
            return $controller->redirect()->toRoute('connexion'); // La route qui a ete definie dans le fichier de config           
        }
       
        
    }
    
}

My Controller and action for switching language here :

<?php
namespace Commun\Controller;
use Commun\Controller\NslabsAbstractController;
class LocaleController extends NslabsAbstractController
{

    public function switchLocaleAction()
    {        
        $locale = $this->post['locale'];                        
        if (empty($locale)) {
            $locale = 'fr';
        }

        $lang = $locale;


        switch ($lang) {
            case 'fr':
                $this->sessionManager->i18nSessionContainer->languageId = 'fr_FR';                   
                break;
            case 'en':
                $this->sessionManager->i18nSessionContainer->languageId = 'en_US';                 
                break;
            default :
                $this->sessionManager->i18nSessionContainer->languageId = 'fr_FR';
        }

        return new \Laminas\Http\Response();
    }


}

I have to say that all my controllers extends my generic NslabsAbstractController wich extends also AbstractActionController in where I have added the ServiceManager and Session Manager as construct params.

This is not necessary and explicitly not recommended. Inject only required elements and not something that might be needed.

Your action to switch the language is okay (besides your generic controller) but the onBootstrap method in your module class is not needed to set the locale and the part to add translation file is wrong. There is difference between to add a translation file and load the messages from the file. Adding a translation file does not load the messages from the file automatically.
Therefore you can move the adding of all translation files to the configuration and the onBootstrap method is not need for that. Create a listener to set the locale.

OK. I will try that and will get back to you very soon. :ok_hand:

Hi I’m happy to say that I have solved my problem
Thanks to everyone

Could you share your final implementation. I just started on translations and would appreciate a working example. Thanks