{"record":{"id":"2a0402c944bcf192","repo":"jeessy2/ddns-go","slug":"i18n-no-such-language-lang-in-langdict-lan","errorCode":null,"errorMessage":"i18n: No such language \"${lang}\" in langDict ${langDict}","messagePattern":"i18n: No such language \"(.+?)\" in langDict (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"static/i18n.js","lineNumber":299,"sourceCode":"}\n\nconst i18n = (keyOrLangDict) => {\n  let key = keyOrLangDict;\n  let langDict = keyOrLangDict;\n  if (typeof keyOrLangDict === 'string') {\n    langDict = I18N_MAP[keyOrLangDict];\n  } else {\n    key = null;\n  }\n  if (!langDict) {\n    console.warn(`i18n: No translation for key \"${key}\"`);\n    return key;\n  }\n  const lang = getLocalLang(Object.keys(langDict));\n  if (lang in langDict) {\n    return langDict[lang];\n  }\n  console.warn(`i18n: No such language \"${lang}\" in langDict ${langDict}`);\n  return key;\n}\n\nconst convertDom = (dom = document) => {\n  dom.querySelectorAll('[data-i18n]').forEach(el => {\n    const key = el.dataset.i18n;\n    el.textContent = i18n(key);\n  });\n  dom.querySelectorAll('[data-i18n-html]').forEach(el => {\n    const key = el.dataset.i18nHtml;\n    el.innerHTML = i18n(key);\n  });\n  dom.querySelectorAll('[data-i18n-attr]').forEach(el => {\n    el.dataset.i18nAttr.split(',').forEach(item => {\n      let [attr, key] = item.split(':');\n      attr = attr.trim();\n      key = key || el.getAttribute(attr);\n      el.setAttribute(attr, i18n(key));","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/static/i18n.js#L281-L317","documentation":"After resolving a langDict, i18n picks the user's language via getLocalLang(Object.keys(langDict)) and returns langDict[lang] only if that key exists. When the resolved language is absent from the dictionary, it logs this warn and returns the raw key. Unlike error 83, the key exists but lacks a translation for the detected language.","triggerScenarios":"i18n('existingKey') or convertDom on data-i18n=\"existingKey\" where I18N_MAP.existingKey exists but does not include the language returned by getLocalLang (e.g. dict has only en/zh, user locale is ja).","commonSituations":"New language added to the UI but existing keys not yet translated; a language dict written with only one locale; getLocalLang returning a code variant (e.g. 'zh-TW') not present in the dict.","solutions":["Add the missing language entry to the key's langDict so every supported language is covered.","Ensure getLocalLang maps locale variants to a language actually present in the dictionaries (e.g. normalize zh-TW -> zh).","Provide an English fallback: if lang not in langDict, return langDict.en before falling back to the key.","Audit all I18N_MAP entries to include the same language set."],"exampleFix":"// before\nif (lang in langDict) {\n  return langDict[lang];\n}\nconsole.warn(`i18n: No such language \"${lang}\" in langDict ${langDict}`);\nreturn key;\n// after\nif (lang in langDict) return langDict[lang];\nif ('en' in langDict) return langDict.en;\nreturn key;","handlingStrategy":"fallback","validationCode":"function hasLang(langDict) {\n  const lang = getLocalLang(Object.keys(langDict));\n  return lang != null && Object.prototype.hasOwnProperty.call(langDict, lang);\n}\nif (!hasLang(I18N_MAP[key])) { /* use fallback lang or default */ }","typeGuard":"function langDictSupports(langDict, lang) {\n  return langDict != null && Object.prototype.hasOwnProperty.call(langDict, lang);\n}","tryCatchPattern":null,"preventionTips":["Give every key the same set of languages; enforce via a schema or test.","Normalize locales in getLocalLang (zh-TW -> zh, en-US -> en).","Always define an 'en' fallback entry per key.","Track untranslated keys with the console.warn output during QA."],"tags":["javascript","i18n","frontend"],"backgroundTag":"missing-translation-language","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}