【问题标题】:htaccess multi language site with sub directories, and default 301htaccess 带有子目录的多语言站点,默认为 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-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 相对于其在我的开发服务器上的目录正常工作,然后理想情况下在没有任何环境特定规则的情况下上线。

额外问题:我是否需要在所有后续重写规则前面添加 ([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/,有什么想法吗?

【问题讨论】:

  • dev.domain.com 上的 DOCUMENT_ROOT 是什么?

标签: .htaccess localization multilingual http-status-code-301


【解决方案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-z{2}]+) 的使用不正确。您可能的意思是 ([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] 它仍然卡在重定向循环中:(
猜你喜欢
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2017-05-06
相关资源
最近更新 更多