8

I'm trying to set up, what I thought would be, a simple language switch. I thought I'd use PHP cookies, but they're not behaving as intended.

I've read a few cookie tutorials and looked at a few similar examples here on StackOverflow, but I must be missing something because it can't get it to work properly.

I'm setting the language by passing it as a URL variable (lang=en or lang=ru). That all seems to be fine. However, the code I have at the moment that sets the cookie seems to be one step behind, so initially it has no value (I'd like it to be 'en' by default), then if the user clicks the 'ENG' button it still has no value, and then if the user clicks Russian the value shows as 'en', and then if I click the 'ENG' button again the value shows as 'ru'.

Here's the code I've cobbled together:

if( $_GET['lang'] ) {
    $lang = (string)$_GET['lang'];
    setcookie( 'lang', $lang, time() + 60*60*24*30 );
} elseif( !isset($_COOKIE['lang']) ) {
    $lang = 'en';
} else {
    $lang = $_COOKIE['lang'];
}

Once I've got this working I intend to use the value of the cookie to display either the English or Russian menu using a bit of conditional PHP.

Thanks.

Matt
  • 325
  • 1
  • 3
  • 12
  • 2
    It isn't a good idea to use cookies to determine the language. Separate URLs are a better bet, people can link directly to the content in the same language as they are using on the page they put the link, and search engines see two separate pages. – Quentin Oct 18 '11 at 07:46
  • @Quentin a point well made. However, I'm working to a tight budget so a quick and simple solution is required. Basically there are (or will be) two main menus, one for English and one for Russian. The site editor will create articles in both languages and then assign them to the relevant menu. Based on the user's choice and using conditional statements only one of these menus will be displayed. It's the easiest way I could think of doing it... – Matt Oct 18 '11 at 13:49
  • @Quentin if separate urls are made, how should the site remember that a page in french should only link to another page on the site in french as well? – compguy24 Feb 14 '14 at 17:47
  • @Quentin, because on this model, the text should be the same for all languages, so the links only point to the content, the language can be added in many different ways. – Rodrigo Aug 21 '15 at 00:06

5 Answers5

8

Thanks for all the suggestions - @Mob set me in the right direction, i.e. processing the cookie on another page and then sending you back to the first.

I did a bit more thinking and experimenting and I've finally solved it. I'll post the code below incase anyone else wants to use this.

On your main page put this:

<form action="language_switcher.php" method="post">
    <select name="lang">
        <option value="en"<?php if( $_COOKIE["language"] == "en" ) { echo " selected"; } ?>>English</option>
        <option value="ru"<?php if( $_COOKIE["language"] == "ru" ) { echo " selected"; } ?>>Russian</option>
    </select>
    <input type="submit" value="Select Language">
</form>

<p>Language: <?php if( isset( $_COOKIE["language"] ) ) { echo $_COOKIE["language"]; } else { echo "<em>not set</em>"; } ?></p>

Then in another file called 'language_switcher.php' put the following code:

$lang = "en";
if( isset( $_POST["lang"] ) ) {
    $lang = $_POST["lang"];
    setcookie ( 'language', $lang, time() + 60*60*24*30, '/', 'mydomain.com');
    header( "Location: /previous_page_url.php" );
}

The user chooses a language and clicks 'Select Language'. The form then sends the form value to 'language_switcher.php', which sets the cookie and then sends the user back to the previous page.

Done! :)

Matt
  • 325
  • 1
  • 3
  • 12
3
if ( !empty($_GET['language']) ) {
    $_COOKIE['language'] = $_GET['language'] === 'en' ? 'en' : 'nl';
} else if ( empty($_COOKIE['language']) ) {
    $_COOKIE['language'] = 'nl';
}
setcookie('language', $_COOKIE['language']);
jgroenen
  • 1,332
  • 1
  • 8
  • 13
3

