| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?PHP // $Id: lang.php,v 1.106.2.11 2008/07/21 15:21:51 mudrd8mz Exp $ 2 /** 3 * Display the admin/language menu and process strings translation. 4 * 5 * @param string $mode the mode of the script: null, "compare", "missing" 6 * @param string $currentfile the filename of the English file to edit (if mode==compare) 7 * @param bool $uselocal save translations into *_local pack? 8 */ 9 10 $dbg = ''; // debug output; 11 12 require_once ('../config.php'); 13 require_once($CFG->libdir.'/adminlib.php'); 14 15 admin_externalpage_setup('langedit'); 16 17 $context = get_context_instance(CONTEXT_SYSTEM); 18 19 define('LANG_SUBMIT_REPEAT', 1); // repeat displaying submit button? 20 define('LANG_SUBMIT_REPEAT_EVERY', 20); // if so, after how many lines? 21 define('LANG_DISPLAY_MISSING_LINKS', 1); // display "go to first/next missing string" links? 22 define('LANG_DEFAULT_FILE', ''); // default file to translate. Empty allowed 23 define('LANG_DEFAULT_HELPFILE', ''); // default helpfile to translate. Empty allowed 24 define('LANG_LINK_MISSING_STRINGS', 1); // create links from "missing" page to "compare" page? 25 define('LANG_DEFAULT_USELOCAL', 0); // should *_utf8_local be used by default? 26 define('LANG_MISSING_TEXT_MAX_LEN', 60); // maximum length of the missing text to display 27 define('LANG_KEEP_ORPHANS', 1); // keep orphaned strings (i.e. strings w/o English reference) 28 define('LANG_SEARCH_EXTRA', 1); // search lang files in extra locations 29 define('LANG_ALWAYS_TEXTAREA', 1); // always use <textarea> even for short strings MDL-15738 30 31 $mode = optional_param('mode', '', PARAM_ALPHA); 32 if ($mode == 'helpfiles') { 33 // use different PARAM_ options according to mode 34 $currentfile = optional_param('currentfile', LANG_DEFAULT_HELPFILE, PARAM_PATH); 35 } else { 36 $currentfile = optional_param('currentfile', LANG_DEFAULT_FILE, PARAM_FILE); 37 } 38 $uselocal = optional_param('uselocal', -1, PARAM_INT); 39 40 if ($uselocal == -1) { 41 if (isset($SESSION->langtranslateintolocal)) { 42 $uselocal = $SESSION->langtranslateintolocal; 43 } else { 44 $uselocal = LANG_DEFAULT_USELOCAL; 45 } 46 } else { 47 $SESSION->langtranslateintolocal = $uselocal; 48 } 49 50 if (!has_capability('moodle/site:langeditmaster', $context, $USER->id, false)) { 51 // Force using _local 52 $uselocal = 1; 53 } 54 55 if (!has_capability('moodle/site:langeditmaster', $context, $USER->id, false) && (!$uselocal)) { 56 print_error('cannoteditmasterlang'); 57 } 58 59 if ((!has_capability('moodle/site:langeditlocal', $context, $USER->id, false)) && ($uselocal)) { 60 print_error('cannotcustomizelocallang'); 61 } 62 63 $strlanguage = get_string("language"); 64 $strcurrentlanguage = get_string("currentlanguage"); 65 $strmissingstrings = get_string("missingstrings"); 66 $streditstrings = get_string("editstrings", 'admin'); 67 $stredithelpdocs = get_string("edithelpdocs", 'admin'); 68 $strthislanguage = get_string("thislanguage"); 69 $strgotofirst = get_string('gotofirst','admin'); 70 $strfilestoredin = get_string('filestoredin', 'admin'); 71 $strfilestoredinhelp = get_string('filestoredinhelp', 'admin'); 72 $strswitchlang = get_string('switchlang', 'admin'); 73 $strchoosefiletoedit = get_string('choosefiletoedit', 'admin'); 74 $streditennotallowed = get_string('langnoeditenglish', 'admin'); 75 $strfilecreated = get_string('filecreated', 'admin'); 76 $strprev = get_string('previous'); 77 $strnext = get_string('next'); 78 $strlocalstringcustomization = get_string('localstringcustomization', 'admin'); 79 $strlangpackmaintaining = get_string('langpackmaintaining', 'admin'); 80 $strnomissingstrings = get_string('nomissingstrings', 'admin'); 81 $streditingnoncorelangfile = get_string('editingnoncorelangfile', 'admin'); 82 $strlanglocalpackage = get_string('langlocalpackage', 'admin'); 83 $strlangmasterpackage = get_string('langmasterpackage', 'admin'); 84 $strlangmasterenglish = get_string('langmasterenglish', 'admin'); 85 86 $currentlang = current_language(); 87 88 switch ($mode) { 89 case "missing": 90 // Missing array keys are not bugs here but missing strings 91 error_reporting(E_ALL ^ E_NOTICE); 92 $title = $strmissingstrings; 93 break; 94 case "compare": 95 $title = $streditstrings; 96 break; 97 case "helpfiles": 98 $title = $stredithelpdocs; 99 default: 100 $title = $strlanguage; 101 break; 102 } 103 $navlinks[] = array('name' => $strlanguage, 'link' => "$CFG->wwwroot/$CFG->admin/lang.php", 'type' => 'misc'); 104 $navigation = build_navigation($navlinks); 105 106 admin_externalpage_print_header(); 107 108 // Prepare and render menu tabs 109 $firstrow = array(); 110 $secondrow = array(); 111 $inactive = NULL; 112 $activated = NULL; 113 $currenttab = $mode; 114 if ($uselocal) { 115 $inactive = array('uselocal'); 116 $activated = array('uselocal'); 117 } else { 118 $inactive = array('usemaster'); 119 $activated = array('usemaster'); 120 } 121 if (has_capability('moodle/site:langeditlocal', $context, $USER->id, false)) { 122 $firstrow[] = new tabobject('uselocal', 123 "$CFG->wwwroot/$CFG->admin/lang.php?mode=$mode&currentfile=$currentfile&uselocal=1", 124 $strlocalstringcustomization ); 125 } 126 if (has_capability('moodle/site:langeditmaster', $context, $USER->id, false)) { 127 $firstrow[] = new tabobject('usemaster', 128 "$CFG->wwwroot/$CFG->admin/lang.php?mode=$mode&currentfile=$currentfile&uselocal=0", 129 $strlangpackmaintaining ); 130 } 131 $secondrow[] = new tabobject('missing', "$CFG->wwwroot/$CFG->admin/lang.php?mode=missing", $strmissingstrings ); 132 $secondrow[] = new tabobject('compare', "$CFG->wwwroot/$CFG->admin/lang.php?mode=compare", $streditstrings ); 133 $secondrow[] = new tabobject('helpfiles', "$CFG->wwwroot/$CFG->admin/lang.php?mode=helpfiles", $stredithelpdocs ); 134 $tabs = array($firstrow, $secondrow); 135 print_tabs($tabs, $currenttab, $inactive, $activated); 136 137 138 if (!$mode) { 139 // TODO this is a very nice place to put some translation statistics 140 print_box_start(); 141 $currlang = current_language(); 142 $langs = get_list_of_languages(false, true); 143 popup_form ("$CFG->wwwroot/$CFG->admin/lang.php?lang=", $langs, "chooselang", $currlang, "", "", "", false, 'self', $strcurrentlanguage.':'); 144 print_box_end(); 145 admin_externalpage_print_footer(); 146 exit; 147 } 148 149 // Get a list of all the root files in the English directory 150 151 $langbase = $CFG->dataroot . '/lang'; 152 $enlangdir = "$CFG->dirroot/lang/en_utf8"; 153 if ($currentlang == 'en_utf8') { 154 $langdir = $enlangdir; 155 } else { 156 $langdir = "$langbase/$currentlang"; 157 } 158 $locallangdir = "$langbase/{$currentlang}_local"; 159 $saveto = $uselocal ? $locallangdir : $langdir; 160 161 if (($mode == 'missing') || ($mode == 'compare')) { 162 // get the list of all English stringfiles 163 $stringfiles = lang_standard_locations(); 164 if (LANG_SEARCH_EXTRA) { 165 $stringfiles += lang_extra_locations(); 166 } 167 if (count($stringfiles) == 0) { 168 error("Could not find English language pack!"); 169 } 170 } elseif ($mode == 'helpfiles') { 171 $helpfiles = lang_help_standard_locations(); 172 if (LANG_SEARCH_EXTRA) { 173 $helpfiles += lang_help_extra_locations(); 174 } 175 if (count($helpfiles) == 0) { 176 error("Could not find help files in the English language pack!"); 177 } 178 } 179 180 181 182 if ($mode == 'missing') { 183 if (!file_exists($langdir)) { 184 error ('to edit this language pack, you need to put it in '.$CFG->dataroot.'/lang'); 185 } 186 187 // Following variables store the HTML output to be echo-ed 188 $m = ''; 189 $o = ''; 190 191 $m_x = false; 192 193 // Total number of strings and missing strings 194 $totalcounter->strings = 0; 195 $totalcounter->missing = 0; 196 197 // For each file, check that a counterpart exists, then check all the strings 198 foreach ($stringfiles as $stringfile) { 199 $location = $stringfile['location']; 200 $plugin = $stringfile['plugin']; 201 $prefix = $stringfile['prefix']; 202 $filename = $stringfile['filename']; 203 unset($string); 204 205 // Get some information about file locations: 206 // $enfilepath = the path to the English file distributed either in the core space or in plugin space 207 // $trfilepath = the path to the translated file distributed either in the lang pack or in plugin space 208 // $lcfilepath = the path to the _local customization 209 // $trfilename = the filename of the translated version of the file (including prefix for non-core files) 210 if ($location || $plugin) { 211 // non-core file in an extra location 212 $enfilepath = "$CFG->dirroot/$location/$plugin/lang/en_utf8/$filename"; 213 $trfilepath = "$CFG->dirroot/$location/$plugin/lang/$currentlang/$filename"; 214 $lcfilepath = "$locallangdir/$filename"; 215 $trfilename = $filename; 216 if (!$m_x) { 217 $m .= '<hr />'; 218 $m_x = true; 219 } 220 } else { 221 // core file in standard location 222 $enfilepath = "$CFG->dirroot/lang/en_utf8/$filename"; 223 $trfilepath = "$langdir/$filename"; 224 $lcfilepath = "$locallangdir/$filename"; 225 $trfilename = $filename; 226 } 227 // $enstring = English strings distributed either in the core space or in plugin space 228 include($enfilepath); 229 $enstring = isset($string) ? $string : array(); 230 unset($string); 231 ksort($enstring); 232 233 //$lcstring = local customizations 234 $lcstring = array(); 235 if (file_exists($lcfilepath)) { 236 include($lcfilepath); 237 $localfileismissing = 0; 238 if (isset($string) && is_array($string)) { 239 $lcstring = $string; 240 } 241 unset($string); 242 ksort($lcstring); 243 } else { 244 $localfileismissing = 1; 245 } 246 247 // $string = translated strings distibuted either in core lang pack or in plugin space 248 $string = array(); 249 if (file_exists($trfilepath)) { 250 include($trfilepath); 251 $fileismissing = 0; 252 } else { 253 $fileismissing = 1; 254 $o .= notify(get_string("filemissing", "", $trfilepath), "notifyproblem", "center", true); 255 } 256 257 $missingcounter = 0; 258 259 $first = true; // first missing string found in the file 260 // For all English strings in the current file check distributed translations and _local customizations 261 foreach ($enstring as $key => $value) { 262 $totalcounter->strings++; 263 $missingstring = false; 264 $missinglocalstring = false; 265 $translationsdiffer = false; 266 if (empty($string[$key]) and $string[$key] != "0") { // MDL-4735 267 // string is missing in distributed pack 268 $missingstring = true; 269 } 270 if (empty($lcstring[$key]) and $lcstring[$key] != "0") { // MDL-4735 271 // string is missing in _local customization 272 $missinglocalstring = true; 273 } 274 if (!$missingstring && !$missinglocalstring && ($lcstring[$key] != $string[$key])) { 275 $translationsdiffer = true; 276 } 277 if ($missingstring || $translationsdiffer) { 278 $value = htmlspecialchars($value); 279 $value = str_replace("$"."a", "\\$"."a", $value); 280 $value = str_replace("%%","%",$value); 281 if ($first) { 282 $m .= "<a href=\"lang.php?mode=missing#$trfilename\">$trfilename"; 283 $m .= $fileismissing ? '*' : ''; 284 $m .= '</a> '; 285 $o .= "<p><a name=\"$trfilename\"></a><b>". 286 get_string("stringsnotset","", $trfilepath)."</b></p><pre>"; 287 $first = false; 288 $somethingfound = true; 289 } 290 if ($missingstring) { 291 $missingcounter++; 292 $totalcounter->missing++; 293 } 294 if ($translationsdiffer) { 295 $missingcounter++; 296 } 297 if (LANG_LINK_MISSING_STRINGS && ($missingstring || $translationsdiffer)) { 298 $missinglinkstart = "<a href=\"lang.php?mode=compare&currentfile=$filename#$key\">"; 299 $missinglinkend = '</a>'; 300 } else { 301 $missinglinkstart = ''; 302 $missinglinkend = ''; 303 } 304 if (strlen($value) > LANG_MISSING_TEXT_MAX_LEN) { 305 $value = lang_xhtml_save_substr($value, 0, LANG_MISSING_TEXT_MAX_LEN) . ' ...'; // MDL-8852 306 } 307 if ($translationsdiffer) { 308 $o .= '// '; 309 } 310 $o .= "$"."string['".$missinglinkstart.$key.$missinglinkend."'] = \"$value\";"; 311 if ($translationsdiffer) { 312 $o .= ' // differs from the translation in _local'; 313 } elseif (!$missinglocalstring) { 314 $o .= ' // translated only in _local'; 315 } 316 $o .= "\n"; 317 } 318 } 319 if (!$first) { 320 $o .= '</pre><hr />'; 321 } 322 } 323 324 if ($totalcounter->missing > 0) { 325 $totalcounter->missingpercent = sprintf('%02.1f', ($totalcounter->missing / $totalcounter->strings * 100)); 326 print_heading(get_string('numberofstrings', 'admin', $totalcounter), '', 4); 327 } else { 328 print_heading($strnomissingstrings, '', 4, 'notifysuccess'); 329 } 330 331 if ($m <> '') { 332 print_box($m, 'filenames'); 333 } 334 335 echo $o; 336 337 if (! $files = get_directory_list("$CFG->dirroot/lang/en_utf8/help", "CVS")) { 338 error("Could not find English language help files!"); 339 } 340 341 foreach ($files as $filekey => $file) { // check all the help files. 342 if (!file_exists("$langdir/help/$file")) { 343 notify(get_string("filemissing", "", "$langdir/help/$file"), 'notifyproblem'); 344 $somethingfound = true; 345 continue; 346 } 347 } 348 349 if (! $files = get_directory_list("$CFG->dirroot/lang/en_utf8/docs", "CVS")) { 350 error("Could not find English language docs files!"); 351 } 352 foreach ($files as $filekey => $file) { // check all the docs files. 353 if (!file_exists("$langdir/docs/$file")) { 354 notify(get_string("filemissing", "", "$langdir/docs/$file"), 'notifyproblem'); 355 $somethingfound = true; 356 continue; 357 } 358 } 359 360 if (!empty($somethingfound)) { 361 print_continue("lang.php"); 362 } else { 363 notice(get_string("languagegood"), "lang.php" ); 364 } 365 366 } else if ($mode == 'compare') { 367 368 if (!file_exists($langbase) ){ 369 if (!lang_make_directory($langbase) ){ 370 error('ERROR: Could not create base lang directory ' . $langbase); 371 } else { 372 echo '<div class="notifysuccess">Created directory '. 373 $langbase .'</div>'."<br />\n"; 374 } 375 } 376 if (!$uselocal && !file_exists($langdir)) { 377 if (!lang_make_directory($langdir)) { 378 error('ERROR: Could not create directory '.$langdir); 379 } else { 380 echo '<div class="notifysuccess">Created directory '. 381 $langdir .'</div>'."<br />\n"; 382 } 383 } 384 if ($uselocal && !file_exists($locallangdir)) { 385 if (!lang_make_directory($locallangdir)) { 386 echo '<div class="notifyproblem">ERROR: Could not create directory '. 387 $locallangdir .'</div>'."<br />\n"; 388 $uselocal = 0; 389 } else { 390 echo '<div class="notifysuccess">Created directory '. 391 $locallangdir .'</div>'."<br />\n"; 392 } 393 } 394 395 if ($currentfile <> '') { 396 if (!$fileinfo = lang_get_file_info($currentfile, $stringfiles)) { 397 error('Unable to find info for: '.$currentfile); 398 } 399 // check the filename is set up correctly, prevents bugs similar to MDL-10920 400 $location = $fileinfo['location']; 401 $plugin = $fileinfo['plugin']; 402 $prefix = $fileinfo['prefix']; 403 $filename = $fileinfo['filename']; 404 if ($location || $plugin) { 405 // file in an extra location 406 if ($currentfile != "{$prefix}{$plugin}.php") { 407 error("Non-core filename mismatch. The file $currentfile should be {$prefix}{$plugin}.php"); 408 } 409 if (!$uselocal) { 410 notify($streditingnoncorelangfile); 411 $editable = false; 412 } 413 } else { 414 // file in standard location 415 if ($currentfile != $filename) { 416 error("Core filename mismatch. The file $currentfile should be $filename"); 417 } 418 } 419 420 // Get some information about file locations: 421 // $enfilepath = the path to the English file distributed either in the core space or in plugin space 422 // $trfilepath = the path to the translated file distributed either in the lang pack or in plugin space 423 // $lcfilepath = the path to the _local customization 424 // $trfilename = the filename of the translated version of the file (including prefix for non-core files) 425 if ($location || $plugin) { 426 // non-core file in an extra location 427 $enfilepath = "$CFG->dirroot/$location/$plugin/lang/en_utf8/$filename"; 428 $trfilepath = "$CFG->dirroot/$location/$plugin/lang/$currentlang/$filename"; 429 $lcfilepath = "$locallangdir/$filename"; 430 $trfilename = $filename; 431 } else { 432 // core file in standard location 433 $enfilepath = "$CFG->dirroot/lang/en_utf8/$filename"; 434 $trfilepath = "$langdir/$filename"; 435 $lcfilepath = "$locallangdir/$filename"; 436 $trfilename = $filename; 437 } 438 } 439 440 if (isset($_POST['currentfile'])){ // Save a file 441 if (!confirm_sesskey()) { 442 print_error('confirmsesskeybad', 'error'); 443 } 444 445 $newstrings = array(); 446 447 foreach ($_POST as $postkey => $postval) { 448 $stringkey = lang_file_string_key($postkey); 449 $newstrings[$stringkey] = $postval; 450 } 451 452 unset($newstrings['currentfile']); 453 454 $packstring = array(); 455 $saveinto = $langdir; 456 if ($uselocal) { 457 if(file_exists($trfilepath)) { 458 include($trfilepath); 459 if (isset($string)) { 460 $packstring = $string; 461 } 462 unset($string); 463 } 464 $saveinto = $locallangdir; 465 } 466 467 if (lang_save_file($saveinto, $currentfile, $newstrings, $uselocal, $packstring)) { 468 notify(get_string("changessaved")." ($saveinto/$currentfile)", "notifysuccess"); 469 } else { 470 error("Could not save the file '$saveinto/$currentfile'!", "lang.php?mode=compare&currentfile=$currentfile"); 471 } 472 unset($packstring); 473 } 474 475 print_box_start('generalbox editstrings'); 476 $menufiles = array(); 477 $menufiles_coregrp = 1; 478 foreach ($stringfiles as $stringfile) { 479 $item_key = $stringfile['filename']; 480 $item_label = $stringfile['filename']; 481 if ($stringfile['location'] != '' && $stringfile['plugin'] != '') { 482 $item_label .= ' ('.$stringfile['location'].'/'.$stringfile['plugin'].')'; 483 if ($menufiles_coregrp == 1) { 484 $menufiles['extra'] = '------------'; 485 $menufiles_coregrp = 0; 486 } 487 } 488 $menufiles[$item_key] = $item_label; 489 } 490 $selectionlabel = '<code class="path">'; 491 //$selectionlabel .= $strfilestoredin; 492 $selectionlabel .= $uselocal ? "{$currentlang}_local" : $currentlang; 493 $selectionlabel .= '/</code>'; 494 popup_form("$CFG->wwwroot/$CFG->admin/lang.php?mode=compare&currentfile=", $menufiles, "choosefile", 495 $currentfile, $strchoosefiletoedit, '', '', false, 'self', $selectionlabel); 496 helpbutton('langswitchstorage', $strfilestoredinhelp, 'moodle'); 497 print_box_end(); 498 499 if ($currentfile <> '') { 500 error_reporting(0); 501 if (!isset($editable) || $editable) { 502 if (!file_exists("$saveto/$currentfile")) { 503 if (!@touch("$saveto/$currentfile")) { 504 print_heading(get_string("filemissing", "", "$saveto/$currentfile"), '', 4, 'error'); 505 } else { 506 print_heading($strfilecreated, '', 4, 'notifysuccess'); 507 } 508 } 509 if ($currentlang == "en_utf8" && !$uselocal) { 510 $editable = false; 511 print_heading($streditennotallowed, '', 4); 512 } elseif ($f = fopen("$saveto/$currentfile","r+")) { 513 $editable = true; 514 fclose($f); 515 } else { 516 $editable = false; 517 notify(get_string("makeeditable", "", "$saveto/$currentfile"), 'notifyproblem'); 518 } 519 } 520 error_reporting($CFG->debug); 521 522 $o = ''; // stores the HTML output to be echo-ed 523 524 unset($string); 525 include($enfilepath); 526 $enstring = isset($string) ? $string : array(); 527 // 528 // Following strings have moved into langconfig.php, but keep the here for backward compatibility 529 // 530 if ($currentlang != 'en' and $currentfile == 'moodle.php') { 531 $enstring['thislanguage'] = "<< TRANSLATORS: Specify the name of your language here. If possible use Unicode Numeric Character References >>"; 532 $enstring['thischarset'] = "<< TRANSLATORS: Charset encoding - always use utf-8 >>"; 533 $enstring['thisdirection'] = "<< TRANSLATORS: This string specifies the direction of your text, either left-to-right or right-to-left. Insert either 'ltr' or 'rtl' here. >>"; 534 $enstring['parentlanguage'] = "<< TRANSLATORS: If your language has a Parent Language that Moodle should use when strings are missing from your language pack, then specify the code for it here. If you leave this blank then English will be used. Example: nl >>"; 535 } 536 unset($string); 537 ksort($enstring); 538 539 @include($lcfilepath); 540 $localstring = isset($string) ? $string : array(); 541 unset($string); 542 ksort($localstring); 543 544 @include($trfilepath); 545 $string = isset($string) ? $string : array(); 546 ksort($string); 547 548 if ($editable) { 549 $o .= "<form id=\"$currentfile\" action=\"lang.php\" method=\"post\">"; 550 $o .= '<div>'; 551 } 552 $o .= "<table summary=\"\" width=\"100%\" class=\"translator\">"; 553 $linescounter = 0; 554 $missingcounter = 0; 555 foreach ($enstring as $key => $envalue) { 556 $linescounter++ ; 557 if (LANG_SUBMIT_REPEAT && $editable && $linescounter % LANG_SUBMIT_REPEAT_EVERY == 0) { 558 $o .= '<tr><td> </td><td><br />'; 559 $o .= '<input type="submit" tabindex="'.$missingcounter.'" name="update" value="'.get_string('savechanges').': '.$currentfile.'" />'; 560 $o .= '<br /> </td></tr>'; 561 } 562 $envalue = nl2br(htmlspecialchars($envalue)); 563 $envalue = preg_replace('/(\$a\-\>[a-zA-Z0-9]*|\$a)/', '<b>$0</b>', $envalue); // Make variables bold. 564 $envalue = str_replace("%%","%",$envalue); 565 $envalue = str_replace("\\","",$envalue); // Delete all slashes 566 567 $o .= "\n\n".'<tr class="'; 568 if ($linescounter % 2 == 0) { 569 $o .= 'r0'; 570 } else { 571 $o .= 'r1'; 572 } 573 $o .= '">'; 574 $o .= '<td dir="ltr" lang="en">'; 575 $o .= '<span id="'.$key.'" class="stren">'.$envalue.'</span>'; 576 $o .= '<br />'."\n"; 577 $o .= '<span class="strkey">'.$key.'</span>'; 578 $o .= '</td>'."\n"; 579 580 // Missing array keys are not bugs here but missing strings 581 error_reporting(E_ALL ^ E_NOTICE); 582 if ($uselocal) { 583 $value = lang_fix_value_from_file($localstring[$key]); 584 $value2 = lang_fix_value_from_file($string[$key]); 585 if ($value == '') { 586 $value = $value2; 587 } 588 } else { 589 $value = lang_fix_value_from_file($string[$key]); 590 $value2 = lang_fix_value_from_file($localstring[$key]); 591 } 592 error_reporting($CFG->debug); 593 $missingtarget = ''; 594 $missingnext = ''; 595 $missingprev = ''; 596 $cellcolour = ''; 597 $usetabindex = false; 598 if (!$value) { 599 // the string is not present in the pack being processed 600 if (!$value2) { 601 $cellcolour = 'class="bothmissing"'; 602 $usetabindex = true; 603 } else { 604 $cellcolour = 'class="mastermissing"'; 605 $usetabindex = true; 606 } 607 $missingcounter++; 608 if (LANG_DISPLAY_MISSING_LINKS) { 609 $missingtarget = '<a name="missing'.$missingcounter.'"></a>'; 610 $missingnext = '<a href="#missing'.($missingcounter+1).'">'. 611 '<img src="' . $CFG->pixpath . '/t/down.gif" class="iconsmall" alt="'.$strnext.'" /></a>'; 612 $missingprev = '<a href="#missing'.($missingcounter-1).'">'. 613 '<img src="' . $CFG->pixpath . '/t/up.gif" class="iconsmall" alt="'.$strprev.'" /></a>'; 614 } 615 } else { 616 // the string is translated in the pack being processed 617 if ($value <> $value2 && ($value2 <> '')) { 618 $cellcolour = 'class="localdifferent"'; 619 $usetabindex = true; 620 $missingcounter++; 621 if (LANG_DISPLAY_MISSING_LINKS) { 622 $missingtarget = '<a name="missing'.$missingcounter.'"></a>'; 623 $missingnext = '<a href="#missing'.($missingcounter+1).'">'. 624 '<img src="' . $CFG->pixpath . '/t/down.gif" class="iconsmall" alt="'.$strnext.'" /></a>'; 625 $missingprev = '<a href="#missing'.($missingcounter-1).'">'. 626 '<img src="' . $CFG->pixpath . '/t/up.gif" class="iconsmall" alt="'.$strprev.'" /></a>'; 627 } 628 } 629 } 630 631 if ($editable) { 632 $o .= '<td '.$cellcolour.' valign="top">'; 633 if ($missingcounter > 1) { 634 $o .= $missingprev; 635 } 636 $o .= $missingtarget."\n"; 637 if (isset($string[$key])) { 638 $valuelen = strlen($value); 639 } else { 640 $valuelen = strlen($envalue); 641 } 642 $cols=40; 643 if ($usetabindex) { 644 $tabindex = 'tabindex="'.$missingcounter.'"'; 645 } else { 646 $tabindex = ''; 647 } 648 if (strstr($value, "\r") or strstr($value, "\n") or $valuelen > $cols) { 649 $rows = ceil($valuelen / $cols); 650 $o .= '<textarea name="stringXXX'.lang_form_string_key($key).'" cols="'.$cols.'" rows="'.$rows.'" '.$tabindex.'>'.$value.'</textarea>'."\n"; 651 } else { 652 if ($valuelen) { 653 $cols = $valuelen + 5; 654 } 655 if (LANG_ALWAYS_TEXTAREA) { 656 $o .= '<textarea name="stringXXX'.lang_form_string_key($key).'" cols="'.$cols.'" rows="1" '.$tabindex.'>'.$value.'</textarea>'."\n"; 657 } else { 658 $o .= '<input type="text" name="stringXXX'.lang_form_string_key($key).'" value="'.$value.'" size="'.$cols.'" '.$tabindex.' />'; 659 } 660 } 661 if ($value2 <> '' && $value <> $value2) { 662 $o .= '<br /><span style="font-size:small">'.$value2.'</span>'; 663 } 664 $o .= $missingnext . '</td>'; 665 666 } else { 667 $o .= '<td '.$cellcolour.' valign="top">'.$value.'<br />'.$value2.'</td>'; 668 } 669 $o .= '</tr>'."\n"; 670 } 671 if ($editable) { 672 $o .= '<tr><td> </td><td><br />'; 673 $o .= '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />'; 674 $o .= '<input type="hidden" name="currentfile" value="'.$currentfile.'" />'; 675 $o .= '<input type="hidden" name="mode" value="compare" />'; 676 $o .= '<input type="submit" name="update" tabindex="'.$missingcounter.'" value="'.get_string('savechanges').': '.$currentfile.'" />'; 677 $o .= '</td></tr>'; 678 } 679 $o .= '</table>'; 680 if ($editable) { 681 $o .= '</div>'; 682 $o .= '</form>'; 683 } 684 685 if (LANG_DISPLAY_MISSING_LINKS) { 686 if ($missingcounter > 0) { 687 print_heading(get_string('numberofmissingstrings', 'admin', $missingcounter), '', 4); 688 if ($editable) { 689 print_heading('<a href="#missing1">'.$strgotofirst.'</a>', "", 4); 690 } 691 } else { 692 print_heading($strnomissingstrings, '', 4, 'notifysuccess'); 693 } 694 } 695 echo $o; 696 697 } else { 698 // no $currentfile specified 699 // no useful information to display - maybe some help? instructions? 700 } 701 702 } elseif ($mode == 'helpfiles') { 703 704 $saveto = $saveto.'/help'; // the edited content will be saved to 705 $enlangdir = $enlangdir.'/help'; // English master help files localtion 706 $langdir = $langdir.'/help'; // current language master help files location 707 $locallangdir = $locallangdir.'/help'; // local modifications of help files location 708 $altdir = $uselocal ? $langdir : $locallangdir; // alternative to $saveto 709 710 $fileeditorrows = 10; // number of textareas' rows 711 $fileeditorcols = 100; // dtto cols 712 $filemissingmark = ' (***)'; // mark to add to non-existing or zero-length files 713 $fileoldmark = ' (old?)'; // mark to add to filenames in selection form if the English version is newer 714 $filetemplate = ''; // template for new files, e.g. CVS identification 715 716 if (isset($_POST['currentfile'])) { // Save a file 717 if (!confirm_sesskey()) { 718 print_error('confirmsesskeybad', 'error'); 719 } 720 if (lang_help_save_file($saveto, $currentfile, $_POST['filedata'])) { 721 notify(get_string("changessaved")." ($saveto/$currentfile)", "notifysuccess"); 722 } else { 723 error("Could not save the file '$currentfile'!", "lang.php?mode=helpfiles&currentfile=$currentfile&sesskey=$USER->sesskey"); 724 } 725 } 726 727 print_box_start('generalbox editstrings'); 728 $menufiles = array(); 729 $menufiles_coregrp = 1; 730 $origlocation = ''; // the location of the currentfile's English source will be stored here 731 $origplugin = ''; // dtto plugin 732 foreach ($helpfiles as $helppath => $helpfile) { 733 $item_key = $helpfile['filename']; 734 $item_label = $helpfile['filename']; 735 if ((!file_exists($saveto.'/'.$helpfile['filename'])) || (filesize($saveto.'/'.$helpfile['filename']) == 0)) { 736 $item_label .= $filemissingmark; 737 } else { 738 if (filemtime($saveto.'/'.$helpfile['filename']) < filemtime($helppath)) { 739 $item_label .= $fileoldmark; 740 } 741 if ($helpfile['location'] != '' && $helpfile['plugin'] != '') { 742 $item_label .= ' ('.$helpfile['location'].'/'.$helpfile['plugin'].')'; 743 if ($menufiles_coregrp == 1) { 744 $menufiles['extra'] = '------------'; 745 $menufiles_coregrp = 0; 746 } 747 } 748 } 749 $menufiles[$item_key] = $item_label; 750 if ($currentfile == $helpfile['filename']) { 751 $origlocation = $helpfile['location']; 752 $origplugin = $helpfile['plugin']; 753 } 754 } 755 $selectionlabel = '<code class="path">'; 756 //$selectionlabel .= $strfilestoredin; 757 $selectionlabel .= $uselocal ? "{$currentlang}_local" : $currentlang; 758 $selectionlabel .= '/help/</code>'; 759 popup_form("$CFG->wwwroot/$CFG->admin/lang.php?mode=helpfiles&currentfile=", $menufiles, "choosefile", 760 $currentfile, $strchoosefiletoedit, '', '', false, 'self', $selectionlabel); 761 helpbutton('langswitchstorage', $strfilestoredinhelp, 'moodle'); 762 print_box_end(); 763 764 if (!empty($currentfile)) { 765 766 if (!file_exists("$saveto/$currentfile")) { 767 $dbg .= "File does not exist: $saveto/$currentfile\n"; 768 //check if directory exist 769 if (!file_exists(dirname("$saveto/$currentfile"))) { 770 if(!lang_make_directory(dirname("$saveto/$currentfile"))) { 771 echo ('Cannot create directory: '.dirname("$saveto/$currentfile")); 772 } 773 } 774 // 775 // file doesn't exist - let's check webserver's permission to create it 776 // 777 if (!@touch("$saveto/$currentfile")) { 778 // 779 // webserver is unable to create new file 780 // 781 notify(get_string('filemissing', '', "$saveto/$currentfile" )); 782 notify(get_string('makeeditable', '', "$saveto/$currentfile")); 783 $editable = false; 784 } else { 785 // 786 // webserver can create new file - we can delete it now and let 787 // it create again if its filesize() > 0 788 // 789 $editable = true; 790 unlink("$saveto/$currentfile"); 791 } 792 } elseif (is_writable("$saveto/$currentfile")) { 793 $editable = true; 794 } else { 795 // 796 // file exists but it is not writeable by web server process :-( 797 // 798 $editable = false; 799 notify(get_string('makeeditable', '', "$saveto/$currentfile")); 800 } 801 802 // master en_utf8 in dataroot is not editable 803 if ((!$uselocal) && ($currentlang == 'en_utf8')) { 804 $editable = false; 805 } 806 807 echo '<div>'; 808 809 if ($uselocal) { 810 $strsavetotitle = $strlanglocalpackage . helpbutton('langpackages', $strlanglocalpackage, 'moodle', true, false, '', true); 811 $straltdirtitle = $strlangmasterpackage . helpbutton('langpackages', $strlangmasterpackage, 'moodle', true, false, '', true); 812 } else { 813 $straltdirtitle = $strlanglocalpackage . helpbutton('langpackages', $strlanglocalpackage, 'moodle', true, false, '', true); 814 $strsavetotitle = $strlangmasterpackage . helpbutton('langpackages', $strlangmasterpackage, 'moodle', true, false, '', true); 815 816 } 817 818 if ($editable) { 819 // generate an editor for the current help file in $saveto 820 echo '<fieldset><legend>'.$strsavetotitle.'</legend>'; 821 echo "<form id=\"helpfileeditor\" action=\"lang.php\" method=\"post\">"; 822 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />'; 823 echo '<input type="hidden" name="currentfile" value="'.$currentfile.'" />'; 824 echo '<input type="hidden" name="mode" value="helpfiles" />'; 825 echo "<div align=\"center\">\n"; 826 echo "<textarea rows=\"$fileeditorrows\" cols=\"$fileeditorcols\" name=\"filedata\">"; 827 if (file_exists("$saveto/$currentfile")) { 828 echo htmlspecialchars(file_get_contents("$saveto/$currentfile")); 829 } else { 830 echo ($filetemplate); 831 } 832 echo "</textarea>\n</div>\n"; 833 echo '<div align="center"><input type="submit" value="'.get_string('savechanges').'" /></div>'; 834 echo '</form>'; 835 $preview_url = lang_help_preview_url($currentfile, !$uselocal); 836 if ($preview_url) { 837 link_to_popup_window($preview_url, 'popup', get_string('preview')); 838 } 839 echo '</fieldset>'; 840 } 841 842 if (is_readable("$altdir/$currentfile")) { 843 // show the content of the same help file in alternative location 844 echo '<fieldset><legend>'.$straltdirtitle.'</legend>'; 845 echo "<div align=\"center\">\n"; 846 echo "<textarea rows=\"$fileeditorrows\" cols=\"$fileeditorcols\" name=\"\">"; 847 if (file_exists("$altdir/$currentfile")) { 848 echo htmlspecialchars(file_get_contents("$altdir/$currentfile")); 849 } else { 850 echo ($filetemplate); 851 } 852 echo "</textarea>\n</div>\n"; 853 $preview_url = lang_help_preview_url($currentfile, $uselocal); 854 if ($preview_url) { 855 link_to_popup_window($preview_url, 'popup', get_string('preview')); 856 } 857 echo '</fieldset>'; 858 } 859 860 // show the content of the original English file either in core space or plugin space 861 if ($origlocation != '' && $origplugin != '') { 862 // non-core help file 863 $ensrc = "$CFG->dirroot/$origlocation/$origplugin/lang/en_utf8/help/$currentfile"; 864 } else { 865 // core help file 866 $ensrc = "$enlangdir/$currentfile"; 867 } 868 if (is_readable($ensrc)) { 869 echo '<fieldset><legend>'.$strlangmasterenglish; 870 helpbutton('langpackages', $strlangmasterenglish); 871 echo '</legend>'; 872 echo "<div align=\"center\">\n<textarea rows=\"$fileeditorrows\" cols=\"$fileeditorcols\" name=\"\">"; 873 echo htmlspecialchars(file_get_contents($ensrc)); 874 echo "</textarea>\n</div>\n"; 875 $preview_url = lang_help_preview_url($currentfile, true, 'en_utf8'); // do not display en_utf8_local 876 if ($preview_url) { 877 link_to_popup_window($preview_url, 'popup', get_string('preview')); 878 } 879 echo '</fieldset>'; 880 } 881 882 echo '</div>'; // translator box 883 error_reporting($CFG->debug); 884 } 885 886 if (false && $CFG->debugdisplay && debugging('', DEBUG_DEVELOPER) ) { 887 echo '<hr />'; 888 print_heading('Debugging info'); 889 echo '<pre class="notifytiny">'; 890 print_r($dbg); 891 print_r("\n\$currentfile = $currentfile"); 892 print_r("\n\$enlangdir = $enlangdir"); 893 print_r("\n\$langdir = $langdir"); 894 print_r("\n\$locallangdir = $locallangdir"); 895 print_r("\n\$saveto = $saveto"); 896 print_r("\n\$altdir = $altdir"); 897 print_r("\n\$origlocation = $origlocation"); 898 print_r("\n\$origplugin = $origplugin"); 899 print_r("\n\$ensrc = $ensrc"); 900 print_r("\n\$helpfiles = "); 901 print_r($helpfiles); 902 echo '</pre>'; 903 } 904 905 } // fi $mode == 'helpfiles' 906 907 908 admin_externalpage_print_footer(); 909 910 ////////////////////////////////////////////////////////////////////// 911 912 /** 913 * Save language translation file. 914 * 915 * Thanks to Petri Asikainen for the original version of code 916 * used to save language files. 917 * 918 * @uses $CFG 919 * @uses $USER 920 * @param string $path Full pathname to the directory to use 921 * @param string $file File to overwrite 922 * @param array $strings Array of strings to write 923 * @param bool $local Should *_local version be saved? 924 * @param array $packstrings Array of default langpack strings (needed if $local) 925 * @return bool Created successfully? 926 */ 927 function lang_save_file($path, $file, $strings, $local, $packstrings) { 928 global $CFG, $USER; 929 if (LANG_KEEP_ORPHANS) { 930 // let us load the current content of the file 931 unset($string); 932 @include("$path/$file"); 933 if (isset($string)) { 934 $orphans = $string; 935 unset($string); 936 } else { 937 $orphans = array(); 938 } 939 } 940 // let us rewrite the file 941 if (!$f = @fopen("$path/$file","w")) { 942 return false; 943 } 944 945 fwrite($f, "<?PHP // \$Id\$ \n"); 946 fwrite($f, " // $file - created with Moodle $CFG->release ($CFG->version)\n"); 947 if ($local) { 948 fwrite($f, " // local modifications from $CFG->wwwroot\n"); 949 } 950 fwrite($f, "\n\n"); 951 ksort($strings); 952 foreach ($strings as $key => $value) { 953 @list($id, $stringname) = explode('XXX',$key); 954 $value = lang_fix_value_before_save($value); 955 if ($id == "string" and $value != ""){ 956 if ((!$local) || (!isset($packstrings[$stringname])) || (lang_fix_value_from_file($packstrings[$stringname]) <> lang_fix_value_from_file($value))) { 957 // Either we are saving the master language pack 958 // or the string is not saved in packstring - fixes PHP notices about missing key 959 // or we are saving local language pack and the strings differ. 960 fwrite($f,"\$string['$stringname'] = '$value';\n"); 961 } 962 if (LANG_KEEP_ORPHANS && isset($orphans[$stringname])) { 963 unset($orphans[$stringname]); 964 } 965 } 966 } 967 if (LANG_KEEP_ORPHANS) { 968 // let us add orphaned strings, i.e. already translated strings without the English referential source 969 foreach ($orphans as $key => $value) { 970 fwrite($f,"\$string['$key'] = '".lang_fix_value_before_save($value)."'; // ORPHANED\n"); 971 } 972 } 973 fwrite($f,"\n?>\n"); 974 fclose($f); 975 return true; 976 } 977 978 /** 979 * Fix value of the translated string after it is load from the file. 980 * 981 * These modifications are typically necessary to work with the same string coming from two sources. 982 * We need to compare the content of these sources and we want to have e.g. "This string\r\n" 983 * to be the same as " This string\n". 984 * 985 * @param string $value Original string from the file 986 * @return string Fixed value 987 */ 988 function lang_fix_value_from_file($value='') { 989 $value = str_replace("\r","",$value); // Bad character caused by Windows 990 $value = preg_replace("/\n{3,}/", "\n\n", $value); // Collapse runs of blank lines 991 $value = trim($value); // Delete leading/trailing white space 992 $value = str_replace("\\","",$value); // Delete all slashes 993 $value = str_replace("%%","%",$value); 994 $value = str_replace("&","&",$value); // Fixes MDL-9248 995 $value = str_replace("<","<",$value); 996 $value = str_replace(">",">",$value); 997 $value = str_replace('"',""",$value); 998 return $value; 999 } 1000 1001 /** 1002 * Fix value of the translated string before it is saved into the file 1003 * 1004 * @uses $CFG 1005 * @param string $value Raw string to be saved into the lang pack 1006 * @return string Fixed value 1007 */ 1008 function lang_fix_value_before_save($value='') { 1009 global $CFG; 1010 if ($CFG->lang != "zh_hk" and $CFG->lang != "zh_tw") { // Some MB languages include backslash bytes 1011 $value = str_replace("\\","",$value); // Delete all slashes 1012 } 1013 if (ini_get_bool('magic_quotes_sybase')) { // Unescape escaped sybase quotes 1014 $value = str_replace("''", "'", $value); 1015 } 1016 $value = str_replace("'", "\\'", $value); // Add slashes for ' 1017 $value = str_replace('"', "\\\"", $value); // Add slashes for " 1018 $value = str_replace("%","%%",$value); // Escape % characters 1019 $value = str_replace("\r", "",$value); // Remove linefeed characters 1020 $value = trim($value); // Delete leading/trailing white space 1021 return $value; 1022 } 1023 1024 /** 1025 * Try and create a new language directory. 1026 * 1027 * Uses PHP>=5.0 syntax of mkdir and tries to create directories recursively. 1028 * 1029 * @uses $CFG 1030 * @param string $directory full path to the directory under $langbase 1031 * @return string|false Returns full path to directory if successful, false if not 1032 */ 1033 function lang_make_directory($dir, $shownotices=true) { 1034 global $CFG; 1035 umask(0000); 1036 if (! file_exists($dir)) { 1037 if (! @mkdir($dir, $CFG->directorypermissions, true)) { // recursive=true; PHP>=5.0 needed 1038 return false; 1039 } 1040 //@chmod($dir, $CFG->directorypermissions); // Just in case mkdir didn't do it 1041 } 1042 return $dir; 1043 } 1044 1045 /** 1046 * Return the string key name for use in HTML form. 1047 * 1048 * Required because '.' in form input names get replaced by '_' by PHP. 1049 * 1050 * @param string $keyfromfile The key name containing '.' 1051 * @return string The key name without '.' 1052 */ 1053 function lang_form_string_key($keyfromfile) { 1054 return str_replace('.', '##46#', $keyfromfile); /// Derived from ., the ascii value for a period. 1055 } 1056 1057 /** 1058 * Return the string key name for use in file. 1059 * 1060 * Required because '.' in form input names get replaced by '_' by PHP. 1061 * 1062 * @param string $keyfromfile The key name without '.' 1063 * @return string The key name containing '.' 1064 */ 1065 function lang_file_string_key($keyfromform) { 1066 return str_replace('##46#', '.', $keyfromform); 1067 } 1068 1069 /** 1070 * Return the substring of the string and take care of XHTML compliance. 1071 * 1072 * There was a problem with pure substr() which could possibly produce XHTML parsing error: 1073 * substr('Marks & Spencer', 0, 9) -> 'Marks &am' ... is not XHTML compliance 1074 * This function takes care of these cases. Fixes MDL-8852. 1075 * 1076 * Thanks to kovacsendre, the author of the function at http://php.net/substr 1077 * 1078 * @param string $str The original string 1079 * @param int $start Start position in the $value string 1080 * @param int $length Optional length of the returned substring 1081 * @return string The substring as returned by substr() with XHTML compliance 1082 * @todo Seems the function does not work with negative $start together with $length being set 1083 */ 1084 function lang_xhtml_save_substr($str, $start, $length = NULL) { 1085 if ($length === 0) { 1086 //stop wasting our time ;) 1087 return ""; 1088 } 1089 1090 //check if we can simply use the built-in functions 1091 if (strpos($str, '&') === false) { 1092 // No entities. Use built-in functions 1093 if ($length === NULL) { 1094 return substr($str, $start); 1095 } else { 1096 return substr($str, $start, $length); 1097 } 1098 } 1099 1100 // create our array of characters and html entities 1101 $chars = preg_split('/(&[^;\s]+;)|/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE); 1102 $html_length = count($chars); 1103 1104 // check if we can predict the return value and save some processing time, i.e.: 1105 // input string was empty OR 1106 // $start is longer than the input string OR 1107 // all characters would be omitted 1108 if (($html_length === 0) or ($start >= $html_length) or (isset($length) and ($length <= -$html_length))) { 1109 return ''; 1110 } 1111 1112 //calculate start position 1113 if ($start >= 0) { 1114 $real_start = $chars[$start][1]; 1115 } else { 1116 //start'th character from the end of string 1117 $start = max($start,-$html_length); 1118 $real_start = $chars[$html_length+$start][1]; 1119 } 1120 1121 if (!isset($length)) { 1122 // no $length argument passed, return all remaining characters 1123 return substr($str, $real_start); 1124 } elseif ($length > 0) { 1125 // copy $length chars 1126 if ($start+$length >= $html_length) { 1127 // return all remaining characters 1128 return substr($str, $real_start); 1129 } else { 1130 //return $length characters 1131 return substr($str, $real_start, $chars[max($start,0)+$length][1] - $real_start); 1132 } 1133 } else { 1134 //negative $length. Omit $length characters from end 1135 return substr($str, $real_start, $chars[$html_length+$length][1] - $real_start); 1136 } 1137 } 1138 1139 /** 1140 * Finds all English string files in the standard lang/en_utf8 location. 1141 * 1142 * Core lang files should always be stored here and not in the module space (MDL-10920). 1143 * The English version of the file may be found in 1144 * $CFG->dirroot/lang/en_utf8/filename 1145 * The localised version of the found file should be saved into 1146 * $CFG->dataroot/lang/currentlang[_local]/filename 1147 * where "filename" is returned as a part of the file record. 1148 * 1149 * @return array Array of a file information. Compatible format with {@link lang_extra_locations()} 1150 */ 1151 function lang_standard_locations() { 1152 global $CFG; 1153 $files = array(); 1154 // Standard location of master English string files. 1155 $places = array($CFG->dirroot.'/lang/en_utf8'); 1156 foreach ($places as $place) { 1157 foreach (get_directory_list($place, '', false) as $file) { 1158 if ((substr($file, -4) == ".php") && ($file != "langconfig.php")) { 1159 $fullpath = $place.'/'.$file; 1160 $files[$fullpath] = array( 1161 'filename' => $file, 1162 'location' => '', 1163 'plugin' => '', 1164 'prefix' => '', 1165 ); 1166 } 1167 } 1168 } 1169 return $files; 1170 } 1171 1172 /** 1173 * Finds all English string files in non-standard location. 1174 * 1175 * Searches for lang/en_utf8/*.php in various types of plugins (blocks, database presets, question types, 1176 * 3rd party modules etc.) and returns an array of found files details. 1177 * 1178 * The English version of the file may be found in 1179 * $CFG->dirroot/location/plugin/lang/en_utf8/filename 1180 * The localised version of the found file should be saved into 1181 * $CFG->dataroot/lang/currentlang[_local]/prefix_plugin.php 1182 * where "location", "plugin", "prefix" and "filename" are returned as a part of the file record. 1183 * 1184 * @return array Array of a file information. Compatible format with {@link lang_standard_locations()} 1185 */ 1186 function lang_extra_locations() { 1187 global $CFG; 1188 $files = array(); 1189 $places = places_to_search_for_lang_strings(); 1190 foreach ($places as $prefix => $directories) { 1191 if ($prefix != '__exceptions') { 1192 foreach ($directories as $directory) { 1193 foreach (get_list_of_plugins($directory) as $plugin) { 1194 $enlangdirlocation = $CFG->dirroot.'/'.$directory.'/'.$plugin.'/lang/en_utf8'; 1195 foreach (get_directory_list($enlangdirlocation, '', false) as $file) { 1196 if ((substr($file, -4) == ".php") && ($file != "langconfig.php")) { 1197 $fullpath = $enlangdirlocation.'/'.$file; 1198 $files[$fullpath] = array( 1199 'filename' => $file, 1200 'location' => $directory, 1201 'plugin' => $plugin, 1202 'prefix' => $prefix, 1203 ); 1204 } 1205 } 1206 } 1207 } 1208 } 1209 } 1210 return $files; 1211 } 1212 1213 /** 1214 * Lookup for a stringfile details. 1215 * 1216 * English files can be stored in several places (core space or module/plugin space). Their translations 1217 * go into the one directory - the current language pack. Therefore, the name of the stringfile may be 1218 * considered as a key of the list of all stringfiles. 1219 * 1220 * @param string $currentfile the filename 1221 * @param array $stringfiles the array of file info returned by {@link lang_extra_locations()} 1222 * @return array Array of a file information (filename, location, plugin, prefix) or null. 1223 */ 1224 function lang_get_file_info($currentfile, $stringfiles) { 1225 $found = false; 1226 foreach ($stringfiles as $path=>$stringfile) { 1227 if ($stringfile['filename'] == $currentfile) { 1228 $found = true; 1229 $ret = $stringfile; 1230 $ret['fullpath'] = $path; 1231 break; 1232 } 1233 } 1234 if ($found) { 1235 return $ret; 1236 } else { 1237 return null; 1238 } 1239 } 1240 1241 /** 1242 * Returns all English help files in the standard lang/en_utf8/help location. 1243 * 1244 * Core help files should always be stored here and not in the module space (MDL-10920). 1245 * The English version of the file may be found in 1246 * $CFG->dirroot/lang/en_utf8/help/filename 1247 * The localised version of the found file should be saved into 1248 * $CFG->dataroot/lang/currentlang[_local]/help/filename 1249 * where "filename" is returned as a part of the file record. 1250 * 1251 * @return array Array of a file information. Compatible format with {@link lang_extra_locations()} 1252 */ 1253 function lang_help_standard_locations() { 1254 global $CFG; 1255 $files = array(); 1256 // Standard location of master English help files. 1257 $places = array($CFG->dirroot.'/lang/en_utf8/help'); 1258 foreach ($places as $place) { 1259 foreach (get_directory_list($place, 'CVS') as $file) { 1260 if ((substr($file, -5) == '.html') || (substr($file, -4) == '.txt' )) { 1261 $fullpath = $place.'/'.$file; 1262 $files[$fullpath] = array( 1263 'filename' => $file, 1264 'location' => '', 1265 'plugin' => '', 1266 'prefix' => '', 1267 ); 1268 } 1269 } 1270 } 1271 return $files; 1272 } 1273 1274 /** 1275 * Returns all English help files in non-standard location. 1276 * 1277 * Searches for lang/en_utf8/help/* files in various types of plugins (blocks, database presets, question types, 1278 * 3rd party modules etc.) and returns an array of found files details. 1279 * 1280 * The English version of the file may be found in 1281 * $CFG->dirroot/location/plugin/lang/en_utf8/help/filename 1282 * The localised version of the found file should be saved into 1283 * $CFG->dataroot/lang/currentlang[_local]/help/prefix_plugin/filename (XXX is "prefix" here right?) 1284 * where "location", "plugin", "prefix" and "filename" are returned as a part of the file record. 1285 * 1286 * @return array Array of a file information. Compatible format with {@link lang_standard_locations()} 1287 */ 1288 function lang_help_extra_locations() { 1289 global $CFG; 1290 $files = array(); 1291 $places = places_to_search_for_lang_strings(); 1292 foreach ($places as $prefix => $directories) { 1293 if ($prefix != '__exceptions') { 1294 foreach ($directories as $directory) { 1295 foreach (get_list_of_plugins($directory) as $plugin) { 1296 $enlangdirlocation = $CFG->dirroot.'/'.$directory.'/'.$plugin.'/lang/en_utf8/help'; 1297 foreach (get_directory_list($enlangdirlocation, 'CVS') as $file) { 1298 if ((substr($file, -5) == '.html') || (substr($file, -4) == '.txt' )) { 1299 $fullpath = $enlangdirlocation.'/'.$file; 1300 $files[$fullpath] = array( 1301 'filename' => $file, 1302 'location' => $directory, 1303 'plugin' => $plugin, 1304 'prefix' => $prefix, 1305 ); 1306 } 1307 } 1308 } 1309 } 1310 } 1311 } 1312 return $files; 1313 } 1314 1315 /** 1316 * Return a preview URL for help file, if available. 1317 * 1318 * @param string $currentfile The relative path to the help file, e.g. "assignment/types.html" - MDL-12291 1319 * @param bool $skiplocal Force displaying the helpfile from a master lang pack 1320 * @param string $forcelang Force language of the help, e.g. "en_utf8" 1321 * @return string $url 1322 */ 1323 function lang_help_preview_url($currentfile, $skiplocal=false, $forcelang = '') { 1324 $currentpathexp = explode('/', $currentfile); 1325 if (count($currentpathexp) > 1) { 1326 $url = '/help.php?module='.implode('/',array_slice($currentpathexp,0,count($currentpathexp)-1)).'&file='.end($currentpathexp); 1327 } else { 1328 $url = '/help.php?module=moodle&file='.$currentfile; 1329 } 1330 if ($skiplocal) { 1331 $url .= '&skiplocal=1'; 1332 } 1333 if ($forcelang) { 1334 $url .= '&forcelang='.$forcelang; 1335 } 1336 return $url; 1337 } 1338 1339 1340 /** 1341 * Saves (overwrites) translated help file. 1342 * 1343 * @param string $helproot The path to the "help" folder 1344 * @param string $file The relative path to the html help file 1345 * @param string $content HTML data to be saved 1346 * @return bool False if save failed, true otherwise 1347 */ 1348 function lang_help_save_file($helproot, $file, $content) { 1349 global $CFG, $USER; 1350 1351 $content = str_replace("\r", "",$content); // Remove linefeed characters 1352 $content = preg_replace("/\n{3,}/", "\n\n", $content); // Collapse runs of blank lines 1353 $content = trim($content); // Delete leading/trailing whitespace 1354 if (is_readable("$helproot/$file") && filesize("$helproot/$file") > 0 && $content == '') { 1355 notify(get_string('langrmyourself', 'admin')); 1356 return true; 1357 } 1358 1359 error_reporting(0); 1360 if (!$f = fopen("$helproot/$file","w")) { 1361 error_reporting($CFG->debug); 1362 return false; 1363 } 1364 error_reporting($CFG->debug); 1365 1366 fwrite($f, stripslashes($content)); 1367 fclose($f); 1368 1369 // Remove file if its empty 1370 if (filesize("$helproot/$file") == 0) { 1371 unlink("$helproot/$file"); 1372 } 1373 1374 return true; 1375 } 1376 1377 1378 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |