PluginProbe ʕ •ᴥ•ʔ
Loco Translate / 2.8.0
Loco Translate v2.8.0
2.8.5 2.8.4 2.5.8 2.6.0 2.6.1 2.6.10 2.6.11 2.6.12 2.6.13 2.6.14 2.6.2 2.6.3 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.6.9 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0 2.8.1 2.8.2 2.8.3 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2 1.2.1 1.2.2 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.17 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7
loco-translate / src / cli / SyncCommand.php
loco-translate / src / cli Last commit date
Commands.php 3 years ago ExtractCommand.php 1 year ago FetchCommand.php 1 year ago SyncCommand.php 1 year ago Utils.php 1 year ago
SyncCommand.php
181 lines
1 <?php
2 /**
3 * Called from Loco_cli_Commands::sync
4 */
5 abstract class Loco_cli_SyncCommand {
6
7
8 /**
9 * @param Loco_package_Project[] $projects project filter
10 * @param Loco_Locale[] $locales locale filter
11 * @param bool $noop whether dry run
12 * @param bool $force whether to always update
13 */
14 public static function run( array $projects, array $locales, $noop = true, $force = false ){
15
16 if( $force && $noop ){
17 throw new Loco_error_Exception('--force makes no sense with --noop');
18 }
19
20 $content_dir = loco_constant('WP_CONTENT_DIR');
21 $wp_locales = new Loco_api_WordPressTranslations;
22
23 // track total number of PO files synced, plus MO and JSON files compiled
24 $updated = 0;
25 $compiled = 0;
26
27 foreach( $projects as $project ){
28 $id = rtrim( $project->getId(), '.' );
29 $base_dir = $project->getBundle()->getDirectoryPath();
30 WP_CLI::log( sprintf('Syncing "%s" (%s)',$project->getName(),$id) );
31 // Check if project has POT, which will be used as default template unless PO overrides
32 $pot = null;
33 $potfile = $project->getPot();
34 if( $potfile && $potfile->exists() ){
35 Loco_cli_Utils::debug('Parsing template: %s',$potfile->getRelativePath($content_dir));
36 try {
37 $pot = Loco_gettext_Data::fromSource( $potfile->getContents() );
38 }
39 catch( Loco_error_ParseException $e ){
40 WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false );
41 $potfile = null;
42 }
43 }
44 /* @var Loco_fs_LocaleFile $pofile */
45 $pofiles = $project->findLocaleFiles('po');
46 foreach( $pofiles as $pofile ){
47 $locale = $pofile->getLocale();
48 $tag = (string) $locale;
49 if( $locales && ! array_key_exists($tag,$locales) ){
50 continue;
51 }
52 // Preempt write errors and print useful file mode info
53 $mofile = $pofile->cloneExtension('mo');
54 if( ! $pofile->writable() || $mofile->locked() ){
55 WP_CLI::warning('Skipping unwritable: '.self::fname($pofile) );
56 Loco_cli_Utils::tabulateFiles( $pofile->getParent(), $pofile, $mofile );
57 continue;
58 }
59 // Parsing candidate PO file (definitions)
60 Loco_cli_Utils::debug('Parsing PO: %s',$pofile->getRelativePath($content_dir));
61 try {
62 $def = Loco_gettext_Data::fromSource( $pofile->getContents() );
63 }
64 catch( Loco_error_ParseException $e ){
65 WP_CLI::error( $e->getMessage().' in '.$pofile->getRelativePath($content_dir), false );
66 continue;
67 }
68 // Check if PO defines alternative template (reference)
69 $ref = $pot;
70 $head = $def->getHeaders();
71 $opts = new Loco_gettext_SyncOptions($head);
72 $translate = $opts->mergeMsgstr();
73 if( $opts->hasTemplate() ){
74 $ref = null;
75 $potfile = $opts->getTemplate();
76 $potfile->normalize( $base_dir );
77 if( $potfile->exists() ){
78 try {
79 Loco_cli_Utils::debug('> Parsing alternative template: %s',$potfile->getRelativePath($content_dir) );
80 $ref = Loco_gettext_Data::fromSource( $potfile->getContents() );
81 }
82 catch( Loco_error_ParseException $e ){
83 WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false );
84 }
85 }
86 else {
87 Loco_cli_Utils::debug('Template not found (%s)', $potfile->basename() );
88 }
89 }
90 if( ! $ref ){
91 WP_CLI::warning( sprintf('Skipping %s; no valid translation template',$pofile->getRelativePath($content_dir) ) );
92 continue;
93 }
94 // Perform merge if we have a reference file
95 Loco_cli_Utils::debug('Merging %s <- %s', $pofile->basename(), $potfile->basename() );
96 $matcher = new Loco_gettext_Matcher($project);
97 $matcher->loadRefs($ref,$translate );
98 // Merge jsons if configured and available
99 if( $opts->mergeJson() ){
100 $siblings = new Loco_fs_Siblings( $potfile->cloneBasename( $pofile->basename() ) );
101 $jsons = $siblings->getJsons( $project->getDomain()->getName() );
102 $njson = $matcher->loadJsons($jsons);
103 Loco_cli_Utils::debug('> merged %u json files', $njson );
104 }
105 // Get fuzzy matching tolerance from plugin settings, can be set temporarily in command line
106 $fuzziness = Loco_data_Settings::get()->fuzziness;
107 $matcher->setFuzziness( (string) $fuzziness );
108 // update matches sources, deferring unmatched for deferred fuzzy match
109 $po = clone $def;
110 $po->clear();
111 $nvalid = count( $matcher->mergeValid($def,$po) );
112 $nfuzzy = count( $matcher->mergeFuzzy($po) );
113 $nadded = count( $matcher->mergeAdded($po) );
114 $ndropped = count( $matcher->redundant() );
115 // TODO Support --previous to keep old strings, or at least comment them out as #| msgid.....
116 if( $nfuzzy || $nadded || $ndropped ){
117 Loco_cli_Utils::debug('> unchanged:%u added:%u fuzzy:%u dropped:%u', $nvalid, $nadded, $nfuzzy, $ndropped );
118 }
119 else {
120 Loco_cli_Utils::debug('> %u identical sources',$nvalid);
121 }
122 // File is synced, but may be identical
123 $po->sort();
124 if( ! $force && $po->equal($def) ){
125 WP_CLI::log( sprintf('No update required for %s', self::fname($pofile) ) );
126 continue;
127 }
128 if( $noop ){
129 WP_CLI::success( sprintf('**DRY RUN** would update %s', self::fname($pofile) ) );
130 continue;
131 }
132 try {
133 $locale->ensureName($wp_locales);
134 $po->localize($locale);
135 $compiler = new Loco_gettext_Compiler($pofile);
136 $bytes = $compiler->writePo($po);
137 Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $pofile->basename());
138 $updated++;
139 // compile MO
140 $bytes = $compiler->writeMo($po);
141 if( $bytes ){
142 Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $mofile->basename());
143 $compiled++;
144 }
145 // Done PO/MO pair, now generate JSON fragments as applicable
146 $jsons = $compiler->writeJson($project,$po);
147 foreach( $jsons as $file ){
148 $compiled++;
149 $param = new Loco_mvc_FileParams([],$file);
150 Loco_cli_Utils::debug('+ %u bytes written to %s',$param->size,$param->name);
151 }
152 // Done compile of this set
153 Loco_error_AdminNotices::get()->flush();
154 WP_CLI::success( sprintf('Updated %s', self::fname($pofile) ) );
155 }
156 catch( Loco_error_WriteException $e ){
157 WP_CLI::error( $e->getMessage(), false );
158 }
159 }
160 }
161 // sync summary
162 if( 0 === $updated ){
163 WP_CLI::log('Nothing updated');
164 }
165 else {
166 WP_CLI::success( sprintf('%u PO files synced, %u files compiled',$updated,$compiled) );
167 }
168 }
169
170
171 /**
172 * Debug file name showing directory location
173 * @param Loco_fs_File
174 * @return string
175 */
176 private static function fname( Loco_fs_File $file ){
177 $dir = new Loco_fs_LocaleDirectory( $file->dirname() );
178 return $file->filename().' ('.$dir->getTypeLabel( $dir->getTypeId() ).')';
179 }
180
181 }