移除Odoo多语言URL路径:通过Nginx实现单域名对应单语言
问题描述
我正在使用Odoo 16.0和18.0(社区版),以Nginx作为反向代理。Odoo原生多语言通过URL路径实现:
www.mycompany.com/en- 英文版本www.mycompany.com/it- 意大利语版本
Odoo会设置名为frontend_lang的Cookie,值为en_US或it_IT。同时默认语言会自动重定向:比如默认语言为英文时,www.mycompany.com/en会重定向到www.mycompany.com/,www.mycompany.it/en会重定向到www.mycompany.it/。
我的两个域名Nginx配置如下:
.com域名配置
#odoo server upstream odoo { server 192.168.1.305:8069; } upstream odoochat { server 192.168.1.305:8072; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } map $sent_http_content_type $content_type_csp { default ""; ~image/ "default-src 'none'"; } # http -> https server { if ($host = www.mycompany.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name www.mycompany.com; rewrite ^(.*) https://$host$1 permanent; } server { listen 443 ssl; listen [::]:443 ssl; listen 443 quic; listen [::]:443 quic; http2 on; server_name www.mycompany.com; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; # log access_log /var/log/nginx/odoo.access.log; error_log /var/log/nginx/odoo.error.log; # Redirect websocket requests to odoo gevent port location /websocket { proxy_pass http://odoochat; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; } # Redirect requests to odoo backend server location / { # Add Headers for odoo proxy mode proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } location @odoo { # Add Headers for odoo proxy mode proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } location ~ ^/[^/]+(!db$)/static/.+$ { # root and try_files both depend on your addons paths root /opt/odoo; try_files /16.0/addons$uri /16.0/OCB$uri @odoo; expires 24h; add_header Content-Security-Policy $content_type_csp; } location /web/filestore { internal; alias /root/.local/share/Odoo; } # common gzip gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript; gzip on; # SSL parameters include snippets/self-signed-certificate.conf; }
.it域名配置
map $http_upgrade $connection_upgrade { default upgrade; '' close; } map $sent_http_content_type $content_type_csp { default ""; ~image/ "default-src 'none'"; } # http -> https server { if ($host = www.mycompany.it) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name www.mycompany.it; rewrite ^(.*) https://$host$1 permanent; } server { listen 443 ssl; listen [::]:443 ssl; listen 443 quic; listen [::]:443 quic; http2 on; server_name www.mycompany.it; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; # log access_log /var/log/nginx/odoo.access.log; error_log /var/log/nginx/odoo.error.log; # Redirect websocket requests to odoo gevent port location /websocket { proxy_pass http://odoochat; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; } # Redirect requests to odoo backend server location / { # Add Headers for odoo proxy mode proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } location @odoo { # Add Headers for odoo proxy mode proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } location ~ ^/[^/]+(!db$)/static/.+$ { # root and try_files both depend on your addons paths root /opt/odoo; try_files /16.0/addons$uri /16.0/OCB$uri @odoo; expires 24h; add_header Content-Security-Policy $content_type_csp; } location /web/filestore { internal; alias /root/.local/share/Odoo; } # common gzip gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript; gzip on; # SSL parameters include snippets/self-signed-certificate.conf; }
目标
实现单域名对应单语言:
www.mycompany.com- 固定对应英文www.mycompany.it- 固定对应意大利语
已尝试方案
曾将proxy_pass http://odoo;修改为proxy_pass http://odoo/en;,但触发了无限循环问题,寻求解决办法。
解决方案
核心思路
直接修改proxy_pass路径会导致Odoo重定向回根路径,进而触发Nginx再次代理到带语言的路径,形成循环。正确的做法是通过设置Cookie强制指定语言,同时拦截Odoo的语言重定向,确保域名与语言绑定。
修改后的Nginx配置
1. .com域名(强制英文)
在server块的location /部分添加Cookie设置,并处理重定向:
server { # 保留原有其他配置(listen、ssl、日志等) # Redirect requests to odoo backend server location / { # 强制设置英文Cookie,优先级高于用户原有Cookie add_header Set-Cookie "frontend_lang=en_US; Path=/; Domain=mycompany.com; HttpOnly; Secure" always; # 拦截Odoo的语言重定向,将/en路径重写回根路径 rewrite ^/en(/.*)?$ $1 break; # 保留原有代理头配置 proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } # 保留原有其他location配置(websocket、@odoo、静态文件等) }
2. .it域名(强制意大利语)
同理,在location /部分添加意大利语Cookie设置:
server { # 保留原有其他配置(listen、ssl、日志等) # Redirect requests to odoo backend server location / { # 强制设置意大利语Cookie add_header Set-Cookie "frontend_lang=it_IT; Path=/; Domain=mycompany.it; HttpOnly; Secure" always; # 拦截Odoo的语言重定向,将/it路径重写回根路径 rewrite ^/it(/.*)?$ $1 break; # 保留原有代理头配置 proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://odoo; proxy_set_header Host $host; } # 保留原有其他location配置(websocket、@odoo、静态文件等) }
补充说明
- Cookie设置:
always参数确保即使是重定向响应也会发送Cookie,强制覆盖用户端可能存在的旧语言Cookie。HttpOnly和Secure提升安全性,仅在HTTPS下生效。 - 重写规则:拦截Odoo自动生成的带语言后缀的重定向,避免用户访问
www.mycompany.com/en时被重定向到根路径后又触发语言检测,确保URL始终保持根路径形式。 - 避免循环:通过Cookie直接指定语言,Odoo会根据Cookie值渲染对应语言页面,无需再通过URL路径传递语言参数,从根源上避免了循环问题。
验证步骤
- 重启Nginx服务:
sudo systemctl restart nginx - 访问
www.mycompany.com,检查Cookie中frontend_lang值为en_US,页面显示英文 - 访问
www.mycompany.it,检查Cookie中frontend_lang值为it_IT,页面显示意大利语 - 尝试手动访问
www.mycompany.com/it,会被重写回根路径并显示英文,不会跳转到意大利语页面
内容的提问来源于stack exchange,提问作者KaMZaTa
相关产品推荐
相关产品推荐

