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/ 以进行开发,那么您的大部分RewriteRules 应该可以正常工作。所以,/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

您正确地假设所有后续规则都需要此正则表达式,否则它们将无法匹配。因此,您的 RewriteRulecasestudies 将不起作用。不关心语言前缀的一种更简单的方法是将 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。让我看看您的更新,我会在短时间内提出解决方案。感谢您的耐心等待。 没问题,排灯节快乐 :) 我期待您的回复 @Horse 301 重定向需要为 RewriteRule ^(.*)$ http://%HTTP_HOST/en/$1 [R=301,L]。这可以确保我们在不预先将项目路径添加到 URL 的情况下进行重定向。 这工作正常(例如对于实时服务器),但在开发服务器上,将 301 更改为 RewriteRule ^(.*)$ http://%HTTP_HOST/devname/projectname/en/$1 [R=301,L] 它仍然卡在重定向循环中:(

以上是关于htaccess 带有子目录的多语言站点,默认为 301的主要内容,如果未能解决你的问题,请参考以下文章

多语言网站的 Htaccess 和 url [关闭]

Nuxt + Laravel 上的多语言站点,带有来自后端的语言环境

织梦多语言站点,{dede:include filename=''/}引入问题

.htaccess 多语言(slug URL/友好 URL)[关闭]

Kentico多语言网站

多语言数据库,具有默认回退功能