How to rewrite location in nginx depending on the client-browser's language?

前端 未结 10 1893
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-02 17:25

How to rewrite location in nginx depending on the client-browser\'s language?

For example: My browser accept-language is \'uk,ru,en\'. When I request locati

相关标签:
10条回答
  • 2020-12-02 17:59

    The downside of using AcceptLanguageModule is you cannot rely on automatic system updates anymore. And with every nginx update (even security one), you have to compile Nginx yourself. The second downside is that module assumes that the accept-language is sorted by quality values already. I rather prefer Lua because it can be installed easily in debian based distros:

    apt-get install nginx-extras
    

    My colleague Fillipo made great nginx-http-accept-lang script in Lua. It correctly handles quality values and does redirect user accordingly. I've made small modification to that script. It accepts supported languages as input parameter and returns the most qualified language according to Accept-Language header. With returned value you can do whatever you want. It can be used for rewrites, setting lang cookie ...

    I'm only using language determination for root path only (location = /). And user lang cookie has preference over browser. My nginx conf looks like this:

    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;
       }
    }
    
    0 讨论(0)
  • 2020-12-02 18:05

    Lua example above is fine, but will fail with error 500 if browser does not send any Accept-Language headers.

    Add this on top of it:

    if ngx.var.http_accept_language == nil then
    ngx.redirect("/en/")
    end
    
    0 讨论(0)
  • 2020-12-02 18:06

    You can use nginx_accept_language_module. Nginx has to be recompiled but its less work than integrating Lua.

    Link to github

    0 讨论(0)
  • 2020-12-02 18:07

    I think it's not good idea to use nginx map $http_accept_language because it does not honor quality value (q in Accept-Language header). Let's imagine you have:

    map $http_accept_language $lang {
        default en;
        ~en en;
        ~da da;
    }
    

    And client will send Accept-Language: da, en-gb;q=0.8, en;q=0.7

    Using nginx map will always map $lang to en because it simply find in header string. But correct mapping will be $lang = da (because Danisch has quality value q=1 which is bigger then English q=0.7 in this case) More on this in RFC: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

    0 讨论(0)
提交回复
热议问题