1 |
<?php |
2 |
/** |
3 |
* based on php.mo 0.1 by Joss Crowcroft (http://www.josscrowcroft.com) |
4 |
* added case for commented unused string |
5 |
* fixed "fuzzy flag first line" bug which didn't saved previous proper string at all |
6 |
* removed unedeed phpmo_convert and phpmo_write_mo_file |
7 |
* |
8 |
* Converts gettext translation '.po' files to binary '.mo' files in PHP. |
9 |
* |
10 |
* Usage: |
11 |
* <?php require('php-mo.php'); phpmo_convert( 'input.po', [ 'output.mo' ] ); ?> |
12 |
* |
13 |
* NB: |
14 |
* - If no $output_file specified, output filename is same as $input_file (but .mo) |
15 |
* - Returns true/false for success/failure |
16 |
* - No warranty, but if it breaks, please let me know |
17 |
* |
18 |
* More info: |
19 |
* https://github.com/josscrowcroft/php.mo |
20 |
* |
21 |
* Based on php-msgfmt by Matthias Bauer (Copyright © 2007), a command-line PHP tool |
22 |
* for converting .po files to .mo. |
23 |
* (http://wordpress-soc-2007.googlecode.com/svn/trunk/moeffju/php-msgfmt/msgfmt.php) |
24 |
* |
25 |
* License: GPL v3 http://www.opensource.org/licenses/gpl-3.0.html |
26 |
*/ |
27 |
|
28 |
function phpmo_clean_helper($x) { |
29 |
if (is_array($x)) { |
30 |
foreach ($x as $k => $v) { |
31 |
$x[$k] = phpmo_clean_helper($v); |
32 |
} |
33 |
} else { |
34 |
if ($x[0] == '"') |
35 |
$x = substr($x, 1, -1); |
36 |
$x = str_replace("\"\n\"", '', $x); |
37 |
$x = str_replace('$', '\\$', $x); |
38 |
} |
39 |
return $x; |
40 |
} |
41 |
|
42 |
/* Parse gettext .po files. */ |
43 |
/* @link http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files */ |
44 |
function phpmo_parse_po_file($in) { |
45 |
// read .po file |
46 |
$fh = @fopen($in, 'r'); |
47 |
if ($fh === false) { |
48 |
// Could not open file resource |
49 |
return false; |
50 |
} |
51 |
|
52 |
// results array |
53 |
$hash = array (); |
54 |
// temporary array |
55 |
$temp = array (); |
56 |
// state |
57 |
$state = null; |
58 |
$fuzzy = false; |
59 |
|
60 |
// iterate over lines |
61 |
while(($line = fgets($fh, 65536)) !== false) { |
62 |
$line = trim($line); |
63 |
if ($line === '') { |
64 |
// save stored entry on empty line |
65 |
// block moved to fix "fuzzy flag first line" bug which didn't saved previous proper string at all |
66 |
if (sizeof($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) { |
67 |
if (!$fuzzy) |
68 |
$hash[] = $temp; |
69 |
$temp = array (); |
70 |
$state = null; |
71 |
$fuzzy = false; |
72 |
} |
73 |
continue; |
74 |
} |
75 |
$array_of_splited_string = preg_split('/\s/', $line, 2); |
76 |
$key = $array_of_splited_string[0]; |
77 |
$data = (isset($array_of_splited_string[1]) ? $array_of_splited_string[1] : ''); |
78 |
|
79 |
switch ($key) { |
80 |
case '#,' : // flag... |
81 |
$fuzzy = in_array('fuzzy', preg_split('/,\s*/', $data)); |
82 |
case '#' : // translator-comments |
83 |
case '#.' : // extracted-comments |
84 |
case '#:' : // reference... |
85 |
case '#|' : // msgid previous-untranslated-string |
86 |
break; |
87 |
case '#~' : // commented-unused-string |
88 |
$temp = array (); |
89 |
$state = null; |
90 |
$fuzzy = false; |
91 |
break; |
92 |
case 'msgctxt' : |
93 |
// context |
94 |
case 'msgid' : |
95 |
// untranslated-string |
96 |
case 'msgid_plural' : |
97 |
// untranslated-string-plural |
98 |
$state = $key; |
99 |
$temp[$state] = $data; |
100 |
break; |
101 |
case 'msgstr' : |
102 |
// translated-string |
103 |
$state = 'msgstr'; |
104 |
$temp[$state][] = $data; |
105 |
break; |
106 |
default : |
107 |
if (strpos($key, 'msgstr[') !== FALSE) { |
108 |
// translated-string-case-n |
109 |
$state = 'msgstr'; |
110 |
$temp[$state][] = $data; |
111 |
} else { |
112 |
// continued lines |
113 |
switch ($state) { |
114 |
case 'msgctxt' : |
115 |
case 'msgid' : |
116 |
case 'msgid_plural' : |
117 |
$temp[$state] .= "\n" . $line; |
118 |
break; |
119 |
case 'msgstr' : |
120 |
$temp[$state][sizeof($temp[$state]) - 1] .= "\n" . $line; |
121 |
break; |
122 |
default : |
123 |
// parse error |
124 |
fclose($fh); |
125 |
return FALSE; |
126 |
} |
127 |
} |
128 |
break; |
129 |
} |
130 |
} |
131 |
fclose($fh); |
132 |
|
133 |
// add final entry |
134 |
if ($state == 'msgstr') |
135 |
$hash[] = $temp; |
136 |
|
137 |
// Cleanup data, merge multiline entries, reindex hash for ksort |
138 |
$temp = $hash; |
139 |
$hash = array (); |
140 |
foreach ($temp as $entry) { |
141 |
foreach ($entry as & $v) { |
142 |
$v = phpmo_clean_helper($v); |
143 |
if ($v === FALSE) { |
144 |
// parse error |
145 |
return FALSE; |
146 |
} |
147 |
} |
148 |
$hash[$entry['msgid']] = $entry; |
149 |
} |
150 |
|
151 |
return $hash; |
152 |
} |
153 |
|
154 |
?> |