Actualización

This commit is contained in:
Xes
2025-04-10 12:49:05 +02:00
parent 4aff98e77b
commit 1cdd00920f
9151 changed files with 1800913 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Script to check that no language file has parse errors.
*
* @package chamilo.cron.lang
*/
/**
* Includes and declarations.
*/
//die();
require_once '../../inc/global.inc.php';
$path = api_get_path(SYS_LANG_PATH).'english';
ini_set('memory_limit', '128M');
/**
* Main code.
*/
$terms = [];
$list = SubLanguageManager::get_lang_folder_files_list($path);
$langs = scandir(api_get_path(SYS_LANG_PATH));
foreach ($langs as $lang) {
$dir = api_get_path(SYS_LANG_PATH).$lang;
if (is_dir($dir) && substr($lang, 0, 1) != '.' && !empty($lang)) {
echo "$lang...";
$ok = true;
foreach ($list as $entry) {
$file = $dir.'/'.$entry;
$out = [];
if (is_file($file)) {
//$terms = array_merge($terms,SubLanguageManager::get_all_language_variable_in_file($file,true));
@exec('php -l '.$file, $out);
if (substr($out[0], 0, 2) != 'No') {
echo $out[0]."\n";
$ok = false;
}
}
}
if ($ok) {
echo "OK\n";
}
}
}
echo "Done\n";

View File

