{"record":{"id":"df510c79161089ca","repo":"GoogleChrome/lighthouse","slug":"unsupported-locale-requestedlocale","errorCode":null,"errorMessage":"Unsupported locale '${requestedLocale}'","messagePattern":"Unsupported locale '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"shared/localization/swap-locale.js","lineNumber":52,"sourceCode":"      \"audits[mainthread-work-breakdown].details.headings[1].text\",\n      \"audits[network-rtt].details.headings[1].text\",\n      \"audits[network-server-latency].details.headings[1].text\"\n    ],\n    ...\n */\n\n/**\n * Returns a new LHR with all strings changed to the new `requestedLocale`.\n * @param {LH.Result} lhr\n * @param {LH.Locale} requestedLocale\n * @return {{lhr: LH.Result, missingIcuMessageIds: string[]}}\n */\nfunction swapLocale(lhr, requestedLocale) {\n  // Copy LHR to avoid mutating provided LHR.\n  lhr = JSON.parse(JSON.stringify(lhr));\n\n  if (!format.hasLocale(requestedLocale)) {\n    throw new Error(`Unsupported locale '${requestedLocale}'`);\n  }\n  const originalLocale = lhr.configSettings.locale;\n  const {icuMessagePaths} = lhr.i18n;\n  const missingIcuMessageIds = [];\n\n  if (!icuMessagePaths) throw new Error('missing icuMessagePaths');\n\n  for (const [i18nId, icuMessagePath] of Object.entries(icuMessagePaths)) {\n    for (const instance of icuMessagePath) {\n      // The path that _formatPathAsString() generated.\n      let path;\n      let values;\n      if (typeof instance === 'string') {\n        path = instance;\n      } else {\n        path = instance.path;\n        // `values` are the string template values to be used. eg. `values: {wastedBytes: 9028}`\n        values = instance.values;","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/shared/localization/swap-locale.js#L34-L70","documentation":"Thrown by swapLocale when the requested locale is not registered/available according to format.hasLocale. swapLocale re-renders an existing LHR into a different locale and refuses to proceed if it cannot look up the locale's messages. (A separate later guard also throws if the LHR is missing icuMessagePaths.)","triggerScenarios":"Calling swapLocale(lhr, requestedLocale) where format.hasLocale(requestedLocale) is false — i.e. the locale messages were never registered via format.registerLocaleData.","commonSituations":"Viewer flow where fetching the locale's JSON failed silently or the locale file was not bundled; passing a locale code that Lighthouse does not ship; locale data not registered before swapLocale runs.","solutions":["Register the locale before swapping: fetch the locale JSON and call format.registerLocaleData(requestedLocale, messages).","Gate the UI/locale picker on format.hasLocale so only registered locales are selectable.","Fall back to the original/default locale when the requested one cannot be loaded."],"exampleFix":"// before\nconst { lhr } = swapLocale(originalLhr, requestedLocale); // may throw\n\n// after\nif (format.hasLocale(requestedLocale)) {\n  const { lhr } = swapLocale(originalLhr, requestedLocale);\n} else {\n  await registerLocaleFor(requestedLocale); // loads + registerLocaleData\n}","handlingStrategy":"validation","validationCode":"if (!format.hasLocale(requestedLocale)) {\n  await ensureLocaleRegistered(requestedLocale); // fetch + registerLocaleData\n}\nconst {lhr} = swapLocale(originalLhr, requestedLocale);","typeGuard":"const canSwap = (/** @type {LH.Locale} */ loc) => format.hasLocale(loc);","tryCatchPattern":"try {\n  swapLocale(lhr, requestedLocale);\n} catch (err) {\n  if (err.message.startsWith('Unsupported locale')) {\n    // fall back to original locale\n  } else if (err.message === 'missing icuMessagePaths') {\n    // LHR has no i18n paths; cannot swap\n  } else throw err;\n}","preventionTips":["Register locale data (registerLocaleData) before invoking swapLocale.","Restrict the locale picker to locales for which format.hasLocale is true.","Treat a failed locale fetch as 'locale unavailable' and keep the current locale."],"tags":["localization","locale","swap-locale","i18n"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}