1

I work on a language switcher on a website in PHP. When I change the langauge with the switcher, the navigation menu's language changes, but when I try to navigate to another page on the nav menu, I get the following error message, and the ?lang= attribute does not appear at the end of the URL:

Fatal error: require_once(): Failed opening required 'languages/.php' (include_path='.:/usr/share/php') in /var/www/clients/client589/web1549/web/HERE_IS_MY_DOMAIN_NAME/config.php on line 20

Here is my PHP code in config.php:


 session_start();

    if (!isset($_SESSION['lang']))
        $_SESSION['lang'] = $_GET['lang'];
    else if (isset($_GET['lang']) && $_SESSION['lang'] != $_GET['lang'] && !empty($_GET['lang'])) {
        if ($_GET['lang'] == "en")
            $_SESSION['lang'] = "en";
        else if ($_GET['lang'] == "fr")
            $_SESSION['lang'] = "fr";
        else if ($_GET['lang'] == "hu")
            $_SESSION['lang'] = "hu";
    }

    require_once "languages/" . $_GET['lang'] . ".php";

I would be really grateful for some help! Thank you in advance.

  • 1
    `require_once "languages/" . $_GET['lang'] . ".php";` Wouldn't you want to include `$_SESSION['lang']` instead of `$_GET['lang']`? – brombeer Mar 20 '23 at 09:30
  • 1
    "_and the ?lang= attribute_" Do you even need that parameter when you navigate to a different page? The selected language should be stored in your session, no need for a parameter – brombeer Mar 20 '23 at 09:32
  • It does not work with $_SESSION['lang'] either.... – Curious Programmer Mar 20 '23 at 10:25

2 Answers2

1

Care needs to be taken when including files that are potentially set via a querystring parameter and consideration also of setting a default value initially if the user has made no choice regarding language. You could try something like this?

<?php
    // language-selector.php
    session_start();
    

    $file=false;
    $path = '%s/languages/%s.php';
    $languages=array('en','fr','hu');
    $default='en';
    
    
    /*
        If the session does already exist and is different to the querystring value
        then change it, otherwise use the session value.
        
        Use an array of languages to only allow known values in querystring - this should also
        be applied to the session value too.
    */
    if( isset( $_SESSION['lang'] ) && in_array( $_SESSION['lang'], $languages ) ){
        
        if( isset( $_GET['lang'] ) && trim( $_GET['lang'] )!=$_SESSION['lang'] && in_array( trim( $_GET['lang'] ), $languages ) ){
            $_SESSION['lang']=trim( $_GET['lang'] );
        }
        
        // use the session value to create the file path to the language file
        $file=sprintf( $path, __DIR__, $_SESSION['lang'] );
        
    }else{
        /*
            The session does not exist. The querystring might also not exist.
            If the GET parameter is not set the default value ( above ) will become the session value.
        */
        if( isset( $_GET['lang'] ) && in_array( trim( $_GET['lang'] ), $languages ) ){
            $_SESSION['lang']=trim( $_GET['lang'] );
        }else{
            $_SESSION['lang']=$default;
        }
        
        $file=sprintf( $path, __DIR__, $_SESSION['lang'] );
    }
    
    // only insert the file if it exists
    if( $file && file_exists( $file ) ) require $file;
?>

This has been tested using 3 local files in a sub-folder called languages. These 3 files are all identical to the following except the language name that is printed

<?php
    //en.php
    if( empty( session_id() ) ) session_start();
    echo '<h1>English</h1>';
    
    if( isset( $_SESSION['lang'] ) ){
        printf('<h2>%s</h2>',$_SESSION['lang']);
    }
    
    echo "<a href='?lang=en'>En</a> - <a href='?lang=fr'>Fr</a> - <a href='?lang=hu'>Hu</a>";
?>

On first invocation the default value (English) is used and becomes the session value. Clicking on any of the links will set that as the new session value and any attempt at setting an unknown value will yield no change.

Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
0

This code seems to work, except that if I click on "Home" sub page in any language, it will return to the English 'Home' page:

    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }

    require get_language_file();
    function get_language_file()
    {
        $_SESSION['lang'] = $_SESSION['lang'] ?? 'en';
        $_SESSION['lang'] = $_GET['lang'] ?? $_SESSION['lang'];


        return "languages/" . $_SESSION['lang'] . ".php";
    }

    function __($str)
    {
        global $lang;
        if (!empty($lang[$str])) {
            return $lang[$str];
        }
        return $str;
    }