Finds localized pages still showing default-language text
Fetch the audited page with 37AuditsBot's user agent, Web Bot Auth signature and the URL's Basic Auth. HTTP 403, HTTP 429 or a Cloudflare challenge is ERROR (590); any other failure is ERROR (500).
Discover the localized versions β <link rel="alternate" hreflang="β¦" href="β¦"> first; when the page publishes none, <a hreflang href> then <a lang href> switcher links. The page itself, x-default and versions in the page's own language (en-GB for an en-US page) are dropped, and at most maxAlternates (default 10) are kept in document order. No version left is INFORMATION (100): the run is not charged.
Fetch every version in parallel (five at a time, 40 s budget). A version that answers 403, 429, a Cloudflare challenge or a bot wall is WARNING (302); any other non-2xx answer or network error is FAIL (401).
Compare the text β the body text nodes of each page outside script, style, noscript, template and svg, whitespace-collapsed, kept when they have at least 3 words containing a letter (or 6 letters in a script without word spaces, such as Japanese). A version's block counts as untranslated when it appears verbatim on the audited page, or when it has at least 8 words and a two-language detector (Lingua, loaded for the audited page's language and the version's only) attributes it to the audited page's language by a clear margin. Detection is skipped, and the reason recorded in data.languageDetection, when either language has no model, the audited page declares no language, or the two pages share a language.
Text the markup hides at load time is left out of the count first, unless countHiddenText is on: an ancestor with the hidden or inert attribute or aria-hidden="true", an inline style with display:none, visibility:hidden or opacity:0, an <option>, a closed <dialog> or <details>, or a class such as hidden, hide, d-none, invisible or anything ending in -hidden (closed mega-menus, inactive tab panels, validation messages waiting for an error). Untranslated blocks found there are listed on the version's summary check in data.hiddenBlocks with the signal that hid them, so the percentage describes what a visitor sees while nothing is lost. Visually hidden text (sr-only, visually-hidden, screen-reader-text) stays counted: screen readers read it, so an untranslated skip link is a real defect. Text hidden by a stylesheet rule alone cannot be told apart from the markup and stays counted.
Two further kinds of block are then left out of the count and recorded apart on the version's summary check: blocks that match the ignored terms (data.ignoredBlocks: the ignoredTerms preference plus the site's own name from its host, so "Liferay OEM Partner" or "Liferay vs. Adobe" with both names listed) and blocks that look like a name (data.nameLikeBlocks: at most five words besides connectors such as "vs." or "&", every one capitalised or an acronym, none a function or action word such as "a", "to", "you" or "apply", and no sentence punctuation at the end). "Digital Asset Management", "Gartner Peer Insightsβ’", "IM Project Manager" and "Diamond Bar, CA 91765" are names; "Create An Account", "Request a demo", "Skip to Main Content" and "All Rights Reserved." are copy and stay counted.
Judge each version β untranslated / blocks at or above untranslatedFailPercent (default 50) is FAIL (400); at or above untranslatedWarningPercent (default 5) is WARNING (300). Every version also gets one check per distinct untranslated block, in document order and capped at 50 per version, so the list of strings to translate is always in the result: WARNING (303) when the version reached the warning threshold, INFORMATION (101) when it stays under it. A version whose <html lang> primary subtag differs from the hreflang that points at it is FAIL (402); a page without <html lang> is WARNING (301).
Aggregate β ERROR, then FAIL (400, 401, 402), then WARNING, else SUCCESS (200).
Up to five untranslated blocks are kept per version in data.samples, sentence-like copy first (ending punctuation, or mostly lower-case words) and Title Case labels last, so "Please enter a valid email address." is quoted before a product name.
Every row maps to one checkRule* method and one CheckCode. CheckCode suffixes use status ranges: 100 information, 200 success, 300β399 warning, 400β499 fail, 500β599 error.
| CheckCode | Status | When it fires | Recommendation | Why it matters |
|---|---|---|---|---|
37A-LocalizationAuditor-100 | INFORMATION | The page publishes no hreflang alternate and no language-switcher link to another language; nothing is compared and the run is not charged (the check carries notApplicable: true). | If the site exists in other languages, add <link rel="alternate" hreflang="β¦"> for each version to "{url}" so visitors and search engines find them and this audit can compare them. | β |
37A-LocalizationAuditor-101 | INFORMATION | One check per distinct text block still in the audited page's language on a localized version that stays under the warning threshold (at most 50 per version, in document order). The version passes; the check lists what is left to translate. | Translate "{text}" into {hreflang} on "{variantUrl}". | β |
37A-LocalizationAuditor-300 | WARNING | A localized version keeps between untranslatedWarningPercent (inclusive) and untranslatedFailPercent (exclusive) of its text blocks in the audited page's language. | Translate the remaining {baseLang} strings on "{variantUrl}" (menus, buttons, footer, form messages), starting with "{sample}", "{sample}", "{sample}"; if the {hreflang} version is not ready, remove it from the published alternates until it is. | Visitors who pick their language and still meet untranslated menus, buttons or messages read the site as careless; the Liferay 2026 Website Localization Report found 56% of multilingual consumers walked away from a purchase over a poorly adapted site. |
37A-LocalizationAuditor-301 | WARNING | The audited page, or a fetched localized version, has no lang attribute on <html> (or an empty one). | Set <html lang="{hreflang}"> on "{pageUrl}": the hreflang that points at it promises {hreflang}. For the audited page: set <html lang="β¦"> to the language the page is written in. | Without a declared language, screen readers mispronounce the page and search engines may file it under the wrong language, so the translation reaches fewer of the people it was made for. |
37A-LocalizationAuditor-302 | WARNING | A localized version answered HTTP 403, HTTP 429, a Cloudflare challenge or a bot wall, so it could not be compared. | Allow 37AuditsBot on {host} (allowlist its user agent or verify its Web Bot Auth signature, see https://www.37audits.com/bot) so the {hreflang} version can be audited. | A locale the auditor cannot read is a locale nobody is checking; problems on it stay invisible until a customer finds them. |
37A-LocalizationAuditor-303 | WARNING | One check per distinct text block still in the audited page's language on a localized version that reached the warning threshold (at most 50 per version, in document order). | Translate "{text}" into {hreflang} on "{variantUrl}". | Each untranslated menu item, button or message is a moment where a visitor who asked for their language is answered in another one; listing them one by one is what lets a translator fix them. |
37A-LocalizationAuditor-400 | FAIL | A localized version keeps at least untranslatedFailPercent of its text blocks in the audited page's language. | Translate "{variantUrl}" into {hreflang} before offering it as the {hreflang} version, or remove that alternate until the translation exists; today visitors who choose {hreflang} read {baseLang} content such as "{sample}", "{sample}", "{sample}". | A language option that opens a page still written in the default language tells the visitor the brand did not bother; most leave, and the Liferay 2026 Website Localization Report found 32% lose trust in the brand itself. |
37A-LocalizationAuditor-401 | FAIL | A localized version could not be fetched: a network error, a timeout or an HTTP status other than 2xx that is not a block. | Fix or remove the {source} link to "{variantUrl}": a visitor choosing {hreflang} currently gets {HTTP 404 / error} instead of the page. | A language link that leads to an error page loses the visitor at the moment they asked to be served in their language, and search engines drop broken alternates from results. |
37A-LocalizationAuditor-402 | FAIL | A localized version declares a primary language on <html lang> other than the one the hreflang (or switcher link) promised for it. | Make "{variantUrl}" declare lang="{hreflang}", or point the {hreflang} alternate at the page that really serves that language instead of one declaring {declaredLang}. | When the promised and declared languages disagree, search engines show the wrong page to the wrong audience and screen readers read it in the wrong voice. |
37A-LocalizationAuditor-500 | ERROR | The audited page could not be fetched: network error, timeout or a non-2xx status that is not a block. | Make "{url}" reachable over HTTP(S) and re-run the audit. Last error was "{error}". | β |
37A-LocalizationAuditor-200 | SUCCESS | All rules passed. Message is "{url}" ({lang}) and its {n} localized versions ({hreflangs}) each keep text in {lang} under {warningPercent}% of their text blocks (highest: {hreflang} at {percent}%). data.variantSummary lists every version with its percent, untranslatedCount, nameLikeCount and ignoredCount. | β | β |
37A-LocalizationAuditor-590 | ERROR | The audited page answered HTTP 403, HTTP 429 or a Cloudflare challenge, so 37AuditsBot was blocked before it could read the page. | Allow 37AuditsBot in your firewall or bot protection: allowlist its user agent, or verify its Web Bot Auth signature. See https://www.37audits.com/bot. | While 37AuditsBot is blocked this audit cannot look at the site, so problems on it go unreported. |
Example messages, measured on https://www.liferay.com/ and https://liferay.dev/ on 2026-10-18:
The result message (also the message of the 200 check) is a summary: the audited URL and its default language, how many localized versions were found, and the verdict in figures for the versions concerned. Check messages carry the detail.
result, pass β "https://www.liferay.com/" has its default language set to en-US. 6 localized versions (es-ES, it-IT, fr-FR, pt-BR, de-DE, ja-JP) were found; all of them keep untranslated text blocks under 5% (highest: de-DE at 4%).
result, untranslated β "https://petrobras.com.br/" has its default language set to pt-BR. 1 localized version (en-US) was found; it shows untranslated text blocks at 36% (48 out of 135).
300 β "https://www.liferay.com/de/" (de-DE) still shows 36 of its 321 text blocks (11%) in en-US: 35 copied verbatim from "https://www.liferay.com/" and 1 recognised by language detection, e.g. "Request a demo", "by 233 verified users as of September 2026, Source:", "Please enter a valid email address.".
400 β "https://dev.liferay.com/es/" (es-ES) is mostly the en-US page: 37 of its 41 text blocks (90%) are still in en-US, 37 copied verbatim from "https://liferay.dev/" and 0 recognised by language detection, e.g. "Explore the Liferay Community Universe.", "The Liferay Community has been integral to our journey.", "Open Source. For Life.".
303 β "Please enter a valid email address." is still in en-US on "https://www.liferay.com/de/" (de-DE): it appears verbatim on "https://www.liferay.com/".
101 β "Create An Account" is still in en-US on "https://www.liferay.com/es/" (es-ES): it appears verbatim on "https://www.liferay.com/". The version stays under the 5% warning threshold.
100 β "https://www.37audits.com/" declares lang="en" and publishes no hreflang alternates or language-switcher links, so there is no localized version to compare.
Findings on a version carry variantUrl, hreflang, source (hreflang or switcher), statusCode, error, blocked, declaredLang, baseUrl, baseLang, totalBlocks, identicalCount, detectedCount, untranslatedCount, distinctUntranslated, percent, warningPercent, failPercent, samples, nameLikeCount, nameLikeBlocks, ignoredCount, ignoredBlocks, hiddenCount, hiddenBlocks (text β hiding signal, such as hidden, aria-hidden, style, <details> or class:atb-tab-panel-hidden) and languageDetection in data. A 303 or 101 finding carries variantUrl, hreflang, baseUrl, baseLang, text, reason (copied or detected), occurrences, xpath (the block's first occurrence on the version, browser style: /html/body/div[2]/footer/span[1], with /text()[n] when the element mixes several text nodes), listed and distinctUntranslated.
Set per monitored URL; the defaults apply to Quick Audit.
| Key | Type | Default | Range | Effect |
|---|---|---|---|---|
untranslatedWarningPercent | integer | 5 | 1β100 | Share of a version's text blocks still in the audited page's language from which 300 fires and the per-block list switches from INFORMATION (101) to WARNING (303). Brand and product names that the name heuristic misses count too, so a site with many of them may raise this. |
untranslatedFailPercent | integer | 50 | 1β100 | Share from which 400 fires instead. A value below the warning threshold makes both equal. |
maxAlternates | integer | 10 | 1β20 | How many localized versions are fetched, in document order. Each one is a request against the audited site. |
ignoredTerms | string | β | β | Product, company and people names allowed to stay untranslated, one per line or separated by semicolons. A block made only of these terms (plus connectors, numbers and punctuation) is left out of the count and listed in data.ignoredBlocks. The site's own name from its host is always ignored. |
countHiddenText | boolean | false | β | Count text the markup hides at load time (closed menus, inactive tabs, validation messages) like visible text. Off, such blocks are left out of the percentage and listed in data.hiddenBlocks instead. Turn it on when menus and messages matter as much as the visible page. |
| Status | Description | Test logic |
|---|---|---|
| INFORMATION | The page has no localized version to compare, or a passing version still has a few untranslated blocks | No hreflang alternate or switcher link to another language (100; the run is not charged), or one check per untranslated block on a version under the warning threshold (101; the response stays SUCCESS). |
| SUCCESS | Every localized version is translated and reachable | Each version answered 2xx, declares the promised language, and keeps untranslated text under untranslatedWarningPercent (200). |
| WARNING | Some text is untranslated, a page declares no language, or a version could not be verified | Untranslated share between the thresholds (300) with one check per untranslated block (303), missing <html lang> (301), or a version that blocked the bot (302). |
| FAIL | A version is mostly untranslated, broken, or in the wrong language | Untranslated share at or above untranslatedFailPercent (400), a version that does not resolve (401), or a declared language that contradicts the hreflang (402). |
| ERROR | The auditor could not compare anything | The audited page could not be fetched (500) or 37AuditsBot was blocked (590). |
A visitor who switched to their language and meets English buttons, validation messages or a whole English page reads it as a signal about the brand, not a technical glitch. The Liferay 2026 Website Localization Report puts the cost at lost purchases for 56% of multilingual consumers and lost brand trust for 32%.
Search engines index each hreflang version for its audience. A Spanish URL full of English text ranks for neither language well.
A Title Case block without a function or action word is treated as a name and left out of the count, so a forgotten button written that way ("Download Brochure") is missed; one with such a word ("Create An Account", "Apply Thank You") is counted. Review data.nameLikeBlocks on the summary check when a locale passes unexpectedly, and add genuine names to ignoredTerms when they slip through (a job title containing "and" or "for", a tagline).
On liferay.com the heuristic removes 29 of the 51 distinct texts reported on 2026-10-18, leaving the UI strings, the footer and the taglines, and every locale drops from 7β11% to about 3%.
Language detection is deliberately conservative: it runs only on blocks of eight words or more and needs a clear margin, because short marketing copy mixing brand names ("Explore o Headless CMS") is otherwise attributed to English.
Tone, idiom, cultural fit, machine-translation quality, and date, currency or address formats: the article's remaining findings need a fluent reader.
Only the audited URL and its own localized versions are compared; other pages of the site may differ.
Versions in the audited page's own language (en-GB for an en-US page) are skipped, since their text is expected to match.
The language detector covers 75 languages; a version in a language without a model is scored by the verbatim comparison alone, which data.languageDetection says.
One audit fetches the page plus up to maxAlternates versions, five at a time, so cost is 2. Lower maxAlternates on sites with many locales if the load matters.
This documentation is built and hosted on Mintlify, a developer documentation platform.
Add this auditor to your monitoring setup and start identifying issues on your websites today.