some changes/bugfixes
[phpbb.git] / phpBB / includes / acp / acp_language.php
blob5805318a93c0b5294d3e3e18eafcd85251f1ae37
1 <?php
2 /**
4 * @package acp
5 * @version $Id$
6 * @copyright (c) 2005 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
9 */
11 /**
12 * @package acp
14 class acp_language
16 var $u_action;
17 var $main_files;
18 var $language_header = '';
19 var $lang_header = '';
21 var $language_file = '';
22 var $language_directory = '';
24 function main($id, $mode)
26 global $config, $db, $user, $auth, $template, $cache;
27 global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
28 global $safe_mode, $file_uploads;
30 include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
32 $this->default_variables();
34 // Check and set some common vars
35 $action = request_var('action', '');
37 $action = (isset($_POST['update_details'])) ? 'update_details' : $action;
38 $action = (isset($_POST['download_file'])) ? 'download_file' : $action;
39 $action = (isset($_POST['upload_file'])) ? 'upload_file' : $action;
40 $action = (isset($_POST['upload_data'])) ? 'upload_data' : $action;
41 $action = (isset($_POST['submit_file'])) ? 'submit_file' : $action;
42 $action = (isset($_POST['remove_store'])) ? 'details' : $action;
44 $lang_id = request_var('id', 0);
45 if (isset($_POST['missing_file']))
47 $missing_file = request_var('missing_file', array('' => 0));
48 list($_REQUEST['language_file'], ) = array_keys($missing_file);
51 $selected_lang_file = request_var('language_file', '|common.' . $phpEx);
53 list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file);
55 $this->language_directory = basename($this->language_directory);
56 $this->language_file = basename($this->language_file);
58 $user->add_lang('acp/language');
59 $this->tpl_name = 'acp_language';
60 $this->page_title = 'ACP_LANGUAGE_PACKS';
62 if ($action == 'upload_data' && request_var('test_connection', ''))
64 $test_connection = false;
65 $action = 'upload_file';
66 $method = request_var('method', '');
68 include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx);
70 switch ($method)
72 case 'ftp':
73 $transfer = new ftp(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', ''));
74 break;
76 case 'ftp_fsock':
77 $transfer = new ftp_fsock(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', ''));
78 break;
80 default:
81 trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR);
82 break;
85 $test_connection = $transfer->open_session();
86 $transfer->close_session();
89 switch ($action)
91 case 'upload_file':
92 include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx);
94 $method = request_var('method', '');
96 $requested_data = call_user_func(array($method, 'data'));
97 foreach ($requested_data as $data => $default)
99 $template->assign_block_vars('data', array(
100 'DATA' => $data,
101 'NAME' => $user->lang[strtoupper($method . '_' . $data)],
102 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'],
103 'DEFAULT' => (!empty($_REQUEST[$data])) ? request_var($data, '') : $default
107 $hidden_data = build_hidden_fields(array(
108 'file' => $this->language_file,
109 'dir' => $this->language_directory,
110 'language_file' => $selected_lang_file,
111 'method' => $method)
114 $hidden_data .= build_hidden_fields(array('entry' => $_POST['entry']), true, STRIP);
116 $template->assign_vars(array(
117 'S_UPLOAD' => true,
118 'NAME' => $method,
119 'U_ACTION' => $this->u_action . "&amp;id=$lang_id&amp;action=upload_data",
120 'U_BACK' => $this->u_action . "&amp;id=$lang_id&amp;action=details&amp;language_file=" . urlencode($selected_lang_file),
121 'HIDDEN' => $hidden_data,
123 'S_CONNECTION_SUCCESS' => (request_var('test_connection', '') && $test_connection === true) ? true : false,
124 'S_CONNECTION_FAILED' => (request_var('test_connection', '') && $test_connection !== true) ? true : false
126 break;
128 case 'update_details':
130 if (!$lang_id)
132 trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
135 $sql = 'SELECT *
136 FROM ' . LANG_TABLE . "
137 WHERE lang_id = $lang_id";
138 $result = $db->sql_query($sql);
139 $row = $db->sql_fetchrow($result);
140 $db->sql_freeresult($result);
142 $sql_ary = array(
143 'lang_english_name' => request_var('lang_english_name', $row['lang_english_name']),
144 'lang_local_name' => request_var('lang_local_name', $row['lang_local_name'], true),
145 'lang_author' => request_var('lang_author', $row['lang_author'], true),
148 $db->sql_query('UPDATE ' . LANG_TABLE . '
149 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
150 WHERE lang_id = ' . $lang_id);
152 add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']);
154 trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action));
155 break;
157 case 'submit_file':
158 case 'download_file':
159 case 'upload_data':
161 if (!$lang_id || empty($_POST['entry']))
163 trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
166 if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files)))
168 trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
171 $sql = 'SELECT *
172 FROM ' . LANG_TABLE . "
173 WHERE lang_id = $lang_id";
174 $result = $db->sql_query($sql);
175 $row = $db->sql_fetchrow($result);
176 $db->sql_freeresult($result);
178 if (!$safe_mode)
180 $mkdir_ary = array('language', 'language/' . $row['lang_iso']);
182 if ($this->language_directory)
184 $mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory;
187 foreach ($mkdir_ary as $dir)
189 $dir = $phpbb_root_path . 'store/' . $dir;
191 if (!is_dir($dir))
193 if (!@mkdir($dir, 0777))
195 trigger_error("Could not create directory $dir", E_USER_ERROR);
197 @chmod($dir, 0777);
202 // Get target filename for storage folder
203 $filename = $this->get_filename($row['lang_iso'], $this->language_directory, $this->language_file, true, true);
204 $fp = fopen($phpbb_root_path . $filename, 'wb');
206 if (!$fp)
208 trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&amp;id=' . $lang_id . '&amp;action=details&amp;language_file=' . urlencode($selected_lang_file)), E_USER_WARNING);
211 if ($this->language_directory == 'email')
213 // Email Template
214 $entry = $this->prepare_lang_entry($_POST['entry'], false);
215 fwrite($fp, $entry);
217 else
219 $name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file;
220 $header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header);
222 if (strpos($this->language_file, 'help_') === 0)
224 // Help File
225 $header .= '$help = array(' . "\n";
226 fwrite($fp, $header);
228 foreach ($_POST['entry'] as $key => $value)
230 if (!is_array($value))
232 continue;
235 $entry = "\tarray(\n";
237 foreach ($value as $_key => $_value)
239 $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n";
242 $entry .= "\t),\n";
243 fwrite($fp, $entry);
246 $footer = ");\n\n?>";
247 fwrite($fp, $footer);
249 else
251 // Language File
252 $header .= $this->lang_header;
253 fwrite($fp, $header);
255 foreach ($_POST['entry'] as $key => $value)
257 $entry = $this->format_lang_array($key, $value);
258 fwrite($fp, $entry);
261 $footer = "));\n\n?>";
262 fwrite($fp, $footer);
266 fclose($fp);
268 if ($action == 'download_file')
270 header('Pragma: no-cache');
271 header('Content-Type: application/octetstream; name="' . $this->language_file . '"');
272 header('Content-disposition: attachment; filename=' . $this->language_file);
274 $fp = fopen($phpbb_root_path . $filename, 'rb');
275 while ($buffer = fread($fp, 1024))
277 echo $buffer;
279 fclose($fp);
281 add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file);
283 exit;
285 else if ($action == 'upload_data')
287 $sql = 'SELECT lang_iso
288 FROM ' . LANG_TABLE . "
289 WHERE lang_id = $lang_id";
290 $result = $db->sql_query($sql);
291 $row = $db->sql_fetchrow($result);
292 $db->sql_freeresult($result);
294 $file = request_var('file', '');
295 $dir = request_var('dir', '');
297 $selected_lang_file = $dir . '|' . $file;
299 $old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true);
300 $lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : '');
302 include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx);
303 $method = request_var('method', '');
305 if ($method != 'ftp' && $method != 'ftp_fsock')
307 trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR);
310 $transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', ''));
312 if (($result = $transfer->open_session()) !== true)
314 trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)), E_USER_WARNING);
317 $transfer->rename($lang_path . $file, $lang_path . $file . '.bak');
318 $result = $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file);
320 if ($result === false)
322 // If failed, try to rename again and print error out...
323 $transfer->delete_file($lang_path . $file);
324 $transfer->rename($lang_path . $file . '.bak', $lang_path . $file);
326 trigger_error($user->lang['UPLOAD_FAILED'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)), E_USER_WARNING);
329 $transfer->close_session();
331 // Remove from storage folder
332 @unlink($phpbb_root_path . 'store/' . $lang_path . $file);
334 add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file);
336 trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)));
339 add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file);
340 $action = 'details';
342 // no break;
344 case 'details':
346 if (!$lang_id)
348 trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
351 $this->page_title = 'LANGUAGE_PACK_DETAILS';
353 $sql = 'SELECT *
354 FROM ' . LANG_TABLE . '
355 WHERE lang_id = ' . $lang_id;
356 $result = $db->sql_query($sql);
357 $lang_entries = $db->sql_fetchrow($result);
358 $db->sql_freeresult($result);
360 $lang_iso = $lang_entries['lang_iso'];
361 $missing_vars = $missing_files = array();
363 // Get email templates
364 $email_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'email', 'txt');
365 $email_files = $email_files['email/'];
367 // Get acp files
368 $acp_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'acp', $phpEx);
369 $acp_files = $acp_files['acp/'];
371 // Get mod files
372 $mods_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'mods', $phpEx);
373 $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array();
375 // Check if our current filename matches the files
376 switch ($this->language_directory)
378 case 'email':
379 if (!in_array($this->language_file, $email_files))
381 trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
383 break;
385 case 'acp':
386 if (!in_array($this->language_file, $acp_files))
388 trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
390 break;
392 case 'mods':
393 if (!in_array($this->language_file, $mods_files))
395 trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
397 break;
399 default:
400 if (!in_array($this->language_file, $this->main_files))
402 trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
406 if (isset($_POST['remove_store']))
408 $store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true);
409 @unlink($phpbb_root_path . $store_filename);
412 include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx);
414 $methods = transfer::methods();
416 foreach ($methods as $method)
418 $template->assign_block_vars('buttons', array(
419 'VALUE' => $method
423 $template->assign_vars(array(
424 'S_DETAILS' => true,
425 'U_ACTION' => $this->u_action . "&amp;action=details&amp;id=$lang_id",
426 'U_BACK' => $this->u_action,
427 'LANG_LOCAL_NAME' => $lang_entries['lang_local_name'],
428 'LANG_ENGLISH_NAME' => $lang_entries['lang_english_name'],
429 'LANG_ISO' => $lang_entries['lang_iso'],
430 'LANG_AUTHOR' => $lang_entries['lang_author'],
431 'ALLOW_UPLOAD' => sizeof($methods)
435 // If current lang is different from the default lang, then first try to grab missing/additional vars
436 if ($lang_iso != $config['default_lang'])
438 $is_missing_var = false;
440 foreach ($this->main_files as $file)
442 if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file)))
444 $missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file);
446 if (sizeof($missing_vars[$file]))
448 $is_missing_var = true;
451 else
453 $missing_files[] = $this->get_filename($lang_iso, '', $file);
457 // Now go through acp/mods directories
458 foreach ($acp_files as $file)
460 if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'acp', $file)))
462 $missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file);
464 if (sizeof($missing_vars['acp/' . $file]))
466 $is_missing_var = true;
469 else
471 $missing_files[] = $this->get_filename($lang_iso, 'acp', $file);
475 if (sizeof($mods_files))
477 foreach ($mods_files as $file)
479 if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'mods', $file)))
481 $missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file);
483 if (sizeof($missing_vars['mods/' . $file]))
485 $is_missing_var = true;
488 else
490 $missing_files[] = $this->get_filename($lang_iso, 'mods', $file);
495 // More missing files... for example email templates?
496 foreach ($email_files as $file)
498 if (!file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'email', $file)))
500 $missing_files[] = $this->get_filename($lang_iso, 'email', $file);
504 if (sizeof($missing_files))
506 $template->assign_vars(array(
507 'S_MISSING_FILES' => true,
508 'L_MISSING_FILES' => sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']),
509 'MISSING_FILES' => implode('<br />', $missing_files))
513 if ($is_missing_var)
515 $template->assign_vars(array(
516 'S_MISSING_VARS' => true,
517 'L_MISSING_VARS_EXPLAIN' => sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']),
518 'U_MISSING_ACTION' => $this->u_action . "&amp;action=$action&amp;id=$lang_id")
521 foreach ($missing_vars as $file => $vars)
523 if (!sizeof($vars))
525 continue;
528 $template->assign_block_vars('missing', array(
529 'FILE' => $file,
530 'TPL' => $this->print_language_entries($vars, '', false),
531 'KEY' => (strpos($file, '/') === false) ? '|' . $file : str_replace('/', '|', $file))
537 // Main language files
538 $s_lang_options = '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['LANGUAGE_FILES'] . '</option>';
539 foreach ($this->main_files as $file)
541 if (strpos($file, 'help_') === 0)
543 continue;
546 $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : '';
548 $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : '';
549 $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>';
552 // Help Files
553 $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>';
554 foreach ($this->main_files as $file)
556 if (strpos($file, 'help_') !== 0)
558 continue;
561 $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : '';
563 $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : '';
564 $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>';
567 // Now every other language directory
568 $check_files = array('email', 'acp', 'mods');
570 foreach ($check_files as $check)
572 if (!sizeof(${$check . '_files'}))
574 continue;
577 $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>';
579 foreach (${$check . '_files'} as $file)
581 $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : '';
583 $selected = ($this->language_directory == $check && $this->language_file == $file) ? ' selected="selected"' : '';
584 $s_lang_options .= '<option value="' . $check . '|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>';
588 // Get Language Entries - if saved within store folder, we take this one (with the option to remove it)
589 $lang = array();
591 $is_email_file = ($this->language_directory == 'email') ? true : false;
592 $is_help_file = (strpos($this->language_file, 'help_') === 0) ? true : false;
594 $file_from_store = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true))) ? true : false;
595 $no_store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file);
597 if (!$file_from_store && !file_exists($phpbb_root_path . $no_store_filename))
599 $print_message = sprintf($user->lang['MISSING_LANGUAGE_FILE'], $no_store_filename);
601 else
603 if ($is_email_file)
605 $lang = file_get_contents($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store));
607 else
609 $help = array();
610 include($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store));
612 if ($is_help_file)
614 $lang = $help;
615 unset($help);
619 $print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file;
622 // Normal language pack entries
623 $template->assign_vars(array(
624 'U_ENTRY_ACTION' => $this->u_action . "&amp;action=details&amp;id=$lang_id#entries",
625 'S_EMAIL_FILE' => $is_email_file,
626 'S_FROM_STORE' => $file_from_store,
627 'S_LANG_OPTIONS' => $s_lang_options,
628 'PRINT_MESSAGE' => $print_message,
632 if (!$is_email_file)
634 $tpl = '';
635 $name = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file;
637 if (isset($missing_vars[$name]) && sizeof($missing_vars[$name]))
639 $tpl .= $this->print_language_entries($missing_vars[$name], '* ');
642 $tpl .= $this->print_language_entries($lang);
644 $template->assign_var('TPL', $tpl);
645 unset($tpl);
647 else
649 $template->assign_vars(array(
650 'LANG' => $lang)
653 unset($lang);
656 return;
658 break;
660 case 'delete':
662 if (!$lang_id)
664 trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
667 $sql = 'SELECT *
668 FROM ' . LANG_TABLE . '
669 WHERE lang_id = ' . $lang_id;
670 $result = $db->sql_query($sql);
671 $row = $db->sql_fetchrow($result);
672 $db->sql_freeresult($result);
674 if ($row['lang_iso'] == $config['default_lang'])
676 trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING);
679 $db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
681 $sql = 'UPDATE ' . USERS_TABLE . "
682 SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
683 WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
684 $db->sql_query($sql);
686 // We also need to remove the translated entries for custom profile fields - we want clean tables, don't we?
687 $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
688 $db->sql_query($sql);
690 $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;
691 $db->sql_query($sql);
693 add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
695 trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
696 break;
698 case 'install':
699 $lang_iso = request_var('iso', '');
700 $lang_iso = basename($lang_iso);
702 if (!$lang_iso || !file_exists("{$phpbb_root_path}language/$lang_iso/iso.txt"))
704 trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
707 $file = file("{$phpbb_root_path}language/$lang_iso/iso.txt");
709 $lang_pack = array(
710 'iso' => $lang_iso,
711 'name' => trim(htmlspecialchars($file[0])),
712 'local_name'=> trim(htmlspecialchars($file[1], ENT_COMPAT, 'UTF-8')),
713 'author' => trim(htmlspecialchars($file[2], ENT_COMPAT, 'UTF-8'))
715 unset($file);
717 $sql = 'SELECT lang_iso
718 FROM ' . LANG_TABLE . "
719 WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'";
720 $result = $db->sql_query($sql);
721 $row = $db->sql_fetchrow($result);
722 $db->sql_freeresult($result);
724 if ($row)
726 trigger_error($user->lang['LANGUAGE_PACK_ALREADY_INSTALLED'] . adm_back_link($this->u_action), E_USER_WARNING);
729 if (!$lang_pack['name'] || !$lang_pack['local_name'])
731 trigger_error($user->lang['INVALID_LANGUAGE_PACK'] . adm_back_link($this->u_action), E_USER_WARNING);
734 // Add language pack
735 $sql_ary = array(
736 'lang_iso' => $lang_pack['iso'],
737 'lang_dir' => $lang_pack['iso'],
738 'lang_english_name' => $lang_pack['name'],
739 'lang_local_name' => $lang_pack['local_name'],
740 'lang_author' => $lang_pack['author']
743 $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
744 $lang_id = $db->sql_nextid();
746 // Now let's copy the default language entries for custom profile fields for this new language - makes admin's life easier.
747 $sql = 'SELECT lang_id
748 FROM ' . LANG_TABLE . "
749 WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
750 $result = $db->sql_query($sql);
751 $default_lang_id = (int) $db->sql_fetchfield('lang_id');
752 $db->sql_freeresult($result);
754 // From the mysql documentation:
755 // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
756 // Due to this we stay on the safe side if we do the insertion "the manual way"
758 $sql = 'SELECT field_id, lang_name, lang_explain, lang_default_value
759 FROM ' . PROFILE_LANG_TABLE . '
760 WHERE lang_id = ' . $default_lang_id;
761 $result = $db->sql_query($sql);
763 while ($row = $db->sql_fetchrow($result))
765 $row['lang_id'] = $lang_id;
766 $db->sql_query('INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row));
768 $db->sql_freeresult($result);
770 $sql = 'SELECT field_id, option_id, field_type, lang_value
771 FROM ' . PROFILE_FIELDS_LANG_TABLE . '
772 WHERE lang_id = ' . $default_lang_id;
773 $result = $db->sql_query($sql);
775 while ($row = $db->sql_fetchrow($result))
777 $row['lang_id'] = $lang_id;
778 $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row));
780 $db->sql_freeresult($result);
782 add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']);
784 trigger_error(sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']) . adm_back_link($this->u_action));
786 break;
788 case 'download':
790 if (!$lang_id)
792 trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
795 $sql = 'SELECT *
796 FROM ' . LANG_TABLE . '
797 WHERE lang_id = ' . $lang_id;
798 $result = $db->sql_query($sql);
799 $row = $db->sql_fetchrow($result);
800 $db->sql_freeresult($result);
802 $use_method = request_var('use_method', '');
803 $methods = array('.tar');
805 $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
806 foreach ($available_methods as $type => $module)
808 if (!@extension_loaded($module))
810 continue;
813 $methods[] = $type;
816 // Let the user decide in which format he wants to have the pack
817 if (!$use_method)
819 $this->page_title = 'SELECT_DOWNLOAD_FORMAT';
821 $radio_buttons = '';
822 foreach ($methods as $method)
824 $radio_buttons .= '<input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" />&nbsp;' . $method . '&nbsp;';
827 $template->assign_vars(array(
828 'S_SELECT_METHOD' => true,
829 'U_BACK' => $this->u_action,
830 'U_ACTION' => $this->u_action . "&amp;action=$action&amp;id=$lang_id",
831 'RADIO_BUTTONS' => $radio_buttons)
834 return;
837 if (!in_array($use_method, $methods))
839 $use_method = '.tar';
842 include_once($phpbb_root_path . 'includes/functions_compress.' . $phpEx);
844 if ($use_method == '.zip')
846 $compress = new compress_zip('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method);
848 else
850 $compress = new compress_tar('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method, $use_method);
853 // Get email templates
854 $email_templates = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt');
855 $email_templates = $email_templates['email/'];
857 // Get acp files
858 $acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx);
859 $acp_files = $acp_files['acp/'];
861 // Get mod files
862 $mod_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx);
863 $mod_files = (isset($mod_files['mods/'])) ? $mod_files['mods/'] : array();
865 // Add main files
866 $this->add_to_archive($compress, $this->main_files, $row['lang_iso']);
868 // Add search files if they exist...
869 if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_ignore_words.' . $phpEx))
871 $this->add_to_archive($compress, array("search_ignore_words.$phpEx"), $row['lang_iso']);
874 if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_synonyms.' . $phpEx))
876 $this->add_to_archive($compress, array("search_synonyms.$phpEx"), $row['lang_iso']);
879 // Write files in folders
880 $this->add_to_archive($compress, $email_templates, $row['lang_iso'], 'email');
881 $this->add_to_archive($compress, $acp_files, $row['lang_iso'], 'acp');
882 $this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods');
884 // Write ISO File
885 $iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n";
886 $iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n";
887 $iso_src .= htmlspecialchars_decode($row['lang_author']);
888 $compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt');
890 // index.html files
891 $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.html');
892 $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.html');
893 $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.html');
895 if (sizeof($mod_files))
897 $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.html');
900 $compress->close();
902 $compress->download('lang_' . $row['lang_iso']);
903 @unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method);
905 exit;
907 break;
910 $sql = 'SELECT user_lang, COUNT(user_lang) AS lang_count
911 FROM ' . USERS_TABLE . '
912 GROUP BY user_lang';
913 $result = $db->sql_query($sql);
915 $lang_count = array();
916 while ($row = $db->sql_fetchrow($result))
918 $lang_count[$row['user_lang']] = $row['lang_count'];
920 $db->sql_freeresult($result);
922 $sql = 'SELECT *
923 FROM ' . LANG_TABLE . '
924 ORDER BY lang_english_name';
925 $result = $db->sql_query($sql);
927 $installed = array();
929 while ($row = $db->sql_fetchrow($result))
931 $installed[] = $row['lang_iso'];
932 $tagstyle = ($row['lang_iso'] == $config['default_lang']) ? '*' : '';
934 $template->assign_block_vars('lang', array(
935 'U_DETAILS' => $this->u_action . "&amp;action=details&amp;id={$row['lang_id']}",
936 'U_DOWNLOAD' => $this->u_action . "&amp;action=download&amp;id={$row['lang_id']}",
937 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;id={$row['lang_id']}",
939 'ENGLISH_NAME' => $row['lang_english_name'],
940 'TAG' => $tagstyle,
941 'LOCAL_NAME' => $row['lang_local_name'],
942 'ISO' => $row['lang_iso'],
943 'USED_BY' => (isset($lang_count[$row['lang_iso']])) ? $lang_count[$row['lang_iso']] : 0,
946 $db->sql_freeresult($result);
948 $new_ary = $iso = array();
949 $dp = @opendir("{$phpbb_root_path}language");
951 if ($dp)
953 while (($file = readdir($dp)) !== false)
955 if ($file[0] != '.' && file_exists("{$phpbb_root_path}language/$file/iso.txt"))
957 if (!in_array($file, $installed))
959 if ($iso = file("{$phpbb_root_path}language/$file/iso.txt"))
961 if (sizeof($iso) == 3)
963 $new_ary[$file] = array(
964 'iso' => $file,
965 'name' => trim($iso[0]),
966 'local_name'=> trim($iso[1]),
967 'author' => trim($iso[2])
974 closedir($dp);
977 unset($installed);
979 if (sizeof($new_ary))
981 foreach ($new_ary as $iso => $lang_ary)
983 $template->assign_block_vars('notinst', array(
984 'ISO' => htmlspecialchars($lang_ary['iso']),
985 'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'),
986 'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'),
987 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;iso=' . urlencode($lang_ary['iso']))
992 unset($new_ary);
997 * Set default language variables/header
999 function default_variables()
1001 global $phpEx;
1003 $this->language_file_header = '<?php
1004 /**
1006 * {FILENAME} [{LANG_NAME}]
1008 * @package language
1009 * @version $' . 'Id: ' . '$
1010 * @copyright (c) ' . date('Y') . ' phpBB Group
1011 * @author {CHANGED} - {AUTHOR}
1012 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
1017 * DO NOT CHANGE
1019 if (empty($lang) || !is_array($lang))
1021 $lang = array();
1024 // DEVELOPERS PLEASE NOTE
1026 // All language files should use UTF-8 as their encoding and the files must not contain a BOM.
1028 // Placeholders can now contain order information, e.g. instead of
1029 // \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows
1030 // translators to re-order the output of data while ensuring it remains correct
1032 // You do not need this where single placeholders are used, e.g. \'Message %d\' is fine
1033 // equally where a string contains only two placeholders which are used to wrap text
1034 // in a url you again do not need to specify an order e.g., \'Click %sHERE%s\' is fine
1037 $this->lang_header = '
1038 $lang = array_merge($lang, array(
1041 // Language files in language root directory
1042 $this->main_files = array("common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx");
1046 * Get filename/location of language file
1048 function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false)
1050 global $phpbb_root_path, $safe_mode;
1052 $check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename;
1054 if ($check_store)
1056 $check_store_filename = ($safe_mode) ? "store/langfile_{$lang_iso}" . (($directory) ? '_' . $directory : '') . "_{$filename}" : "store/language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename;
1058 if (!$only_return_filename && file_exists($phpbb_root_path . $check_store_filename))
1060 return $check_store_filename;
1062 else if ($only_return_filename)
1064 return $check_store_filename;
1068 return $check_filename;
1072 * Add files to archive
1074 function add_to_archive(&$compress, $filelist, $lang_iso, $directory = '')
1076 global $phpbb_root_path;
1078 foreach ($filelist as $file)
1080 // Get source filename
1081 $source = $this->get_filename($lang_iso, $directory, $file, true);
1082 $destination = 'language/' . $lang_iso . '/' . (($directory) ? $directory . '/' : '') . $file;
1084 // Add file to archive
1085 $compress->add_custom_file($phpbb_root_path . $source, $destination);
1090 * Little helper to add some hardcoded template bits
1092 function add_input_field()
1094 $keys = func_get_args();
1096 $non_static = array_shift($keys);
1097 $value = array_shift($keys);
1099 if (!$non_static)
1101 return '<strong>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</strong>';
1104 // If more then 270 characters, then we present a textarea, else an input field
1105 $textarea = (utf8_strlen($value) > 270) ? true : false;
1106 $tpl = '';
1108 $tpl .= ($textarea) ? '<textarea name="' : '<input type="text" name="';
1109 $tpl .= 'entry[' . implode('][', array_map('utf8_htmlspecialchars', $keys)) . ']"';
1111 $tpl .= ($textarea) ? ' cols="80" rows="5" class="langvalue">' : ' class="langvalue" value="';
1112 $tpl .= htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
1113 $tpl .= ($textarea) ? '</textarea>' : '" />';
1115 return $tpl;
1119 * Print language entries
1121 function print_language_entries(&$lang_ary, $key_prefix = '', $input_field = true)
1123 $tpl = '';
1125 foreach ($lang_ary as $key => $value)
1127 if (is_array($value))
1129 // Write key
1130 $tpl .= '
1131 <tr>
1132 <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td>
1133 </tr>';
1135 foreach ($value as $_key => $_value)
1137 if (is_array($_value))
1139 // Write key
1140 $tpl .= '
1141 <tr>
1142 <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '&nbsp; &nbsp;<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td>
1143 </tr>';
1145 foreach ($_value as $__key => $__value)
1147 // Write key
1148 $tpl .= '
1149 <tr>
1150 <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</strong></td>
1151 <td class="row2">';
1153 $tpl .= $this->add_input_field($input_field, $__value, $key, $_key, $__key);
1155 $tpl .= '</td>
1156 </tr>';
1159 else
1161 // Write key
1162 $tpl .= '
1163 <tr>
1164 <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td>
1165 <td class="row2">';
1167 $tpl .= $this->add_input_field($input_field, $_value, $key, $_key);
1169 $tpl .= '</td>
1170 </tr>';
1174 $tpl .= '
1175 <tr>
1176 <td class="spacer" colspan="2">&nbsp;</td>
1177 </tr>';
1179 else
1181 // Write key
1182 $tpl .= '
1183 <tr>
1184 <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td>
1185 <td class="row2">';
1187 $tpl .= $this->add_input_field($input_field, $value, $key);
1189 $tpl .= '</td>
1190 </tr>';
1194 return $tpl;
1198 * Compare two language files
1200 function compare_language_files($source_lang, $dest_lang, $directory, $file)
1202 global $phpbb_root_path, $phpEx;
1204 $return_ary = array();
1206 $lang = array();
1207 include("{$phpbb_root_path}language/{$source_lang}/" . (($directory) ? $directory . '/' : '') . $file);
1208 $lang_entry_src = $lang;
1210 $lang = array();
1212 if (!file_exists($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true)))
1214 return array();
1217 include($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true));
1219 $lang_entry_dst = $lang;
1221 unset($lang);
1223 $diff_array_keys = array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst));
1224 unset($lang_entry_dst);
1226 foreach ($diff_array_keys as $key)
1228 $return_ary[$key] = $lang_entry_src[$key];
1231 unset($lang_entry_src);
1233 return $return_ary;
1237 * Return language string value for storage
1239 function prepare_lang_entry($text, $store = true)
1241 $text = (STRIP) ? stripslashes($text) : $text;
1243 // Adjust for storage...
1244 if ($store)
1246 $text = str_replace("'", "\\'", str_replace('\\', '\\\\', $text));
1249 return $text;
1253 * Format language array for storage
1255 function format_lang_array($key, $value, $tabs = "\t")
1257 $entry = '';
1259 if (!is_array($value))
1261 $entry .= "{$tabs}'{$key}'\t=> '" . $this->prepare_lang_entry($value) . "',\n";
1263 else
1265 $_tabs = $tabs . "\t";
1266 $entry .= "\n{$tabs}'{$key}'\t=> array(\n";
1268 foreach ($value as $_key => $_value)
1270 $entry .= $this->format_lang_array($_key, $_value, $_tabs);
1273 $entry .= "{$tabs}),\n\n";
1276 return $entry;