Multilingual QR codes — the fallback chain that works

How to wire one printed sign to seven languages without a splash screen, with the Accept-Language fallback chain that makes multilingual QR codes work.

Jun 6, 2026 16 min read Linked.Codes
Multilingual QR codes — the fallback chain that works

Multilingual QR codes succeed or fail in the half-second between the scan and the first frame of content. A French-speaking visitor in front of a Florentine altarpiece doesn't want a flag picker, a cookie banner, or an English fallback they'll quietly resent. They want French. Their phone is already telling your server what language they read — the question is whether your redirect listens.

This is the operational playbook for that one redirect. Which header to read, what to do when the exact locale isn't translated, when to override the user's pick, how to handle the visitor whose phone language doesn't match their preference, and where the whole chain breaks if you skip a step. The widget further down lets you paste in a real Accept-Language header and watch the fallback chain resolve, language by language, until something matches.

How multilingual QR codes actually pick a language

A QR code is just a printed redirect. Scan it, the phone hits linked.codes/p/altar-1 (or whatever short link is encoded), and the server has roughly 200 milliseconds to issue a 302 Location header before the visitor starts wondering if anything's happening. The choice the server makes in that window is the entire multilingual experience. Get it right and the visitor never notices the machinery. Get it wrong and they think the venue doesn't care about them.

Every modern browser sends an Accept-Language header on every request. The header is a comma-separated, weighted preference list. A French iPhone in standard configuration sends:

Accept-Language: fr-FR,fr;q=0.9,en;q=0.8,en-US;q=0.7

That string means: "I prefer continental French (weight 1.0 implicit), then any French (0.9), then English (0.8), then American English (0.7)." The q value is the quality factor — higher is better, weights between 0 and 1. The default is 1.0 when none is given. The list is sorted client-side; the server doesn't have to re-sort. RFC 9110 specifies the syntax in detail, but those are the only three rules that matter for redirect work.

The redirect reads the list, walks it in order, and serves the first translation it has. No exact match? Drop the region tag and try the base language. No base match? Move to the next entry in the list. No match anywhere? Fall back to the venue's working language. That's the chain. Five lines of pseudocode. The complexity is in the edge cases.

Multilingual QR redirect chain — how Accept-Language resolves to a translation How a multilingual QR redirect resolves Accept-Language to a translation Accept-Language: fr-CA,fr;q=0.9,en;q=0.7 — phone sends this on every request Step 1 — exact locale fr-CA page? No (only fr available) try next ↓ Step 2 — base language fr page? Yes — French translation exists serve → Step 3 — next preferred en page? skipped — step 2 matched Step 4 — venue default it (working language)? skipped — step 2 matched Result Serve /fr/altar-1 — visitor sees European French, which a Quebec reader prefers over English by a wide margin.
The chain walks in priority order. First match wins. The header is opinionated for a reason — it represents the user's explicit OS-level preference, not a guess.

That's it. That's the whole runtime path. Everything else in this post is about what to put in the language table and what to do when the table doesn't cover the case.

What the language table should contain

Translating into every language your platform supports is a trap. Professional translation runs $0.10 to $0.25 per word for tourism copy, and a single placard with 400 words of wall text costs $40 to $100 per language to translate well. Multiply by fifty placards and twelve languages and the program collapses under its own translation invoice before launch.

Three rules keep the table honest.

Match the visitor data, not the platform's language list. Most ticketing systems and most venue analytics tools report country of origin for visitors. The top five countries usually account for 80% of foreign visitors. Translate into the languages those five countries speak (and the local language). For a museum in Florence, that's typically English, French, German, Spanish, and the local Italian. For a Tokyo shrine, English, Mandarin, Korean, and Japanese.

Three good translations beat seven mediocre ones. A visitor reading their own language poorly translated rates the experience worse than one reading English, because the awkward phrasing reads as the venue not caring. The bar is "a native speaker can't tell this was translated by anyone other than a careful human." Anything below that bar is a downgrade.

Machine translation is for visitors, not venues. A visitor whose language you don't serve will reach for Chrome or Safari's built-in page translation. That's their call and they don't blame you for the quality. Putting auto-translated copy behind a venue-branded redirect inverts the responsibility — now the awkward phrasing is yours. Either pay a human or don't translate.

