Fix Glossary page in Russian and Korean (#36852)

This commit is contained in:
Peter Bengtsson 2023-05-04 12:28:18 -04:00 коммит произвёл GitHub
Родитель 55158284ac
Коммит 1e7a672b0f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 91 добавлений и 33 удалений

Просмотреть файл

@ -148,31 +148,8 @@ async function translateTree(dir, langObj, enTree) {
})
)
// A lot of translations have corruptions around the AUTOTITLE links.
// We've requested that these are corrected back but as a temporary
// solution we'll manually recover now.
// See internal issue #2762
// In late 2023, search in the translations repos if these things are
// still happening and if not, the following lines can be removed.
content = content.replaceAll('[AUTOTITLE"을 참조하세요]', '[AUTOTITLE]')
content = content.replaceAll('[AUTOTITLE"을]', '[AUTOTITLE]')
content = content.replaceAll('["AUTOTITLE]', '"[AUTOTITLE]')
// The page content/code-security/secret-scanning/secret-scanning-patterns.md
// uses some intricate tables in Markdown where exact linebreaks can
// cause the page to render incorrectly. Instead of becoming a `<table>`,
// it becomes a massive `<p>` tag.
// Ideally, we should have a better solution that doesn't require such
// "sensitive" Markdown but for now, this change is important so the
// Markdown-to-HTML rendering doesn't become totally broken.
// See internal issue #2984
content = content.replaceAll(
'{%- for entry in secretScanningData %} |',
'{%- for entry in secretScanningData %}\n|'
)
// The "content" isn't a frontmatter key
translatedData.markdown = content
translatedData.markdown = correctTranslatedContentStrings(content)
item.page = new Page(
Object.assign(
@ -204,6 +181,42 @@ async function translateTree(dir, langObj, enTree) {
return item
}
/**
* A lot of translations have minor corruptions that will lead to rendering
* failing (and having to rely on English fallback). Many of these are
* easy to manually correct for.
*
* This function is a temporary solution to correct for these corruptions.
* It looks for easy "low hanging fruit" that we can correct for.
*
*/
export function correctTranslatedContentStrings(content) {
// A lot of translations have corruptions around the AUTOTITLE links.
// We've requested that these are corrected back but as a temporary
// solution we'll manually recover now.
// See internal issue #2762
// In late 2023, search in the translations repos if these things are
// still happening and if not, the following lines can be removed.
content = content.replaceAll('[AUTOTITLE"을 참조하세요]', '[AUTOTITLE]')
content = content.replaceAll('[AUTOTITLE"을]', '[AUTOTITLE]')
content = content.replaceAll('["AUTOTITLE]', '"[AUTOTITLE]')
// The page content/code-security/secret-scanning/secret-scanning-patterns.md
// uses some intricate tables in Markdown where exact linebreaks can
// cause the page to render incorrectly. Instead of becoming a `<table>`,
// it becomes a massive `<p>` tag.
// Ideally, we should have a better solution that doesn't require such
// "sensitive" Markdown but for now, this change is important so the
// Markdown-to-HTML rendering doesn't become totally broken.
// See internal issue #2984
content = content.replaceAll(
'{%- for entry in secretScanningData %} |',
'{%- for entry in secretScanningData %}\n|'
)
return content
}
/**
* The siteTree is a nested object with pages for every language and version, useful for nav because it
* contains parent, child, and sibling relationships:

Просмотреть файл

@ -1,25 +1,57 @@
import { getDataByLanguage } from '../../lib/get-data.js'
import liquid from '../../lib/render-content/liquid.js'
import { executeWithFallback } from '../../lib/render-with-fallback.js'
import { correctTranslatedContentStrings } from '../../lib/page-data.js'
export default async function glossaries(req, res, next) {
if (!req.pagePath.endsWith('get-started/quickstart/github-glossary')) return next()
// When the current language is *not* English, we'll need to get the English
// glossary based on the term. We'll use this to render the translated
// glossaries. For example, if the Korean translation has a corruption
// in its description we need to know the English equivalent.
const enGlossaryMap = new Map()
// But we don't need to bother if the current language is English.
if (req.context.currentLanguage !== 'en') {
const enGlossariesRaw = getDataByLanguage('glossaries.external', 'en')
enGlossariesRaw.forEach(({ term, description }) => {
enGlossaryMap.set(term, description)
})
}
// The glossaries Yaml file contains descriptions that might contain
// Liquid. They need to be rendered out.
// The github-glossary.md file uses Liquid to generate the Markdown.
// It uses Liquid to say `{{ glossary.description }}` but once that's
// injected there it needs to have its own possible Liquid rendered out.
const glossariesRaw = getDataByLanguage('glossaries.external', req.context.currentLanguage)
const glossaries = await Promise.all(
glossariesRaw.map(async (glossary) => {
// It's important to use `Object.assign` here to avoid mutating the
// original object because from `getDataByLanguage`, reads from an
// in-memory cache so if we mutated it, it would be mutated for all.
return Object.assign({}, glossary, {
description: await liquid.parseAndRender(glossary.description, req.context),
const glossaries = (
await Promise.all(
glossariesRaw.map(async (glossary) => {
let { description } = glossary
if (req.context.currentLanguage !== 'en') {
description = correctTranslatedContentStrings(description)
}
description = await executeWithFallback(
req.context,
() => liquid.parseAndRender(description, req.context),
(enContext) => {
const { term } = glossary
// It *could* be that the translation is referring to a term
// that no longer exists in the English glossary. In that case,
// simply skip this term.
if (!enGlossaryMap.has(term)) return
const enDescription = enGlossaryMap.get(term)
return liquid.parseAndRender(enDescription, enContext)
}
)
// It's important to use `Object.assign` here to avoid mutating the
// original object because from `getDataByLanguage`, reads from an
// in-memory cache so if we mutated it, it would be mutated for all.
return Object.assign({}, glossary, { description })
})
})
)
)
).filter(Boolean)
req.context.glossaries = glossaries.sort((a, b) => a.term.localeCompare(b.term))

Просмотреть файл

@ -0,0 +1,13 @@
import { languageKeys } from '../../lib/languages.js'
import { getDOM } from '../helpers/e2etest.js'
const langs = languageKeys.filter((lang) => lang !== 'en')
describe('glossary', () => {
test.each(langs)('GitHub glossary page in %s', async (lang) => {
// This will implicitly test that the page works with a 200 OK
const $ = await getDOM(`/${lang}/get-started/quickstart/github-glossary`)
const h2s = $('#article-contents h2')
expect(h2s.length).toBeGreaterThan(0)
})
})