Skip to content

Commit b87a46c

Browse files
committed
feat(format-po): add foldLength and compactMultiline options
Upgrade pofile-ts to v3.1.0 and expose new serialization options: - foldLength: Maximum line width before folding (default: 80, 0 = disable) - compactMultiline: Compact format for multiline strings (default: true) These options enable better compatibility with translation platforms like Crowdin that may have issues with empty first lines in multiline strings. Refs: #2235
1 parent 98d205b commit b87a46c

File tree

7 files changed

+75
-15
lines changed

7 files changed

+75
-15
lines changed

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"normalize-path": "^3.0.0",
8181
"ora": "^5.1.0",
8282
"picocolors": "^1.1.1",
83-
"pofile-ts": "^3.0.0",
83+
"pofile-ts": "^3.1.0",
8484
"pseudolocale": "^2.0.0",
8585
"source-map": "^0.7.6",
8686
"threads": "^1.7.0"

packages/format-po-gettext/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"cldr-core": "^45.0.0",
5151
"node-gettext": "^3.0.0",
5252
"plurals-cldr": "^2.0.1",
53-
"pofile-ts": "^3.0.0"
53+
"pofile-ts": "^3.1.0"
5454
},
5555
"devDependencies": {
5656
"@lingui/jest-mocks": "workspace:^",

packages/format-po-gettext/src/po-gettext.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { parse as parseIcu, Select, SelectCase } from "@messageformat/parser"
22
import pluralsCldr from "plurals-cldr"
3-
import { parsePo, stringifyPo, createItem, type PoItem } from "pofile-ts"
3+
import { parsePo, stringifyPo, createItem, type PoItem, type SerializeOptions } from "pofile-ts"
44
import gettextPlurals from "node-gettext/lib/plurals"
55

66
import type { CatalogFormatter, CatalogType, MessageType } from "@lingui/conf"
@@ -514,6 +514,15 @@ export function formatter(
514514

515515
const formatter = poFormatter(options)
516516

517+
// Build serialize options from the formatter options
518+
const serializeOptions: SerializeOptions = {}
519+
if (options.foldLength !== undefined) {
520+
serializeOptions.foldLength = options.foldLength
521+
}
522+
if (options.compactMultiline !== undefined) {
523+
serializeOptions.compactMultiline = options.compactMultiline
524+
}
525+
517526
return {
518527
catalogExtension: ".po",
519528
templateExtension: ".pot",
@@ -543,7 +552,7 @@ export function formatter(
543552
)
544553
})
545554

546-
return formatter.parse(stringifyPo(po), ctx) as CatalogType
555+
return formatter.parse(stringifyPo(po, serializeOptions), ctx) as CatalogType
547556
},
548557

549558
serialize(catalog, ctx): string {
@@ -587,7 +596,7 @@ export function formatter(
587596
po.items = newItems
588597
}
589598

590-
return stringifyPo(po)
599+
return stringifyPo(po, serializeOptions)
591600
},
592601
}
593602
}

packages/format-po/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"@lingui/conf": "5.6.1",
4747
"@lingui/message-utils": "5.6.1",
4848
"date-fns": "^3.6.0",
49-
"pofile-ts": "^3.0.0"
49+
"pofile-ts": "^3.1.0"
5050
},
5151
"devDependencies": {
5252
"@lingui/jest-mocks": "workspace:^",

packages/format-po/src/__snapshots__/po.test.ts.snap

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,14 @@ msgstr "Keeps any flags that are defined"
342342
343343
#. js-lingui-explicit-id
344344
msgid "veryLongString"
345-
msgstr "One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. \\"What's happened to me?\\" he thought. It wasn't a dream. His room, a proper human"
345+
msgstr "One morning, when Gregor Samsa woke from troubled dreams, he found "
346+
"himself transformed in his bed into a horrible vermin. He lay on his "
347+
"armour-like back, and if he lifted his head a little he could see his "
348+
"brown belly, slightly domed and divided by arches into stiff sections. "
349+
"The bedding was hardly able to cover it and seemed ready to slide off "
350+
"any moment. His many legs, pitifully thin compared with the size of the "
351+
"rest of him, waved about helplessly as he looked. \\"What's happened to "
352+
"me?\\" he thought. It wasn't a dream. His room, a proper human"
346353
347354
#. hello
348355
#. world

packages/format-po/src/po.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type PoFile,
88
type PoItem,
99
type Headers as POHeaders,
10+
type SerializeOptions,
1011
} from "pofile-ts"
1112

