How to redirect based on Accept-Language with Apache / mod_rewrite

10,165

Solution 1

I would put the language indicator at the start of the URL path like /en/… or /de/…. Then you can use a single script that checks the preferred language and redirects the request by prepending the language indicator:

// negotiate-language.php
$availableLanguages = array('en', 'de');
if (!preg_match('~^/[a-z]{2}/~', $_SERVER['REQUEST_URI'])) {
    $preferedLanguage = someFunctionToDeterminThePreferedLanguage();
    if (in_array($preferedLanguage, $availableLanguages)) {
        header('Location: http://example.com/'.$preferedLanguage.$_SERVER['REQUEST_URI']);
    } else {
        // language negotiation failed!
        header($_SERVER['SERVER_PROTOCOL'].' 300 Multiple Choices', true, 300);
        // send a document with a list of the available language representations of REQUEST_URI
    }
    exit;
}

And the corresponding rules:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ negotiate-language.php [L]
RewriteRule ^([a-z]{2})/([^/]+)$ $2_$1.php [L]

Note that you need a proper someFunctionToDeterminThePreferedLanguage function as Accept-Language header field is not a single value but a list of qualified values. So there might be more than just one value and the first value is not always the prefered value.

Solution 2

in htaccess

RewriteEngine on
RewriteCond %{HTTP:Accept-Language} (en) [NC]
RewriteRule .* server.com/press_en.php [L]


RewriteCond %{HTTP:Accept-Language} (de) [NC]
RewriteRule .* server.com/press_de.php [L]
Share:
10,165
meleyal
Author by

meleyal

Updated on June 04, 2022

Comments

  • meleyal
    meleyal almost 2 years

    For language redirects we currently create folders in the web root containing an index.php file which checks the HTTP_ACCEPT_LANGUAGE server variable. e.g. for the url www.example.com/press/

    in /var/www/site/press/index.php:

    <?php
      if ($_SERVER["HTTP_ACCEPT_LANGUAGE"] == "en")
        header("location: ../press_en.php");
      else 
        header("location: ../press_de.php");
    ?>
    

    As the site has grown, we now have many such folders. I am trying to clean this up by moving the redirects to a single .htaccess file:

    RewriteEngine on
    
    # Set the base path here
    RewriteBase /path/to/site/
    
    # The 'Accept-Language' header starts with 'en'
    RewriteCond %{HTTP:Accept-Language} (^en) [NC]
    
    # EN redirects
    RewriteRule press(/?)$   press_en.php [L,R]
    
    # DE redirects (for all languages not EN)
    RewriteRule press(/?)$   press_de.php [L,R]
    

    The idea is the same as the php file, but it doesn't work. I have tried all the possible language settings / orders in Firefox preferences, and checked the headers are correct, but it always serves the press_de.php file.

    What am I doing wrong, or is there a better way? (not including content negotiation / multiviews or anything that requires renaming files, this is not currently an option).