For language redirects we presently create folders within the web root that contains a catalog.perl file which inspections the HTTP_ACCEPT_LANG server variable. e.g. for that url

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

    header("location: ../press_en.php");
    header("location: ../press_de.php");

As they have grown, we've many such folders. I'm attempting to clean this up by moving the redirects to some 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 concept is equivalent to the php file, however it does not work. I've attempted all of the possible language configurations / orders in Opera preferences, and checked the headers are correct, however it always serves the press_de.php file.

What shall we be held doing wrong, or it is possible to better way? (excluding content settlement / multiviews or something that requires renaming files, this isn't presently a choice).

I'd place the language indicator at the beginning of the URL path like /en/… or /de/…. Then use a single script that inspections the most well-liked language and redirects the request by prepending the word what indicator:

// negotiate-language.php
$availableLanguages = array('en', 'de');
if (!preg_match('~^/[a-z]{2}/~', $_SERVER['REQUEST_URI'])) {
    $preferedLanguage = someFunctionToDeterminThePreferedLanguage();
    if (in_array($preferedLanguage, $availableLanguages)) {
    } 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

And also the corresponding rules:

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

Note that you'll require an effective someFunctionToDeterminThePreferedLanguage work as Accept-Language header field isn't a single value but a listing of qualified values. So there can be not only one value and also the first value isn't necessarily the prefered value.