Per-language {title, description, keywords, source} resolver
extracted from article-metadata.ts to keep that orchestrator below the
600-line drift-guard cap (see test/unit/source-file-size.test.js).
This module owns three closely-coupled concerns that are tedious to keep
coherent across separate files:
resolvePerLanguageEditorial — the Tier-1/Tier-2/Tier-3 editorial
selection (localized brief → English brief → empty/template) with the
script-aware safety net that strips English headlines from non-Latin
locales so RTL/CJK pages never ship pure-ASCII <title> text.
resolveOneLanguage — the actual {title, description} composer
that picks across (manifest override → editorial headline →
summary-derived → contextual fallback), clamps to the per-script SEO
budgets, and stitches localized SEO labels into both surfaces.
appendRunNumberSuffix — preserved as a no-op for backward
compatibility. Run numbers never appear in user-facing titles.
SEO-fidelity contracts enforced here:
Non-Latin locales never ship pure-ASCII descriptions (Gate 4b in
executive-brief-seo-extraction.test.js). When the English editorial
falls through to ar/he/ja/ko/zh and the description would otherwise be
Latin-only, enrichment is forced so localized Date: / Context: /
reader labels are spliced in. The base content stays for SEO topical
relevance; the localized framing makes the snippet locale-correct.
Non-Latin titles always carry a locale-script glyph (Gate 4a). The
English-summary-derived title candidate is rejected for non-Latin
locales when its content is pure ASCII, forcing fall-through to the
localized template title from buildTemplateFallback.
Per-script SERP-fill clamp (Gate "OPTIMAL_DESC SERP-fill ratio"):
descriptions are clamped to SEO_BUDGETS.metaDescription (155 Latin /
78 CJK / 150 RTL) whenever the source content actually matches the
locale's script. English-content fallbacks keep the universal 180-char
cap so the article-metadata.test.js ≥100 / ≥120 reader-floor
assertions remain satisfiable for cross-lingual content reuse.
Description
Per-language
{title, description, keywords, source}resolver extracted fromarticle-metadata.tsto keep that orchestrator below the 600-line drift-guard cap (seetest/unit/source-file-size.test.js).This module owns three closely-coupled concerns that are tedious to keep coherent across separate files:
<title>text.{title, description}composer that picks across (manifest override → editorial headline → summary-derived → contextual fallback), clamps to the per-script SEO budgets, and stitches localized SEO labels into both surfaces.SEO-fidelity contracts enforced here:
executive-brief-seo-extraction.test.js). When the English editorial falls through to ar/he/ja/ko/zh and the description would otherwise be Latin-only, enrichment is forced so localizedDate:/Context:/readerlabels are spliced in. The base content stays for SEO topical relevance; the localized framing makes the snippet locale-correct.SEO_BUDGETS.metaDescription(155 Latin / 78 CJK / 150 RTL) whenever the source content actually matches the locale's script. English-content fallbacks keep the universal 180-char cap so the article-metadata.test.js ≥100 / ≥120 reader-floor assertions remain satisfiable for cross-lingual content reuse.