jeessy2/ddns-go · warning

i18n: No such language "${lang}" in langDict ${langDict}

Error message

i18n: No such language "${lang}" in langDict ${langDict}

What it means

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.

Source

Thrown at static/i18n.js:299

}

const i18n = (keyOrLangDict) => {
  let key = keyOrLangDict;
  let langDict = keyOrLangDict;
  if (typeof keyOrLangDict === 'string') {
    langDict = I18N_MAP[keyOrLangDict];
  } else {
    key = null;
  }
  if (!langDict) {
    console.warn(`i18n: No translation for key "${key}"`);
    return key;
  }
  const lang = getLocalLang(Object.keys(langDict));
  if (lang in langDict) {
    return langDict[lang];
  }
  console.warn(`i18n: No such language "${lang}" in langDict ${langDict}`);
  return key;
}

const convertDom = (dom = document) => {
  dom.querySelectorAll('[data-i18n]').forEach(el => {
    const key = el.dataset.i18n;
    el.textContent = i18n(key);
  });
  dom.querySelectorAll('[data-i18n-html]').forEach(el => {
    const key = el.dataset.i18nHtml;
    el.innerHTML = i18n(key);
  });
  dom.querySelectorAll('[data-i18n-attr]').forEach(el => {
    el.dataset.i18nAttr.split(',').forEach(item => {
      let [attr, key] = item.split(':');
      attr = attr.trim();
      key = key || el.getAttribute(attr);
      el.setAttribute(attr, i18n(key));

View on GitHub (pinned to 5874c2e666)

Solutions

  1. Add the missing language entry to the key's langDict so every supported language is covered.
  2. Ensure getLocalLang maps locale variants to a language actually present in the dictionaries (e.g. normalize zh-TW -> zh).
  3. Provide an English fallback: if lang not in langDict, return langDict.en before falling back to the key.
  4. Audit all I18N_MAP entries to include the same language set.

Example fix

// before
if (lang in langDict) {
  return langDict[lang];
}
console.warn(`i18n: No such language "${lang}" in langDict ${langDict}`);
return key;
// after
if (lang in langDict) return langDict[lang];
if ('en' in langDict) return langDict.en;
return key;
Defensive patterns

Strategy: fallback

Validate before calling

function hasLang(langDict) {
  const lang = getLocalLang(Object.keys(langDict));
  return lang != null && Object.prototype.hasOwnProperty.call(langDict, lang);
}
if (!hasLang(I18N_MAP[key])) { /* use fallback lang or default */ }

Type guard

function langDictSupports(langDict, lang) {
  return langDict != null && Object.prototype.hasOwnProperty.call(langDict, lang);
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of jeessy2/ddns-go@5874c2e666 (2026-09-03). Data as JSON: /api/errors/2a0402c944bcf192. Report an issue: GitHub.