Let's say you have an nginx set up to serve static files in a localized manner (for example HTML exported by next.js).
Your paths may look like this:
/de-DE
/en-US
/de-DE/about-us
/en-US/about-us
...
Now, if users reach the root of your domain, you want them to be redirected to the best matching language-specific path. There is a module, which you can re-compile nginx with to get support for this, but it completely ignores the quality setting: https://www.nginx.com/resources/wiki/modules/accept_language/
An alternative is to make the redirect using nginx's support for JavaScript.
Here's what the JavaScript for this might look like:
var defaultLocale = "en-US";
var locales = ["en-US", "de-DE"];
function getBestLocale(acceptLanguage) {
if (!acceptLanguage || !acceptLanguage.trim()) {
return defaultLocale;
}
var localeSearch = locales.map((locale) => ({ locale, lowerLocale: locale.toLowerCase() }));
var bestLocale = defaultLocale;
var bestQuality = -1;
// Example (q is 1 by default, but can be set manually): en-US,en;q=0.5,de;q=0.9
var acceptLanguageParts = acceptLanguage.toLowerCase().split(",");
for (var i = 0; i < acceptLanguageParts.length; i++) {
var parts = acceptLanguageParts[i].split(";");
var locale = parts.shift();
var q = parts.find((part) => part.startsWith("q="));
var quality = q ? parseFloat(q.substr(2)) : 1;
if (quality > bestQuality) {
// Check for exact match first
var match = localeSearch.find((l) => l.lowerLocale === locale);
if (match) {
bestLocale = match.locale;
bestQuality = quality;
continue;
}
// Check for for simple prefix match (for example if locale="en", test for "en-")
var prefix = locale + "-";
match = localeSearch.find((l) => l.lowerLocale.startsWith(prefix));
if (match) {
bestLocale = match.locale;
bestQuality = quality;
continue;
}
// Check for for less ideal prefix match (for example if locale="en-US", test for "en-")
prefix = locale.split("-")[0] + "-";
match = localeSearch.find((l) => l.lowerLocale.startsWith(prefix));
if (match) {
bestLocale = match.locale;
bestQuality = quality;
continue;
}
}
}
return bestLocale;
}
function localeRedirect(r) {
var locale = getBestLocale(r.headersIn["Accept-Language"]);
r.headersOut["Location"] = "/" + locale + "/";
r.status = 302;
r.sendHeader();
r.finish();
}
export default { localeRedirect };
Now, all you need to do is adjust your nginx configuration to load and execute this script:
js_import /etc/nginx/conf.d/nginxLib.js;
server {
# ...
location = / {
js_content nginxLib.localeRedirect;
}
# ...
}
Also make sure that you have loaded the JavaScript module in your root nginx.conf:
load_module modules/ngx_http_js_module.so;