Comment le répertoire « manual » (ou docs) de Apache est-il configuré pour que la sélection d’une langue soit mémorisée à travers le chemin utilisé ?

Pour résumer :
http://httpd.apache.org/docs/2.0/mod/mod_alias.html renvoie le doc dans la langue déterminée automatiquement en fonction des réglages du navigateur
http://httpd.apache.org/docs/2.0/en/mod/mod_alias.html renvoie le doc forcé en anglais et contenant des liens relatif vers les autres pages qui restent sous l’arborescence « docs/2.0/en/ », ainsi que des liens de changement de langues, qui envoient vers « docs/2.0/ja/mod/mod_alias.html » par exemple.

Voici la directive magique :
AliasMatch ^/manual(?:/(?:de|en|fr|ja|ko|ru))?(/.*)?$ "/var/www/manual$1"
<Directory "/var/www/manual">
Options Indexes
AllowOverride None
Order allow,deny
Allow from all
<Files *.html>
SetHandler type-map
</Files>
SetEnvIf Request_URI ^/manual/de/ prefer-language=de
SetEnvIf Request_URI ^/manual/en/ prefer-language=en
SetEnvIf Request_URI ^/manual/fr/ prefer-language=fr
SetEnvIf Request_URI ^/manual/ja/ prefer-language=ja
SetEnvIf Request_URI ^/manual/ko/ prefer-language=ko
SetEnvIf Request_URI ^/manual/ru/ prefer-language=ru
RedirectMatch 301 ^/manual(?:/(de|en|fr|ja|ko|ru)){2,}(/.*)?$ /manual/$1$2
</Directory>

Le cœur est « SetEnvIf Request_URI ^/manual/fr/ prefer-language=fr »
prefer-language force la langue qui va être utilisée, avec ce SetEnv on force la langue fr si le chemin utilisé contient « manual/fr ».

Le reste est là pour que comme souhaité toute requête vers /manual/xx/doc.html charge physiquement le document /manual/doc.html.
L’AliasMatch fait correspondre les requêtes de ce type de sous-répertoire vers le directory /manual.

Il reste la touche finale, le RedirectMatch : Attention, c’est subtil !
Chaque fichier peut être chargée de deux manières différentes, sans avoir de quelle manière il a été chargé ! :
– soit par son url négociée : /manual/doc.html
– soit par son url qui force la langue utilisée : /manual/fr/doc.html
Du coup le lien relatif qui doit rediriger vers /manual/en ignore s’il doit rediriger vers ./en/doc.html ou vers ../en/doc.html. En fait il va systématiquement faire le premier, donc quand la page a été chargée depuis /manual/fr/doc.html, il envoit vers /manual/fr/en/doc.html !
C’est ici qu’intervient l’expression régulière du RedirectMatch : Elle détecte que le chemin est du type /manual/fr/en/doc.htm et réécrit dans ce cas la requête pour orienter vers /manual/en/doc.htm

Dernier point : La directive « SetHandler type-map » pour les fichier .html dit que ceux-ci sont des fichiers type-map, et vont contenir les instructions qui indiquent le fichier réel à utiliser sous la forme :

URI: invoking.html.de
Content-Language: de
Content-type: text/html; charset=ISO-8859-1

A multiplier par le nombre de langues différentes dans lesquelles le fichier est présent.

C’est plus efficace que de reposer sur l’instruction MultiViews qui devra elle énumérer les fichiers présent dans le répertoire.

———–
Les petits malins se poseront encore des question au sujet des expressions régulières utilisées :
Dans PCRE, (?:match_group_value) signifie que le group ne sera pas capturé, donc qu’il ne sera pas pris en compte dans les référence avec $n.

Donc pour le AliasMatch, dans (?:/(?:de|en|fr|ja|ko|ru))?, on utilise 2 fois « ?: » et donc rien n’est capturé. Seul le (/.*)? à la fin de l’expression est pris en compte pour la réécriture et est présent dans $1.

Et pour le RedirectMatch, (?:/(de|en|fr|ja|ko|ru)){2,} ne capture que le texte « de », « en », ou « ja », sans le « / » qui précède, {2,} indique qu’au minimum deux match du type « /xx » sont attendus (sinon l’expression ne matchera pas, et donc la redirection ne sera pas fait), de plus le fonctionnement de PCRE fait que les match successifs écrasent les précédents trouvés, donc dans $1 on retrouvera la dernière des valeurs de type « /xx » qui est présente dans cette partie de l’URL.