-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathpot-to-php.js
executable file
·137 lines (113 loc) · 3.36 KB
/
pot-to-php.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env node
/**
* External dependencies
*/
const gettextParser = require( 'gettext-parser' );
const fs = require( 'fs' );
const TAB = '\t';
const NEWLINE = '\n';
const fileHeader =
[
'<?php',
'/* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */',
'$generated_i18n_strings = array(',
].join( NEWLINE ) + NEWLINE;
const fileFooter =
NEWLINE +
[ ');', '/* THIS IS THE END OF THE GENERATED FILE */' ].join( NEWLINE ) +
NEWLINE;
/**
* Escapes single quotes.
*
* @param {string} input The string to be escaped.
* @return {string} The escaped string.
*/
function escapeSingleQuotes( input ) {
return input.replace( /'/g, "\\'" );
}
/**
* Converts a translation parsed from the POT file to lines of WP PHP.
*
* @param {Object} translation The translation to convert.
* @param {string} textdomain The text domain to use in the WordPress translation function call.
* @param {string} context The context for the translation.
* @return {string} Lines of PHP that match the translation.
*/
function convertTranslationToPHP( translation, textdomain, context = '' ) {
let php = '';
// The format of gettext-js matches the terminology in gettext itself.
let original = translation.msgid;
const comments = translation.comments ?? {};
if ( Object.values( comments ).length ) {
if ( comments.reference ) {
// All references are split by newlines, add a // Reference prefix to make them tidy.
php +=
TAB +
'// Reference: ' +
comments.reference
.split( NEWLINE )
.join( NEWLINE + TAB + '// Reference: ' ) +
NEWLINE;
}
if ( comments.translator ) {
// All extracted comments are split by newlines, add a tab to line them up nicely.
const translator = comments.translator
.split( NEWLINE )
.join( NEWLINE + TAB + ' ' );
php += TAB + `/* ${ translator } */${ NEWLINE }`;
}
if ( comments.extracted ) {
php +=
TAB + `/* translators: ${ comments.extracted } */${ NEWLINE }`;
}
}
if ( '' !== original ) {
original = escapeSingleQuotes( original );
if ( ! translation.msgid_plural ) {
if ( ! context ) {
php += TAB + `__( '${ original }', '${ textdomain }' )`;
} else {
php +=
TAB +
`_x( '${ original }', '${ translation.msgctxt }', '${ textdomain }' )`;
}
} else {
const plural = escapeSingleQuotes( translation.msgid_plural );
if ( ! context ) {
php +=
TAB +
`_n_noop( '${ original }', '${ plural }', '${ textdomain }' )`;
} else {
php +=
TAB +
`_nx_noop( '${ original }', '${ plural }', '${ translation.msgctxt }', '${ textdomain }' )`;
}
}
}
return php;
}
function convertPOTToPHP( potFile, phpFile, options ) {
const poContents = fs.readFileSync( potFile );
const parsedPO = gettextParser.po.parse( poContents );
let output = [];
for ( const context of Object.keys( parsedPO.translations ) ) {
const translations = parsedPO.translations[ context ];
const newOutput = Object.values( translations )
.map( ( translation ) =>
convertTranslationToPHP(
translation,
options.textdomain,
context
)
)
.filter( ( php ) => php !== '' );
output = [ ...output, ...newOutput ];
}
const fileOutput =
fileHeader + output.join( ',' + NEWLINE + NEWLINE ) + fileFooter;
fs.writeFileSync( phpFile, fileOutput );
}
const args = process.argv.slice( 2 );
convertPOTToPHP( args[ 0 ], args[ 1 ], {
textdomain: args[ 2 ],
} );