From 039abb76e500112aa2bb0fdb819bdcdd4cbdb3d5 Mon Sep 17 00:00:00 2001 From: Arvid Andersson Date: Mon, 14 Sep 2026 21:44:22 +0200 Subject: [PATCH] Parse PO flags spread across several #, lines - gettext allows flags on one `#,` line or across several, and gettext-parser joins the latter with a newline rather than a comma - Splitting on commas alone produced one bogus flag, "fuzzy\npython-format", which no membership test could match - Add a test parsed from real PO text covering both forms Co-Authored-By: Claude Opus 5 (1M context) --- src/utils/po-utils.ts | 4 +++- tests/utils/po-utils.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/utils/po-utils.ts b/src/utils/po-utils.ts index 7fdbbf8..f36884e 100644 --- a/src/utils/po-utils.ts +++ b/src/utils/po-utils.ts @@ -127,9 +127,11 @@ export function normalizeReferences(reference: string | string[]): string[] { return normalized; } +// gettext allows flags on one `#,` line or spread across several, and +// gettext-parser joins the latter with a newline rather than a comma. function parsePoFlags(flag: string | undefined): string[] | undefined { if (!flag) return undefined; - const flags = flag.split(/,\s*/).map(f => f.trim()).filter(Boolean); + const flags = flag.split(/[,\n]\s*/).map(f => f.trim()).filter(Boolean); return flags.length > 0 ? flags : undefined; } diff --git a/tests/utils/po-utils.test.js b/tests/utils/po-utils.test.js index 5a7d212..e700554 100644 --- a/tests/utils/po-utils.test.js +++ b/tests/utils/po-utils.test.js @@ -453,6 +453,32 @@ msgstr[1] "%(count)d items" expect(result['Copyright notice'].metadata.source_references).toEqual(['src/components/Footer.tsx:9']); }); + // gettext allows flags on separate `#,` lines and gettext-parser joins them + // with a newline. Splitting on commas alone produced one bogus flag, + // "fuzzy\npython-format". Parsed from real PO text rather than a hand-built + // entry, so this guards the gettext-parser integration and not just the split. + it('should split flags spread across several #, lines', () => { + const content = `msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\\n" + +#, fuzzy +#, python-format +msgid "Welcome %(name)s" +msgstr "Bienvenue %(name)s" + +#, fuzzy, c-format +msgid "Goodbye %(name)s" +msgstr "Au revoir %(name)s" +`; + + const result = poEntriesToApiFormat(parsePoFile(content)); + + expect(result['Welcome %(name)s'].metadata.po_flags).toEqual(['fuzzy', 'python-format']); + // the single-line form must keep working + expect(result['Goodbye %(name)s'].metadata.po_flags).toEqual(['fuzzy', 'c-format']); + }); + it('should preserve fuzzy flag in plural forms', () => { const entries = [ {