{"record":{"id":"53c083a9dd573541","repo":"marktext/marktext","slug":"translation-file-not-found-for-language-languag","errorCode":null,"errorMessage":"Translation file not found for language: ${language}","messagePattern":"Translation file not found for language: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/desktop/src/common/i18n.ts","lineNumber":36,"sourceCode":"    return translationsCache[language]\n  }\n\n  try {\n    // Used in both main and preload processes, so we can't lean on\n    // `global.__static`, which is main-only.\n    // In development, prefer the pre-minified file when present, but fall back\n    // to the raw .json so `pnpm run dev` works without running minify-locales.\n    let localePath: string\n    if (process.env.NODE_ENV === 'development' || process.env.PERF_TESTING === 'true') {\n      const minPath = path.join(process.cwd(), 'static', 'locales', `${language}.min.json`)\n      const rawPath = path.join(process.cwd(), 'static', 'locales', `${language}.json`)\n      localePath = fs.existsSync(minPath) ? minPath : rawPath\n    } else {\n      localePath = path.join(process.resourcesPath, 'static', 'locales', `${language}.min.json`)\n    }\n\n    if (!fs.existsSync(localePath)) {\n      throw new Error(`Translation file not found for language: ${language}`)\n    }\n\n    const content = fs.readFileSync(localePath, 'utf8')\n\n    const translationData: Translations = JSON.parse(content)\n\n    translationsCache[language] = translationData\n    return translationData\n  } catch (error) {\n    console.error('Error loading translation:', error)\n    if (language !== 'en') {\n      return loadTranslations('en')\n    }\n    return null\n  }\n}\n\n/**","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/marktext/marktext/blob/e52106fd1cdcbd33c1258b7b0cdc7013c4c5d86c/packages/desktop/src/common/i18n.ts#L18-L54","documentation":"Thrown by loadTranslations() when the resolved locale JSON path does not exist on disk. In dev/PERF_TESTING the resolver prefers ${language}.min.json and falls back to ${language}.json under <cwd>/static/locales; in production it reads process.resourcesPath/static/locales/${language}.min.json. The function catches its own throw and retries with 'en', so this only surfaces to callers (returns null) if the English file itself is missing.","triggerScenarios":"Calling loadTranslations with a language code that has no matching locale file; running `pnpm run dev` from a directory other than packages/desktop (process.cwd() resolves static/locales relative to cwd); a production build where minify-locales was skipped so ${language}.min.json is absent; a language string outside SUPPORTED_LANGUAGES passed straight through.","commonSituations":"Developers running the renderer/preload from the repo root instead of packages/desktop hit the wrong cwd. Production packages built without `pnpm run minify-locales` lack the .min.json files. A stale preference.json referencing a removed language code triggers it on startup.","solutions":["Run dev from the repo root via `pnpm run dev` (the workspace proxy sets cwd to packages/desktop) so process.cwd()/static/locales resolves.","For production builds, ensure `pnpm run minify-locales` runs before packaging (it is wired into build:win/mac/linux but not dev).","Validate the language against getSupportedLanguages()/isLanguageSupported() before passing it to loadTranslations.","If adding a new language, place both the raw ${code}.json and minified ${code}.min.json in packages/desktop/static/locales/."],"exampleFix":"// before\nloadTranslations(userLang)\n// after\nimport { isLanguageSupported } from 'common/i18n'\nconst lang = isLanguageSupported(userLang) ? userLang : 'en'\nloadTranslations(lang)","handlingStrategy":"validation","validationCode":"import { isLanguageSupported } from 'common/i18n'\nfunction safeLang(lang: string): string {\n  return isLanguageSupported(lang) ? lang : 'en'\n}\n// then: loadTranslations(safeLang(userLang))","typeGuard":"function isValidLanguage(lang: string): lang is import('common/i18n').SupportedLanguage {\n  return ['en','zh-CN','zh-TW','es','fr','de','ja','ko','pt','tr'].includes(lang)\n}","tryCatchPattern":"// loadTranslations already self-recurses to 'en' on error and returns null;\n// callers should treat null as 'use key as fallback':\nconst t = getTranslation(key, lang) // returns key if translations null","preventionTips":["Run dev via the workspace proxy (`pnpm run dev`) so cwd is packages/desktop.","Always run minify-locales before production builds.","Whitelist languages via isLanguageSupported before persisting them in preferences.","Keep both .json and .min.json in static/locales when adding a language."],"tags":["i18n","locale","filesystem","config"],"backgroundTag":null,"analyzedSha":"e52106fd1cdcbd33c1258b7b0cdc7013c4c5d86c","analyzedAt":"2026-08-12T13:58:32.443Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}