3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * Fetches language packages from download.moodle.org server
21 * Language packages are available at http://download.moodle.org/langpack/2.0/
22 * in ZIP format together with a file languages.md5 containing their hashes
24 * Locally, language packs are saved into $CFG->dataroot/lang/
27 * @copyright 2005 Yu Zhang
28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 require_once(dirname(dirname(__FILE__
)).'/config.php');
32 require_once($CFG->libdir
.'/adminlib.php');
33 require_once($CFG->libdir
.'/filelib.php');
34 require_once($CFG->libdir
.'/componentlib.class.php');
36 $thisversion = '2.0'; // TODO this information should be taken from version.php or similar source
38 admin_externalpage_setup('langimport');
40 if (!empty($CFG->skiplangupgrade
)) {
41 echo $OUTPUT->header();
42 echo $OUTPUT->box(get_string('langimportdisabled', 'admin'));
43 echo $OUTPUT->footer();
47 $mode = optional_param('mode', 0, PARAM_INT
); // action
48 $pack = optional_param('pack', array(), PARAM_SAFEDIR
); // pack to install
49 $uninstalllang = optional_param('uninstalllang', '', PARAM_LANG
); // installed pack to uninstall
50 $confirm = optional_param('confirm', 0, PARAM_BOOL
); // uninstallation confirmation
52 define('INSTALLATION_OF_SELECTED_LANG', 2);
53 define('DELETION_OF_SELECTED_LANG', 4);
54 define('UPDATE_ALL_LANG', 5);
56 get_string_manager()->reset_caches();
59 $notice_error = array();
61 if (($mode == INSTALLATION_OF_SELECTED_LANG
) and confirm_sesskey() and !empty($pack)) {
63 make_upload_directory('temp');
64 make_upload_directory('lang');
66 if (is_array($pack)) {
69 $packs = array($pack);
72 foreach ($packs as $pack) {
73 if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion, $pack.'.zip', 'languages.md5', 'lang')) {
74 $status = $cd->install();
77 if ($cd->get_error() == 'remotedownloaderror') {
79 $a->url
= 'http://download.moodle.org/langpack/'.$thisversion.'/'.$pack.'.zip';
80 $a->dest
= $CFG->dataroot
.'/lang';
81 print_error($cd->get_error(), 'error', 'langimport.php', $a);
83 print_error($cd->get_error(), 'error', 'langimport.php');
86 case COMPONENT_INSTALLED
:
87 $notice_ok[] = get_string('langpackinstalled','admin',$pack);
88 if ($parentlang = get_parent_language($pack)) {
89 // install also parent pack if specified
90 if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion,
91 $parentlang.'.zip', 'languages.md5', 'lang')) {
96 case COMPONENT_UPTODATE
:
100 echo $OUTPUT->notification('Had an unspecified error with the component installer, sorry.');
105 if ($mode == DELETION_OF_SELECTED_LANG
and !empty($uninstalllang)) {
106 if ($uninstalllang == 'en') {
107 $notice_error[] = 'English language pack can not be uninstalled';
109 } else if (!$confirm and confirm_sesskey()) {
110 echo $OUTPUT->header();
111 echo $OUTPUT->confirm(get_string('uninstallconfirm', 'admin', $uninstalllang),
112 'langimport.php?mode='.DELETION_OF_SELECTED_LANG
.'&uninstalllang='.$uninstalllang.'&confirm=1',
114 echo $OUTPUT->footer();
117 } else if (confirm_sesskey()) {
118 $dest1 = $CFG->dataroot
.'/lang/'.$uninstalllang;
119 $dest2 = $CFG->dirroot
.'/lang/'.$uninstalllang;
122 if (file_exists($dest1)){
123 $rm1 = remove_dir($dest1);
125 if (file_exists($dest2)){
126 $rm2 = remove_dir($dest2);
129 $notice_ok[] = get_string('langpackremoved','admin');
130 } else { //nothing deleted, possibly due to permission error
131 $notice_error[] = 'An error has occurred, language pack is not completely uninstalled, please check file permissions';
136 if ($mode == UPDATE_ALL_LANG
) {
139 if (!$availablelangs = get_remote_list_of_languages()) {
140 print_error('cannotdownloadlanguageupdatelist', 'error');
142 $md5array = array(); // (string)langcode => (string)md5
143 foreach ($availablelangs as $alang) {
144 $md5array[$alang[0]] = $alang[1];
147 // filter out unofficial packs
148 $currentlangs = array_keys(get_string_manager()->get_list_of_translations(true));
149 $updateablelangs = array();
150 foreach ($currentlangs as $clang) {
151 if (!array_key_exists($clang, $md5array)) {
152 $notice_ok[] = get_string('langpackupdateskipped', 'admin', $clang);
155 $dest1 = $CFG->dataroot
.'/lang/'.$clang;
156 $dest2 = $CFG->dirroot
.'/lang/'.$clang;
158 if (file_exists($dest1.'/langconfig.php') ||
file_exists($dest2.'/langconfig.php')){
159 $updateablelangs[] = $clang;
163 // then filter out packs that have the same md5 key
164 $neededlangs = array(); // all the packs that needs updating
165 foreach ($updateablelangs as $ulang) {
166 if (!is_installed_lang($ulang, $md5array[$ulang])) {
167 $neededlangs[] = $ulang;
171 make_upload_directory('temp');
172 make_upload_directory('lang');
174 $updated = false; // any packs updated?
175 foreach ($neededlangs as $pack) {
180 // delete old directories
181 $dest1 = $CFG->dataroot
.'/lang/'.$pack;
182 $dest2 = $CFG->dirroot
.'/lang/'.$pack;
185 if (file_exists($dest1)) {
186 if (!remove_dir($dest1)) {
187 $notice_error[] = 'Could not delete old directory '.$dest1.', update of '.$pack.' failed, please check permissions.';
191 if (file_exists($dest2)) {
192 if (!remove_dir($dest2)) {
193 $notice_error[] = 'Could not delete old directory '.$dest2.', update of '.$pack.' failed, please check permissions.';
198 // copy and unzip new version
199 if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion, $pack.'.zip', 'languages.md5', 'lang')) {
200 $status = $cd->install();
203 case COMPONENT_ERROR
:
204 if ($cd->get_error() == 'remotedownloaderror') {
206 $a->url
= 'http://download.moodle.org/langpack/'.$thisversion.'/'.$pack.'.zip';
207 $a->dest
= $CFG->dataroot
.'/lang';
208 print_error($cd->get_error(), 'error', 'langimport.php', $a);
210 print_error($cd->get_error(), 'error', 'langimport.php');
214 case COMPONENT_UPTODATE
:
215 // should not get here
218 case COMPONENT_INSTALLED
:
219 $notice_ok[] = get_string('langpackupdated', 'admin', $pack);
227 $notice_ok[] = get_string('langupdatecomplete','admin');
229 $notice_ok[] = get_string('nolangupdateneeded','admin');
232 get_string_manager()->reset_caches();
234 echo $OUTPUT->header();
235 echo $OUTPUT->heading(get_string('langimport', 'admin'));
237 $installedlangs = get_string_manager()->get_list_of_translations(true);
239 $missingparents = array();
240 foreach ($installedlangs as $installedlang => $unused) {
241 $parent = get_parent_language($installedlang);
242 if (empty($parent) or ($parent === 'en')) {
245 if (!isset($installedlangs[$parent])) {
246 $missingparents[$installedlang] = $parent;
250 if ($availablelangs = get_remote_list_of_languages()) {
254 $availablelangs = array();
255 echo $OUTPUT->box_start();
256 print_string('remotelangnotavailable', 'admin', $CFG->dataroot
.'/lang/');
257 echo $OUTPUT->box_end();
261 $info = implode('<br />', $notice_ok);
262 echo $OUTPUT->notification($info, 'notifysuccess');
266 $info = implode('<br />', $notice_error);
267 echo $OUTPUT->notification($info, 'notifyproblem');
270 if ($missingparents) {
271 foreach ($missingparents as $l=>$parent) {
273 $a->lang
= $installedlangs[$l];
274 $a->parent
= $parent;
275 foreach ($availablelangs as $alang) {
276 if ($alang[0] == $parent) {
277 $shortlang = $alang[0];
278 $a->parent
= $alang[2].' ('.$shortlang.')';
281 $info = get_string('missinglangparent', 'admin', $a);
282 echo $OUTPUT->notification($info, 'notifyproblem');
286 echo $OUTPUT->box_start();
288 echo html_writer
::start_tag('table');
289 echo html_writer
::start_tag('tr');
291 // list of installed languages
292 $url = new moodle_url('/admin/langimport.php', array('mode' => DELETION_OF_SELECTED_LANG
));
293 echo html_writer
::start_tag('td', array('valign' => 'top'));
294 echo html_writer
::start_tag('form', array('id' => 'uninstallform', 'action' => $url->out(), 'method' => 'post'));
295 echo html_writer
::start_tag('fieldset');
296 echo html_writer
::label(get_string('installedlangs','admin'), 'uninstalllang');
297 echo html_writer
::empty_tag('br');
298 echo html_writer
::select($installedlangs, 'uninstalllang', '', false, array('size' => 15));
299 echo html_writer
::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
300 echo html_writer
::empty_tag('br');
301 echo html_writer
::empty_tag('input', array('type' => 'submit', 'value' => get_string('uninstall','admin')));
302 echo html_writer
::end_tag('fieldset');
303 echo html_writer
::end_tag('form');
305 $url = new moodle_url('/admin/langimport.php', array('mode' => UPDATE_ALL_LANG
));
306 echo html_writer
::start_tag('form', array('id' => 'updateform', 'action' => $url->out(), 'method' => 'post'));
307 echo html_writer
::tag('fieldset', html_writer
::empty_tag('input', array('type' => 'submit', 'value' => get_string('updatelangs','admin'))));
308 echo html_writer
::end_tag('form');
310 echo html_writer
::end_tag('td');
312 // list of available languages
314 foreach ($availablelangs as $alang) {
315 if (!empty($alang[0]) and trim($alang[0]) !== 'en' and !is_installed_lang($alang[0], $alang[1])) {
316 $options[$alang[0]] = $alang[2].' ('.$alang[0].')';
319 if (!empty($options)) {
320 echo html_writer
::start_tag('td', array('valign' => 'top'));
321 $url = new moodle_url('/admin/langimport.php', array('mode' => INSTALLATION_OF_SELECTED_LANG
));
322 echo html_writer
::start_tag('form', array('id' => 'installform', 'action' => $url->out(), 'method' => 'post'));
323 echo html_writer
::start_tag('fieldset');
324 echo html_writer
::label(get_string('availablelangs','install'), 'pack');
325 echo html_writer
::empty_tag('br');
326 echo html_writer
::select($options, 'pack[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
327 echo html_writer
::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
328 echo html_writer
::empty_tag('br');
329 echo html_writer
::empty_tag('input', array('type' => 'submit', 'value' => get_string('install','admin')));
330 echo html_writer
::end_tag('fieldset');
331 echo html_writer
::end_tag('form');
332 echo html_writer
::end_tag('td');
335 echo html_writer
::end_tag('tr');
336 echo html_writer
::end_tag('table');
337 echo $OUTPUT->box_end();
338 echo $OUTPUT->footer();
341 ////////////////////////////////////////////////////////////////////////////////
342 // Local functions /////////////////////////////////////////////////////////////
343 ////////////////////////////////////////////////////////////////////////////////
346 * checks the md5 of the zip file, grabbed from download.moodle.org,
347 * against the md5 of the local language file from last update
348 * @param string $lang
349 * @param string $md5check
352 function is_installed_lang($lang, $md5check) {
354 $md5file = $CFG->dataroot
.'/lang/'.$lang.'/'.$lang.'.md5';
355 if (file_exists($md5file)){
356 return (file_get_contents($md5file) == $md5check);
362 * Returns the list of available language packs from download.moodle.org
364 * @return array|bool false if can not download
366 function get_remote_list_of_languages() {
367 $source = 'http://download.moodle.org/langpack/2.0/languages.md5';
368 $availablelangs = array();
370 if ($content = download_file_content($source)) {
371 $alllines = explode("\n", $content);
372 foreach($alllines as $line) {
374 $availablelangs[] = explode(',', $line);
377 return $availablelangs;