htaccess 带有子目录的多语言站点,默认为 301
Posted
技术标签:
【中文标题】htaccess 带有子目录的多语言站点,默认为 301【英文标题】:htaccess multi language site with sub directories, and default 301 【发布时间】:2013-11-03 10:25:25 【问题描述】:我在设置我的 htaccess 以允许使用子目录方法的多种语言时遇到一些问题,例如:
http://www.domain.com/en/
http://www.domain.com/sw/
http://www.domain.com/ie/
更复杂的是,该项目目前还没有上线,它在开发服务器上。例如,我目前正在访问该项目:
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-z2]+)(/)?$ 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 相对于其在我的开发服务器上的目录正常工作,然后理想情况下在没有任何环境特定规则的情况下上线。
额外问题:我是否需要在所有后续重写规则前面添加 ([az2]+) 位,或者我是否可以捕获所有会影响所有进一步规则的内容?
编辑 ------------------
我已按照建议将其缩减为以下...
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/
,有什么想法吗?
【问题讨论】:
dev.domain.com
上的 DOCUMENT_ROOT 是什么?
【参考方案1】:
您是否尝试过以下链接中的答案?它应该做你想要达到的目标。
Endless Redirect Loop by htaccess rules multi language
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]
【讨论】:
此解决方案仅适用于根目录,不适用于内部子文件夹。例如xyz.com/test/en 将不起作用【参考方案2】:如果.htaccess 不能改变
将您的 DEV 服务器项目的 <VirtualHost>
配置更改为
<VirtualHost *:80>
ServerName dev.domain.com
ServerAlias project.domain.com
DocumentRoot "/home/webserver_dir/devname/projectname"
</VirtualHost>
这些更改通常会放在您的 httpd-vhosts.conf 文件中。您的 .htaccess 文件现在将拥有
RewriteBase /
将root标记为开发和实时服务器的base目录。
如果您尝试在同一个 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 必须只查看和应用规则live(/devX/projectX/
目录之后的内容),这就是转移 DocumentRoot
所做的事情对我们来说。
如果对 .htaccess 进行最少的修改就可以了
不是每个人都可以访问 Apache 的 .conf 文件。某些主机完全正确地拒绝修改它们的请求。这就是为什么,如果他们至少启用了 mod-rewrite,很多网站的设置都可以修改。其中之一是使用RewriteBase
来处理不同的部署目录。
因此,如果您将RewriteBase /
保持在live 上,但将其更改为RewriteBase /devX/projectX/
以进行开发,那么您的大部分RewriteRule
s 应该可以正常工作。所以,/devname/projectname/
应该正确重定向到/devname/projectname/en/
。
您对
([a-z2]+)
的使用不正确。您可能的意思是 ([a-z]2)
恰好捕获两个字母。如果您打算捕获两个或更多,它将变为([a-z]2,)
。因此,您的 default load 重写将变为
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
匹配 ^(/)?$
不是必需的,因为您已经对上面没有语言目录前缀的所有 URL 执行 301
重定向到 /en/$1
,理想情况下应该是
RewriteCond %REQUEST_URI !^/(en|sw)(/|$) [NC]
RewriteRule ^(.*)$ en/$1 [R=301,L]
否则,/en
也会被重定向到 /en/en
。
【讨论】:
很好的答案,我将使用第二部分,尽管现在它给了我反复出现的重定向问题,即使我输入了你描述的规则。我已经更新了我的问题并简化了 htaccess @Horse 我很抱歉。我不在(庆祝排灯节 - 印度的一个盛大节日 :)),无法回复您的 cmets。让我看看您的更新,我会在短时间内提出解决方案。感谢您的耐心等待。 没问题,排灯节快乐 :) 我期待您的回复 @Horse301
重定向需要为 RewriteRule ^(.*)$ http://%HTTP_HOST/en/$1 [R=301,L]
。这可以确保我们在不预先将项目路径添加到 URL 的情况下进行重定向。
这工作正常(例如对于实时服务器),但在开发服务器上,将 301 更改为 RewriteRule ^(.*)$ http://%HTTP_HOST/devname/projectname/en/$1 [R=301,L]
它仍然卡在重定向循环中:(以上是关于htaccess 带有子目录的多语言站点,默认为 301的主要内容,如果未能解决你的问题,请参考以下文章
Nuxt + Laravel 上的多语言站点,带有来自后端的语言环境
织梦多语言站点,{dede:include filename=''/}引入问题