@@ -0,0 +1,217 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This class takes the creation and querying of an SQLite DB in charge. The
* goal of this DB is to get stats on the usage of language vars for a common
* user.
*
* @package chamilo.cron.lang
*/
/**
* This class takes the creation and querying of an SQLite DB in charge. The
* goal of this DB is to get stats on the usage of language vars for a common
* user. This class requires the SQLite extension of PHP to be installed. The
* check for the availability of sqlite_open() should be made before calling
* the constructor (preferably).
*/
class langstats
{
public $db; //database connector
public $error; //stored errors
public $db_type = 'sqlite';
public function __construct($file = '')
{
switch ($this->db_type) {
case 'sqlite':
if (!class_exists('SQLite3')) {
$this->error = 'SQLiteNotAvailable';
return false; //cannot use if sqlite not installed
}
if (empty($file)) {
$file = api_get_path(SYS_ARCHIVE_PATH).'/langstasdb';
}
if (is_file($file) && is_writeable($file)) {
$this->db = new SQLite3($file, SQLITE3_OPEN_READWRITE);
} else {
try {
$this->db = new SQLite3($file);
} catch (Exception $e) {
$this->error = 'DatabaseCreateError';
error_log('Exception: '.$e->getMessage());
return false;
}
$err = $this->db->exec(
'CREATE TABLE lang_freq ('
.' id integer PRIMARY KEY AUTOINCREMENT, ' //autoincrement in SQLITE
.' term_name text, term_file text, term_count integer default 0)'
);
if ($err === false) {
$this->error = 'CouldNotCreateTable';
return false;
}
$err = $this->db->exec(
'CREATE INDEX lang_freq_terms_idx ON lang_freq(term_name, term_file)'
);
if ($err === false) {
$this->error = 'CouldNotCreateIndex';
return false;
}
// Table and index created, move on.
}
break;
case 'mysql': //implementation not finished
if (!function_exists('mysql_connect')) {
$this->error = 'SQLiteNotAvailable';
return false; //cannot use if sqlite not installed
}
$err = Database::query('SELECT * FROM lang_freq');
if ($err === false) { //the database probably does not exist, create it
$err = Database::query(
'CREATE TABLE lang_freq ('
.' id int PRIMARY KEY AUTO_INCREMENT, '
.' term_name text, term_file text default \'\', term_count int default 0)'
);
if ($err === false) {
$this->error = 'CouldNotCreateTable';
return false;
}
} // if no error, we assume the table exists
break;
}
return $this->db;
}
/**
* Add a count for a specific term.
*
* @param string The language term used
* @param string The file from which the language term came from
*
* @return mixed
*/
public function add_use($term, $term_file = '')
{
$term = $this->db->escapeString($term);
$term_file = $this->db->escapeString($term_file);
$sql = "SELECT id, term_name, term_file, term_count FROM lang_freq WHERE term_name='$term' and term_file='$term_file'";
$ress = $this->db->query($sql);
if ($ress === false) {
$this->error = 'CouldNotQueryTermFromTable';
return false;
}
$i = 0;
while ($row = $ress->fetchArray(SQLITE3_BOTH)) {
$num = $row[3];
$num++;
$i++;
$res = $this->db->query(
'UPDATE lang_freq SET term_count = '.$num.' WHERE id = '.$row[0]
);
if ($res === false) {
$this->error = 'CouldNotUpdateTerm';
return false;
} else {
return $row[0];
}
}
if ($i == 0) {
//No term found in the table, register as new term
$resi = $this->db->query(
"INSERT INTO lang_freq(term_name, term_file, term_count) VALUES ('$term', '$term_file', 1)"
);
if ($resi === false) {
$this->error = 'CouldNotInsertRow';
return false;
} else {
return $this->db->lastInsertRowID();
}
}
return true;
}
/**
* Function to get a list of the X most-requested terms.
*
* @param int Limit of terms to show
*
* @return array List of most requested terms
*/
public function get_popular_terms($num = 1000)
{
$num = (int) $num;
$res = $this->db->query(
'SELECT * FROM lang_freq
ORDER BY term_count DESC LIMIT '.$num
);
$list = [];
while ($row = $res->fetchArray()) {
$list[] = $row;
}
return $list;
}
/**
* Clear all records in lang_freq.
*
* @return resource true
*/
public function clear_all()
{
$res = sqlite_query($this->db, 'DELETE FROM lang_freq WHERE 1=1');
return $res;
}
/**
* Returns an array of all the language variables with their corresponding
* file of origin. This function tolerates a certain rate of error due to
* the duplication of variables in language files.
*
* @return array variable => origin file
*/
public function get_variables_origin()
{
$path = api_get_path(SYS_LANG_PATH).'english/';
$vars = [];
$priority = ['trad4all'];
foreach ($priority as $file) {
$list = SubLanguageManager::get_all_language_variable_in_file(
$path.$file.'.inc.php',
true
);
foreach ($list as $var => $trad) {
$vars[$var] = $file.'.inc.php';
}
}
$files = scandir($path);
foreach ($files as $file) {
if (substr($file, 0, 1) == '.' or in_array($file, $priority)) {
continue;
}
$list = SubLanguageManager::get_all_language_variable_in_file(
$path.$file,
true
);
foreach ($list as $var => $trad) {
$vars[$var] = $file;
}
}
return $vars;
}
}

View File

