Parse and serialize Gettext PO files for JavaScript internationalization and localization.
npx @tessl/cli install tessl/npm-pofile@1.1.00
# Pofile
1
2
Pofile is a JavaScript library for parsing and serializing GNU Gettext PO (Portable Object) files, widely used for internationalization (i18n) and localization (l10n) of software applications. It provides comprehensive support for all standard Gettext features including message contexts, plural forms, translator comments, extracted comments, reference strings, and message flags.
3
4
## Package Information
5
6
- **Package Name**: pofile
7
- **Package Type**: npm
8
- **Language**: JavaScript (with TypeScript definitions)
9
- **Installation**: `npm install pofile`
10
11
## Core Imports
12
13
```javascript
14
var PO = require('pofile');
15
```
16
17
For ES modules (modern environments):
18
19
```javascript
20
import PO from 'pofile';
21
```
22
23
The package exports a single PO class constructor function.
24
25
## Basic Usage
26
27
```javascript
28
var PO = require('pofile');
29
30
// Create new empty PO file
31
var po = new PO();
32
33
// Parse PO file from string
34
var po = PO.parse(myString);
35
36
// Load PO file from disk (Node.js only)
37
PO.load('text.po', function (err, po) {
38
if (err) throw err;
39
// Use po object
40
});
41
42
// Create a translation item
43
var item = new PO.Item();
44
item.msgid = 'Hello';
45
item.msgstr = ['Hola'];
46
po.items.push(item);
47
48
// Save to disk (Node.js only)
49
po.save('out.po', function (err) {
50
if (err) throw err;
51
});
52
53
// Serialize to string
54
var poString = po.toString();
55
```
56
57
## Capabilities
58
59
### PO File Management
60
61
Create, load, parse, and save PO files with full support for headers and comments.
62
63
```javascript { .api }
64
/**
65
* PO constructor - creates new empty PO file instance
66
*/
67
function PO();
68
69
/**
70
* Load PO file from filesystem (Node.js only)
71
* @param filename - Path to PO file
72
* @param callback - Callback with (err, po) parameters
73
*/
74
PO.load = function(filename, callback);
75
76
/**
77
* Parse PO file content from string
78
* @param data - PO file content as string
79
* @returns PO instance
80
*/
81
PO.parse = function(data);
82
83
/**
84
* Parse Plural-Forms header value
85
* @param pluralFormsString - Plural-Forms header value
86
* @returns Object with nplurals and plural properties
87
*/
88
PO.parsePluralForms = function(pluralFormsString);
89
```
90
91
### PO File Serialization
92
93
Convert PO objects back to standard PO file format.
94
95
```javascript { .api }
96
/**
97
* Write PO file to disk (Node.js only)
98
* @param filename - Output file path
99
* @param callback - Callback with (err) parameter
100
*/
101
po.save = function(filename, callback);
102
103
/**
104
* Serialize PO object to string format
105
* @returns String representation of PO file
106
*/
107
po.toString = function();
108
```
109
110
### Translation Item Management
111
112
Create and manage individual translation entries with full Gettext feature support.
113
114
```javascript { .api }
115
/**
116
* PO.Item constructor - creates new translation item/entry
117
* @param options - Object with nplurals property
118
*/
119
function PO.Item(options);
120
121
/**
122
* Serialize item to PO file entry format
123
* @returns String representation of PO item
124
*/
125
item.toString = function();
126
```
127
128
## Data Structures
129
130
### PO Class Properties
131
132
```javascript { .api }
133
/**
134
* PO file instance properties
135
*/
136
interface PO {
137
/** Array of translator comments found at file header */
138
comments: string[];
139
140
/** Array of extracted comments from source code */
141
extractedComments: string[];
142
143
/** PO file headers with standard Gettext header fields */
144
headers: {
145
'Project-Id-Version': string;
146
'Report-Msgid-Bugs-To': string;
147
'POT-Creation-Date': string;
148
'PO-Revision-Date': string;
149
'Last-Translator': string;
150
'Language': string;
151
'Language-Team': string;
152
'Content-Type': string;
153
'Content-Transfer-Encoding': string;
154
'Plural-Forms': string;
155
[name: string]: string;
156
};
157
158
/** Order of headers as they appear in file (used to preserve header sequence when serializing) */
159
headerOrder: string[];
160
161
/** Collection of translation items/entries */
162
items: PO.Item[];
163
}
164
```
165
166
### PO.Item Class Properties
167
168
```javascript { .api }
169
/**
170
* Translation item/entry properties
171
*/
172
interface PO.Item {
173
/** Original message identifier */
174
msgid: string;
175
176
/** Message context for disambiguation */
177
msgctxt: string | null;
178
179
/** Plural form message identifier */
180
msgid_plural: string | null;
181
182
/** Translated message strings (plural forms) */
183
msgstr: string[];
184
185
/** Source code references where message appears */
186
references: string[];
187
188
/** Translator comments */
189
comments: string[];
190
191
/** Comments extracted from source code */
192
extractedComments: string[];
193
194
/** Message flags (e.g., fuzzy, c-format) */
195
flags: { [flag: string]: boolean };
196
197
/** Whether entry is marked obsolete (entries marked with #~ prefix) */
198
obsolete: boolean;
199
200
/** Number of plural forms (defaults to 2) */
201
nplurals: number;
202
}
203
```
204
205
### Parsed Plural Forms
206
207
```javascript { .api }
208
/**
209
* Result of parsing Plural-Forms header
210
*/
211
interface ParsedPluralForms {
212
/** Number of plural forms (undefined if not specified) */
213
nplurals: string | undefined;
214
215
/** Plural form expression (undefined if not specified) */
216
plural: string | undefined;
217
}
218
```
219
220
## Usage Examples
221
222
### Creating Translation Items
223
224
```javascript
225
var PO = require('pofile');
226
var po = new PO();
227
228
// Simple translation
229
var item1 = new PO.Item();
230
item1.msgid = 'Hello World';
231
item1.msgstr = ['Hola Mundo'];
232
po.items.push(item1);
233
234
// Translation with context
235
var item2 = new PO.Item();
236
item2.msgctxt = 'greeting';
237
item2.msgid = 'Hello';
238
item2.msgstr = ['Hola'];
239
po.items.push(item2);
240
241
// Plural translation
242
var item3 = new PO.Item();
243
item3.msgid = 'There is %d item';
244
item3.msgid_plural = 'There are %d items';
245
item3.msgstr = ['Hay %d elemento', 'Hay %d elementos'];
246
po.items.push(item3);
247
248
// Translation with comments and references
249
var item4 = new PO.Item();
250
item4.msgid = 'File';
251
item4.msgstr = ['Archivo'];
252
item4.comments = ['Menu item for File menu'];
253
item4.extractedComments = ['Translators: Keep this short'];
254
item4.references = ['src/menus.js:42'];
255
item4.flags = { fuzzy: true };
256
po.items.push(item4);
257
```
258
259
### Working with Headers
260
261
```javascript
262
var PO = require('pofile');
263
var po = new PO();
264
265
// Set standard headers
266
po.headers['Project-Id-Version'] = 'My App 1.0';
267
po.headers['Language'] = 'es';
268
po.headers['Content-Type'] = 'text/plain; charset=UTF-8';
269
po.headers['Plural-Forms'] = 'nplurals=2; plural=(n != 1);';
270
271
// Control header order
272
po.headerOrder = ['Project-Id-Version', 'Language', 'Content-Type', 'Plural-Forms'];
273
```
274
275
### Parsing and Processing Files
276
277
```javascript
278
var PO = require('pofile');
279
var fs = require('fs');
280
281
// Parse from string
282
var content = fs.readFileSync('messages.po', 'utf8');
283
var po = PO.parse(content);
284
285
// Process items
286
po.items.forEach(function(item) {
287
if (item.flags.fuzzy) {
288
console.log('Fuzzy translation:', item.msgid);
289
}
290
291
if (item.msgid_plural) {
292
console.log('Plural forms:', item.msgstr.length);
293
}
294
295
if (item.msgctxt) {
296
console.log('Context:', item.msgctxt, 'for', item.msgid);
297
}
298
});
299
300
// Filter untranslated items
301
var untranslated = po.items.filter(function(item) {
302
return item.msgstr.every(function(str) { return str === ''; });
303
});
304
305
console.log('Untranslated items:', untranslated.length);
306
307
// Filter obsolete items (marked with #~ prefix)
308
var obsolete = po.items.filter(function(item) {
309
return item.obsolete;
310
});
311
312
console.log('Obsolete items:', obsolete.length);
313
```
314
315
### Handling Plural Forms
316
317
```javascript
318
var PO = require('pofile');
319
320
// Parse plural forms header
321
var pluralInfo = PO.parsePluralForms('nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;');
322
console.log('Number of plural forms:', pluralInfo.nplurals);
323
console.log('Plural expression:', pluralInfo.plural);
324
325
// Create item with proper plural count
326
var item = new PO.Item({ nplurals: parseInt(pluralInfo.nplurals) });
327
item.msgid = 'You have %d message';
328
item.msgid_plural = 'You have %d messages';
329
item.msgstr = ['Tienes %d mensaje', 'Tienes %d mensajes', 'Tienes %d mensajes'];
330
```
331
332
## Platform Support
333
334
- **Node.js**: Full support including file I/O operations (`PO.load`, `po.save`)
335
- **Browser**: Supported via Browserify (excludes file I/O methods)
336
- **Bower**: Available as browser package
337
338
File I/O methods (`PO.load` and `po.save`) are only available in Node.js environments and will not work in browsers.
339
340
## Error Handling
341
342
The library follows Node.js error handling conventions:
343
344
```javascript
345
// Loading files
346
PO.load('messages.po', function(err, po) {
347
if (err) {
348
console.error('Failed to load PO file:', err.message);
349
return;
350
}
351
// Process po object
352
});
353
354
// Saving files
355
po.save('output.po', function(err) {
356
if (err) {
357
console.error('Failed to save PO file:', err.message);
358
return;
359
}
360
console.log('PO file saved successfully');
361
});
362
```
363
364
Parsing operations (`PO.parse`) are synchronous and will throw exceptions on invalid input.