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
|
<?php
/** * Ajax "sync" route. * Extracts strings from source (POT or code) and returns to the browser for in-editor merge. */ class Loco_ajax_SyncController extends Loco_mvc_AjaxController {
/** * {@inheritdoc} */ public function render(){ $post = $this->validate(); $bundle = Loco_package_Bundle::fromId( $post->bundle ); $project = $bundle->getProjectById( $post->domain ); if( ! $project instanceof Loco_package_Project ){ throw new Loco_error_Exception('No such project '.$post->domain); }
// Merging on back end is only required if existing target file exists. // It always should do, and the editor is not permitted to contain unsaved changes when syncing. if( ! $post->has('path') ){ throw new Loco_error_Exception('path argument required'); } $file = new Loco_fs_File( $post->path ); $base = loco_constant('WP_CONTENT_DIR'); $file->normalize($base); $target = Loco_gettext_Data::load($file);
// POT file always synced with source code $type = $post->type; if( 'pot' === $type ){ $potfile = null; } // allow front end to configure source file. (will have come from $target headers) else if( $post->sync ){ $potfile = new Loco_fs_File( $post->sync ); $potfile->normalize($base); } // else use project-configured template path (must return a file) else { $potfile = $project->getPot(); } // keep existing behaviour when template is missing, but add warning according to settings. if( $potfile && ! $potfile->exists() ){ $conf = Loco_data_Settings::get()->pot_expected; if( 2 === $conf ){ throw new Loco_error_Exception('Plugin settings disallow missing templates'); } if( 1 === $conf ){ // Translators: %s will be replaced with the name of a missing POT file Loco_error_AdminNotices::warn( sprintf( __('Falling back to source extraction because %s is missing','loco-translate'), $potfile->basename() ) ); } $potfile = null; } // defaults: no msgstr and no json $translate = false; $syncjsons = []; // Parse existing POT for source if( $potfile ){ $this->set('pot', $potfile->basename() ); try { $source = Loco_gettext_Data::load($potfile); } catch( Exception $e ){ // translators: Where %s is the name of the invalid POT file throw new Loco_error_ParseException( sprintf( __('Translation template is invalid (%s)','loco-translate'), $potfile->basename() ) ); } // Sync options are passed through from editor controller via JS $opts = new Loco_gettext_SyncOptions( new LocoPoHeaders ); $opts->setSyncMode( $post->mode ); // Only copy msgstr fields from source if it's a user-defined PO template and "copy translations" was selected. if( 'pot' !== $potfile->extension() ){ $translate = $opts->mergeMsgstr(); } // Only merge JSON translations if specified. This requires we know the localised path where they will be if( $opts->mergeJson() ){ $siblings = new Loco_fs_Siblings($potfile); $syncjsons = $siblings->getJsons( $project->getDomain()->getName() ); } } // else extract POT from source code else { $this->set('pot', '' ); $domain = (string) $project->getDomain(); $extr = new Loco_gettext_Extraction($bundle); $extr->addProject($project); // bail if any files were skipped if( $list = $extr->getSkipped() ){ $n = count($list); $maximum = Loco_mvc_FileParams::renderBytes( wp_convert_hr_to_bytes( Loco_data_Settings::get()->max_php_size ) ); $largest = Loco_mvc_FileParams::renderBytes( $extr->getMaxPhpSize() ); // Translators: (1) Number of files (2) Maximum size of file that will be included (3) Size of the largest encountered $text = _n('%1$s file has been skipped because it\'s %3$s. (Max is %2$s). Check all strings are present before saving.','%1$s files over %2$s have been skipped. (Largest is %3$s). Check all strings are present before saving.',$n,'loco-translate'); $text = sprintf( $text, number_format($n), $maximum, $largest ); // not failing, just warning. Nothing will be saved until user saves editor state Loco_error_AdminNotices::warn( $text ); } // Have source strings. These cannot contain any translations. $source = $extr->includeMeta()->getTemplate($domain); } // establish on back end what strings will be added, removed, and which could be fuzzy-matches $matcher = new Loco_gettext_Matcher($project); $matcher->loadRefs($source,$translate); // merging JSONs must be done before fuzzy matching as it may add source strings if( $syncjsons ) { $matcher->loadJsons($syncjsons); } // Fuzzy matching only applies to syncing PO files. POT files will always do hard sync (add/remove) if( 'po' === $type ){ $fuzziness = Loco_data_Settings::get()->fuzziness; $matcher->setFuzziness( (string) $fuzziness ); } else { $matcher->setFuzziness('0'); } // update matches sources, deferring unmatched for deferred fuzzy match $merged = clone $target; $merged->clear(); $this->set( 'done', $matcher->merge($target,$merged) ); $merged->sort(); $this->set( 'po', $merged->jsonSerialize() ); return parent::render(); } }
|