A cookie is not accessible until the setting page has been reloaded or another page has been accessed (in other words, you cannot set and access a cookie in the same page).

Check this code out :

if( $_GET['lang'] ) {
    $lang = (string)$_GET['lang'];
    setcookie( 'lang', $lang, time() + 60*60*24*30,'/' );
} elseif(  !$_GET['lang']) ) {
    $lang = 'en';
} else {
    $lang = $_GET['lang'];
}
header("Location: redirect_file.php")

Then in redirect_file.php, you redirect back to the cookie page. Perform some checks if you want to avoid redirect loops.

Mob
  • 10,958
  • 6
  • 41
  • 58
  • I understand that, but is what I'm trying to do not possible? Here's the flow: User clicks 'ENG' button, page reloads sending URL variable 'lang=en' and setting cookie value. – Matt Oct 17 '11 at 13:19
0

I used PHP's $_SERVER['PHP_SELF'] to refresh current page and take into account the language selected.

Sample code enclosed. file name : language_switcher.php

<?php

    error_reporting(E_ERROR);

    $lang = "en";

    if( isset( $_COOKIE["language"] ) ) { 
       $lang = $_COOKIE["language"]; 
    }

    if( isset( $_POST["lang"] ) ) {
       $lang = $_POST["lang"];
       setcookie ( 'language', $lang, time() + 60*60*24*30, '/','localhost');
       $refresh = $_SERVER['PHP_SELF'];
       header( "Location: $refresh");
    }
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Test Page Language Toggle</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>

<body>

    <?php 
      // Text definitions
      $text = array(
      'en' => array(
            'selectlang' => 'Select Language',
            'lingua' => 'Language: ',
            'filename' => 'You are in this location: '
          ),
      'fr' => array(
            'selectlang' => 'Séléctionner',
            'lingua' => 'Langue: ',
            'filename' => 'Vous lisez ce fichier: '
          )
      );

    ?>

    <form action="language_switcher.php" method="post">
        <select name="lang">
            <option value="en"<?php if( $_COOKIE["language"] == "en" ) { echo "selected"; } ?>>English</option>
            <option value="fr"<?php if( $_COOKIE["language"] == "fr" ) { echo " selected"; } ?>>Français</option>
        </select>
        <input type="submit" value="<?php echo $text[$lang][selectlang]; ?>">
    </form>

    <p><?php echo $text[$lang][lingua]; if( isset( $_COOKIE["language"] ) ) { echo $_COOKIE["language"]; } else { echo "<em>not set</em>"; } ?></p>

    <br>
    <p><?php echo $text[$lang][filename] . $_SERVER['PHP_SELF']; ?></p>

</body>
</html>
0

Try this one,

if ( !isset( $_GET['lang'] ) ) { 
    if ( isset( $_COOKIE['lang'] ) ) { 
        $lang = $_COOKIE['lang']; 
    } 
    else { 
        $lang = 'en'; 
    } 
} 
else { 
    $lang = (string)$_GET['lang']; 
    setcookie( 'lang', $lang, time() + 60*60*24*30 ); 
}

If the lang directive is not set in GET, check if there is a cookie set.

If it is use its value, or use 'en' by default. If the lang directive is set, set a cookie.

It's pretty much the same code, but a bit optimized. (It's better to put conditions that appear the most on top of ifs.

ikromm
  • 523
  • 6
  • 13
  • Thanks for that, but it seems to do the same thing, i.e. it's one step behind. There were a couple of typos which I've corrected here: `if ( !isset( $_GET['lang'] ) ) { if ( isset( $_COOKIE['lang'] ) ) { $lang = $_COOKIE['lang']; } else { $lang = 'en'; } } else { $lang = (string)$_GET['lang']; setcookie( 'lang', $lang, time() + 60*60*24*30 ); }` – Matt Oct 17 '11 at 13:12
  • indeed, i missed a couple of parenthesis – ikromm Oct 18 '11 at 07:43