{"record":{"id":"e6f668378463ebe4","repo":"jeessy2/ddns-go","slug":"i18n-no-translation-for-key-key","errorCode":null,"errorMessage":"i18n: No translation for key \"${key}\"","messagePattern":"i18n: No translation for key \"(.+?)\"","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"static/i18n.js","lineNumber":292,"sourceCode":"  }\n  for (const l of langs) {\n    if (l.split('-')[0] === langValue.split('-')[0]) {\n      return l;\n    }\n  }\n  return 'en';\n}\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);","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/static/i18n.js#L274-L310","documentation":"The i18n function in static/i18n.js looks up I18N_MAP[keyOrLangDict] when given a string key; if no dictionary is registered for that key (langDict falsy), it logs this console.warn and returns the key unchanged. convertDom relies on it, so an unknown data-i18n key leaves raw key text in the DOM.","triggerScenarios":"Calling i18n('someKey') (or an element with data-i18n=\"someKey\" processed by convertDom) where I18N_MAP has no entry for someKey.","commonSituations":"Typo in a data-i18n attribute; new UI key added before adding its translation entry to I18N_MAP; key renamed in one language file but not registered in the map; dynamic keys built from strings that don't exist.","solutions":["Add the missing key to I18N_MAP with translations for each supported language.","Fix typos in the data-i18n attribute or the i18n() call argument so it matches an existing key.","Add a build-time/lint check that every data-i18n value exists in I18N_MAP.","If intentional fallback is desired, keep the key-return behavior but route through a silent fallback for optional keys."],"exampleFix":"// before\n<span data-i18n=\"setting_title\"></span>\n// after — ensure the key exists\nI18N_MAP.setting_title = { en: 'Settings', zh: '设置' };\n<span data-i18n=\"setting_title\"></span>","handlingStrategy":"validation","validationCode":"// guard before translating\nfunction hasTranslation(key) {\n  return typeof key === 'string' && Object.prototype.hasOwnProperty.call(I18N_MAP, key);\n}\nconst text = hasTranslation(key) ? i18n(key) : key;","typeGuard":"function isKnownI18nKey(key) {\n  return typeof key === 'string' && Object.prototype.hasOwnProperty.call(I18N_MAP, key);\n}","tryCatchPattern":null,"preventionTips":["Keep data-i18n keys in sync with I18N_MAP; lint/CI-check every key referenced in markup.","Centralize key constants instead of hand-typed strings.","Add unit tests iterating all DOM data-i18n values against I18N_MAP.","Review console warnings in dev builds to catch missing keys early."],"tags":["javascript","i18n","frontend"],"backgroundTag":"missing-translation-key","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"}