/var/www/html_nl/wp-content/plugins/loco-translate/src/ajax/SyncController.php


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( 
=== $conf ){
                throw new 
Loco_error_Exception('Plugin settings disallow missing templates');
            }
            if( 
=== $conf ){
                
// Translators: %s will be replaced with the name of a missing POT file
                
Loco_error_AdminNotices::warnsprintf__('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_ParseExceptionsprintf__('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::renderByteswp_convert_hr_to_bytesLoco_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$textnumber_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();
    }
    
    
}