Skip to content

Commit b0e92ea

Browse files
heiskrCopilot
andauthored
Use full Liquid render in count-translation-corruptions (#60581)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e2c0fd8 commit b0e92ea

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

src/article-api/transformers/rest-transformer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,21 @@ import type { Context, Page } from '@/types'
22
import type { PageTransformer } from './types'
33
import type { Operation } from '@/rest/components/types'
44
import { renderContent } from '@/content-render/index'
5+
import { engine } from '@/content-render/liquid/engine'
6+
import { apiTransformerTags } from '@/article-api/liquid-renderers'
57
import { loadTemplate } from '@/article-api/lib/load-template'
68
import { summarizeSchema } from '@/article-api/lib/summarize-schema'
79
import matter from '@gr2m/gray-matter'
810
import { fastTextOnly } from '@/content-render/unified/text-only'
911
import GithubSlugger from 'github-slugger'
1012

13+
// Register article-api-specific Liquid tags on the shared engine.
14+
// These are only used by REST templates and kept here (not in engine.ts)
15+
// to avoid a circular dependency: rest-tags → renderContent → engine.
16+
for (const [tagName, tagClass] of Object.entries(apiTransformerTags)) {
17+
engine.registerTag(tagName, tagClass as any)
18+
}
19+
1120
const DEBUG = process.env.RUNNER_DEBUG === '1' || process.env.DEBUG === '1'
1221

1322
/**

src/content-render/liquid/engine.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { Tool, tags as toolTags } from './tool'
1010
import { Spotlight, tags as spotlightTags } from './spotlight'
1111
import { Prompt } from './prompt'
1212
import IndentedDataReference from './indented-data-reference'
13-
import { apiTransformerTags } from '@/article-api/liquid-renderers'
1413

1514
// Type assertions for .js files without type definitions
1615
// Copilot: Remove these assertions when the corresponding .js files are converted to TypeScript
@@ -41,11 +40,6 @@ for (const tag in spotlightTags) {
4140

4241
engine.registerTag('prompt', anyPrompt)
4342

44-
// Register API transformer tags
45-
for (const [tagName, tagClass] of Object.entries(apiTransformerTags)) {
46-
engine.registerTag(tagName, tagClass as any)
47-
}
48-
4943
/**
5044
* Like the `size` filter, but specifically for
5145
* getting the number of keys in an object

src/languages/scripts/count-translation-corruptions.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import path from 'path'
22
import fs from 'fs'
33

44
import { program } from 'commander'
5-
import { TokenizationError } from 'liquidjs'
65
import walk from 'walk-sync'
76

8-
import { getLiquidTokens } from '@/content-linter/lib/helpers/liquid-utils'
7+
import { engine } from '@/content-render/liquid/engine'
8+
import { allVersions } from '@/versions/lib/all-versions'
99
import languages from '@/languages/lib/languages-server'
1010
import warmServer from '@/frame/lib/warm-server'
1111
import type { Site } from '@/types'
@@ -92,7 +92,7 @@ async function main(languageCodes: string[]) {
9292
const languageResults: LanguageResult[] = []
9393

9494
for (const languageCode of langCodes) {
95-
languageResults.push(run(languageCode, site, reusables))
95+
languageResults.push(await run(languageCode, site, reusables))
9696
}
9797

9898
const totalCount = languageResults.reduce((sum, r) => sum + r.total, 0)
@@ -134,22 +134,39 @@ function getReusables(): Reusables {
134134
return reusables
135135
}
136136

137-
function run(languageCode: string, site: Site, englishReusables: Reusables): LanguageResult {
137+
// Build a minimal Liquid render context for validating translated content.
138+
// ifversion needs currentVersionObj; data tags call getDataByLanguage() internally.
139+
const defaultVersion = 'free-pro-team@latest'
140+
function buildRenderContext(languageCode: string) {
141+
return {
142+
currentLanguage: languageCode,
143+
currentVersion: defaultVersion,
144+
currentVersionObj: allVersions[defaultVersion],
145+
}
146+
}
147+
148+
async function run(
149+
languageCode: string,
150+
site: Site,
151+
englishReusables: Reusables,
152+
): Promise<LanguageResult> {
138153
const language = languages[languageCode as keyof typeof languages]
139154

140155
const corruptions: CorruptionEntry[] = []
141156
const wheres = new Map<string, number>()
142157
const illegalTags = new Map<string, number>()
158+
const context = buildRenderContext(languageCode)
143159

144-
function countError(error: TokenizationError, where: string, file: string) {
145-
const errorWithExtras = error as TokenizationError & {
146-
originalError?: Error
147-
token?: { content?: string }
148-
}
149-
const originalError = errorWithExtras.originalError
150-
const errorString = originalError ? originalError.message : error.message
160+
// Suppress console.warn during rendering — the {% data %} tag warns
161+
// when it can't find translated data, which is expected noise.
162+
const originalWarn = console.warn
163+
console.warn = () => {}
164+
165+
function countError(error: Error, where: string, file: string) {
166+
const errorString = error.message
151167

152168
let illegalTag: string | undefined
169+
const errorWithExtras = error as Error & { token?: { content?: string } }
153170
if (errorString.includes('illegal tag syntax') && errorWithExtras.token?.content) {
154171
illegalTag = errorWithExtras.token.content
155172
illegalTags.set(illegalTag, (illegalTags.get(illegalTag) || 0) + 1)
@@ -171,9 +188,9 @@ function run(languageCode: string, site: Site, englishReusables: Reusables): Lan
171188

172189
for (const [where, string] of strings) {
173190
try {
174-
getLiquidTokens(string)
191+
await engine.parseAndRender(string, context)
175192
} catch (error) {
176-
if (error instanceof TokenizationError) {
193+
if (error instanceof Error) {
177194
countError(error, where, page.relativePath)
178195
} else {
179196
throw error
@@ -190,12 +207,12 @@ function run(languageCode: string, site: Site, englishReusables: Reusables): Lan
190207
code: languageCode,
191208
relativePath,
192209
})
193-
getLiquidTokens(correctedContent)
210+
await engine.parseAndRender(correctedContent, context)
194211
} catch (error) {
195-
if (error instanceof TokenizationError) {
196-
countError(error, 'reusable', relativePath)
197-
} else if (error instanceof Error && error.message.startsWith('ENOENT')) {
212+
if (error instanceof Error && error.message.startsWith('ENOENT')) {
198213
continue
214+
} else if (error instanceof Error) {
215+
countError(error, 'reusable', relativePath)
199216
} else {
200217
throw error
201218
}
@@ -207,6 +224,8 @@ function run(languageCode: string, site: Site, englishReusables: Reusables): Lan
207224
.slice(0, 10)
208225
.map(([tag, count]) => ({ tag, count }))
209226

227+
console.warn = originalWarn
228+
210229
return {
211230
language: languageCode,
212231
languageName: language.name,

0 commit comments

Comments
 (0)