1
0
mirror of synced 2025-12-23 11:54:18 -05:00

fall back to English on corrupt content files (#32629)

This commit is contained in:
Peter Bengtsson
2022-11-17 20:11:29 +01:00
committed by GitHub
parent e4a069f014
commit 6d88215b46
3 changed files with 61 additions and 9 deletions

View File

@@ -1,6 +1,20 @@
import path from 'path' import path from 'path'
import fs from 'fs/promises' import fs from 'fs/promises'
import Page from './page.js'
import languages from './languages.js'
import Page, { FrontmatterErrorsError } from './page.js'
// If you run `export DEBUG_TRANSLATION_FALLBACKS=true` in your terminal,
// every time a translation file fails to initialize we fall back to English
// and write a warning to stdout.
const DEBUG_TRANSLATION_FALLBACKS = Boolean(
JSON.parse(process.env.DEBUG_TRANSLATION_FALLBACKS || 'false')
)
// If you don't want to fall back to English automatically on corrupt
// translation files, set `export THROW_TRANSLATION_ERRORS=true`
const THROW_TRANSLATION_ERRORS = Boolean(
JSON.parse(process.env.THROW_TRANSLATION_ERRORS || 'false')
)
// Module level cache // Module level cache
const _basePaths = new Map() const _basePaths = new Map()
@@ -30,11 +44,39 @@ export default async function createTree(originalPath, langObj) {
const relativePath = filepath.replace(`${basePath}/`, '') const relativePath = filepath.replace(`${basePath}/`, '')
// Initialize the Page! This is where the file reads happen. // Initialize the Page! This is where the file reads happen.
const page = await Page.init({ let page
try {
page = await Page.init({
basePath, basePath,
relativePath, relativePath,
languageCode: langObj.code, languageCode: langObj.code,
}) })
} catch (err) {
if (
!THROW_TRANSLATION_ERRORS &&
err instanceof FrontmatterErrorsError &&
langObj.code !== 'en'
) {
// Something corrupt in the `.md` file caused it to throw an
// error from reading it in. Let's "gracefully" recover by
// swapping this one out for the English content and pretend it
// exists in this other language.
const englishBasePath = getBasePath(languages.en.dir)
page = await Page.init({
basePath: englishBasePath,
relativePath,
languageCode: langObj.code,
})
if (DEBUG_TRANSLATION_FALLBACKS) {
console.warn(
`Unable to initialized ${path.join(basePath, relativePath)} due to frontmatter errors. ` +
`Will proceed with using ${path.join(englishBasePath, relativePath)} instead.`
)
}
} else {
throw err
}
}
if (!page) { if (!page) {
// Do not throw an error if Early Access is not available. // Do not throw an error if Early Access is not available.

View File

@@ -25,6 +25,13 @@ import { allTools } from './all-tools.js'
// every single time, we turn it into a Set once. // every single time, we turn it into a Set once.
const productMapKeysAsSet = new Set(Object.keys(productMap)) const productMapKeysAsSet = new Set(Object.keys(productMap))
export class FrontmatterErrorsError extends Error {
constructor(message, frontmatterErrors) {
super(message)
this.frontmatterErrors = frontmatterErrors
}
}
class Page { class Page {
static async init(opts) { static async init(opts) {
opts = await Page.read(opts) opts = await Page.read(opts)
@@ -61,7 +68,10 @@ class Page {
constructor(opts) { constructor(opts) {
if (opts.frontmatterErrors.length) { if (opts.frontmatterErrors.length) {
throw new Error(JSON.stringify(opts.frontmatterErrors, null, 2)) throw new FrontmatterErrorsError(
`${opts.frontmatterErrors.length} frontmatter errors trying to load ${opts.fullPath}`,
opts.frontmatterErrors
)
} }
delete opts.frontmatterErrors delete opts.frontmatterErrors
Object.assign(this, { ...opts }) Object.assign(this, { ...opts })

View File

@@ -3,7 +3,7 @@ import path from 'path'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import { describe, expect } from '@jest/globals' import { describe, expect } from '@jest/globals'
import Page from '../../lib/page.js' import Page, { FrontmatterErrorsError } from '../../lib/page.js'
import { allVersions } from '../../lib/all-versions.js' import { allVersions } from '../../lib/all-versions.js'
import enterpriseServerReleases, { latest } from '../../lib/enterprise-server-releases.js' import enterpriseServerReleases, { latest } from '../../lib/enterprise-server-releases.js'
import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js' import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js'
@@ -727,7 +727,7 @@ describe('catches errors thrown in Page class', () => {
}) })
} }
await expect(getPage).rejects.toThrowError('invalid frontmatter entry') await expect(getPage).rejects.toThrow(FrontmatterErrorsError)
}) })
test('missing versions frontmatter', async () => { test('missing versions frontmatter', async () => {