Home Dynamic QR Language Routing
Language Routing
Answer in the language the phone already asked for, without asking again.
Halle Nord screws its wall labels to the wall three weeks before a show opens. The visitors come from everywhere and the building is in Berlin, so language is the only signal that follows the reader rather than the room.
The rule engine
What the scanner gets
The rule lists "de", not "de-DE". The exact tag misses and the primary subtag catches, so every German-speaking variant reaches one label instead of needing a rule each.
Every preference in the header is tried in turn: an exact tag match anywhere beats a primary-subtag match anywhere. That is two passes rather than one, and it is why en-GB can separate while fr-CA still reaches the French label.
Get this wrong and the visitor who flew furthest is the one standing in front of a label they cannot read. The label is screwed to the wall; the rule is the only part still editable.
no subscription · pay per scan · nothing to cancel
The visitor who flew furthest is the one you lose
Routing translations by country is the shortcut everyone reaches for first, and it is wrong in exactly the cases that matter most: the visitor, the migrant, the border town, the multilingual country.
- Switzerland has four national languages and one country code.
- A tourist scanning your museum sign is in your country and does not read your language.
- A language picker asks the reader to solve a problem their browser already solved.
- Machine-translating the destination answers the same question with worse information.
What Halle Nord set up before the labels went up
Group the locale tags you publish
A group holds the tags that share a destination. Use a primary subtag like de to catch every German variant, or a full tag like en-gb to separate one.
[{ "name": "Deutsch", "values": ["de"] }]The header is read in preference order
Accept-Language is an ordered list. Each preference is tried in turn, and an exact tag match anywhere beats a primary-subtag match anywhere · two passes, not one.
An untranslated language gets a page you wrote
A reader whose language you do not publish lands on your default rather than a machine translation of it. A missing header does the same.
What one wall label does for a room full of languages
- Split en-GB from en-US, or do not
langMatch the full tag to separate a regional variant, or the subtag to treat them alike. The precision is yours to choose per group.
- Correct for people who travelled
Language follows the reader, not the border they happen to be standing behind. That is the whole reason to prefer it over country for words.
- No picker, no extra tap
The preference is already in the request. Asking for it again is a step that loses readers and answers worse.
- Pairs with market routing
Country decides prices and legal text; language decides the words. Each is its own rule at 5 credits per change.
- An honest fallback
An unpublished language reaches a default written by a person, rather than an automatic translation nobody proofread.
- Nothing to reprint when you add a language
A new translation is a new group on the same rule. The label on the wall does not know how many languages you publish.
Questions
Which header does language routing read?
Accept-Language, which browsers send on every request from the preference the reader set in their operating system or browser. Nothing is asked of them at scan time.
How are en-GB and en-US told apart?
By matching the full tag. Each preference in the list is checked for an exact tag match across all your groups first, and only then for a primary-subtag match. A group holding en-gb catches British English while a group holding en catches whatever is left.
Should I route by language or by country?
By language when the difference is words, and by country when the difference is the storefront, the price or the legal text. A multilingual country makes the distinction obvious.
What if the browser sends no language at all?
The scan takes your default destination, and so does a preference list matching none of your groups. An unpublished language is never sent somewhere unintended.
Do other QR platforms do this?
Several ship a language condition. We have not audited how each one matches, so we are not going to characterise them. What this page can show you is exactly how ours behaves, including the case where it deliberately does not match.