Htaccess многоязычный сайт с подкаталогами, а по умолчанию 301

У меня возникают проблемы с настройкой htaccess, чтобы разрешить использование нескольких языков с использованием метода подкаталогов, например:

http://www.domain.com/en/
http://www.domain.com/sw/
http://www.domain.com/ie/

Также, чтобы усложнить ситуацию, проект в настоящее время не работает, его на dev-сервере. Например, Я в настоящее время обращаюсь к проекту по адресу:

http://dev.domain.com/devname/projectname/

И я хочу, чтобы приведенное выше автоматически 301 перенаправлялось на:

http://dev.domain.com/devname/projectname/en/

Вот мой htaccess:

Options +FollowSymLinks -MultiViews
RewriteEngine on

# ----------------------------------------------------------------------
# MULTI LANGUAGE SUB DIRECTORY
# ----------------------------------------------------------------------

RewriteCond %{REQUEST_URI} !^/(en|sw)/
RewriteRule ^(.*)$ en/$1 [R=301,L]

# ----------------------------------------------------------------------
# Rewrite rules
# ----------------------------------------------------------------------

## CASE STUDIES ##
RewriteRule ^casestudies/([^/\.]+).html$ index.php?controller=contents&method=viewCasestudy&link=$1 [L,QSA]

## PRODUCTS ##
RewriteRule ^products/([^/\.]+).html$ index.php?controller=contents&method=viewProduct&link=$1 [L,QSA]

RewriteRule ^([a-z{2}]+)(/)?$ index.php?controller=contents&method=viewHome&lang=$1 [L,QSA] # Default load
RewriteRule ^(/)?$ index.php?controller=contents&method=viewHome [L,QSA] # Default load

Приведенное выше будет перенаправлено на:

http://dev.domain.com/home/webserver_dir/devname/projectname/en/

.., и если я использую RewriteBase, он, похоже, просто...

http://dev.domain.com/en/

Итак, мой вопрос:. Как заставить URL-адреса языка корректно работать с каталогом на моем dev-сервере, а затем идеально будет работать, когда он будет работать без каких-либо особых правил среды.

Бонусный вопрос: Нужно ли добавить бит ([az {2}] +) перед всеми моими последующими правилами перезаписи или я могу уловить все, что повлияет на все дальнейшие правила

РЕДАКТИРОВАТЬ -----------------------------

Я сократил его до следующего, как было предложено...

Options +FollowSymLinks -MultiViews
RewriteEngine on

RewriteBase /devname/projectname/

RewriteCond %{REQUEST_URI} !^/(en|sw)(/|$) [NC]
RewriteRule ^(.*)$ en/$1 [R=301,L]
RewriteRule ^([a-z]{2})/?$ index.php?controller=contents&method=viewHome&lang=$1 [NC,L,QSA] # Default load

... но теперь его перенаправление на http://dev.domain.com/devname/projectname/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/en/, любые идеи?

Ответ 1

Вы пробовали ответ в следующей ссылке? Он должен делать то, что вы пытаетесь достичь.

Endless Redirect Loop с помощью правил htaccess с несколькими языками

RewriteEngine On
RewriteBase /   

# empty url -> redirect to en/
RewriteCond %{QUERY_STRING} !lang=(en|de)
RewriteRule ^$ en/ [R=301,L]

# url is ONLY '/en' or '/de' -> redirect to /en/ or /de/ (adding slash)
RewriteRule ^(en|de)$  $1/ [R=301,L]

# now all urls have en/ de/ -> parse them
RewriteRule ^(en|de)/(.*)$  $2?lang=$1&%{query_STRING} [L]

Ответ 2

Если .htaccess не должен меняться

Измените конфигурацию <VirtualHost> для проекта сервера DEV как

<VirtualHost *:80>
    ServerName dev.domain.com
    ServerAlias project.domain.com
    DocumentRoot "/home/webserver_dir/devname/projectname"
</VirtualHost>

Эти изменения обычно попадают в ваш файл httpd-vhosts.conf. Теперь ваши файлы .htaccess будут иметь

RewriteBase /

чтобы отметить корень как ваш базовый каталог как для ваших разработчиков, так и для живых серверов.

Если вы пытаетесь выполнить версию своих проектов или протестировать несколько проектов на одном и том же узле dev, вам нужно будет включить схему именования в имена доменов вместо URL-адреса. Например,

<VirtualHost *:80>
    ServerName dev1.domain.com
    ServerAlias project1.domain.com
    DocumentRoot "/home/webserver_dir/dev1/project1"
</VirtualHost>

<VirtualHost *:80>
    ServerName dev2.domain.com
    ServerAlias project2.domain.com
    DocumentRoot "/home/webserver_dir/dev2/project2"
</VirtualHost>

Суть в том, что вы не можете иметь те же правила файла .htaccess, которые не тронуты различными каталогами развертывания, если вы не прибегаете к mod-rewrite-способу if-else mumbo jumbo, который будет просто добавлен в беспорядок после того, как вы перейдете в живую.

Для того, чтобы правила работали прозрачно, Apache должен видеть и применять правила о том, что происходит вживую (содержимое, которое приходит после /devX/projectX/), что и делает для нас DocumentRoot.

Если минимальные моды до .htaccess в порядке

Не все имеют доступ к файлам Apache.conf. Некоторые хосты нарушают права на отклонения запросов на их изменение. Вот почему, если у них есть хотя бы поддержка mod-rewrite, можно настроить множество настроек веб-сайта. Один из них - использовать RewriteBase для обработки различных каталогов развертывания.

Итак, если вы сохраняете RewriteBase / на live, но меняете его на RewriteBase /devX/projectX/ для разработки, большая часть вашего RewriteRule должна работать как есть. Таким образом, /devname/projectname/ должен правильно перенаправляться на /devname/projectname/en/.


Неверное использование ([a-z{2}]+). Вероятно, вы имели в виду ([a-z]{2}) для захвата ровно двух букв. Если вы хотите захватить два или более, это станет ([a-z]{2,}). Таким образом, ваша перезагрузка по умолчанию станет
RewriteRule ^([a-z]{2})/?$ index.php?controller=contents&method=viewHome&lang=$1 [NC,L,QSA] # Default load

Вы правы предположить, что вам понадобится это регулярное выражение для всех последующих правил, иначе они не совпадут. Таким образом, ваш RewriteRule для casestudies не будет работать. Более простой способ не заботиться о префиксе языка - это отказаться от ^ начала привязки пути URL как

RewriteRule /casestudies/([^/\.]+).html$ index.php?controller=contents&method=viewCasestudy&link=$1 [NC,L,QSA]
RewriteRule /products/([^/\.]+).html$ index.php?controller=contents&method=viewProduct&link=$1 [NC,L,QSA]

Ваш последний RewriteRule соответствие ^(/)?$ не требуется, потому что вы уже выполняете перенаправление 301 для всех URL-адресов без префикса языкового каталога до /en/$1 выше, что в идеале должно быть

RewriteCond %{REQUEST_URI} !^/(en|sw)(/|$) [NC]
RewriteRule ^(.*)$ en/$1 [R=301,L]

В противном случае /en также будет перенаправлен на /en/en.