@@ -0,0 +1,84 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This script prints a list of most used language terms. The registration of
* frequency for language variables is a very heavy operation.
* To enable, add "$_configuration['language_measure_frequency' ] = 1;" at the
* end of main/inc/conf/configuration.php. Remove when done.
* Add ?output=1 to the URL to generate languag files in /tmp/lang/ with just
* the number of terms you want.
*/
/**
* Requires.
*/
exit();
require_once '../../inc/global.inc.php';
require_once 'langstats.class.php';
/**
* Init.
*/
$terms_limit = 10000 + 50;
$x_most_popular = 2000;
$output = false;
$ls = new langstats();
if ($ls === false) {
exit($ls->error);
}
$list = $ls->get_popular_terms($x_most_popular);
if ($_GET['output'] == 1) {
$output = true;
$variables_origin = $ls->get_variables_origin();
}
/**
* Display.
*/
if (count($list) == 0) {
echo 'No terms loaded so far';
}
if (count($list) > 0) {
$i = 1;
$j = 1;
$k = 0;
$files = [];
$trans = [];
echo 'Number of records: '.count($list).'<br />';
echo '<table><tr><th>Index</th><th>Registration order</th><th>Term</th>'.($output == 1 ? '<th>Origin</th>' : '').'<th>Count</th></tr>';
foreach ($list as $elem) {
if ($k > $terms_limit) {
break;
}
$fixed_elem = $elem;
if ($output) {
if (empty($variables_origin[$elem['term_name']]) && !empty($variables_origin['lang'.$elem['term_name']])) {
$fixed_elem = ['id' => $elem['id'], 'term_name' => 'lang'.$elem['term_name'], 'term_count' => $elem['term_count']];
}
if (empty($variables_origin[$fixed_elem['term_name']])) {
continue;
}
$files[$variables_origin[$fixed_elem['term_name']]][] = $fixed_elem['term_name'];
$translation = get_lang($fixed_elem['term_name']);
$k += str_word_count($translation);
$trans[$fixed_elem['term_name']] = $translation;
$j++;
}
echo '<tr><td>', $i,
'</td><td>', $fixed_elem['id'],
'</td><td>', $fixed_elem['term_name'];
if ($output) {
echo '</td><td>'.$variables_origin[$fixed_elem['term_name']];
}
echo '</td><td>', $fixed_elem['term_count'], '</td></tr>';
$i++;
}
echo '</table>';
if ($output) {
@mkdir('/tmp/lang');
foreach ($files as $file => $terms) {
@touch('/tmp/lang/'.$file);
file_put_contents('/tmp/lang/'.$file, "<?php".PHP_EOL);
foreach ($terms as $term) {
file_put_contents('/tmp/lang/'.$file, '$'.$term.' = "'.str_replace('"', '\"', $trans[$term]).'";'.PHP_EOL, FILE_APPEND);
}
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This script generates a directory based on the English language variables
* but only composed of the 10,000 (can be configured) most frequent words
* used in Chamilo. This implies first using the langstats.php script, which
* in turn implies configuring an additional variable in configuration.php
* (see langstats.php for more info).
* When running the language_builder, please make sure this parameter is
* set to 0 in the configuration.php file, otherwise it will take *ages*.
*/
require_once '../../inc/global.inc.php';
require_once 'langstats.class.php';
global $_configuration;
$_configuration['language_measure_frequency'] = 0;
$langstats = new langstats();
$orig_lang = 'english';
/**
* Init.
*/
$words_limit = 10000; //change this if you want more words
$terms_limit = 3000; //change this if you think you'll need more terms
$terms = $langstats->get_popular_terms($terms_limit);
$words_counter = 0;
$i = 0;
$terms_in_limit = [];
$lang_dir = api_get_path(SYS_LANG_PATH);
$arch_dir = api_get_path(SYS_ARCHIVE_PATH);
/**
* Code run.
*/
foreach ($terms as $row) {
if ($words_counter > 10000) {
break;
}
$words = str_word_count(get_lang($row['term_name'], null, $orig_lang));
$words_counter += $words;
$terms_in_limit[$row['term_name']] = $i;
//echo "Term <b>".$row['term_name']."</b> is <b>'".get_lang($row['term_name'],null,$orig_lang)."'</b> which means $words words<br /><br />\n";
//if ($words_counter%1000 >= 0) {
//echo "Reached $words_counter words at term $i (".$row['term_name']." used ".$row['term_count']." times)...<br />\n";
//}
$i++;
}
//echo $words_counter.'<br />';
echo "Reached ".count($terms_in_limit)." terms for the $words_counter most-used words<br /><br />\n";
echo "Scanning English files, trying to find these terms...<br />\n";
if (!is_dir($arch_dir.'/langstats')) {
mkdir($arch_dir.'/langstats');
mkdir($arch_dir.'/langstats/'.$orig_lang);
}
$list_files = scandir($lang_dir.'/'.$orig_lang);
$j = 1;
$terms_found = [];
$words_found = 0;
$global_var = []; //keep the combination of all vars
$terms_in_limit = array_flip($terms_in_limit);
foreach ($list_files as $file) {
if (substr($file, 0, 1) == '.') {
continue;
}
//echo "'".substr($file,0,-8)."',<br />"; //print in a PHP array format
$vars = file($lang_dir.'/'.$orig_lang.'/'.$file);
$local_var = [];
$file_string = '<?php'."\n";
foreach ($vars as $line) {
$var = [];
$res = preg_match('/^(\$\w*)/', $line, $var);
if ($res > 0) {
//echo $var[1]."<br />";
if (in_array(substr($var[1], 1), $terms_in_limit)) {
//echo "Var ".$var[1]." was in the limit<br />";
$local_var[$var[1]] = $line;
$file_string .= $line;
$terms_found[] = substr($var[1], 1); //e.g. store Tools
$words_found += str_word_count(get_lang($var[1], null, $orig_lang));
} elseif (in_array(substr($var[1], 5), $terms_in_limit)) {
//echo "Var ".$var[1]." was in the limit<br />";
$local_var[$var[1]] = $line;
$file_string .= $line;
$terms_found[] = substr($var[1], 5); //e.g. store langTools
$words_found += str_word_count(get_lang(substr($var[1], 5), null, $orig_lang));
} //else do not care
}
}
echo "Writing ".$arch_dir.'/langstats/'.$orig_lang.'/'.$file."<br />\n";
file_put_contents($arch_dir.'/langstats/'.$orig_lang.'/'.$file, $file_string);
$global_var += $local_var;
}
$terms_diff = count($global_var) - count($terms_in_limit);
echo count(
$global_var
)." terms found in English files (summing up to $words_found words). Some terms ($terms_diff in this case) might have appeared in two different files<br />";
/**
* Display results.
*/
echo "Difference between filtered and found in English:<br />";
//print_r($terms_found);
echo "<pre>".print_r(array_diff($terms_in_limit, $terms_found), 1)."</pre>";
echo "#";

View File

@@ -0,0 +1,85 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Cron script to list used, but undefined, language variables.
*
* @package chamilo.cron
*/
/**
* Includes and declarations.
*/
exit();
require_once __DIR__.'/../../inc/global.inc.php';
$path = api_get_path(SYS_LANG_PATH).'english';
ini_set('memory_limit', '128M');
/**
* Main code.
*/
$terms = [];
$list = SubLanguageManager::get_lang_folder_files_list($path);
foreach ($list as $entry) {
$file = $path.'/'.$entry;
if (is_file($file)) {
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
}
}
// get only the array keys (the language variables defined in language files)
$defined_terms = array_flip(array_keys($terms));
$terms = null;
$hidePlugins = !empty($_GET['hidePlugins']);
// now get all terms found in all PHP files of Chamilo (this takes some time and memory)
$undefined_terms = [];
$l = strlen(api_get_path(SYS_PATH));
$files = getAllPhpFiles(api_get_path(SYS_PATH));
foreach ($files as $file) {
$isPlugin = preg_match('#/plugin/#', $file);
if ($isPlugin && $hidePlugins) {
continue;
}
//echo 'Analyzing '.$file."<br />";
$shortfile = substr($file, $l);
$lines = file($file);
foreach ($lines as $line) {
$myterms = [];
// Find terms but ignore those starting with ->get_lang(), which are
// for plugins
$res = preg_match_all('/(?<!-\>)get_lang\(\'(\\w*)\'\)/', $line, $myterms);
if ($res > 0) {
foreach ($myterms[1] as $term) {
if (!isset($defined_terms[$term]) && !isset($defined_terms['lang'.$term])) {
$undefined_terms[$term] = $shortfile;
//echo "Undefined: $term<br />";
}
}
}
$res = 0;
$res = preg_match_all('/\{[\'"](\\w*)[\'"]\|get_lang\}/', $line, $myterms);
if ($res > 0) {
foreach ($myterms[1] as $term) {
if (!isset($defined_terms[$term]) && !isset($defined_terms['lang'.$term])) {
$undefined_terms[$term] = $shortfile;
//echo "Undefined: $term<br />";
}
}
}
}
flush();
}
//$undefined_terms = array_flip($undefined_terms);
if (count($undefined_terms) < 1) {
exit("No missing terms<br />\n");
} else {
echo "The following terms were nowhere to be found: <br />\n<table>";
}
$i = 1;
foreach ($undefined_terms as $term => $file) {
$isPlugin = substr($file, 0, 7) == 'plugin/';
echo "<tr><td>$i</td><td>$term</td><td>in $file";
if ($isPlugin) {
echo " <span style=\"color: #00ff00;\">(this one should be taken care of by the plugin's language files)</span>";
}
echo "</td></tr>\n";
$i++;
}
echo "</table>\n";

View File

@@ -0,0 +1,129 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Cron script to list unused, but defined, language variables.
*
* @package chamilo.cron.lang
*/
/**
* Includes and declarations.
*/
exit();
require_once __DIR__.'/../../inc/global.inc.php';
$path = api_get_path(SYS_LANG_PATH).'english';
ini_set('memory_limit', '128M');
/**
* Main code.
*/
$terms = [];
$list = SubLanguageManager::get_lang_folder_files_list($path);
foreach ($list as $entry) {
$file = $path.'/'.$entry;
if (is_file($file)) {
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
}
}
// get only the array keys (the language variables defined in language files)
$defined_terms = array_flip(array_keys($terms));
$terms = null;
echo count($defined_terms)." terms were found in language files<br />";
// now get all terms found in all PHP files of Chamilo (this takes some
// time and memory)
$usedTerms = [];
$l = strlen(api_get_path(SYS_PATH));
$files = getAllPhpFiles(api_get_path(SYS_PATH));
$files[] = api_get_path(SYS_PATH).'main/install/data.sql';
// Browse files
foreach ($files as $file) {
//echo 'Analyzing '.$file."<br />";
$shortFile = substr($file, $l);
//echo 'Analyzing '.$shortFile."<br />";
$lines = file($file);
$isDataSQL = false;
if (substr($file, -21) === 'main/install/data.sql') {
$isDataSQL = true;
}
// Browse lines inside file $file
foreach ($lines as $line) {
if ($isDataSQL) {
// Check main/install/data.sql
// Should recognize stuff like
// INSERT INTO settings_current (variable, type, category, selected_value, title, comment) VALUES ('enable_profile_user_address_geolocalization', 'radio', 'User', 'false', 'EnableProfileUsersAddressGeolocalizationTitle', 'EnableProfileUsersAddressGeolocalizationComment');
// INSERT INTO settings_options (variable, value, display_text) VALUES ('enable_profile_user_address_geolocalization', 'true', 'Yes');
// ('show_teacher_data',NULL,'radio','Platform','true','ShowTeacherDataTitle','ShowTeacherDataComment',NULL,NULL, 1),
$res = 0;
$myTerms = [];
$res = preg_match_all('/\'(\w*)\',/', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[1] as $term) {
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
$usedTerms[$term] = $shortFile;
}
}
} else {
$myTerms = [];
$res = preg_match_all('/get_lang\(\'(\\w*)\'\)/', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[1] as $term) {
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
$usedTerms[$term] = $shortFile;
}
} else {
$res = 0;
$myTerms = [];
// Should catch:
// {{ 'CopyTextToClipboard' | get_lang }}
// {{ "HelloX" | get_lang | format(show_user_info.user_info.complete_name) }}
// {{ "StudentCourseProgressX" | get_lang | format(item.student_info.progress) }}
$res = preg_match_all('/\{\s*[\'"](\w*)[\'"]\s*\|\s*get_lang\s*(\|\s*\w*(\s*\([\w_\.,\s]*\))?\s*)?\}/', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[1] as $term) {
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
$usedTerms[$term] = $shortFile;
}
}
// {{ display.panel('PersonalDataResponsibleOrganizationTitle' | get_lang , personal_data.responsible ) }}
// {{ display.panel('PersonalDataIntroductionTitle' | get_lang , 'PersonalDataIntroductionText' | get_lang) }}
$myTerms = [];
$res = preg_match_all('/\{\s*[\w\.]*\([\'"](\w*)[\'"]\s*\|\s*get_lang\s*(,\s*[\w_\.,\s\|\'"]*\s*)?\)\s*\}/', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[1] as $term) {
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
$usedTerms[$term] = $shortFile;
}
}
}
}
}
flush();
}
// Compare defined terms VS used terms. Used terms should be smaller than
// defined terms, and this should prove the concept that there are much
// more variables than what we really use
if (count($usedTerms) < 1) {
exit("No used terms<br />\n");
} else {
echo "The following terms were defined but never used: <br />\n<table>";
}
$i = 1;
foreach ($defined_terms as $term => $file) {
// remove "lang" prefix just in case
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
if (!isset($usedTerms[$term])) {
echo "<tr><td>$i</td><td>$term</td></tr>\n";
$i++;
}
}
echo "</table>\n";

