зеркало из https://github.com/github/docs.git
Fix Glossary page in Russian and Korean (#36852)
This commit is contained in:
Родитель
55158284ac
Коммит
1e7a672b0f
|
@ -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)
|
||||
})
|
||||
})
|
Загрузка…
Ссылка в новой задаче