To redirect based on browser language in OpenResty Edge, create a page rule that matches the request URI / and the Accept-Language request header sent by the client, then attach a redirect action to the matching locale, such as /fr/. Mark it an Always-Top rule so it runs first, and add a catch-all rule that falls back to /en/ for every other language. The change ships to every gateway node with no server reload, restart, or binary upgrade.

In this post, we walk through both rules step by step in the OpenResty Edge Admin console, and verify them with curl and a browser. If you are after a simpler rule, see how to redirect HTTP to HTTPS with a 301 page rule first.

Diagram: OpenResty Edge redirects visitors to language-specific URIs based on the Accept-Language header

The origin site that serves different languages by location

Let’s say we have an origin site which supports different languages at different locations. For example, this is the /en/ location.

$ curl 'http://test-edge.com/en/'
Hello, world!

Note the English text, “Hello World”.

And we also have a French version under the /fr/ location.

$ curl 'http://test-edge.com/fr/'
Bonjour, le monde!

This is French text.

Create a page rule to redirect by Accept-Language

The goal here is when the client accesses the root location, /, we can automatically redirect to a language-specific location. We’ll use the Accept-Language request header sent by the clients.

OpenResty Edge redirecting the root URI to a language-specific location based on the Accept-Language header

As always, let’s go to the OpenResty Edge’s Admin web console. This is our sample deployment of the console. Every user has her own local deployment.

This time we use our on-going sample application for the test-edge.com domain.

Let’s enter this application.

Opening the test-edge.com application in the OpenResty Edge Admin console

We already have an upstream defined.

The my_backend upstream already defined for the application

This my_backend upstream has only 1 backend server. It is also the origin site we just tested at the beginning.

The my_backend upstream with a single backend server pointing to the origin site

And we also have a page rule already defined.

The existing page rule list for the application

This page rule sets up a reverse proxy to the my_backend upstream which we just saw earlier.

The existing page rule configured as a reverse proxy to the my_backend upstream

Create a new page rule.

Creating a new page rule in the OpenResty Edge console

We enable a rule condition to check for the URI /.

Enabling a rule condition to match the request URI

Let’s see all the variables we can choose from.

The list of variables available for a page rule condition

Select URI.

Selecting the URI variable for the condition

We choose the string equality operator.

Choosing the string-equality operator for the URI condition

The string-equality operator selected for the URI condition

Enter the value / to match the root location only.

Entering / as the value to match the root location only

And a second condition to check the language.

Adding a second condition to check the request language

Choosing the variable for the language condition

We choose “Request header” for the variable.

Selecting Request header as the variable for the language condition

Enter the request header name, “Accept-Language”.

Entering Accept-Language as the request header name to match

For the match operator,

Opening the match-operator list for the Accept-Language condition

We choose “prefix”.

Choosing the prefix match operator for the Accept-Language header

This is because when multiple languages are specified at the same time, we only care about the first one.

For the matched value, we select the regular expression type, “Regex”.

Selecting the Regex match type for the Accept-Language value

The Regex match type selected for the Accept-Language value

Enter the regex value, “fr\b”.

Entering the regex fr\b to match French tags such as fr and fr-CA

The “\b” sequence means matching a word boundary. Then both “fr” and “fr-CA” will get matched, for example.

Here we check the “Caseless” box to do case insensitive matching.

Enabling the Caseless option for case-insensitive Accept-Language matching

Note that we now have two conditions and they are AND’d together. That is, both of them must be matched for the actions below to be executed. The conditions are now complete.

Now we add a new action.

Adding a new action to the page rule

Search for the action “redirect”.

Choose the action type, “redirect”.

Choosing the redirect action type

Then we configure the target URI to jump to.

Configuring the target URI for the redirect action

Choose “custom”. We want to enter the URI ourselves.

Choosing a custom target URI for the redirect

Enter “/fr/”.

Entering /fr/ as the redirect target for French visitors

Keep the remaining fields intact.

Keeping the remaining redirect fields at their defaults

We skip any subsequent rules if this rule is matched.

Enabling skip of subsequent rules when this rule matches

We need to make sure that this rule always runs before other rules. Let’s mark it as an Always-Top rule. An Always-Top rule is not a “normal rule”.

Marking the rule as an Always-Top rule so it runs before normal rules

Save this rule.

Saving the French Accept-Language redirect rule

We can see the newly added page rule is indeed on the top of the rule list.

The new redirect rule appearing at the top of the page rule list

It is indeed before our previous proxy rule.

We need to make a new release to push out our new page rule, as always.

Making a new configuration release to push out the page rule

Shipping the new configuration release to the gateway clusters

Ship it!

The configuration release fully synchronized to all gateway clusters

It is fully synchronized.

The new page rule pushed to every gateway cluster and server

Now the new page rule has been pushed to all the gateway clusters and servers.

Our configuration changes do NOT require server reload, restart, or binary upgrade. So it’s very efficient and scalable.

OpenResty Edge syncs configuration to gateway nodes with no reload, restart, or binary upgrade

Test the French Accept-Language redirect with curl

On the terminal, we can send HTTP requests with curl.

curl -I -H 'Accept-Language: fr-CA, fr, en' http://test-edge.com/

Note that we specify 3 languages: fr-CA, fr, and en. So French takes precedence over English for this request.