View File

@@ -0,0 +1,92 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Script to switch all PHP files in Chamilo to a more Gettext-like syntax.
*
* @package chamilo.cron.lang
*/
/**
* Includes and declarations.
*/
exit();
require_once __DIR__.'/../../inc/global.inc.php';
$path = api_get_path(SYS_LANG_PATH).'english';
ini_set('memory_limit', '128M');
/**
* Main code.
*/
$terms = [];
$list = SubLanguageManager::get_lang_folder_files_list($path);
foreach ($list as $entry) {
$file = $path.'/'.$entry;
if (is_file($file)) {
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
}
}
foreach ($terms as $index => $translation) {
$terms[$index] = trim(rtrim($translation, ';'), '"');
}
// get only the array keys (the language variables defined in language files)
$defined_terms = array_flip(array_keys($terms));
echo count($defined_terms)." terms were found in language files".PHP_EOL;
// now get all terms found in all PHP files of Chamilo (this takes some
// time and memory)
$usedTerms = [];
$l = strlen(api_get_path(SYS_PATH));
$files = getAllPhpFiles(api_get_path(SYS_PATH));
$rootLength = strlen(api_get_path(SYS_PATH));
$countFiles = 0;
$countReplaces = 0;
// Browse files
foreach ($files as $file) {
if (substr($file, $rootLength, 6) === 'vendor' || substr($file, $rootLength, 3) === 'web') {
continue;
}
//echo 'Analyzing '.$file.PHP_EOL;
$shortFile = substr($file, $l);
//echo 'Analyzing '.$shortFile.PHP_EOL;
$lines = file($file);
// Browse lines inside file $file
foreach ($lines as $line) {
$myTerms = [];
$res = preg_match_all('/get_lang\(([\'"](\\w*)[\'"])\)/m', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[2] as $term) {
echo "Found term $term - ".print_r($myTerms, 1).PHP_EOL;
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
if (!empty($terms[$term])) {
$translation = $terms[$term];
$quotedTerm = $myTerms[1][0];
//echo "Would do sed -i \"s#$quotedTerm#'$translation'#g\" $file here\n";
system("sed -i \"s#$term#'$translation'#g\" $file");
$countReplaces++;
}
}
} else {
$res = 0;
$res = preg_match_all('/\{\s*([\'"](\\w*)[\'"])\s*\|get_lang\}/m', $line, $myTerms);
if ($res > 0) {
foreach ($myTerms[2] as $term) {
echo "Found term $term".PHP_EOL;
if (substr($term, 0, 4) == 'lang') {
$term = substr($term, 4);
}
if (!empty($terms[$term])) {
$translation = $terms[$term];
$quotedTerm = $myTerms[1][0];
//echo "Would do sed -i \"s#$quotedTerm#'$translation'#g\" $file here\n";
system("sed -i \"s#$term#'$translation'#g\" $file");
$countReplaces++;
}
}
}
}
}
$countFiles++;
flush();
}
echo "Done analyzing $countFiles files, with $countReplaces replacements!\n";