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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
<?php /** * Called from Loco_cli_Commands::sync */ abstract class Loco_cli_SyncCommand {
/** * @param Loco_package_Project[] $projects project filter * @param Loco_Locale[] $locales locale filter * @param bool $noop whether dry run * @param bool $force whether to always update */ public static function run( array $projects, array $locales, $noop = true, $force = false ){ if( $force && $noop ){ throw new Loco_error_Exception('--force makes no sense with --noop'); }
$content_dir = loco_constant('WP_CONTENT_DIR'); $wp_locales = new Loco_api_WordPressTranslations; // track total number of PO files synced, plus MO and JSON files compiled $updated = 0; $compiled = 0;
foreach( $projects as $project ){ $id = rtrim( $project->getId(), '.' ); $base_dir = $project->getBundle()->getDirectoryPath(); WP_CLI::log( sprintf('Syncing "%s" (%s)',$project->getName(),$id) ); // Check if project has POT, which will be used as default template unless PO overrides $pot = null; $potfile = $project->getPot(); if( $potfile && $potfile->exists() ){ Loco_cli_Utils::debug('Parsing template: %s',$potfile->getRelativePath($content_dir)); try { $pot = Loco_gettext_Data::fromSource( $potfile->getContents() ); } catch( Loco_error_ParseException $e ){ WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false ); $potfile = null; } } /* @var Loco_fs_LocaleFile $pofile */ $pofiles = $project->findLocaleFiles('po'); foreach( $pofiles as $pofile ){ $locale = $pofile->getLocale(); $tag = (string) $locale; if( $locales && ! array_key_exists($tag,$locales) ){ continue; } // Preempt write errors and print useful file mode info $mofile = $pofile->cloneExtension('mo'); if( ! $pofile->writable() || $mofile->locked() ){ WP_CLI::warning('Skipping unwritable: '.self::fname($pofile) ); Loco_cli_Utils::tabulateFiles( $pofile->getParent(), $pofile, $mofile ); continue; } // Parsing candidate PO file (definitions) Loco_cli_Utils::debug('Parsing PO: %s',$pofile->getRelativePath($content_dir)); try { $def = Loco_gettext_Data::fromSource( $pofile->getContents() ); } catch( Loco_error_ParseException $e ){ WP_CLI::error( $e->getMessage().' in '.$pofile->getRelativePath($content_dir), false ); continue; } // Check if PO defines alternative template (reference) $ref = $pot; $head = $def->getHeaders(); $opts = new Loco_gettext_SyncOptions($head); $translate = $opts->mergeMsgstr(); if( $opts->hasTemplate() ){ $ref = null; $potfile = $opts->getTemplate(); $potfile->normalize( $base_dir ); if( $potfile->exists() ){ try { Loco_cli_Utils::debug('> Parsing alternative template: %s',$potfile->getRelativePath($content_dir) ); $ref = Loco_gettext_Data::fromSource( $potfile->getContents() ); } catch( Loco_error_ParseException $e ){ WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false ); } } else { Loco_cli_Utils::debug('Template not found (%s)', $potfile->basename() ); } } if( ! $ref ){ WP_CLI::warning( sprintf('Skipping %s; no valid translation template',$pofile->getRelativePath($content_dir) ) ); continue; } // Perform merge if we have a reference file Loco_cli_Utils::debug('Merging %s <- %s', $pofile->basename(), $potfile->basename() ); $matcher = new Loco_gettext_Matcher($project); $matcher->loadRefs($ref,$translate ); // Merge jsons if configured and available if( $opts->mergeJson() ){ $siblings = new Loco_fs_Siblings( $potfile->cloneBasename( $pofile->basename() ) ); $jsons = $siblings->getJsons( $project->getDomain()->getName() ); $njson = $matcher->loadJsons($jsons); Loco_cli_Utils::debug('> merged %u json files', $njson ); } // Get fuzzy matching tolerance from plugin settings, can be set temporarily in command line $fuzziness = Loco_data_Settings::get()->fuzziness; $matcher->setFuzziness( (string) $fuzziness ); // update matches sources, deferring unmatched for deferred fuzzy match $po = clone $def; $po->clear(); $nvalid = count( $matcher->mergeValid($def,$po) ); $nfuzzy = count( $matcher->mergeFuzzy($po) ); $nadded = count( $matcher->mergeAdded($po) ); $ndropped = count( $matcher->redundant() ); // TODO Support --previous to keep old strings, or at least comment them out as #| msgid..... if( $nfuzzy || $nadded || $ndropped ){ Loco_cli_Utils::debug('> unchanged:%u added:%u fuzzy:%u dropped:%u', $nvalid, $nadded, $nfuzzy, $ndropped ); } else { Loco_cli_Utils::debug('> %u identical sources',$nvalid); } // File is synced, but may be identical $po->sort(); if( ! $force && $po->equal($def) ){ WP_CLI::log( sprintf('No update required for %s', self::fname($pofile) ) ); continue; } if( $noop ){ WP_CLI::success( sprintf('**DRY RUN** would update %s', self::fname($pofile) ) ); continue; } try { $locale->ensureName($wp_locales); $po->localize($locale); $compiler = new Loco_gettext_Compiler($pofile); $bytes = $compiler->writePo($po); Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $pofile->basename()); $updated++; // compile MO $bytes = $compiler->writeMo($po); if( $bytes ){ Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $mofile->basename()); $compiled++; } // Done PO/MO pair, now generate JSON fragments as applicable $jsons = $compiler->writeJson($project,$po); foreach( $jsons as $file ){ $compiled++; $param = new Loco_mvc_FileParams([],$file); Loco_cli_Utils::debug('+ %u bytes written to %s',$param->size,$param->name); } // Done compile of this set Loco_error_AdminNotices::get()->flush(); WP_CLI::success( sprintf('Updated %s', self::fname($pofile) ) ); } catch( Loco_error_WriteException $e ){ WP_CLI::error( $e->getMessage(), false ); } } } // sync summary if( 0 === $updated ){ WP_CLI::log('Nothing updated'); } else { WP_CLI::success( sprintf('%u PO files synced, %u files compiled',$updated,$compiled) ); } }
/** * Debug file name showing directory location * @param Loco_fs_File * @return string */ private static function fname( Loco_fs_File $file ){ $dir = new Loco_fs_LocaleDirectory( $file->dirname() ); return $file->filename().' ('.$dir->getTypeLabel( $dir->getTypeId() ).')'; }
}
|