mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-22 09:21:30 +01:00
* Qual: Spelling outside htdocs # Qual: Fix spelling of files not in the htdocs subdirectory. Highlight: - Change in email test from unvalid to invalid that should give the same test result. * Update Dolibarr-soapui-project.xml --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
367 lines
11 KiB
PHP
367 lines
11 KiB
PHP
<?php
|
|
/* Copyright (C) 2009-2012 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \file dev/translation/langAutoParser.class.php
|
|
* \ingroup dev
|
|
* \brief This file is an example for a command line script
|
|
*/
|
|
|
|
/**
|
|
* Class to parse language files and translate them
|
|
* This is a language automatic translator parser for Dolibarr
|
|
*/
|
|
class autoTranslator
|
|
{
|
|
private $_translatedFiles = array();
|
|
private $_destlang = '';
|
|
private $_refLang = '';
|
|
private $_langDir = '';
|
|
private $_limittofile = '';
|
|
private $_time;
|
|
private $_time_end;
|
|
private $_outputpagecode = 'UTF-8';
|
|
private $_apikey;
|
|
//private $_outputpagecode = 'ISO-8859-1';
|
|
const DIR_SEPARATOR = '/';
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $_destlang Destination lang
|
|
* @param string $_refLang Ref lang
|
|
* @param string $_langDir Dir lang
|
|
* @param string $_limittofile Limit to file
|
|
* @param string $_apikey Api key
|
|
* @return void
|
|
*/
|
|
public function __construct($_destlang, $_refLang, $_langDir, $_limittofile, $_apikey)
|
|
{
|
|
|
|
// Set environment variables
|
|
$this->_destlang = $_destlang;
|
|
$this->_refLang = $_refLang;
|
|
$this->_langDir = $_langDir.self::DIR_SEPARATOR;
|
|
$this->_time = date('Y-m-d H:i:s');
|
|
$this->_limittofile = $_limittofile;
|
|
$this->_apikey = $_apikey;
|
|
|
|
// Translate
|
|
//ini_set('default_charset','UTF-8');
|
|
ini_set('default_charset', $this->_outputpagecode);
|
|
$this->parseRefLangTranslationFiles();
|
|
}
|
|
|
|
/**
|
|
* Parse file
|
|
*
|
|
* @return void
|
|
*/
|
|
private function parseRefLangTranslationFiles()
|
|
{
|
|
$files = $this->getTranslationFilesArray($this->_refLang);
|
|
$counter = 1;
|
|
foreach ($files as $file) {
|
|
if ($this->_limittofile && $this->_limittofile != $file) {
|
|
continue;
|
|
}
|
|
$counter++;
|
|
$fileContent = null;
|
|
$refPath = $this->_langDir.$this->_refLang.self::DIR_SEPARATOR.$file;
|
|
$fileContent = file($refPath, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
|
|
print "Processing file " . $file . ", with ".count($fileContent)." lines<br>\n";
|
|
|
|
// Define target dirs
|
|
$targetlangs=array($this->_destlang);
|
|
if ($this->_destlang == 'all') {
|
|
$targetlangs=array();
|
|
|
|
// If we must process all languages
|
|
$arraytmp=dol_dir_list($this->_langDir, 'directories', 0);
|
|
foreach ($arraytmp as $dirtmp) {
|
|
if ($dirtmp['name'] === $this->_refLang) {
|
|
continue; // We discard source language
|
|
}
|
|
$tmppart=explode('_', $dirtmp['name']);
|
|
if (preg_match('/^en/i', $dirtmp['name'])) {
|
|
continue; // We discard en_* languages
|
|
}
|
|
if (preg_match('/^fr/i', $dirtmp['name'])) {
|
|
continue; // We discard fr_* languages
|
|
}
|
|
if (preg_match('/^es/i', $dirtmp['name'])) {
|
|
continue; // We discard es_* languages
|
|
}
|
|
if (preg_match('/ca_ES/i', $dirtmp['name'])) {
|
|
continue; // We discard es_CA language
|
|
}
|
|
if (preg_match('/pt_BR/i', $dirtmp['name'])) {
|
|
continue; // We discard pt_BR language
|
|
}
|
|
if (preg_match('/nl_BE/i', $dirtmp['name'])) {
|
|
continue; // We discard nl_BE language
|
|
}
|
|
if (preg_match('/^\./i', $dirtmp['name'])) {
|
|
continue; // We discard files .*
|
|
}
|
|
if (preg_match('/^CVS/i', $dirtmp['name'])) {
|
|
continue; // We discard CVS
|
|
}
|
|
$targetlangs[]=$dirtmp['name'];
|
|
}
|
|
//var_dump($targetlangs);
|
|
}
|
|
|
|
// Process translation of source file for each target languages
|
|
foreach ($targetlangs as $my_destlang) {
|
|
$this->_translatedFiles = array();
|
|
|
|
$destPath = $this->_langDir.$my_destlang.self::DIR_SEPARATOR.$file;
|
|
// Check destination file presence
|
|
if (! file_exists($destPath)) {
|
|
// No file present, we generate file
|
|
echo "File not found: " . $destPath . ". We generate it.<br>\n";
|
|
$this->createTranslationFile($destPath, $my_destlang);
|
|
} else {
|
|
echo "Updating file: " . $destPath . "<br>\n";
|
|
}
|
|
|
|
// Translate lines
|
|
$fileContentDest = file($destPath, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
|
|
$newlines=0;
|
|
foreach ($fileContent as $line) {
|
|
$key = $this->getLineKey($line);
|
|
$value = $this->getLineValue($line);
|
|
if ($key && $value) {
|
|
$newlines+=$this->translateFileLine($fileContentDest, $file, $key, $value, $my_destlang);
|
|
}
|
|
}
|
|
|
|
$this->updateTranslationFile($destPath, $file, $my_destlang);
|
|
echo "New translated lines: " . $newlines . "<br>\n";
|
|
//if ($counter ==3) die('fim');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update file with new translations
|
|
*
|
|
* @param string $destPath Target path
|
|
* @param string $file File
|
|
* @param string $my_destlang Target language code
|
|
* @return void
|
|
*/
|
|
private function updateTranslationFile($destPath, $file, $my_destlang)
|
|
{
|
|
$this->_time_end = date('Y-m-d H:i:s');
|
|
|
|
if (isset($this->_translatedFiles[$file]) && count($this->_translatedFiles[$file])>0) {
|
|
$fp = fopen($destPath, 'a');
|
|
fwrite($fp, "\n");
|
|
fwrite($fp, "\n");
|
|
fwrite($fp, "// START - Lines generated via autotranslator.php tool (".$this->_time.").\n");
|
|
fwrite($fp, "// Reference language: ".$this->_refLang." -> ".$my_destlang."\n");
|
|
foreach ($this->_translatedFiles[$file] as $line) {
|
|
fwrite($fp, $line . "\n");
|
|
}
|
|
fwrite($fp, "// STOP - Lines generated via autotranslator.php tool (".$this->_time_end.").\n");
|
|
fclose($fp);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Create a new translation file
|
|
*
|
|
* @param string $path Path
|
|
* @param string $my_destlang Target language code
|
|
* @return void
|
|
*/
|
|
private function createTranslationFile($path, $my_destlang)
|
|
{
|
|
$fp = fopen($path, 'w+');
|
|
fwrite($fp, "/*\n");
|
|
fwrite($fp, " * Language code: {$my_destlang}\n");
|
|
fwrite($fp, " * Automatic generated via autotranslator.php tool\n");
|
|
fwrite($fp, " * Generation date " . $this->_time. "\n");
|
|
fwrite($fp, " */\n");
|
|
fclose($fp);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Put in array _translatedFiles[$file], line of a new translated pair
|
|
*
|
|
* @param string $content Existing content of dest file
|
|
* @param string $file Target file name translated (xxxx.lang)
|
|
* @param string $key Key to translate
|
|
* @param string $value Existing value in source file
|
|
* @param string $my_destlang Language code (ie: fr_FR)
|
|
* @return int 0=Nothing translated, 1=Record translated
|
|
*/
|
|
private function translateFileLine($content, $file, $key, $value, $my_destlang)
|
|
{
|
|
|
|
//print "key =".$key."\n";
|
|
foreach ($content as $line) {
|
|
$destKey = $this->getLineKey($line);
|
|
$destValue = $this->getLineValue($line);
|
|
// If translated return
|
|
//print "destKey=".$destKey."\n";
|
|
if (trim($destKey) == trim($key)) { // Found already existing translation (key already exits in dest file)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if ($key == 'CHARSET') {
|
|
$val=$this->_outputpagecode;
|
|
} elseif (preg_match('/^Format/', $key)) {
|
|
$val=$value;
|
|
} elseif ($value=='-') {
|
|
$val=$value;
|
|
} else {
|
|
// If not translated then translate
|
|
if ($this->_outputpagecode == 'UTF-8') {
|
|
$val=$this->translateTexts(array($value), substr($this->_refLang, 0, 2), substr($my_destlang, 0, 2));
|
|
} else {
|
|
$val=mb_convert_encoding($this->translateTexts(array($value), substr($this->_refLang, 0, 2), substr($my_destlang, 0, 2)), 'ISO-8859-1');
|
|
}
|
|
}
|
|
|
|
$val=trim($val);
|
|
|
|
if (empty($val)) {
|
|
return 0;
|
|
}
|
|
|
|
$this->_translatedFiles[$file][] = $key . '=' . $val ;
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* getLineKey
|
|
*
|
|
* @param string $line Line found into file
|
|
* @return string Key
|
|
*/
|
|
private function getLineKey($line)
|
|
{
|
|
$arraykey = explode('=', $line, 2);
|
|
return trim($arraykey[0]);
|
|
}
|
|
|
|
/**
|
|
* getLineValue
|
|
*
|
|
* @param string $line Line found into file
|
|
* @return string Value
|
|
*/
|
|
private function getLineValue($line)
|
|
{
|
|
$arraykey = explode('=', $line, 2);
|
|
return trim(isset($arraykey[1]) ? $arraykey[1] : '');
|
|
}
|
|
|
|
/**
|
|
* getTranslationFilesArray
|
|
*
|
|
* @param string $lang Language code
|
|
* @return array Array
|
|
*/
|
|
private function getTranslationFilesArray($lang)
|
|
{
|
|
$dir = new DirectoryIterator($this->_langDir.$lang);
|
|
while ($dir->valid()) {
|
|
if (!$dir->isDot() && $dir->isFile() && ! preg_match('/^\./', $dir->getFilename())) {
|
|
$files[] = $dir->getFilename();
|
|
}
|
|
$dir->next();
|
|
}
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* Return translation of a value
|
|
*
|
|
* @param array $src_texts Array with one value
|
|
* @param string $src_lang Language code source (us, fr, it, ...)
|
|
* @param string $dest_lang Language code target (es, de, ...)
|
|
* @return string Value translated
|
|
*/
|
|
private function translateTexts($src_texts, $src_lang, $dest_lang)
|
|
{
|
|
// We want to be sure that src_lang and dest_lang are using 2 chars only
|
|
$tmp=explode('_', $src_lang);
|
|
if (!empty($tmp[1]) && $tmp[0] == $tmp[1]) {
|
|
$src_lang=$tmp[0];
|
|
}
|
|
$tmp=explode('_', $dest_lang);
|
|
if (!empty($tmp[1]) && $tmp[0] == $tmp[1]) {
|
|
$dest_lang=$tmp[0];
|
|
}
|
|
|
|
//setting language pair
|
|
$lang_pair = $src_lang.'|'.$dest_lang;
|
|
|
|
$src_text_to_translate=preg_replace('/%s/', 'SSSSS', implode('', $src_texts));
|
|
$src_text_to_translate=preg_replace('/'.preg_quote('\n\n').'/', ' NNNNN ', $src_text_to_translate);
|
|
|
|
// Define GET URL v1
|
|
//$url = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=".urlencode($src_text_to_translate)."&langpair=".urlencode($lang_pair);
|
|
// Example: http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=Setup%20area&langpair=en_US|fr_FR
|
|
// Define GET URL v2
|
|
$url = "https://www.googleapis.com/language/translate/v2?key=".$this->_apikey."&q=".urlencode($src_text_to_translate)."&source=".urlencode($src_lang)."&target=".urlencode($dest_lang);
|
|
// Example: https://www.googleapis.com/language/translate/v2?key=_apikey&q=Setup%20area&source=en_US&target=fr_FR
|
|
|
|
// Send request
|
|
//print "Url to translate: ".$url."\n";
|
|
|
|
if (! function_exists("curl_init")) {
|
|
print "Error, your PHP does not support curl functions.\n";
|
|
die();
|
|
}
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_REFERER, "Mozilla");
|
|
$body = curl_exec($ch);
|
|
curl_close($ch);
|
|
//sleep(1); // This is to avoid to overload server.
|
|
|
|
// now, process the JSON string
|
|
$json = json_decode($body, true);
|
|
|
|
if ((!empty($json['responseStatus']) && $json['responseStatus'] != 200)
|
|
|| count($json['data']['translations']) == 0) {
|
|
print "Error: ".$json['responseStatus']." ".$url."\n";
|
|
return false;
|
|
}
|
|
|
|
$rep=$json['data']['translations'][0]['translatedText'];
|
|
$rep=preg_replace('/SSSSS/i', '%s', $rep);
|
|
$rep=preg_replace('/NNNNN/i', '\n\n', $rep);
|
|
$rep=preg_replace('/'/i', '\'', $rep);
|
|
|
|
//print "OK ".join('',$src_texts).' => '.$rep."\n";
|
|
|
|
return $rep;
|
|
}
|
|
}
|