: Rewrite to SEO friendly URLs for language negotiation with type-map files on plain html files using .htaccess When visiting the website www.example.com/ the visitor should be redirected to the
When visiting the website example.com/ the visitor should be redirected to the correct language version, e.g. example.com/en for english and example.com/es for spanish.
My current implementation only works when visiting example.com/index.var and redirects to example.com/index.en. Now I want to rewrite this to example.com/en/
My implementation is based on httpd.apache.org/docs/2.4/content-negotiation.html.
.htaccess
Options -MultiViews
RewriteEngine On
RewriteBase /
AddHandler type-map .var
LanguagePriority en es de
ForceLanguagePriority Fallback
index.var
URI: index; vary="language"
URI: index.en.html
Content-type: text/html
Content-language: en
URI: index.es.html
Content-type: text/html;charset=utf-8
Content-language: es
URI: index.de.html
Content-type: text/html;charset=utf-8
Content-language: de
Important: MultiViews are disabled
Looking forward to your great solutions.
to explain this a little more in detail...
Here's an example of my file structure:
File should be rewritten or redirected to
- index.var --> /
- index.en.html --> /en/
- index.es.html --> /es/
- about.var --> /about
- about.en.html --> /en/about
- about.es.html --> /es/about
- images/img_1.jpg --> /images/img_1.jpg
- images/logo.var --> /images/logo.png (not a file)
- images/logo.en.png --> /en/images/logo.png
- images/logo.es.png --> /es/images/logo.png
Rewriting of images and other resources is optional. It's only important to get rewriting of html files right.
The Apache Documentation is a working example of this (using content negotiation).
More posts by @Smith883
3 Comments
Sorted by latest first Latest Oldest Best
I think I've found the solution on Apache's SVN repository. (I haven't tested it yet)
Configuration for Multilingual Site
Configuration for Multilingual Error Pages
Configuration with Languages and Encodings Setup
The implementation here uses the .html extension for type-map files instead of .var. That means, if you want to use html files with the extension .html instead of .html.en, you have to replace
AddHandler type-map .html
with
AddHandler type-map .var
like I did.
I would use rewrite rules to issue 301 permanent redirects:
RewriteEngine on
# First handle the index.XX.html files
# where the language code is moved to the front directory
# and the index and html are removed
RewriteCond %{REQUEST_URI} !^/?([a-z]{2})/
RewriteRule ^/?(.*/)?index.([a-z]{2}).html$ // [L,R=301]
# Then handle other file.XX.html files
# where the language code is moved to the front directory
# the file name is preserved, but the html is removed
RewriteCond %{REQUEST_URI} !^/?([a-z]{2})/
RewriteRule ^/?(.*).([a-z]{2}).html$ // [L,R=301]
# Handle all other file.XX.xyz
# where the language code is moved to the front directory
# and the file name and extension are preserved
RewriteCond %{REQUEST_URI} !^/?([a-z]{2})/
RewriteRule ^/?(.*).([a-z]{2}).([a-z]+)$ //. [L,R=301]
This detects a two character language code using the regular expression ([a-z]{2}). You could instead using something like (en|es|de) with a specific list of supported languages. Doing so could reduce mistakes based on two digit codes used for something other than language (like maybe a gzipped javascript file: .js.gz.) It would also allow you to expand the rules to include country info if needed (like en-us.)
All the rules have a RewriteCond that makes sure they don't apply in the language subdirectories. That should help prevent infinite loops or other problems
The rules start with /? which consumes any leading slash so the rules can be used either in .htaccess or in an Apache .conf file.
The first rule makes the directory path preceding index optional using a question mark in the section (.*/)?. It allows that rule apply to the root index.XX.html files.
I didn't put in a rule for the .var files because it sounds like you already have something in place for them. You would need to continue to handle those files as you do now.
I tested these rules on my local Apache server by putting them in .htaccess and hitting the site with curl. They seem to do the right thing:
$ curl -s --head 'http://example.com/index.en.html'
HTTP/1.1 301 Moved Permanently
Location: example.com/en/
$ curl -s --head 'http://example.com/index.es.html'
HTTP/1.1 301 Moved Permanently
Location: example.com/es/
$ curl -s --head 'http://example.com/about.en.html'
HTTP/1.1 301 Moved Permanently
Location: example.com/en/about
$ curl -s --head 'http://example.com/about.es.html'
HTTP/1.1 301 Moved Permanently
Location: example.com/es/about
$ curl -s --head 'http://example.com/images/logo.en.png'
HTTP/1.1 301 Moved Permanently
Location: example.com/en/images/logo.png
$ curl -s --head 'http://example.com/images/logo.es.png'
HTTP/1.1 301 Moved Permanently
Location: example.com/es/images/logo.png
I would just do this in PHP. I'm not sure how to do it in htaccess.
I would make index.php :
<?php
header("Status: 200 OK");
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
switch ($lang){
case "fr":
//echo "PAGE FR";
include("index_fr.php");//include check session FR
break;
case "it":
//echo "PAGE IT";
include("index_it.php");
break;
case "en":
//echo "PAGE EN";
include("index_en.php");
break;
default:
//echo "PAGE EN - Setting Default";
include("index_en.php");//include EN in all other cases of different lang detection
break;
}
?>
Or if you want the redirect you can do:
<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
switch ($lang){
case "en":
header('Location: www.example.com/en/', true, 302);
exit;
case "es":
header('Location: www.example.com/es/', true, 302);
exit;
case "de":
header('Location: www.example.com/en/', true, 302);
exit;
default:
//echo "PAGE EN - Setting Default";
include("index_en.php");//include EN in all other cases of different lang detection
break;
}
?>
Terms of Use Create Support ticket Your support tickets Stock Market News! © vmapp.org2024 All Rights reserved.