1213
import { CatalogFormatter, CatalogType, MessageType } from "@lingui/conf"
@@ -107,6 +108,40 @@ export type PoFormatterOptions = {
107108
* @default true
108109
*/
109110
printPlaceholdersInComments?: boolean | { limit?: number }
111+
112+
/**
113+
* Maximum line width before folding long strings.
114+
*
115+
* When a string exceeds this length, it will be split across multiple lines.
116+
* Set to `0` to disable folding (strings will only break on actual newlines).
117+
*
118+
* @default 80
119+
*/
120+
foldLength?: number
121+
122+
/**
123+
* Use compact format for multiline strings.
124+
*
125+
* When `true` (default), multiline strings start with content on the first line:
126+
* ```po
127+
* msgid "First line\n"
128+
* "Second line"
129+
* ```
130+
*
131+
* When `false`, uses GNU gettext's traditional format with an empty first line:
132+
* ```po
133+
* msgid ""
134+
* "First line\n"
135+
* "Second line"
136+
* ```
137+
*
138+
* The compact format is recommended as it's compatible with translation
139+
* platforms like Crowdin that may strip empty first lines, avoiding
140+
* unnecessary diffs.
141+
*
142+
* @default true
143+
*/
144+
compactMultiline?: boolean
110145
}
111146

112147
function isGeneratedId(id: string, message: MessageType): boolean {
@@ -288,7 +323,16 @@ export function formatter(options: PoFormatterOptions = {}): CatalogFormatter {
288323
}
289324

290325
po.items = serialize(catalog, options)
291-
return stringifyPo(po)
326+
327+
const serializeOptions: SerializeOptions = {}
328+
if (options.foldLength !== undefined) {
329+
serializeOptions.foldLength = options.foldLength
330+
}
331+
if (options.compactMultiline !== undefined) {
332+
serializeOptions.compactMultiline = options.compactMultiline
333+
}
334+
335+
return stringifyPo(po, serializeOptions)
292336
},
293337
}
294338
}

yarn.lock

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3029,7 +3029,7 @@ __metadata:
30293029
normalize-path: ^3.0.0
30303030
ora: ^5.1.0
30313031
picocolors: ^1.1.1
3032-
pofile-ts: ^3.0.0
3032+
pofile-ts: ^3.1.0
30333033
pseudolocale: ^2.0.0
30343034
source-map: ^0.7.6
30353035
threads: ^1.7.0
@@ -3135,7 +3135,7 @@ __metadata:
31353135
mockdate: ^3.0.5
31363136
node-gettext: ^3.0.0
31373137
plurals-cldr: ^2.0.1
3138-
pofile-ts: ^3.0.0
3138+
pofile-ts: ^3.1.0
31393139
unbuild: 2.0.0
31403140
languageName: unknown
31413141
linkType: soft
@@ -3149,7 +3149,7 @@ __metadata:
31493149
"@lingui/message-utils": 5.6.1
31503150
date-fns: ^3.6.0
31513151
mockdate: ^3.0.5
3152-
pofile-ts: ^3.0.0
3152+
pofile-ts: ^3.1.0
31533153
unbuild: 2.0.0
31543154
languageName: unknown
31553155
linkType: soft
@@ -13769,10 +13769,10 @@ __metadata:
1376913769
languageName: node
1377013770
linkType: hard
1377113771

13772-
"pofile-ts@npm:^3.0.0":
13773-
version: 3.0.0
13774-
resolution: "pofile-ts@npm:3.0.0"
13775-
checksum: 9d4a1737a4dad8e6ae9f7716ba050a9f5c758403f57e09abff50c5613b16095d2c7e13aadfaa888ad06df3d6905153b561a23b4332d18383ee2e59d9ff664237
13772+
"pofile-ts@npm:^3.1.0":
13773+
version: 3.1.0
13774+
resolution: "pofile-ts@npm:3.1.0"
13775+
checksum: 4e95606bca124b612334a80c3af7e9305da394ef74617070c0e70aa8fdf23240bd2f6882336fa90ee7f93e01cd2d758df376e682b11c5c2882a8b9ca88ffd6b5
1377613776
languageName: node
1377713777
linkType: hard
1377813778

0 commit comments

Comments
 (0)