International tourist arrivals hit 1.4 billion in 2024 — 99% of pre-pandemic levels, per UN Tourism's annual barometer. A visitor crossing into a country whose language they don't speak is the default tourism case, not the exception. The redirect that respects their language is the layer venues should plan around first.

For a venue that doesn't have visitor-mix data, a sensible European default is: local language plus English, French, German, Italian, Spanish. Add Japanese and Mandarin if East Asian group tours are a meaningful fraction of summer bookings. Arabic for venues serving Gulf travellers. The broader operational rules in the tourism QR playbook cover audio-guide and exhibit-page choices on top of the language layer.

The fallback chain — try this with your own header

Paste an Accept-Language header into the picker below and watch the chain resolve against a sample tourism site that has translations in English, French, German, Italian, Spanish, and Japanese. The output shows which step matched, which translations got skipped, and what the visitor actually sees.

Accept-Language fallback resolver
Try a preset:
Resolution chain — translations available: en, fr, de, it, es, ja

The Brazilian preset is the interesting one. A Portuguese-speaking visitor reading pt-BR,pt;q=0.9,es;q=0.7 lands on the venue's Spanish page if Portuguese isn't translated — because the visitor put Spanish above English in their preference list. That's right. Spanish and Portuguese share enough vocabulary that a Brazilian reader prefers Spanish to English. The header is doing real work the venue couldn't have predicted.

The wildcard preset is the other interesting case. Some scripted browsers and older devices send just * — meaning "I accept anything." That's not the visitor expressing a preference. The right behaviour is to serve the venue default and show the manual switcher prominently so a human reader can correct the guess.

When the Accept-Language header is wrong

The phone sends the OS-level language. That's set when the phone was bought and rarely revisited. Two cases break the assumption.

Travellers on someone else's phone. A British grandmother using her German daughter-in-law's iPhone to scan a museum placard reads English at home but is about to receive a German page. The detection is technically correct — the phone is set to German — but it's wrong about the human. The visible manual switcher fixes this in one tap.

Devs and tinkerers with weird locales. A non-trivial number of phones in any high-traffic tourist destination have Accept-Language strings that don't match the speaker. Developers set their phones to English-US even when they speak German. Expats keep their phones in their original language. People who bought a phone abroad never changed the locale. None of this matters if the manual switcher is visible — the visitor taps the right flag and moves on. It matters a lot if the switcher is buried in a hamburger menu.

The switcher belongs at the top of every translated page, visible without scrolling, with the language names written in their own script: English not EN, Deutsch not DE, 日本語 not JP, العربية not AR. A two-letter code is a developer convenience; a self-named language is a reader convenience. Reader wins.

The override should also stick. Once a visitor manually picks German, the redirect should remember that choice for the rest of their visit — usually with a short-lived cookie tied to the venue domain. The cookie reads on subsequent scans (different placard, same venue), the visitor stays in German throughout the tour, and the cookie expires after a day so the next visitor from a different language community gets the auto-detection again.

A 24-hour lang cookie scoped to the venue's redirect domain is the cleanest version of this. First scan reads Accept-Language and sets lang=fr. Subsequent scans within the venue read the cookie first and only consult Accept-Language if the cookie is missing or expired. The visitor's language follows them through the building.

Language-cookie pattern — multilingual QR codes that remember the visitor's choice Language-cookie pattern — multilingual QR codes that remember First scan read Accept-Language set lang=fr (24h) Manual override visitor taps Deutsch overwrite lang=de Next placard cookie wins serve German directly Cookie rules — keep them honest • 24-hour expiry — next visitor's phone gets fresh detection • Scoped to the venue redirector — not third-party tracking • Cleared by the visible "language" switcher in the page header • SameSite=Lax, Secure, HttpOnly when possible • Functional, not analytic — no banner needed under GDPR • Falls back to Accept-Language if cookie missing
One cookie, one purpose, one day. The chain reads cookie first, header second, default third. The visitor's language follows them through the visit without a banner.

A functional cookie this minimal doesn't need a GDPR consent banner. It's analogous to a session cookie or a shopping-cart cookie — strictly necessary for the requested service (a translated page the visitor explicitly chose). The European Data Protection Board's guidance on cookie consent draws the line at tracking and profiling, not language preferences. The full text is in the EDPB's 2023 cookie guidelines.