Sending a curl request with Accept-Language fr-CA, fr, en to test the redirect

Run this command.

Note that it is indeed a redirect to /fr/.

The response showing a redirect to /fr/ for a French Accept-Language header

We can make curl follow redirects automatically.

curl -L -H 'Accept-Language: fr, en' http://test-edge.com/

Note the -L option.

Running curl with -L to follow the language redirect automatically

Run this command.

We can see the French text returned.

The French page content returned after following the redirect

Add a fallback page rule to redirect other languages to English

Next we’d add a generic page rule to redirect to the English page for other languages.

Creating a second page rule for the English fallback

Create a new page rule.

Enabling a URI condition on the fallback rule

We still enable a rule condition to check for the URI /.

Selecting the URI variable for the fallback condition

The URI variable selected for the fallback condition

Still select URI.

Choosing the string-equality operator for the fallback condition

Still string equality.

Preparing to enter the URI value for the fallback condition

Entering / to match the root location for the fallback rule

Enter value / as before.

The fallback condition matching the root URI without a language check

The condition is now complete. This time we don’t bother checking the request header.

Add a new redirect action as before.

Adding a redirect action to the fallback rule

Choosing the redirect action type for the fallback rule

Configuring the redirect target for the fallback rule

Choosing a custom target URI, then entering /en/ as the fallback redirect target

This time, we enter “/en/” for the target URI.

Enabling skip of subsequent rules for the fallback rule

We skip any subsequent rules if this rule is matched.

Keeping the fallback rule running before other normal rules

We still make sure that this rule runs before any other “normal rules”.

Saving the English fallback redirect rule

Save this rule.

The fallback rule ordered before the proxy rule but after the French rule

We can see the newly added page rule is before the proxy rule but after the French language rule.

Making a new configuration release again

Make a new configuration release again.

Shipping the updated configuration release

Shipping the release to all gateway clusters again

Ship it again!

The updated configuration synchronized again

It is synchronized again.

Test the English fallback redirect in a browser

We can test the / location with the web browser. This web browser uses the English language setting.

http://test-edge.com/

We can see the English text “Hello, world” is displayed in the web browser.

The browser showing the English page with the URL rewritten to /en/

And we can also see from the address bar, the URI becomes /en/. This is what I’d like to cover today.

FAQ

How does OpenResty Edge detect the visitor’s language?

It reads the Accept-Language request header, which clients send with each request. The page rule matches that header with a prefix condition and a regex such as fr\b, so both fr and regional variants like fr-CA match. Any client that sets Accept-Language—including curl—triggers the same redirect.

Can I redirect by browser language without editing nginx.conf?

Yes. The whole rule is built in the OpenResty Edge Admin console: a URI condition, an Accept-Language header condition, and a redirect action. After you publish a release, the rule is pushed to every gateway cluster with no server reload, restart, or binary upgrade.

How do I set a default language fallback?

Add a second page rule that matches only the root URI /, with no Accept-Language condition, and a redirect action to /en/. Order the language-specific rules above it so the fallback runs last. In this tutorial the French rule matches French clients first, and every other language falls through to the English page.

Why mark the language redirect as an Always-Top rule?

An Always-Top rule always runs before normal rules, so the language redirect is evaluated before the reverse-proxy rule that serves the root location. Combined with “skip subsequent rules when matched,” this guarantees the client is redirected to the correct locale before any other rule can respond.

What happens when the client sends several languages at once?

The Accept-Language header can list multiple languages, for example fr-CA, fr, en. Because the condition uses a prefix match, only the first (highest-priority) language is considered. In that example French takes precedence over English, so the request is redirected to /fr/.

What is OpenResty Edge

OpenResty Edge is our all-in-one gateway software for microservices and distributed traffic architectures. It combines traffic management, private CDN construction, API gateway, security, and more to help you easily build, manage, and protect modern applications. OpenResty Edge delivers industry-leading performance and scalability to meet the demanding needs of high concurrency, high load scenarios. It supports scheduling containerized application traffic such as K8s and manages massive domains, making it easy to meet the needs of large websites and complex applications.

If you like this tutorial, please subscribe to this blog site and/or our YouTube channel. Thank you!

About The Author

Yichun Zhang (Github handle: agentzh), is the original creator of the OpenResty® open-source project and the CEO of OpenResty Inc..

Yichun is one of the earliest advocates and leaders of “open-source technology”. He worked at many internationally renowned tech companies, such as Cloudflare, Yahoo!. He is a pioneer of “edge computing”, “dynamic tracing” and “machine coding”, with over 22 years of programming and 16 years of open source experience. Yichun is well-known in the open-source space as the project leader of OpenResty®, adopted by more than 40 million global website domains.

OpenResty Inc., the enterprise software start-up founded by Yichun in 2017, has customers from some of the biggest companies in the world. Its flagship product, OpenResty XRay, is a non-invasive profiling and troubleshooting tool that significantly enhances and utilizes dynamic tracing technology. And its OpenResty Edge product is a powerful distributed traffic management and private CDN software product.

As an avid open-source contributor, Yichun has contributed more than a million lines of code to numerous open-source projects, including Linux kernel, Nginx, LuaJIT, GDB, SystemTap, LLVM, Perl, etc. He has also authored more than 60 open-source software libraries.