我最近创建了两个文件夹,其中包含索引文件,文件夹的语言分别为 pt
(巴西)和 en
(英语)。
当用户访问页面时,我使用一个控制结构来检查用户的浏览器语言,如果浏览器语言是pt,则将用户重定向到https://mywebsite.com/pt/index
,否则将用户重定向到{{ 1}}。
也许这个我不得不翻译的想法,不是那么专业,不过没关系,重点是我想把网站的URL文件夹中的路径去掉,也就是我想让它出现{{1 }} 不管我是否重定向了用户,你明白吗?
也就是说,如果我将用户重定向到 https://mywebsite.com/en/index
,我不希望显示 https://mywebsite.com/index
,只显示 https://mywebsite.com/en/index
。
是否可以使用 Nginx 执行此操作?
编辑
树 (/var/www)
/pt
index.php
/index
pt/index.php
├── mywebsite.com
│ └── html
│ ├── 404.html
│ ├── css
│ │ ├── bootstrap.css
│ │ └── style.css
│ ├── index.php
│ ├── jquery
│ │ └── jquery.js
│ ├── js
│ │ ├── bootstrap.js
│ │ └── vue.js
│ ├── logout.php
│ ├── pt
│ │ ├── index.php
│ │ ├── logout.php
│ │ ├── signin.php
│ │ └── signup.php
│ ├── signin.php
│ ├── signup.php
└── html
├── index.html
└── index.nginx-debian.html
Nginx ( /etc/nginx/sites-available/mywebsite )
<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
if($lang == 'pt') {
header('Location: pt/');
return;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>English</title>
</head>
<body>
<h1>Welcome! You're browsing the website with the English language.</h1>
</body>
</html>
我说的控制结构现在在代码中可见。真的,这是有效的,但我不知道我所做的是否合适,是否专业,是否存在风险...
所以从现在可用的信息来看,当用户进入页面时,脚本会检查用户浏览器的语言,如果是<?php
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
if(!$lang == 'pt') {
header('Location: https://mywebsite.com');
return;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Português</title>
</head>
<body>
<h1>Bem vindo! Você está navegando no website com o idioma Português.</h1>
</body>
</html>
,它将重定向到葡萄牙语页面,以及该页面如何用葡萄牙语位于名称为 server {
root /var/www/mywebsite.com/html;
try_files $uri $uri/ @extensionless-php;
index index.php;
server_name mywebsite.com www.mywebsite.com;
error_page 403 http://mywebsite.com/forbidden.html;
error_page 404 =301 http://mywebsite.com/404.html;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
internal;
}
location @extensionless-php {
rewrite ^(.*)$ $1.php last;
}
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
access_log /var/log/wss-access-ssl.log;
error_log /var/log/wss-error-ssl.log;
}
server {
if ($host = www.mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name mywebsite.com www.mywebsite.com;
return 404; # managed by Certbot
的文件夹中,很快该文件夹的名称将出现在 URL 中
我想知道是否有隐藏文件夹名称的方法?
注意:
Richard Smith 说:用户需要能够选择/更改语言。在我这样做以翻译成用户的语言之前,我使用了一个 Google Translate button 可以将页面翻译成用户选择的语言,但是,我认为它不是那么酷,它使网站变得缓慢加载,而巴西的大多数用户甚至都没有使用过。于是就想着怎么把页面自动翻译成用户的浏览器语言,上面的代码我做了,但我真的不知道这样做是不是最好的
Ivan Shatsky 说:在 nginx 配置中选择两个不同的根文件夹之一。 我不太明白这是什么意思。我应该在 /etc/nginx/sites-available 中创建另一个配置文件吗?
答案 0 :(得分:0)
不,这并不意味着您以任何方式需要第二个配置文件。
首先,您检查 Accept-Language
HTTP 标头(记录在 RFC 7231 中)的方式远非完美。例如,它可以等于 de;q=0.9,pt;q=0.8,en;q=0.7
。前两个字符是 de
,但用户仍然更喜欢葡萄牙语而不是英语。使用 PHP,您可以检查所有首选语言列表并另外检查每种语言的权重,但 nginx 配置不是编程语言,因此假设首选语言列表按权重排序,就像大多数现代浏览器确实如此。假设以下树结构:
mywebsite.com
└── html
├── 404.html
├── css
│ ├── bootstrap.css
│ └── style.css
├── jquery
│ └── jquery.js
├── js
│ ├── bootstrap.js
│ └── vue.js
├── en
│ ├── index.php
│ ├── logout.php
│ ├── signin.php
│ └── signup.php
└── pt
├── index.php
├── logout.php
├── signin.php
└── signup.php
现在您可以通过以下方式为 PHP 文件使用不同的根文件夹:
map $http_accept_language $used_language {
~en.*pt(*SKIP)(*F)|pt pt; # when "pt" substring present and not preceded with "en"
~pt.*en(*SKIP)(*F)|en en; # when "en" substring present and not preceded with "pt"
default en; # or use "pt" if you want the Portuguese to be default
}
server {
root /var/www/mywebsite.com/html;
...
location ~ \.php$ {
root /var/www/mywebsite.com/html/$used_language; # override root folder
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
internal;
}
...
}
(正则表达式 provided by Wiktor Stribiżew)
map
块可以简化为
map $http_accept_language $used_language {
~en.*pt(*SKIP)(*F)|pt pt; # when "pt" substring present and not preceded with "en"
default en;
}
或
map $http_accept_language $used_language {
~pt.*en(*SKIP)(*F)|en en; # when "en" substring present and not preceded with "pt"
default pt;
}
您可以将整个树结构(css
、js
等)复制到 en
和 pt
文件夹中,并使用动态根文件夹作为全局站点根只有一个 root
指令,但如果您只在 PHP 文件中拥有本地化内容,我认为这没有意义。
重要警告
由于现在您通过相同的 URL 提供不同的内容,您应该指定 Vary
标头以通知您的服务器和访问用户之间的任何缓存层您的内容可能因 Accept-Language
HTTP 标头值而有所不同:
location ~ \.php$ {
add_header Vary "Accept-Language";
...
}
Cookies
现在是 Richard Smith 的建议。我完全同意用户应该能够切换语言。这是一个结合上一个答案的示例:
nginx config
map $http_accept_language $language_by_header {
~en.*pt(*SKIP)(*F)|pt pt; # when "pt" substring present and not preceded with "en"
~pt.*en(*SKIP)(*F)|en en; # when "en" substring present and not preceded with "pt"
default en; # or use "pt" if you want the Portuguese to be default
}
map $cookie_language $used_language {
pt pt;
en en;
# detect language from "Accept-Language" header when no "language" cookie present
default $language_by_header;
}
server {
root /var/www/mywebsite.com/html;
...
location ~ \.php$ {
root /var/www/mywebsite.com/html/$used_language; # override root folder
add_header Vary "Accept-Language";
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
internal;
}
...
}
en/index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>English</title>
<script type='text/javascript' src='/js/functions.js'></script>
</head>
<body>
<h1>Welcome! You're browsing the website with the English language.</h1>
<a onclick="setCookie('pt');" href="<?php echo $_SERVER['REQUEST_URI']; ?>">pt</a>
</body>
</html>
pt/index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Português</title>
<script type='text/javascript' src='/js/functions.js'></script>
</head>
<body>
<h1>Bem vindo! Você está navegando no website com o idioma Português.</h1>
<a onclick="setCookie('en');" href="<?php echo $_SERVER['REQUEST_URI']; ?>">en</a>
</body>
</html>
js/functions.js
function setCookie(lc) {
var today = new Date();
// cookie expiry date - plus 30 days from today
var expiry = new Date(today.getTime() + 30 * 24 * 3600 * 1000);
document.cookie = 'language=' + lc + '; path=/; expires=' + expiry.toGMTString();
}
当然这个例子需要一些解释,就像之前的nginx配置一样,但是写长的解释对于像我这样的非英语母语者来说是一项非常耗时的任务,我现在真的很缺乏时间,试试自己理解任何你能理解的东西,如果你需要一些额外的解释,请在评论中问我一个问题。