source: spip-zone/_plugins_/trad-lang/trunk/inc/salvatore_ecriveur.php @ 119824

Last change on this file since 119824 was 119824, checked in by Cerdic, 2 years ago

on peut passer un message de commit a l'ecriveur

  • Property svn:eol-style set to native
File size: 16.2 KB
Line 
1<?php
2
3/*
4    This file is part of Salvatore, the translation robot of Trad-lang (SPIP)
5
6    Salvatore is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    Trad-Lang is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with Trad-Lang; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20    Copyright 2003-2020
21        Florent Jugla <florent.jugla@eledo.com>,
22        Philippe Riviere <fil@rezo.net>,
23        Chryjs <chryjs!@!free!.!fr>,
24        kent1 <kent1@arscenic.info>
25        Cerdic <cedric@yterium.com>
26*/
27
28include_spip('base/abstract_sql');
29include_spip('inc/charsets');
30include_spip('inc/config');
31include_spip('inc/filtres');
32include_spip('inc/texte');
33include_spip('inc/xml');
34include_spip('inc/lang_liste');
35include_spip('inc/session');
36
37
38/**
39 * @param array $liste_sources
40 * @param string $dir_modules
41 * @throws Exception
42 */
43function salvatore_ecrire($liste_sources, $dir_modules = null, $message_commit=''){
44        include_spip('inc/salvatore');
45        salvatore_init();
46
47        // on va lire dans la base, il faut qu'elle soit a jour
48        salvatore_verifier_base_upgradee();
49
50        if (is_null($dir_modules)){
51                $dir_modules = _DIR_SALVATORE_MODULES;
52        }
53        salvatore_check_dir($dir_modules);
54        $gestionnaire_url = $GLOBALS['meta']['adresse_site'];
55        if (defined('_SALVATORE_TEST_URL_GESTIONNAIRE')) {
56                $gestionnaire_url = _SALVATORE_TEST_URL_GESTIONNAIRE;
57        }
58
59        foreach ($liste_sources as $source){
60                salvatore_log("\n<info>--- Module " . $source['module'] . " | " . $source['dir_module'] . " | " . $source['url'] . "</info>");
61
62                $module = $source['module'];
63                $dir_module = $dir_modules . $source['dir_module'];
64
65                if ($autre_gestionnaire = salvatore_verifier_gestionnaire_traduction($dir_module, $module)){
66                        salvatore_fail("[Lecteur] Erreur sur $module", "Erreur : import impossible, le fichier est traduit autre part : $autre_gestionnaire\n");
67                }
68
69                $id_tradlang_module = sql_getfetsel('id_tradlang_module', 'spip_tradlang_modules', 'module = ' . sql_quote($source[1]));
70
71                // url de l'interface de traduction d'un module
72                $url_trad = url_absolue(generer_url_entite($id_tradlang_module, 'tradlang_module'), $gestionnaire_url);
73                export_trad_module($source, $gestionnaire_url, $url_trad, $message_commit);
74        }
75}
76
77//
78// Genere les fichiers de traduction d'un module
79// TODO
80//
81function export_trad_module($source, $url_site, $url_trad, $message_commit = ''){
82        global $tmp;
83
84        // sanity check
85        if (!is_dir($tmp . $source[1] . '/')){
86                return false;
87        }
88
89        $module = sql_fetsel('id_tradlang_module,limite_trad,lang_mere', 'spip_tradlang_modules', 'module = ' . sql_quote($source[1]));
90
91        $seuil_export = 50;
92        if (is_numeric($module['limite_trad']) and $module['limite_trad']>0){
93                $seuil_export = $module['limite_trad'];
94        } elseif (function_exists('lire_config')) {
95                $seuil_export = lire_config('tradlang/seuil_export_tradlang', 50);
96        }
97        if (intval($module['id_tradlang_module'])>=1){
98                // charger la langue originale, pour la copier si necessaire
99                $count_original = 0;
100                $res = sql_allfetsel('id, id_tradlang_module,str,comm,statut', 'spip_tradlangs', 'id_tradlang_module = ' . intval($module['id_tradlang_module']) . ' AND lang = ' . sql_quote($module['lang_mere']) . ' AND statut="OK"', 'id');
101                foreach ($res as $row){
102                        $row['statut'] = 'NEW';
103                        $lorigine[$row['id']] = $row;
104                        $id_tradlang_module = $row['id_tradlang_module'];
105                        $count_original++;
106                }
107
108                $liste_lang = $liste_lang_non_exportees = $liste_lang_supprimer = array();
109                $minimal = ceil((($count_original*$seuil_export)/100));
110                salvatore_log("\nMinimal = $minimal ($seuil_export %)\n");
111
112                $res = sql_allfetsel('lang,COUNT(*) as N', 'spip_tradlangs', 'module = ' . sql_quote($source[1]) . ' AND statut != "NEW" AND statut != "attic"', 'lang', 'lang');
113                foreach ($res as $row){
114                        /**
115                         * Le fichier est il suffisamment traduit
116                         */
117                        if ($row['N']>=$minimal){
118                                $liste_lang[] = $row['lang'];
119                        } else {
120                                /**
121                                 * Le fichier n'est pas suffisamment traduit et n'existe pas, on ne fera donc rien
122                                 */
123                                if (!file_exists($tmp . $source[1] . '/' . $source[1] . '_' . $row['lang'] . '.php')){
124                                        $liste_lang_non_exportees[] = $row['lang'];
125                                } else {
126                                        /**
127                                         * Il n'est pas suffisamment traduit, cependant, il existe déjà
128                                         * On ne va donc pas le supprimer à la barbare, mais on le met à jour quand même
129                                         */
130                                        $liste_lang[] = $row['lang'];
131                                        $liste_lang_supprimer[] = $row['lang'];
132                                        $percent = (($row['N']/$count_original)*100);
133                                        if ($percent<($seuil_export-15)){
134                                                $message_commit .= "La langue '" . $row['lang'] . "' devrait être supprimée car trop peu traduite (" . number_format($percent, 2) . " %)\n";
135                                        }
136                                }
137                        }
138                }
139
140                // traiter chaque langue
141                $infos = $commiteurs = array();
142                foreach ($liste_lang as $lang){
143                        salvatore_log("Generation de la langue $lang ");
144                        // Proteger les caracteres typographiques a l'interieur des tags html
145                        $typo = (in_array($lang, array('eo', 'fr', 'cpf')) || strncmp($lang, 'fr_', 3)==0) ? 'fr' : 'en';
146                        $typographie = charger_fonction($typo, 'typographie');
147                        $tab = "\t";
148
149                        $x = $tous = $tradlangs = array();
150                        $prev = '';
151                        $traduits = $modifs = $relire = 0;
152
153                        // On ne prend que les MODIF, les RELIRE et les OK pour ne pas rendre les sites multilingues en français
154                        $res = sql_allfetsel('id_tradlang,id,str,comm,statut,md5', 'spip_tradlangs', 'module = "' . $source[1] . '" AND lang = "' . $lang . '" AND statut != "NEW" AND statut != "attic"', 'id');
155                        foreach ($res as $row){
156                                $tradlangs[] = $row['id_tradlang'];
157                                $tous[$row['id']] = $row;
158                        }
159                        ksort($tous);
160
161                        foreach ($tous as $row){
162                                if ($row['statut']=='OK'){
163                                        $traduits++;
164                                } elseif ($row['statut']=='MODIF') {
165                                        $modifs++;
166                                } elseif ($row['statut']=='RELIRE') {
167                                        $relire++;
168                                }
169
170                                if (strlen($row['comm'])>1){
171                                        // On remplace les sauts de lignes des commentaires sinon ça crée des erreurs php
172                                        $row['comm'] = str_replace(array("\r\n", "\n", "\r"), ' ', $row['comm']);
173                                        // Conversion des commentaires en utf-8
174                                        $row['comm'] = unicode_to_utf_8(html_entity_decode(preg_replace('/&([lg]t;)/S', '&amp;\1', $row['comm']), ENT_NOQUOTES, 'utf-8'));
175                                }
176
177                                if ($prev!=strtoupper($row['id'][0])){
178                                        $x[] = "\n$tab// " . strtoupper($row['id'][0]);
179                                }
180                                $prev = strtoupper($row['id'][0]);
181
182                                if (strlen($row['statut']) and ($row['statut']!='OK')){
183                                        $row['comm'] .= ' ' . $row['statut'];
184                                }
185                                if (trim($row['comm'])){
186                                        $row['comm'] = ' # ' . trim($row['comm']); // on rajoute les commentaires ?
187                                }
188
189                                $str = $row['str'];
190
191                                /**
192                                 * On enlève les sauts de lignes windows pour des sauts de ligne linux
193                                 */
194                                $str = str_replace("\r\n", "\n", $str);
195
196                                /**
197                                 * protection dans les balises genre <a href="..." ou <img src="..."
198                                 * cf inc/filtres
199                                 */
200                                if (preg_match_all(_TYPO_BALISE, $str, $regs, PREG_SET_ORDER)){
201                                        foreach ($regs as $reg){
202                                                $insert = $reg[0];
203                                                // hack: on transforme les caracteres a proteger en les remplacant
204                                                // par des caracteres "illegaux". (cf corriger_caracteres())
205                                                $insert = strtr($insert, _TYPO_PROTEGER, _TYPO_PROTECTEUR);
206                                                $str = str_replace($reg[0], $insert, $str);
207                                        }
208                                }
209
210                                /**
211                                 * Protéger le contenu des balises <html> <code> <cadre> <frame> <tt> <pre>
212                                 */
213                                define('_PROTEGE_BLOCS_HTML', ',<(html|code|cadre|pre|tt)(\s[^>]*)?>(.*)</\1>,UimsS');
214                                if ((strpos($str, '<')!==false) and preg_match_all(_PROTEGE_BLOCS_HTML, $str, $matches, PREG_SET_ORDER)){
215                                        foreach ($matches as $reg){
216                                                $insert = $reg[0];
217                                                // hack: on transforme les caracteres a proteger en les remplacant
218                                                // par des caracteres "illegaux". (cf corriger_caracteres())
219                                                $insert = strtr($insert, _TYPO_PROTEGER, _TYPO_PROTECTEUR);
220                                                $str = str_replace($reg[0], $insert, $str);
221                                        }
222                                }
223
224                                /**
225                                 * On applique la typographie de la langue
226                                 */
227                                $str = $typographie($str);
228                                /**
229                                 * On remet les caractères normaux sur les caractères illégaux
230                                 */
231                                $str = strtr($str, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
232
233                                $str = unicode_to_utf_8(html_entity_decode(preg_replace('/&([lg]t;)/S', '&amp;\1', $str), ENT_NOQUOTES, 'utf-8'));
234
235                                /**
236                                 * Calcul du nouveau md5
237                                 */
238                                $newmd5 = md5($str);
239
240                                /**
241                                 * Si le md5 ou la chaine à changé, on la met à jour dans la base
242                                 */
243                                if (($row['md5']!=$newmd5) || ($str!=$row['str'])){
244                                        $r = sql_updateq('spip_tradlangs', array('md5' => $newmd5, 'str' => $str), 'id_tradlang = ' . intval($row['id_tradlang']));
245                                }
246
247                                $x[] = $tab . var_export($row['id'], 1) . ' => ' . var_export($str, 1) . ',' . $row['comm'];
248                        }
249                        $orig = ($lang==$source[2]) ? $source[0] : false;
250
251                        salvatore_log(" - traduction ($traduits/$count_original OK | $relire/$count_original RELIRE | $modifs/$count_original MODIFS), export\n");
252                        // historiquement les fichiers de lang de spip_loader ne peuvent pas etre securises
253                        $secure = ($source[1]=='tradloader')
254                                ? ''
255                                : "if (!defined('_ECRIRE_INC_VERSION')) {
256        return;
257}\n\n";
258
259                        $fd = fopen($tmp . $source[1] . '/' . $source[1] . '_' . $lang . '.php', 'w');
260
261                        # supprimer la virgule du dernier item
262                        $x[count($x)-1] = preg_replace('/,([^,]*)$/', '\1', $x[count($x)-1]);
263
264                        $contenu = join("\n", $x);
265
266                        // L'URL du site de traduction
267                        $url_trad = parametre_url($url_trad, 'lang_cible', $lang);
268                        /**
269                         * Ecrire le fichier de langue complet
270                         */
271                        fwrite(
272                                $fd,
273                                '<' . '?php
274// This is a SPIP language file  --  Ceci est un fichier langue de SPIP
275'
276
277                                . ($orig
278                                        ? '// Fichier source, a modifier dans ' . $orig
279                                        : '// extrait automatiquement de ' . $url_trad . '
280// ** ne pas modifier le fichier **
281'
282                                )
283                                . "\n" . $secure . '$GLOBALS[$GLOBALS[\'idx_lang\']] = array(
284'
285                                . $contenu
286                                . '
287);
288'
289                        );
290                        fclose($fd);
291
292                        // noter la langue et les traducteurs pour lang/module.xml
293                        $infos[$lang] = $people_unique = array();
294                        $infos[$lang]['traducteurs'] = array();
295                        $infos[$lang]['traduits'] = $traduits;
296                        $infos[$lang]['modifs'] = $modifs;
297                        $infos[$lang]['relire'] = $relire;
298                        if (defined('_ID_AUTEUR_SALVATORE') and intval(_ID_AUTEUR_SALVATORE)>0){
299                                $people_unique[] = _ID_AUTEUR_SALVATORE;
300                        }
301                        $s = sql_allfetsel('DISTINCT(traducteur)', 'spip_tradlangs', 'id_tradlang_module = ' . intval($module['id_tradlang_module']) . ' AND lang = ' . sql_quote($lang));
302                        foreach ($s as $t){
303                                $traducteurs_lang = explode(',', $t['traducteur']);
304                                foreach ($traducteurs_lang as $traducteur){
305                                        if (!in_array($traducteur, $people_unique)){
306                                                if (is_numeric($traducteur) and $id_auteur = intval($traducteur)){
307                                                        $traducteur_supp['nom'] = extraire_multi(sql_getfetsel('nom', 'spip_auteurs', 'id_auteur = ' . $id_auteur));
308                                                        $traducteur_supp['lien'] = url_absolue(generer_url_entite($id_auteur, 'auteur'), $url_site);
309                                                } elseif (trim(strlen($traducteur))>0) {
310                                                        $traducteur_supp['nom'] = trim($traducteur);
311                                                        $traducteur_supp['lien'] = '';
312                                                }
313                                                if (isset($traducteur_supp['nom'])){
314                                                        $infos[$lang]['traducteurs'][strtolower($traducteur_supp['nom'])] = $traducteur_supp;
315                                                }
316                                                unset($traducteur_supp);
317                                                $people_unique[] = $traducteur;
318                                        }
319                                }
320                        }
321                        unset($people_unique);
322
323                        if (substr(exec('svn status ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . '_' . $lang . '.php'), 0, 1)=='?'){
324                                if ($module['limite_trad']==0){
325                                        passthru('svn add ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php 2> /dev/null") ? salvatore_log("$log\n") : '';
326                                } elseif (!in_array($source[1], array('ecrire', 'spip', 'public'))) {
327                                        if ((intval(($infos[$lang]['traduits']/$count_original)*100)>$seuil_export)){
328                                                passthru('svn add ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php* 2> /dev/null") ? salvatore_log("$log\n") : '';
329                                        }
330                                }
331                        }
332                        /**
333                         * Le fichier a été modifié ou ajouté (svn status A ou M)
334                         *
335                         * On récupère la date de dernier changement avec svn info
336                         * On cherche toutes les dernières modifications dans la base de donnée
337                         * Si un seul auteur de révisions (Hors salvatore et -1) on l'ajoute comme commiteur
338                         * Si plusieurs auteurs le commiteur sera Salvatore
339                         */
340                        if (in_array(substr(exec('svn status ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php"), 0, 1), array('A', 'M'))){
341                                $last_change = exec('env LC_MESSAGES=en_US.UTF-8 svn info ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php | awk '/^Last Changed Date/ { print $4 \" \" $5 }'");
342                                $auteur_versions = sql_allfetsel('id_auteur', 'spip_versions', 'objet="tradlang" AND date > ' . sql_quote($last_change) . ' AND ' . sql_in('id_objet', $tradlangs) . ' AND id_auteur != "-1" AND id_auteur !=' . intval(_ID_AUTEUR_SALVATORE), 'id_auteur');
343                                if (count($auteur_versions)==1){
344                                        $email = sql_getfetsel('email', 'spip_auteurs', 'id_auteur = ' . intval($auteur_versions[0]['id_auteur']));
345                                        if ($email){
346                                                $commiteurs[$lang] = $email;
347                                        }
348                                        salvatore_log("\nLe commiteur sera pour la langue $lang : " . $commiteurs[$lang] . " \n");
349                                }
350                        }
351                }
352
353                // ecrire lang/module.xml
354                $xml = "<traduction module=\"$source[1]\" gestionnaire=\"salvatore\" url=\"$url_site\" source=\"$source[0]\" reference=\"$source[2]\">\n";
355                foreach ($infos as $lang => $info){
356                        if (count($info['traducteurs']>0)){
357                                $xml .= "       <langue code=\"$lang\" url=\"" . parametre_url($url_trad, 'lang_cible', $lang) . "\" total=\"$count_original\" traduits=\"" . $info['traduits'] . '" relire="' . $info['relire'] . '" modifs="' . $info['modifs'] . '" nouveaux="' . ($count_original-($info['modifs']+$info['traduits']+$info['relire'])) . '" pourcent="' . number_format((($info['traduits']/$count_original)*100), 2) . "\">\n";
358                                ksort($info['traducteurs']);
359                                foreach ($info['traducteurs'] as $nom => $people){
360                                        $xml .= '               <traducteur nom="' . entites_html($people['nom']) . '" lien="' . entites_html($people['lien']) . "\" />\n";
361                                }
362                                $xml .= "       </langue>\n";
363                        } else {
364                                $xml .= "       <langue code=\"$lang\" url=\"" . parametre_url($url_trad, 'lang_cible', $lang) . "\" />\n";
365                        }
366                }
367                unset($traducteurs[$source[2]]);
368                $xml .= "</traduction>\n";
369
370                ecrire_fichier($tmp . $source[1] . '/' . $source[1] . '.xml', $xml);
371
372                if (isset($liste_lang_non_exportees) and (count($liste_lang_non_exportees)>0)){
373                        $liste_lang_non_exportees_string = implode(', ', $liste_lang_non_exportees);
374                        salvatore_log("\nLes langues suivantes ne sont pas exportées car trop peu traduites:\n");
375                        salvatore_log("$liste_lang_non_exportees_string\n");
376                }
377                if (isset($liste_lang_supprimer) and (count($liste_lang_supprimer)>0)){
378                        $liste_lang_supprimer_string = implode(', ', $liste_lang_supprimer);
379                        salvatore_log("\nLes langues suivantes devraient être supprimées car trop peu traduites:\n");
380                        salvatore_log("$liste_lang_supprimer_string\n");
381                }
382                if ($module['limite_trad']==0){
383                        foreach ($liste_lang as $lang){
384                                passthru('svn add ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php* 2> /dev/null") ? salvatore_log("$log\n") : '';
385                        }
386                } elseif (!in_array($source[1], array('ecrire', 'spip', 'public'))) {
387                        salvatore_log('Limite trad = ' . $seuil_export);
388                        foreach ($liste_lang as $lang){
389                                if ((intval(($infos[$lang]['traduits']/$count_original)*100)>$seuil_export)
390                                        and (substr(exec('svn status ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php"), 0, 1)=='?')){
391                                        passthru('svn add ' . _DIR_SALVATORE_TMP . $source[1] . '/' . $source[1] . "_$lang.php* 2> /dev/null") ? salvatore_log("$log\n") : '';
392                                }
393                        }
394                }
395                salvatore_log("\n" . passthru('svn status ' . _DIR_SALVATORE_TMP . $source[1] . '/') . "\n");
396                if (strlen($message_commit)>1 || count($commiteurs)>0){
397                        $fd = fopen($tmp . $source[1] . '/message_commit.inc', 'w');
398                        # ecrire le fichier
399                        fwrite(
400                                $fd,
401                                '<' . '?php
402$message_commit = "' . $message_commit . '";
403
404$commiteurs = ' . var_export($commiteurs, 1) . ';
405
406?' . '>
407'
408                        );
409                        fclose($fd);
410                }
411        } else {
412                salvatore_log("\n Ce module n'existe pas\n");
413        }
414}
Note: See TracBrowser for help on using the repository browser.