最简单的是
if ($arg_lang = en) {
return 301 /en$uri;
}
但是,如果您有任何其他查询参数,它们将因此重定向规则而丢失。要保留所有其他查询参数,您可以执行以下操作:
if ($args ~ (.*)(^|&)lang=en(\2|$)&?(.*)) {
set $args $1$3$4;
return 301 /en$uri$is_args$args;
}
为了支持多种语言,我想到的第一个解决方案是
if ($args ~ (.*)(^|&)lang=([^&]*)(\2|$)&?(.*)) {
set $args $1$4$5;
return 301 /$3$uri$is_args$args;
}
但是如果你有一些畸形的lang
查询参数值将导致重定向到不存在的页面。过滤lang
仅支持语言的值您可以使用map http://nginx.org/en/docs/http/ngx_http_map_module.html#map指示:
map $arg_lang $prefix {
en /en;
de /de;
...
# if none matched, value of $prefix variable would be an empty string
}
map $args $stripped_args {
# remove "lang" query argument if exists
~(.*)(^|&)lang=[^&]*(\2|$)&?(.*) $1$3$4;
default $args;
}
server {
...
if ($prefix) {
set $args $stripped_args;
return 301 $prefix$uri$is_args$args;
}
...
}
如果您的 URI 语言前缀与lang
查询参数值(或者可以通过一些正则表达式从中派生),第一个map
块可以简化:
map $arg_lang $prefix {
~^(en|de|...)$ /$1;
}
Update
正如OP所说,当我们收到这样的请求时,可能会有一个警告example.com/de/some/path/?lang=en
这将被重定向到不存在的页面example.com/en/de/some/path/
。为了避免这种情况,我们可以定义额外的map
阻止并从 URI 中去除语言前缀:
map $arg_lang $prefix {
~^(en|de|...)$ /$1;
}
map $args $stripped_args {
# remove "lang" query argument if exists
~(.*)(^|&)lang=[^&]*(\2|$)&?(.*) $1$3$4;
default $args;
}
map $uri $stripped_uri {
# remove language prefix from URI if one exists
~^/(en|de|...)(/.*)$ $2;
default $uri;
}
server {
...
if ($prefix) {
set $args $stripped_args;
return 301 $prefix$stripped_uri$is_args$args;
}
...
}