The cookie is also the cleanest way to handle the audio-guide case. A visitor who picked German for the first wall placard gets German audio at every numbered stop automatically. Without the cookie, every QR redirect re-reads Accept-Language from scratch, and the visitor who manually overrode the language on placard one finds themselves dropped back into auto-detection at placard two. The cookie removes that drift.

A QR + multilingual redirect stack on your own short domain, no recurring SaaS line item, runs the fallback chain at the edge in single-digit milliseconds.

See the lifetime tier

Encoding the language in the printed QR — three patterns

There's a design question that comes up the moment a venue starts shipping multilingual placards: should the printed QR encode the language directly, or should the redirect figure it out at runtime? Three patterns are in the wild.

One QR per placard, runtime language detection. The placard prints one QR pointing at linked.codes/p/altar-1. The redirect detects the visitor's language. This is what the rest of this post has assumed. It's the right answer for almost every case because reprinting placards is expensive and language tables change.

One QR per placard per language, with language baked into the URL. The placard prints five QRs side by side, each pointing at linked.codes/p/altar-1-fr, altar-1-de, etc. with a flag icon beside each. This works mechanically but it's terrible visual design — five QRs on a small placard look like a circuit board and visitors don't know which one to scan. The flag icons help but the placard becomes unreadable from more than a metre away. Acceptable for outdoor information signs with lots of space. Wrong for compact wall placards.

One QR per language, separate placards for separate language readers. A nature reserve might print "English visitors scan here" on one sign and "Deutsche Besucher scannen hier" on another, fifty metres apart along the trail. This is the right call for venues where visitors self-segregate by language — a Spanish-speaking tour group on a fixed itinerary. It's overkill for a museum where every visitor walks past every placard.

The runtime-detection pattern wins for ninety percent of venues. The decision becomes hard only when the venue's analytics show a clear segmentation of visitor flow by language — and even then, the cookie pattern usually does the segmentation better than physical placement does.

Three placard patterns for multilingual QR codes — runtime detection, per-language URLs, separate signs Three placard patterns for multilingual QR codes — which one fits the venue Runtime detection One QR per placard Redirect picks language 90% of venues Reprint-proof QR per language FR DE EN IT ES 5 QRs side by side Reads like a circuit board Visitor confused Outdoor info signs only Wrong for wall placards Separate signs EN DE 50m apart on the trail "English visitors scan here" "Deutsche Besucher hier" Fixed tour groups Overkill for museums
Three placards, three trade-offs. The runtime-detection pattern is the only one that survives a translation-table change without a reprint, which is why it wins for almost every venue.
The visitor doesn't scan a QR code. They scan to read something. Treat the language layer like the venue treats lighting and acoustics — invisible when it works, glaringly wrong when it doesn't.

The five places multilingual QR programs break

Across enough deployments, the same five mistakes show up. None of them are exotic.

Translations done by machine and presented as native. Every native speaker spots this in the first paragraph. The visitor doesn't have evidence the venue did it on purpose, just evidence the venue doesn't care. Pay a human translator for the languages you want to serve, or don't serve those languages at all. The middle path — auto-translation with a human "review" — usually means the reviewer reads English and tweaks the comma placement, which fixes nothing.

Language switcher buried in a menu. The switcher belongs at the top of the page, visible immediately, with self-named language labels. A flag-icon row that fits on one line of a phone screen takes thirty pixels of vertical space and saves the visit. A "Languages" entry inside a hamburger menu is a usability failure dressed as cleanliness.

No fallback to base language. A visitor with pt-BR lands on the English page because the venue only translated to pt-PT and the codes don't match exactly. Strip the region. pt-BR falls through to pt. The Portuguese page may have minor regional differences a Brazilian reader notices, but it's vastly closer to their language than English is.

Manual overrides that don't stick. The visitor manually picks Spanish on placard one. The next placard re-runs Accept-Language detection and serves German again. Set the cookie. Read it on subsequent requests. This is one of the most common mistakes and it makes the whole multilingual layer feel broken even when every other part works.

Translating the wall text without translating the vCard contact card or audio guide. A visitor reading German on the placard hits the audio-guide QR and gets English audio. Or scans the "follow the curator" QR and downloads an English-language vCard. The language has to follow the visitor across every QR-driven surface in the venue. The cookie pattern is what makes that work.

What this looks like for the venue operator

