编辑文件:.compile-mo.php
<?php /** * Minimal .po -> .mo (gettext binary) compiler. * Usage: php .compile-mo.php input.po output.mo * * Reads a GNU gettext .po source and writes the binary .mo that WordPress * loads via load_child_theme_textdomain(). Pure-PHP, no msgfmt dependency. */ if ( $argc < 3 ) { fwrite( STDERR, "Usage: php .compile-mo.php <input.po> <output.mo>\n" ); exit( 1 ); } $input = $argv[1]; $output = $argv[2]; $lines = file( $input, FILE_IGNORE_NEW_LINES ); if ( false === $lines ) { fwrite( STDERR, "Cannot read $input\n" ); exit( 1 ); } /** Parse the .po into [msgid => msgstr]. */ $entries = array(); $cur_id = array(); $cur_str = array(); $target = null; // 'id' | 'str' | null $flush = function () use ( &$entries, &$cur_id, &$cur_str, &$target ) { if ( null !== $target ) { $id = implode( '', $cur_id ); if ( ! isset( $entries[ $id ] ) ) { $entries[ $id ] = implode( '', $cur_str ); } } $cur_id = array(); $cur_str = array(); $target = null; }; foreach ( $lines as $line ) { if ( preg_match( '/^msgid\s+"(.*)"\s*$/', $line, $m ) ) { $flush(); $cur_id = array( $m[1] ); $target = 'id'; } elseif ( preg_match( '/^msgstr\s+"(.*)"\s*$/', $line, $m ) ) { $cur_str = array( $m[1] ); $target = 'str'; } elseif ( preg_match( '/^"(.*)"\s*$/', $line, $m ) ) { if ( 'str' === $target ) { $cur_str[] = $m[1]; } elseif ( 'id' === $target ) { $cur_id[] = $m[1]; } } } $flush(); /** Unescape gettext string escapes. */ $unescape = function ( $s ) { $find = array( '\\n', '\\t', '\\r', '\\"', '\\\\' ); $replace = array( "\n", "\t", "\r", '"', '\\' ); return str_replace( $find, $replace, $s ); }; /** Keep header + translated entries only. */ $translations = array(); foreach ( $entries as $id => $str ) { $id = $unescape( $id ); $str = $unescape( $str ); if ( '' === $id || '' !== $str ) { $translations[ $id ] = $str; } } $ids = array_keys( $translations ); $strs = array_values( $translations ); $count = count( $ids ); /** Assemble string tables + blob. */ $id_table = array(); $str_table = array(); $id_blob = ''; $str_blob = ''; foreach ( $ids as $s ) { $id_table[] = array( strlen( $s ), strlen( $id_blob ) ); $id_blob .= $s . "\x00"; } foreach ( $strs as $s ) { $str_table[] = array( strlen( $s ), strlen( $str_blob ) ); $str_blob .= $s . "\x00"; } $header_size = 7 * 4; $o_table_at = $header_size; $t_table_at = $o_table_at + $count * 8; $data_at = $t_table_at + $count * 8; // hash table size 0 $mo = ''; $mo .= pack( 'V', 0x950412de ); // magic $mo .= pack( 'V', 0 ); // revision $mo .= pack( 'V', $count ); // N strings $mo .= pack( 'V', $o_table_at );// original table offset $mo .= pack( 'V', $t_table_at );// translation table offset $mo .= pack( 'V', 0 ); // hash size $mo .= pack( 'V', 0 ); // hash offset foreach ( $id_table as $o ) { $mo .= pack( 'V', $o[0] ); // length $mo .= pack( 'V', $data_at + $o[1] ); // offset } foreach ( $str_table as $o ) { $mo .= pack( 'V', $o[0] ); $mo .= pack( 'V', $data_at + strlen( $id_blob ) + $o[1] ); } $mo .= $id_blob; $mo .= $str_blob; $bytes = file_put_contents( $output, $mo ); if ( false === $bytes ) { fwrite( STDERR, "Cannot write $output\n" ); exit( 1 ); } echo "OK: $count entries -> $output ($bytes bytes)\n";
保存
返回