如何根据客户端浏览器的语言重写nginx中的位置?

RKI*_*RKI 24 browser rewrite nginx

如何根据客户端浏览器的语言重写nginx中的位置?

例如:我的浏览器接受语言是' uk,ru,en '.当我请求位置时,mysite.org nginx必须转发到mysite.org/uk

小智 20

如果无法将AcceptLanguageModule模块添加到系统中,则可以通过此设置管理$ language_suffix.

rewrite (.*) $1/$http_accept_language
Run Code Online (Sandbox Code Playgroud)

更具弹性的方法是使用地图:

map $http_accept_language $lang {
        default en;
        ~es es;
        ~fr fr;
}

...

rewrite (.*) $1/$lang;
Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用,即使我将浏览器配置为仅限法语,它总是将我带到英文页面 (4认同)
  • 此映射不符合首选项.为了改变这种映射,你可以将正则表达式从`~es es;`更改为`〜*^ es es;`这将把语言映射到出现在`Accept-Language`标题上的第一种语言(假设浏览器首先提供首选语言,我认为非常频繁) (2认同)

mau*_*n85 12

我认为使用nginx并不是一个好主意,map $http_accept_language因为它不符合质量值(qAccept-Language标题中).我们假设你有:

map $http_accept_language $lang {
    default en;
    ~en en;
    ~da da;
}
Run Code Online (Sandbox Code Playgroud)

并且客户将发送 Accept-Language: da, en-gb;q=0.8, en;q=0.7

使用nginx map将始终映射$lang到,en因为它只是在标题字符串中找到.但正确的映射将是$lang = da(因为在这种情况下q=1,Danisch的质量值比英语更大q=0.7)在RFC中有更多相关信息:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

  • 我想这是对@brian-coca 答案的评论? (2认同)

mau*_*n85 10

使用AcceptLanguageModule的缺点是您不能再依赖自动系统更新了.每次更新nginx(甚至是安全版)都需要自己编译Nginx.第二个缺点是模块假定接受语言已经按质量值排序.我更喜欢Lua,因为它可以很容易地安装在基于debian的发行版中:

apt-get install nginx-extras
Run Code Online (Sandbox Code Playgroud)

我的同事Fillipo 在Lua中制作了很棒的nginx-http-accept-lang脚本.它正确处理质量值并相应地重定向用户.我对该脚本做了一些小修改.它接受支持的语言作为输入参数,并根据Accept-Language标头返回最合格的语言.使用返回值,您可以随心所欲.它可以用于重写,设置lang cookie ...

我只对根路径使用语言确定(location = /).而用户lang cookie优先于浏览器.我的nginx conf看起来像这样:

map $cookie_lang $pref_lang {
    default "";
    ~en en;
    ~sk sk;
}

server {
    listen 80 default_server;

    root /usr/share/nginx/html;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location = / {
        # $lang_sup holds comma separated languages supported by site
        set $lang_sup "en,sk";
        set_by_lua_file $lang /etc/nginx/lang.lua $lang_sup;
        if ($pref_lang) {
            set $lang $pref_lang;
        }
        add_header Set-Cookie lang=$lang;
        rewrite (.*) $scheme://$server_name/$lang$1;
    }

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
   }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

好的,我遇到了同样的问题,并且“滥用” Lua使基于浏览器语言的重定向成为可能。

# Use Lua for HTTP redirect so the site works
# without the proxy backend.
location = / {
    rewrite_by_lua '
        for lang in (ngx.var.http_accept_language .. ","):gmatch("([^,]*),") do
            if string.sub(lang, 0, 2) == "en" then
                ngx.redirect("/en/index.html")
            end
            if string.sub(lang, 0, 2) == "nl" then
                ngx.redirect("/nl/index.html")
            end
            if string.sub(lang, 0, 2) == "de" then
                ngx.redirect("/de/index.html")
            end
        end
        ngx.redirect("/en/index.html")
    ';
}
Run Code Online (Sandbox Code Playgroud)

注意:NGINx需要编译liblua。对于Debian / Ubuntu:

apt-get install nginx-extras
Run Code Online (Sandbox Code Playgroud)