Setting up a multilingual QR program at a small heritage venue takes a different shape from the version a big national museum runs. The small venue has fewer placards, fewer languages, no in-house translation budget, and no engineering team. Three things make the program fit that scale.

First, a short-link platform that does language routing as a first-class feature, not a configuration mode buried behind enterprise pricing. The redirect rules live in the platform and update from a dashboard, not a YAML file. The QR codes platform docs cover the dynamic-redirect setup that this whole pattern depends on.

Second, a single short domain the venue owns and prints across every placard. The custom-domain-for-QR-codes pattern is operationally identical whether the placards are in one language or twelve — the visitor sees scan.museum.example/altar-1 and that domain is what the venue's audience associates with the placard signage. Domain durability is the foundation that the multilingual layer sits on.

Third, a clear separation between the placard system (durable, infrequent change) and the page content (frequent change, language-specific). The QR encodes the durable short link. The page behind the short link gets updated as translations land. New language? Add a row to the table. Updated wall text? Edit five translations. The placards on the wall don't move.

The other QR worth printing alongside the multilingual wall placard is a "find this trail / next exhibit / car park" code that opens a maps app to the right place. The visitor's preferred maps app varies by phone — Apple's on iPhones, Google's on Android, neither on a handful of Huawei devices — and a Location QR code generator writes either a single-place link or a Directions-mode link that resolves correctly across all three without the venue choosing a side. Useful at trailheads, museum exits, and any tourism placard where the next step is "go there" rather than "read more."

The messenger layer follows the same regional-default logic the language layer does. A Yerevan or Tbilisi heritage venue serving Russian-speaking visitors benefits from a Telegram channel QR pointed at the venue's daily-update channel, because Russian-language tourism in the region runs on Telegram rather than WhatsApp — print the messenger the visitor already opens, not the global default.

How do multilingual QR codes detect the visitor's language?

The browser sends an Accept-Language header on every request, listing the user's preferred languages with weighted priorities. The redirect reads that header, walks the list in priority order, and serves the first translation that exists. Exact-locale match first (fr-CA), then base language (fr), then the next preferred language, then the venue default. The visitor never sees a splash screen — the page they land on is already in their language.

Should I serve fr-FR to a fr-CA visitor when I only have continental French?

Yes. A Canadian French reader prefers European French over English by a wide margin — they share enough vocabulary and grammar that the regional differences are minor. Strip the region tag (fr-CA becomes fr) and serve the base-language page. The same applies to pt-BR falling back to pt, es-MX to es, and de-AT to de.

Do I need a cookie banner for the language cookie?

No, if the cookie is strictly functional — used only to remember the visitor's language preference for the current visit. The European Data Protection Board's guidance treats functional cookies (sessions, language, shopping cart) as exempt from explicit consent. Keep the cookie scoped to the venue domain, short-lived (24 hours is standard), and not shared with third parties. Tracking cookies are a different conversation.

What does Accept-Language wildcard (*) mean?

It means "I accept any language" — the visitor's browser hasn't expressed a preference. Some scripted browsers, older devices, and certain accessibility tools send just *. Serve the venue's default language and make the manual switcher prominent so the visitor can correct the guess in one tap.

How many languages should a small venue translate into?

Start with the top five countries of origin from your visitor data — most venues have this in their ticketing system. Translate into the languages those countries speak, plus the local language. For most European venues, that's English, French, German, Italian, Spanish. Japanese and Mandarin for East Asian group-tour traffic. Three good human translations always beat seven mediocre ones — machine translation behind a venue-branded QR damages trust because visitors notice the awkward phrasing.

What if the visitor's phone is set to a language I don't translate?

The fallback chain walks through their entire preference list before giving up. A German phone with English secondary lands on English if German isn't translated. After exhausting the list, the venue default is served. The manual switcher at the top of every page lets the visitor override if they read a language better than their default. Don't try to be clever — let the chain do its work and let the human override what the chain gets wrong.

Should I print separate QRs for each language on the placard?

Almost always no. Five QRs side by side look like a circuit board and make the placard unreadable. Print one QR, do language detection at the redirect, and offer the manual switcher on the resulting page. The exception is venues where visitors self-segregate by language (fixed-itinerary tour groups), in which case separate signs along the route make sense.

Sourcesshow citations

Try it on your own domain

Branded short links and dynamic QR codes, on your subdomain or your own domain. One-time purchase, no per-click fees.