From 20f3e62a5004328ae5db8cc1bc28490b3fce799a Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Thu, 1 Aug 2013 17:23:26 +0000
Subject: [PATCH] Make default data translatable

This is one of the last major hurdles to make osTicket fully translatable.
With the advent of 1.7.0, database migration is based on the MD5 hash of the
install SQL file. Therefore, the install SQL script cannot be modified (ie.
translated) or else the system cannot be migrated, since the MD5 hash will
no longer match up.

This patch pulls initial data out of the install file so that it can be
translatable. Eventually the install worksheet can allow a drop-down box of
the default system language. The default data from that language will be
loaded into the system.
---
 bootstrap.php                                 | 237 ++++++++++++++++++
 client.inc.php                                |   2 +-
 include/class.dept.php                        |  18 +-
 include/class.filter.php                      |   9 +-
 include/class.i18n.php                        | 174 +++++++++++++
 include/class.sla.php                         |   3 +
 include/class.template.php                    |  29 ++-
 include/i18n/README.md                        |  31 +++
 include/i18n/en_US/config.yaml                |  16 ++
 include/i18n/en_US/department.yaml            |  32 +++
 include/i18n/en_US/email_template_group.yaml  |  19 ++
 include/i18n/en_US/filter.yaml                |  37 +++
 include/i18n/en_US/group.yaml                 |  81 ++++++
 include/i18n/en_US/help_topic.yaml            |  38 +++
 include/i18n/en_US/priority.yaml              |  24 ++
 include/i18n/en_US/sla.yaml                   |  22 ++
 include/i18n/en_US/team.yaml                  |  16 ++
 .../en_US/templates/email/assigned.alert.yaml |  32 +++
 .../en_US/templates/email/message.alert.yaml  |  34 +++
 .../templates/email/message.autoresp.yaml     |  24 ++
 .../en_US/templates/email/note.alert.yaml     |  31 +++
 .../templates/{ => email}/staff.pwreset.yaml  |   7 +-
 .../en_US/templates/email/ticket.alert.yaml   |  32 +++
 .../templates/email/ticket.autoreply.yaml     |  30 +++
 .../templates/email/ticket.autoresp.yaml      |  25 ++
 .../en_US/templates/email/ticket.notice.yaml  |  27 ++
 .../en_US/templates/email/ticket.overdue.yaml |  29 +++
 .../templates/email/ticket.overlimit.yaml     |  30 +++
 .../en_US/templates/email/ticket.reply.yaml   |  30 +++
 .../en_US/templates/email/transfer.alert.yaml |  31 +++
 .../i18n/en_US/templates/page/landing.yaml    |  23 ++
 .../i18n/en_US/templates/page/offline.yaml    |  21 ++
 .../i18n/en_US/templates/page/thank-you.yaml  |  20 ++
 include/i18n/en_US/templates/premade.yaml     |  24 ++
 include/staff/tpl.inc.php                     |   8 +-
 include/upgrader/streams/core.sig             |   2 +-
 .../streams/core/16fcef4a-43fbf5b9.patch.sql  |  25 ++
 main.inc.php                                  | 215 +---------------
 setup/inc/class.installer.php                 |   6 +
 setup/inc/streams/core/install-mysql.sql      | 111 +-------
 setup/setup.inc.php                           |  17 +-
 41 files changed, 1266 insertions(+), 356 deletions(-)
 create mode 100644 bootstrap.php
 create mode 100644 include/class.i18n.php
 create mode 100644 include/i18n/README.md
 create mode 100644 include/i18n/en_US/config.yaml
 create mode 100644 include/i18n/en_US/department.yaml
 create mode 100644 include/i18n/en_US/email_template_group.yaml
 create mode 100644 include/i18n/en_US/filter.yaml
 create mode 100644 include/i18n/en_US/group.yaml
 create mode 100644 include/i18n/en_US/help_topic.yaml
 create mode 100644 include/i18n/en_US/priority.yaml
 create mode 100644 include/i18n/en_US/sla.yaml
 create mode 100644 include/i18n/en_US/team.yaml
 create mode 100644 include/i18n/en_US/templates/email/assigned.alert.yaml
 create mode 100644 include/i18n/en_US/templates/email/message.alert.yaml
 create mode 100644 include/i18n/en_US/templates/email/message.autoresp.yaml
 create mode 100644 include/i18n/en_US/templates/email/note.alert.yaml
 rename include/i18n/en_US/templates/{ => email}/staff.pwreset.yaml (78%)
 create mode 100644 include/i18n/en_US/templates/email/ticket.alert.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.autoreply.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.autoresp.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.notice.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.overdue.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.overlimit.yaml
 create mode 100644 include/i18n/en_US/templates/email/ticket.reply.yaml
 create mode 100644 include/i18n/en_US/templates/email/transfer.alert.yaml
 create mode 100644 include/i18n/en_US/templates/page/landing.yaml
 create mode 100644 include/i18n/en_US/templates/page/offline.yaml
 create mode 100644 include/i18n/en_US/templates/page/thank-you.yaml
 create mode 100644 include/i18n/en_US/templates/premade.yaml
 create mode 100644 include/upgrader/streams/core/16fcef4a-43fbf5b9.patch.sql

diff --git a/bootstrap.php b/bootstrap.php
new file mode 100644
index 000000000..9f7e49e9e
--- /dev/null
+++ b/bootstrap.php
@@ -0,0 +1,237 @@
+<?php
+
+#Set Dir constants
+$here = substr(realpath(dirname(__file__)),
+    strlen($_SERVER['DOCUMENT_ROOT']));
+// Determine the path in the URI used as the base of the osTicket
+// installation
+if (!defined('ROOT_PATH'))
+    define('ROOT_PATH', str_replace('\\', '/', $here.'/')); //root path. Damn directories
+
+#Get real path for root dir ---linux and windows
+define('ROOT_DIR',str_replace('\\', '/', realpath(dirname(__FILE__))).'/');
+define('INCLUDE_DIR',ROOT_DIR.'include/'); //Change this if include is moved outside the web path.
+define('PEAR_DIR',INCLUDE_DIR.'pear/');
+define('SETUP_DIR',ROOT_DIR.'setup/');
+
+define('UPGRADE_DIR', INCLUDE_DIR.'upgrader/');
+define('I18N_DIR', INCLUDE_DIR.'i18n/');
+
+class Bootstrap {
+
+    function init() {
+        #Disable Globals if enabled....before loading config info
+        if(ini_get('register_globals')) {
+           ini_set('register_globals',0);
+           foreach($_REQUEST as $key=>$val)
+               if(isset($$key))
+                   unset($$key);
+        }
+
+        #Disable url fopen && url include
+        ini_set('allow_url_fopen', 0);
+        ini_set('allow_url_include', 0);
+
+        #Disable session ids on url.
+        ini_set('session.use_trans_sid', 0);
+        #No cache
+        session_cache_limiter('nocache');
+        #Cookies
+        # TODO: Determine root path
+        session_set_cookie_params(86400, dirname($_SERVER['PHP_SELF']),
+            $_SERVER['HTTP_HOST'], self::https());
+
+        #Error reporting...Good idea to ENABLE error reporting to a file. i.e display_errors should be set to false
+        $error_reporting = E_ALL & ~E_NOTICE;
+        if (defined('E_STRICT')) # 5.4.0
+            $error_reporting &= ~E_STRICT;
+        if (defined('E_DEPRECATED')) # 5.3.0
+            $error_reporting &= ~(E_DEPRECATED | E_USER_DEPRECATED);
+        error_reporting($error_reporting); //Respect whatever is set in php.ini (sysadmin knows better??)
+
+        #Don't display errors
+        ini_set('display_errors', 1);
+        ini_set('display_startup_errors', 1);
+
+        //Default timezone
+        if (!ini_get('date.timezone')) {
+            if(function_exists('date_default_timezone_set')) {
+                if(@date_default_timezone_get()) //Let PHP determine the timezone.
+                    @date_default_timezone_set(@date_default_timezone_get());
+                else //Default to EST - if PHP can't figure it out.
+                    date_default_timezone_set('America/New_York');
+            } else { //Default when all fails. PHP < 5.
+                ini_set('date.timezone', 'America/New_York');
+            }
+        }
+    }
+
+    function https() {
+       return
+            (isset($_SERVER['HTTPS'])
+                && strtolower($_SERVER['HTTPS']) == 'on')
+            || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
+                && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https');
+    }
+
+    function defineTables($prefix) {
+        #Tables being used sytem wide
+        define('SYSLOG_TABLE',$prefix.'syslog');
+        define('SESSION_TABLE',$prefix.'session');
+        define('CONFIG_TABLE',$prefix.'config');
+
+        define('CANNED_TABLE',$prefix.'canned_response');
+        define('CANNED_ATTACHMENT_TABLE',$prefix.'canned_attachment');
+        define('PAGE_TABLE', $prefix.'page');
+        define('FILE_TABLE',$prefix.'file');
+        define('FILE_CHUNK_TABLE',$prefix.'file_chunk');
+
+        define('STAFF_TABLE',$prefix.'staff');
+        define('TEAM_TABLE',$prefix.'team');
+        define('TEAM_MEMBER_TABLE',$prefix.'team_member');
+        define('DEPT_TABLE',$prefix.'department');
+        define('GROUP_TABLE',$prefix.'groups');
+        define('GROUP_DEPT_TABLE', $prefix.'group_dept_access');
+
+        define('FAQ_TABLE',$prefix.'faq');
+        define('FAQ_ATTACHMENT_TABLE',$prefix.'faq_attachment');
+        define('FAQ_TOPIC_TABLE',$prefix.'faq_topic');
+        define('FAQ_CATEGORY_TABLE',$prefix.'faq_category');
+
+        define('TICKET_TABLE',$prefix.'ticket');
+        define('TICKET_THREAD_TABLE',$prefix.'ticket_thread');
+        define('TICKET_ATTACHMENT_TABLE',$prefix.'ticket_attachment');
+        define('TICKET_LOCK_TABLE',$prefix.'ticket_lock');
+        define('TICKET_EVENT_TABLE',$prefix.'ticket_event');
+        define('TICKET_EMAIL_INFO_TABLE',$prefix.'ticket_email_info');
+        define('TICKET_PRIORITY_TABLE',$prefix.'ticket_priority');
+        define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
+
+        define('TOPIC_TABLE',$prefix.'help_topic');
+        define('SLA_TABLE', $prefix.'sla');
+
+        define('EMAIL_TABLE',$prefix.'email');
+        define('EMAIL_TEMPLATE_GRP_TABLE',$prefix.'email_template_group');
+        define('EMAIL_TEMPLATE_TABLE',$prefix.'email_template');
+
+        define('FILTER_TABLE', $prefix.'filter');
+        define('FILTER_RULE_TABLE', $prefix.'filter_rule');
+
+        define('API_KEY_TABLE',$prefix.'api_key');
+        define('TIMEZONE_TABLE',$prefix.'timezone');
+    }
+
+    function loadConfig() {
+        #load config info
+        $configfile='';
+        if(file_exists(INCLUDE_DIR.'ost-config.php')) //NEW config file v 1.6 stable ++
+            $configfile=INCLUDE_DIR.'ost-config.php';
+        elseif(file_exists(ROOT_DIR.'ostconfig.php')) //Old installs prior to v 1.6 RC5
+            $configfile=ROOT_DIR.'ostconfig.php';
+        elseif(file_exists(INCLUDE_DIR.'settings.php')) { //OLD config file.. v 1.6 RC5
+            $configfile=INCLUDE_DIR.'settings.php';
+            //Die gracefully on upgraded v1.6 RC5 installation - otherwise script dies with confusing message.
+            if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']), 'settings.php'))
+                die('Please rename config file include/settings.php to include/ost-config.php to continue!');
+        } elseif(file_exists(ROOT_DIR.'setup/'))
+            header('Location: '.ROOT_PATH.'setup/');
+
+        if(!$configfile || !file_exists($configfile)) die('<b>Error loading settings. Contact admin.</b>');
+
+        require($configfile);
+        define('CONFIG_FILE',$configfile); //used in admin.php to check perm.
+
+        # This is to support old installations. with no secret salt.
+        if (!defined('SECRET_SALT'))
+            define('SECRET_SALT',md5(TABLE_PREFIX.ADMIN_EMAIL));
+        #Session related
+        define('SESSION_SECRET', MD5(SECRET_SALT)); //Not that useful anymore...
+        define('SESSION_TTL', 86400); // Default 24 hours
+    }
+
+    function connect() {
+        #Connect to the DB && get configuration from database
+        $ferror=null;
+        $options = array();
+        if (defined('DBSSLCA'))
+            $options['ssl'] = array(
+                'ca' => DBSSLCA,
+                'cert' => DBSSLCERT,
+                'key' => DBSSLKEY
+            );
+
+        if (!db_connect(DBHOST, DBUSER, DBPASS, $options)) {
+            $ferror='Unable to connect to the database -'.db_connect_error();
+        }elseif(!db_select_database(DBNAME)) {
+            $ferror='Unknown or invalid database '.DBNAME;
+        }
+
+        if($ferror) //Fatal error
+            self::croak($ferror);
+    }
+
+    function croak($message) {
+        $msg=$ferror."\n\n".THISPAGE;
+        Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg, sprintf('"osTicket Alerts"<%s>', ADMIN_EMAIL));
+        //Display generic error to the user
+        die("<b>Fatal Error:</b> Contact system administrator.");
+        exit;
+    }
+}
+
+Bootstrap::init();
+
+/*############## Do NOT monkey with anything else beyond this point UNLESS you really know what you are doing ##############*/
+
+#Current version && schema signature (Changes from version to version)
+define('THIS_VERSION','1.7.0+'); //Shown on admin panel
+//Path separator
+if(!defined('PATH_SEPARATOR')){
+    if(strpos($_ENV['OS'],'Win')!==false || !strcasecmp(substr(PHP_OS, 0, 3),'WIN'))
+        define('PATH_SEPARATOR', ';' ); //Windows
+    else
+        define('PATH_SEPARATOR',':'); //Linux
+}
+
+//Set include paths. Overwrite the default paths.
+ini_set('include_path', './'.PATH_SEPARATOR.INCLUDE_DIR.PATH_SEPARATOR.PEAR_DIR);
+
+#include required files
+require(INCLUDE_DIR.'class.osticket.php');
+require(INCLUDE_DIR.'class.ostsession.php');
+require(INCLUDE_DIR.'class.usersession.php');
+require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
+require(INCLUDE_DIR.'class.log.php');
+require(INCLUDE_DIR.'class.mcrypt.php');
+require(INCLUDE_DIR.'class.misc.php');
+require(INCLUDE_DIR.'class.timezone.php');
+require(INCLUDE_DIR.'class.http.php');
+require(INCLUDE_DIR.'class.signal.php');
+require(INCLUDE_DIR.'class.nav.php');
+require(INCLUDE_DIR.'class.page.php');
+require(INCLUDE_DIR.'class.format.php'); //format helpers
+require(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
+require(INCLUDE_DIR.'class.mailer.php');
+if (extension_loaded('mysqli'))
+    require_once INCLUDE_DIR.'mysqli.php';
+else
+    require(INCLUDE_DIR.'mysql.php');
+
+#CURRENT EXECUTING SCRIPT.
+define('THISPAGE', Misc::currentURL());
+define('THISURI', $_SERVER['REQUEST_URI']);
+
+#Cookies
+session_set_cookie_params(86400, ROOT_PATH, $_SERVER['HTTP_HOST'],
+    osTicket::is_https());
+
+define('DEFAULT_MAX_FILE_UPLOADS',ini_get('max_file_uploads')?ini_get('max_file_uploads'):5);
+define('DEFAULT_PRIORITY_ID',1);
+
+define('EXT_TICKET_ID_LEN',6); //Ticket create. when you start getting collisions. Applies only on random ticket ids.
+
+#Global overwrite
+if($_SERVER['HTTP_X_FORWARDED_FOR']) //Can contain multiple IPs - use the last one.
+    $_SERVER['REMOTE_ADDR'] =  array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
+
+?>
diff --git a/client.inc.php b/client.inc.php
index 262b8680c..85c9624bb 100644
--- a/client.inc.php
+++ b/client.inc.php
@@ -15,7 +15,7 @@
 **********************************************************************/
 if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!');
 
-$thisdir=str_replace('\\\\', '/', realpath(dirname(__FILE__))).'/'; 
+$thisdir=str_replace('\\', '/', realpath(dirname(__FILE__))).'/';
 if(!file_exists($thisdir.'main.inc.php')) die('Fatal Error.');
 
 require_once($thisdir.'main.inc.php');
diff --git a/include/class.dept.php b/include/class.dept.php
index 8e34e2ba4..1d838be2b 100644
--- a/include/class.dept.php
+++ b/include/class.dept.php
@@ -351,7 +351,8 @@ class Dept {
         if($id && $id!=$vars['id'])
             $errors['err']='Missing or invalid Dept ID (internal error).';
 
-        if(!$vars['email_id'] || !is_numeric($vars['email_id']))
+        if(!isset($vars['id'])
+                && (!$vars['email_id'] || !is_numeric($vars['email_id'])))
             $errors['email_id']='Email selection required';
 
         if(!is_numeric($vars['tpl_id']))
@@ -365,18 +366,18 @@ class Dept {
             $errors['name']='Department already exists';
         }
 
-        if(!$vars['ispublic'] && ($vars['id']==$cfg->getDefaultDeptId()))
+        if(!$vars['ispublic'] && $cfg && ($vars['id']==$cfg->getDefaultDeptId()))
             $errors['ispublic']='System default department cannot be private';
 
         if($errors) return false;
 
 
         $sql='SET updated=NOW() '
-            .' ,ispublic='.db_input($vars['ispublic'])
-            .' ,email_id='.db_input($vars['email_id'])
-            .' ,tpl_id='.db_input($vars['tpl_id'])
-            .' ,sla_id='.db_input($vars['sla_id'])
-            .' ,autoresp_email_id='.db_input($vars['autoresp_email_id'])
+            .' ,ispublic='.db_input(isset($vars['ispublic'])?$vars['ispublic']:0)
+            .' ,email_id='.db_input(isset($vars['email_id'])?$vars['email_id']:0)
+            .' ,tpl_id='.db_input(isset($vars['tpl_id'])?$vars['tpl_id']:0)
+            .' ,sla_id='.db_input(isset($vars['sla_id'])?$vars['sla_id']:0)
+            .' ,autoresp_email_id='.db_input(isset($vars['autoresp_email_id'])?$vars['autoresp_email_id']:0)
             .' ,manager_id='.db_input($vars['manager_id']?$vars['manager_id']:0)
             .' ,dept_name='.db_input(Format::striptags($vars['name']))
             .' ,dept_signature='.db_input(Format::striptags($vars['signature']))
@@ -393,6 +394,9 @@ class Dept {
             $errors['err']='Unable to update '.Format::htmlchars($vars['name']).' Dept. Error occurred';
 
         } else {
+            if (isset($vars['id']))
+                $sql .= ', dept_id='.db_input($vars['id']);
+
             $sql='INSERT INTO '.DEPT_TABLE.' '.$sql.',created=NOW()';
             if(db_query($sql) && ($id=db_insert_id()))
                 return $id;
diff --git a/include/class.filter.php b/include/class.filter.php
index 182e47ca0..5ee3f1bca 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -385,7 +385,8 @@ class Filter {
                 elseif($vars["rule_w$i"]=='email' && $vars["rule_h$i"]=='equal' && !Validator::is_email($vars["rule_v$i"]))
                     $errors["rule_$i"]='Valid email required for the match type';
                 else //for everything-else...we assume it's valid.
-                    $rules[]=array('w'=>$vars["rule_w$i"],'h'=>$vars["rule_h$i"],'v'=>$vars["rule_v$i"]);
+                    $rules[]=array('what'=>$vars["rule_w$i"],
+                        'how'=>$vars["rule_h$i"],'val'=>$vars["rule_v$i"]);
             }elseif($vars["rule_v$i"]) {
                 $errors["rule_$i"]='Incomplete selection';
             }
@@ -581,9 +582,9 @@ class FilterRule {
         if($errors) return false;
 
         $sql=' updated=NOW() '.
-             ',what='.db_input($vars['w']).
-             ',how='.db_input($vars['h']).
-             ',val='.db_input($vars['v']).
+             ',what='.db_input($vars['what']).
+             ',how='.db_input($vars['how']).
+             ',val='.db_input($vars['val']).
              ',isactive='.db_input(isset($vars['isactive'])?$vars['isactive']:1);
 
 
diff --git a/include/class.i18n.php b/include/class.i18n.php
new file mode 100644
index 000000000..67f1c4276
--- /dev/null
+++ b/include/class.i18n.php
@@ -0,0 +1,174 @@
+<?php
+/*********************************************************************
+    class.i18n.php
+
+    Internationalization and localization helpers for osTicket
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require_once INCLUDE_DIR.'class.error.php';
+require_once INCLUDE_DIR.'class.yaml.php';
+require_once INCLUDE_DIR.'class.config.php';
+
+class Internationalization {
+
+    // Languages in order of decreasing priority. Always use en_US as a
+    // fallback
+    var $langs = array('en_US');
+
+    function Internationalization($language=false) {
+        if ($language)
+            array_unshift($this->langs, $language);
+    }
+
+    function getTemplate($path) {
+        return new DataTemplate($path, $this->langs);
+    }
+
+    /**
+     * Loads data from the I18N_DIR for the target language into the
+     * database. This is intended to be done at the time of installation;
+     * however, care should be taken in this process to ensure that the
+     * process could be repeated if an administrator wanted to change the
+     * system language and reload the data.
+     */
+    function loadDefaultData() {
+        $models = array(
+            'email_template_group.yaml' => 'EmailTemplateGroup', # notrans
+            'department.yaml' =>    'Dept', # notrans
+            'sla.yaml' =>           'SLA', # notrans
+            // Note that department and sla are required for help_topic
+            'help_topic.yaml' =>    'Topic', # notrans
+            'filter.yaml' =>        'Filter', # notrans
+            'team.yaml' =>          'Team', # notrans
+            // Note that group requires department
+            'group.yaml' =>         'Group', # notrans
+        );
+
+        $errors = array();
+        foreach ($models as $yaml=>$m)
+            if ($objects = $this->getTemplate($yaml)->getData())
+                foreach ($objects as $o)
+                    // Model::create($o)
+                    call_user_func_array(
+                        array($m, 'create'), array($o, &$errors));
+
+        // Priorities
+        $priorities = $this->getTemplate('priority.yaml')->getData();
+        foreach ($priorities as $name=>$info) {
+            $sql = 'INSERT INTO '.PRIORITY_TABLE
+                .' SET priority='.db_input($name)
+                .', priority_desc='.db_input($info['priority_desc'])
+                .', priority_color='.db_input($info['priority_color'])
+                .', priority_urgency='.db_input($info['priority_urgency']);
+            db_query($sql);
+        }
+
+        // Configuration
+        if (($tpl = $this->getTemplate('config.yaml'))
+                && ($data = $tpl->getData())) {
+            foreach ($data as $section=>$items) {
+                $_config = new Config($section);
+                foreach ($items as $key=>$value)
+                    $_config->set($key, $value);
+            }
+        }
+
+        // Pages
+        $_config = new OsticketConfig();
+        foreach (array('landing','thank-you','offline') as $type) {
+            $tpl = $this->getTemplate("templates/page/{$type}.yaml");
+            if (!($page = $tpl->getData()))
+                continue;
+            $sql = 'INSERT INTO '.PAGE_TABLE.' SET type='.db_input($type)
+                .', name='.db_input($page['name'])
+                .', body='.db_input($page['body'])
+                .', lang='.db_input($tpl->getLang())
+                .', notes='.db_input($page['notes'])
+                .', created=NOW(), updated=NOW(), isactive=1';
+            if (db_query($sql) && ($id = db_insert_id()))
+                $_config->set("{$type}_page_id", $id);
+        }
+
+        // Canned response examples
+        if (($tpl = $this->getTemplate('templates/premade.yaml'))
+                && ($canned = $tpl->getData())) {
+            foreach ($canned as $c) {
+                $sql = 'INSERT INTO '.CANNED_TABLE
+                    .' SET title='.db_input($c['title'])
+                    .', lang='.db_input($tpl->getLang())
+                    .', response='.db_input($c['response'])
+                    .', notes='.db_input($c['notes'])
+                    .', created=NOW(), updated=NOW(), isenabled=1';
+                if (db_query($sql) && ($id = db_insert_id())
+                        && isset($c['attachments'])) {
+                    foreach ($c['attachments'] as $att) {
+                        if ($fileId = AttachmentFile::save($att))
+                            $sql ='INSERT INTO '.CANNED_ATTACHMENT_TABLE
+                                 .' SET canned_id='.db_input($id)
+                                 .', file_id='.db_input($fileId);
+                            db_query($sql);
+                    }
+                }
+            }
+        }
+
+        // Email templates
+        // TODO: Lookup tpl_id
+        $tpl = EmailTemplateGroup::lookup(1);
+        foreach ($tpl->all_names as $name=>$info) {
+            if (($tp = $this->getTemplate("templates/email/$name.yaml"))
+                    && ($t = $tp->getData())) {
+                $t['tpl_id'] = $tpl->getId();
+                $t['code_name'] = $name;
+                EmailTemplate::create($t, $errors);
+            }
+        }
+    }
+}
+
+class DataTemplate {
+    // Base folder for default data and templates
+    var $base = I18N_DIR;
+
+    var $filepath;
+    var $data;
+
+    /**
+     * Searches for the files matching the template in the order of the
+     * received languages. Once matched, the language is captured so that
+     * template itself does not have to keep track of the language for which
+     * it is defined.
+     */
+    function DataTemplate($path, $langs=array('en_US')) {
+        foreach ($langs as $l) {
+            if (file_exists("{$this->base}/$l/$path")) {
+                $this->lang = $l;
+                $this->filepath = realpath("{$this->base}/$l/$path");
+                break;
+            }
+        }
+    }
+
+    function getData() {
+        if (!isset($this->data) && $this->filepath)
+            $this->data = YamlDataParser::load($this->filepath);
+            // TODO: If there was a parsing error, attempt to try the next
+            //       language in the list of requested languages
+        return $this->data;
+    }
+
+    function getLang() {
+        return $this->lang;
+    }
+}
+
+?>
diff --git a/include/class.sla.php b/include/class.sla.php
index 59f320472..12bb19b5b 100644
--- a/include/class.sla.php
+++ b/include/class.sla.php
@@ -188,6 +188,9 @@ class SLA {
 
             $errors['err']='Unable to update SLA. Internal error occurred';
         }else{
+            if (isset($vars['id']))
+                $sql .= ', id='.db_input($vars['id']);
+
             $sql='INSERT INTO '.SLA_TABLE.' SET '.$sql.',created=NOW() ';
             if(db_query($sql) && ($id=db_insert_id()))
                 return $id;
diff --git a/include/class.template.php b/include/class.template.php
index fd068d7a8..eec65759d 100644
--- a/include/class.template.php
+++ b/include/class.template.php
@@ -13,6 +13,7 @@
 
     vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
+require_once INCLUDE_DIR.'class.i18n.php';
 require_once INCLUDE_DIR.'class.yaml.php';
 
 class EmailTemplateGroup {
@@ -298,8 +299,8 @@ class EmailTemplateGroup {
         elseif(($tid=EmailTemplateGroup::getIdByName($vars['name'])) && $tid!=$id)
             $errors['name']='Template name already exists';
 
-        if(!$id && (!$vars['tpl_id'] || !($tpl=EmailTemplateGroup::lookup($vars['tpl_id']))))
-            $errors['tpl_id']='Selection required';
+        if(!$id && ($vars['tpl_id'] && !($tpl=EmailTemplateGroup::lookup($vars['tpl_id']))))
+            $errors['tpl_id']='Invalid template group specified';
 
         if($errors) return false;
 
@@ -315,7 +316,7 @@ class EmailTemplateGroup {
 
             $errors['err']='Unable to update the template. Internal error occurred';
 
-        } elseif($tpl && ($info=$tpl->getInfo())) {
+        } else {
 
             $sql='INSERT INTO '.EMAIL_TEMPLATE_GRP_TABLE
                 .' SET created=NOW(), '.$sql;
@@ -324,15 +325,18 @@ class EmailTemplateGroup {
                 return false;
             }
 
-            $sql='INSERT INTO '.EMAIL_TEMPLATE_TABLE.'
+            if ($tpl && ($info=$tpl->getInfo())) {
+                $sql='INSERT INTO '.EMAIL_TEMPLATE_TABLE.'
                     (created, updated, tpl_id, code_name, subject, body)
                     SELECT NOW() as created, NOW() as updated, '.db_input($new_id)
                     .' as tpl_id, code_name, subject, body
                     FROM '.EMAIL_TEMPLATE_TABLE
                     .' WHERE tpl_id='.db_input($tpl->getId());
 
-            if(db_query($sql) && db_insert_id())
-                return $new_id;
+                if(!db_query($sql) || !db_insert_id())
+                    return false;
+            }
+            return $new_id;
         }
 
         return false;
@@ -423,8 +427,8 @@ class EmailTemplate {
     }
 
     function save($id, $vars, &$errors) {
-        if(!$vars['subj'])
-            $errors['subj']='Message subject required';
+        if(!$vars['subject'])
+            $errors['subject']='Message subject required';
 
         if(!$vars['body'])
             $errors['body']='Message body required';
@@ -441,7 +445,7 @@ class EmailTemplate {
 
         if ($id) {
             $sql='UPDATE '.EMAIL_TEMPLATE_TABLE.' SET updated=NOW() '
-                .', subject='.db_input($vars['subj'])
+                .', subject='.db_input($vars['subject'])
                 .', body='.db_input($vars['body'])
                 .' WHERE id='.db_input($this->getId());
 
@@ -450,7 +454,7 @@ class EmailTemplate {
             $sql='INSERT INTO '.EMAIL_TEMPLATE_TABLE.' SET created=NOW(),
                 updated=NOW(), tpl_id='.db_input($vars['tpl_id'])
                 .', code_name='.db_input($vars['code_name'])
-                .', subject='.db_input($vars['subj'])
+                .', subject='.db_input($vars['subject'])
                 .', body='.db_input($vars['body']);
             if (db_query($sql) && ($id=db_insert_id()))
                 return $id;
@@ -488,7 +492,10 @@ class EmailTemplate {
     function fromInitialData($name, $group=null) {
         $templ = new EmailTemplate(0, $group);
         $lang = ($group) ? $group->getLanguage() : 'en_US';
-        $info = YamlDataParser::load(I18N_DIR . "$lang/templates/$name.yaml");
+        $i18n = new Internationalization($lang);
+        if ((!($tpl = $i18n->getTemplate("templates/email/$name.yaml")))
+                || (!($info = $tpl->getData())))
+            return false;
         if (isset($info['subject']) && isset($info['body'])) {
             $templ->ht = $info;
             return $templ;
diff --git a/include/i18n/README.md b/include/i18n/README.md
new file mode 100644
index 000000000..5cc60a15e
--- /dev/null
+++ b/include/i18n/README.md
@@ -0,0 +1,31 @@
+Note to Translators
+===================
+It is our hope that osTicket can and will be translated to the native
+language of every osTicket administrator. If you are considering helping in
+the translation effort, thank you.
+
+Please use the project Github page to share your work and cooperate with
+other translators and translations. If you are uncomfortable with git or
+github, you can submit your changes and suggestions to i18n@osticket.com.
+
+How to translate
+----------------
+Please note that translation is not the practice of turning words from one
+language to another. It is the process of capturing and presenting the
+spirit of a text into another language. Please take the time to understand
+the context of the texts, phrases, and documents before describing them in
+your target language.
+
+What not to translate
+---------------------
+Comments are meant to serve as a consistent hint to the context of the text.
+
+Starting a new translation
+--------------------------
+Copy the entire en_US folder and all its contents and subfolders to a new
+language code, such as de_DE. This is recommended as opposed to copying the
+contents of another translation, because the en_US folder is the most
+up-to-date in terms of content. osTicket is developed with en_US as the
+primary language. Therefore new features will be implemented against the
+en_US data first. If you are beginning a new translation, start with the
+most current texts.
diff --git a/include/i18n/en_US/config.yaml b/include/i18n/en_US/config.yaml
new file mode 100644
index 000000000..02ef35e5b
--- /dev/null
+++ b/include/i18n/en_US/config.yaml
@@ -0,0 +1,16 @@
+#
+# Default configuration. The format is key: value and the data will be
+# inserted into the %config table at install time
+#
+---
+core:
+    allowed_filetypes: '.doc, .pdf'
+    time_format: ' h:i A'
+    date_format: 'm/d/Y'
+    datetime_format: 'm/d/Y g:i a'
+    daydatetime_format: 'D, M j Y g:ia'
+    default_timezone_id: 0
+    default_priority_id: 2
+    enable_daylight_saving: 0
+
+    reply_separator: '-- do not edit --'
diff --git a/include/i18n/en_US/department.yaml b/include/i18n/en_US/department.yaml
new file mode 100644
index 000000000..7bedf7190
--- /dev/null
+++ b/include/i18n/en_US/department.yaml
@@ -0,0 +1,32 @@
+#
+# Departments defined initially for the system
+#
+# Fields:
+# id - (int:optional) id number in the database
+# name - (string) Short name of the department
+# signature - (string) Descriptive name of the department
+#
+# NOTE: The department listed first by ID# will be the default department
+#
+---
+- id: 1
+  name: Support
+  signature: |
+    Support Dept
+  ispublic: 1
+  sla_id: 0
+  tpl_id: 0
+  # The email_id and autoresonse_emaiL_id are reuired, but will be set to
+  # the default email later in the install process
+  email_id: 0
+  autoresp_email_id: 0
+
+- id: 2
+  name: Billing
+  signature: |
+    Billing Dept
+  ispublic: 1
+  sla_id: 1
+  tpl_id: 0
+  email_id: 0
+  autoresp_email_id: 0
diff --git a/include/i18n/en_US/email_template_group.yaml b/include/i18n/en_US/email_template_group.yaml
new file mode 100644
index 000000000..41c5aca70
--- /dev/null
+++ b/include/i18n/en_US/email_template_group.yaml
@@ -0,0 +1,19 @@
+#
+# Default email template group for the system
+#
+# NOTE: The language field is defined for the email tempate group model, but
+#       is not considered by the installer. Whatever language the install
+#       loads data for, the same language will be used to load the email
+#       templates
+#
+# Fields:
+# isactive - (bool:0|1) true or false if the templates should be initially
+#       usable
+# name - (string) descriptive name for the template group
+# notes - Administrative notes (viewable internally only)
+#
+---
+- isactive: 1
+  name: osTicket Default Template
+  notes: |
+    Default osTicket templates
diff --git a/include/i18n/en_US/filter.yaml b/include/i18n/en_US/filter.yaml
new file mode 100644
index 000000000..da95a9869
--- /dev/null
+++ b/include/i18n/en_US/filter.yaml
@@ -0,0 +1,37 @@
+#
+# Default ticket filters installed for the system
+#
+# NOTE: The SYSTEM BAN LIST is critically important and should _never_ be
+#       removed from this file. The name 'SYSTEM BAN LIST' is also important
+#       and should not be translated -- it is not displayed on the interface
+#
+# Fields:
+# isactive - (bool:0|1) true or false if the filter is initially enabled
+# execorder - (int) order the filters should be executed in (lowest first)
+# reject_ticket - (bool:0|1) if a ticket matches the filter it should be
+#       rejected (ie. not be created).
+# name - (string) Descriptive name for the filter
+# notes - (string) Administrative notes (viewable internally only)
+# rules - (list<FilterRule>) List of rules for the filter
+#
+# Fields for FilterRule:
+# isactive - (bool:0|1) true if the rule should be considered
+# what - (enum<email|>) field to check
+# how - (enum<equals|contains|dncontain>) how to check for <val>
+# val - (string) search value
+---
+- isactive: 1
+  execorder: 99
+  reject_ticket: 1
+  # NOTE: Don't translate 'Email'
+  target: Email
+  # NOTE: Don't translate 'SYSTEM BAN LIST'
+  name: SYSTEM BAN LIST
+  notes: |
+    Internal list for email banning. Do not remove
+
+  rules:
+    - isactive: 1
+      what: email
+      how: equal
+      val: test@example.com
diff --git a/include/i18n/en_US/group.yaml b/include/i18n/en_US/group.yaml
new file mode 100644
index 000000000..6a358db73
--- /dev/null
+++ b/include/i18n/en_US/group.yaml
@@ -0,0 +1,81 @@
+#
+# Default groups defined for the system
+#
+# Fields:
+# isactive - (bool:0|1) true or false if the group should be initially
+#       usable
+# name - (string) descriptive name for the group
+# notes - (string) administrative notes (viewable internally only)
+# can_create_tickets - (bool:0|1) true or false if users of the group can
+#       create new tickets
+# can_edit_tickets - (bool:0|1) true or false if users of the group can
+#       modify and update existing tickets
+# can_delete_tickets - (bool:0|1) true or false if members of the group can
+#       delete tickets (permanently)
+# can_close_tickets - (bool:0|1) true or false if members of the group can
+#       close active tickets
+# can_assign_ticets - (bool:0|1) true or false if members of the group can
+#       assign tickets to staff
+# can_transfer_tickets - (bool:0|1) true or false if members of the group
+#       can change the department tickets are assigne dto
+# can_ban_emails - (bool:0|1) true or false if members of the group can add
+#       emails to the system ban list
+# can_manage_premade - (bool:0|1) true or false if members of the group can
+#       create, modify, and delete canned responses
+# can_manage_faq - (bool:0|1) true or false if members of the group can
+#       manage the customer-facing and internal knowledgebase
+#
+# depts: (list<Department<id>>) id's of the departments to which the group
+#       should initially have access
+#
+---
+- isactive: 1
+  name: Admins
+  notes: |
+    System overlords
+  can_create_tickets: 1
+  can_edit_tickets: 1
+  can_delete_tickets: 1
+  can_close_tickets: 1
+  can_assign_tickets: 1
+  can_transfer_tickets: 1
+  can_ban_emails: 1
+  can_manage_premade: 1
+  can_manage_faq: 1
+  can_post_ticket_reply: 1
+
+  depts: [1, 2]
+
+- isactive: 1
+  name: Managers
+  notes: |
+    Inhabitants of the ivory tower
+  can_create_tickets: 1
+  can_edit_tickets: 1
+  can_delete_tickets: 1
+  can_close_tickets: 1
+  can_assign_tickets: 1
+  can_transfer_tickets: 1
+  can_ban_emails: 1
+  can_manage_premade: 1
+  can_manage_faq: 1
+  can_post_ticket_reply: 1
+
+  depts: [1, 2]
+
+- isactve: 1
+  name: Staff
+  notes: |
+    Lowly staff members
+  can_create_tickets: 1
+  can_edit_tickets: 1
+  can_delete_tickets: 0
+  can_close_tickets: 1
+  can_assign_tickets: 1
+  can_transfer_tickets: 1
+  can_ban_emails: 0
+  can_manage_premade: 0
+  can_manage_faq: 0
+  can_post_ticket_reply: 1
+
+  depts: [1, 2]
diff --git a/include/i18n/en_US/help_topic.yaml b/include/i18n/en_US/help_topic.yaml
new file mode 100644
index 000000000..39b77320a
--- /dev/null
+++ b/include/i18n/en_US/help_topic.yaml
@@ -0,0 +1,38 @@
+#
+# Default help topics installed for the system
+#
+# Fields:
+# id - (int:optional) id number in the database
+# topic - (string) descriptive name of the help topic
+# isactive - (bool:0|1) if the help topic should be initially usable
+# ispublic - (bool:0|1) true or false if end users should be able to see the
+#       help topic. In other words, true or false if the help topic is _not_
+#       for internal use only
+# noautoresp - (bool:0|1) true or false if the autoresponder should be
+#       disabled for tickets assigned to this help topic
+# dept_id - (int) id number of the department with which this help topic is
+#       associated
+# sla_id - (int:optional) id number of the sla with which this help topic is
+#       associated
+# notes - (string) administrative notes (internally viewable only)
+#
+---
+- isactive: 1
+  ispublic: 1
+  noautoresp: 0
+  dept_id: 1
+  sla_id: 1
+  priority_id: 2
+  topic: Support
+  notes: |
+    Tickets that primarily concern the support deparment
+
+- isactive: 1
+  ispublic: 1
+  noautoresp: 0
+  dept_id: 1
+  sla_id: 0
+  priority_id: 2
+  topic: Billing
+  notes: |
+    Tickets that primarily concern the sales and billing deparments
diff --git a/include/i18n/en_US/priority.yaml b/include/i18n/en_US/priority.yaml
new file mode 100644
index 000000000..760c84efd
--- /dev/null
+++ b/include/i18n/en_US/priority.yaml
@@ -0,0 +1,24 @@
+#
+# Default system data for ticket priorities
+#
+---
+low:
+    priority_id: 1
+    priority_desc: Low
+    priority_color: "#DDFFDD"
+    priority_urgency: 4
+normal:
+    priority_id: 2
+    priority_desc: Normal
+    priority_color: "#FFFFF0A"
+    priority_urgency: 3
+high:
+    priority_id: 3
+    priority_desc: High
+    priority_color: "#FEE7E7"
+    priority_urgency: 2
+emergency:
+    priority_id: 4
+    priority_desc: Emergency
+    priority_color: "#FEE7E7"
+    priority_urgency: 1
diff --git a/include/i18n/en_US/sla.yaml b/include/i18n/en_US/sla.yaml
new file mode 100644
index 000000000..3b9132547
--- /dev/null
+++ b/include/i18n/en_US/sla.yaml
@@ -0,0 +1,22 @@
+#
+# Initial Service-Level-Agreements (SLA) defined for the system
+#
+# Fields:
+# id - (int:optional) id number in the database
+# isactive - (bool:0|1) true of false if the SLA should initially be active
+# enable_priority_escalation - (bool:0|1) true or false if the SLA should
+#       cause the ticket priority to be escalated when it is marked overdue
+# disable_overdue_alerts - (bool:0|1) - true or false if the overdue alert
+#       emails should _not_ go out for tickets assigned to this SLA
+# grace_period - (int) number or hours after the ticket is opened before it
+#       is marked overdue
+# name - (string) descriptive name of the SLA
+# notes - (string) administrative notes (viewable internally only)
+---
+- id: 1
+  isactive: 1
+  enable_priority_escalation: 1
+  disable_overdue_alert: 0
+  grace_period: 48
+  name: Default SLA
+  notes: |
diff --git a/include/i18n/en_US/team.yaml b/include/i18n/en_US/team.yaml
new file mode 100644
index 000000000..16ae12449
--- /dev/null
+++ b/include/i18n/en_US/team.yaml
@@ -0,0 +1,16 @@
+#
+# Initial teams defined for the system.
+#
+# Fields:
+# isenabled - (bool:1|0) true or false if the team should be initially
+#       enabled
+# noalerts - (bool:1|0)
+# name - Descriptive name for the team
+# notes - Administrative notes (viewable internal only)
+#
+---
+- isenabled: 1
+  noalerts: 0
+  name: Level I Support
+  notes: |
+    Tier 1 support, responsible for the initial iteraction with customers
diff --git a/include/i18n/en_US/templates/email/assigned.alert.yaml b/include/i18n/en_US/templates/email/assigned.alert.yaml
new file mode 100644
index 000000000..b2e9ffbd6
--- /dev/null
+++ b/include/i18n/en_US/templates/email/assigned.alert.yaml
@@ -0,0 +1,32 @@
+#
+# Email template: assigned.alert.yaml
+#
+# Sent to staff members when a ticket is assigned to them. Tickets can be
+# assigned automatically by the system or manually by another staff member.
+# Use %{assigner} to distinguish who made the assignment.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to staff members when a ticket is assigned to them. Tickets can be
+    assigned automatically by the system or manually by another staff
+    member.  Use %{assigner} to distinguish who made the assignment.
+
+subject: |
+    Ticket #%{ticket.number} Assigned to you
+body: |
+    %{assignee},
+
+    Ticket #%{ticket.number} has been assigned to you by %{assigner}
+
+    ----------------------
+
+    %{comments}
+
+    ----------------------
+
+    To view complete details, simply login to the support system.
+
+    %{ticket.staff_link}
+
+    - Your friendly Support Ticket System - powered by osTicket.
diff --git a/include/i18n/en_US/templates/email/message.alert.yaml b/include/i18n/en_US/templates/email/message.alert.yaml
new file mode 100644
index 000000000..b5d505d9f
--- /dev/null
+++ b/include/i18n/en_US/templates/email/message.alert.yaml
@@ -0,0 +1,34 @@
+#
+# Email template: message.alert.yaml
+#
+# Sent to staff members when a new message is posted by a user to a ticket.
+# This can occur if the users responds to an email from the system or visits
+# the customer web portal and posts a new message there.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to staff members when a new message is posted by a user to a
+    ticket.  This can occur if the users responds to an email from the
+    system or visits the customer web portal and posts a new message there.
+
+subject: |
+    New Message Alert
+body: |
+    %{recipient},
+
+    New message appended to ticket #%{ticket.number}
+
+    ----------------------
+    Name: %{ticket.name}
+    Email: %{ticket.email}
+    Dept: %{ticket.dept.name}
+
+    %{message}
+    ----------------------
+
+    To view/respond to the ticket, please login to the support ticket system.
+
+    %{ticket.staff_link}
+
+    - Your friendly Customer Support System - powered by osTicket.
diff --git a/include/i18n/en_US/templates/email/message.autoresp.yaml b/include/i18n/en_US/templates/email/message.autoresp.yaml
new file mode 100644
index 000000000..52e16e4f6
--- /dev/null
+++ b/include/i18n/en_US/templates/email/message.autoresp.yaml
@@ -0,0 +1,24 @@
+#
+# Email template: message.autoresp.yaml
+#
+# Sent to a user when the user posts a new message to a ticket. This can
+# happen if the users responds to an email from the system or visits the
+# customer web portal and posts a new message there.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to a user when the user posts a new message to a ticket. This can
+    happen if the users responds to an email from the system or visits the
+    customer web portal and posts a new message there.
+
+subject: |
+    [#%{ticket.number}] Message Added
+body: |
+    %{ticket.name},
+
+    Your reply to support request #%{ticket.number} has been noted.
+
+    You can view this support request progress online here: %{ticket.client_link}.
+
+    %{signature}
diff --git a/include/i18n/en_US/templates/email/note.alert.yaml b/include/i18n/en_US/templates/email/note.alert.yaml
new file mode 100644
index 000000000..0a77d5622
--- /dev/null
+++ b/include/i18n/en_US/templates/email/note.alert.yaml
@@ -0,0 +1,31 @@
+#
+# Email template: note.alert.yaml
+#
+# Sent to staff members when a new internal note is appended to a ticket.
+# Internal notes can only be added by staff members.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to staff members when a new internal note is appended to a ticket.
+    Internal notes can only be added by staff members.
+
+subject: |
+    New Internal Note Alert
+body: |
+    %{recipient},
+
+    Internal note appended to ticket #%{ticket.number}
+
+    ----------------------
+    * %{note.title} *
+
+    %{note.message}
+    ----------------------
+
+    To view/respond to the ticket, please login to the support ticket
+    system.
+
+    %{ticket.staff_link}
+
+    - Your friendly Customer Support System - powered by osTicket.
diff --git a/include/i18n/en_US/templates/staff.pwreset.yaml b/include/i18n/en_US/templates/email/staff.pwreset.yaml
similarity index 78%
rename from include/i18n/en_US/templates/staff.pwreset.yaml
rename to include/i18n/en_US/templates/email/staff.pwreset.yaml
index 2ed5b3da4..39b96083a 100644
--- a/include/i18n/en_US/templates/staff.pwreset.yaml
+++ b/include/i18n/en_US/templates/email/staff.pwreset.yaml
@@ -5,7 +5,12 @@
 # password</a> link in the staff control login screen
 #
 ---
-subject: osTicket Staff Password Reset
+notes: |
+    Sent when a staff member requests a password reset via the <a>Forgot my
+    password</a> link in the staff control login screen
+
+subject: |
+    osTicket Staff Password Reset
 body: |
     You or perhaps somebody you know has submitted a password reset request on
     your behalf for the helpdesk at %{url}.
diff --git a/include/i18n/en_US/templates/email/ticket.alert.yaml b/include/i18n/en_US/templates/email/ticket.alert.yaml
new file mode 100644
index 000000000..167b77f31
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.alert.yaml
@@ -0,0 +1,32 @@
+#
+# Email template: ticket.alert.yaml
+#
+# Sent to a staff member when a new ticket is created in the system. This
+# applies to tickets created via email, the web portal, or the api.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to a staff member when a new ticket is created in the system. This
+    applies to tickets created via email, the web portal, or the api.
+
+subject: |
+    New Ticket Alert
+body: |
+    %{recipient},
+
+    New ticket #%{ticket.number} created.
+
+    -----------------------
+    Name: %{ticket.name}
+    Email: %{ticket.email}
+    Dept: %{ticket.dept.name}
+
+    %{message}
+
+    -----------------------
+    To view/respond to the ticket, please login to the support ticket system.
+
+    %{ticket.staff_link}
+
+    - Your friendly Customer Support System - powered by osTicket.
diff --git a/include/i18n/en_US/templates/email/ticket.autoreply.yaml b/include/i18n/en_US/templates/email/ticket.autoreply.yaml
new file mode 100644
index 000000000..19328f502
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.autoreply.yaml
@@ -0,0 +1,30 @@
+#
+# Email template: ticket.autoreply.yaml
+#
+# Sent to a user when an automatic canned response is posted to a ticket
+# when it is created
+#
+%YAML 1.0
+---
+notes: |
+    Sent to a user when an automatic canned response is posted to a ticket
+    when it is created.
+
+    Available variables for replacement: %{ticket.*}, %{response}
+
+subject: |
+    Support Ticket Opened [#%{ticket.number}]
+body: |
+    %{ticket.name},
+
+    A request for support has been created and assigned ticket
+    #%{ticket.number} with the following auto-reply:
+
+    %{response}
+
+
+    We hope this response has sufficiently answered your questions. If not,
+    please do not open another ticket. If need be, representative will
+    follow-up with you as soon as possible.
+
+    You can view this ticket's progress online here: %{ticket.client_link}.
diff --git a/include/i18n/en_US/templates/email/ticket.autoresp.yaml b/include/i18n/en_US/templates/email/ticket.autoresp.yaml
new file mode 100644
index 000000000..b958b3bd3
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.autoresp.yaml
@@ -0,0 +1,25 @@
+#
+# Email template: ticket.autoresp.yaml
+#
+# Sent to a user when a new ticket is created
+#
+---
+notes: |
+    Sent to a user when a new ticket is created
+
+subject: |
+    Support Ticket Opened [#%{ticket.number}]
+body: |
+    %{ticket.name},
+
+    A request for support has been created and assigned ticket
+    #%{ticket.number}. A representative will follow-up with you as soon as
+    possible.
+
+    You can view this ticket's progress online here: %{ticket.client_link}.
+
+    If you wish to send additional comments or information regarding this
+    issue, please don't open a new ticket.  Simply login using the link
+    above and update the ticket.
+
+    %{signature}
diff --git a/include/i18n/en_US/templates/email/ticket.notice.yaml b/include/i18n/en_US/templates/email/ticket.notice.yaml
new file mode 100644
index 000000000..c843efb43
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.notice.yaml
@@ -0,0 +1,27 @@
+#
+# Email template: ticket.notice.yaml
+#
+# Sent to a user when a staff member creates a ticket on the user's behalf.
+# This is most commonly performed when user's call in on the phone.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to a user when a staff member creates a ticket on the user's behalf.
+    This is most commonly performed when user's call in on the phone.
+
+subject: |
+    [#%{ticket.number}] %{ticket.subject}
+body: |
+    %{ticket.name},
+
+    Our customer care team has created a ticket, #%{ticket.number} on your
+    behalf, with the following message.
+
+    %{message}
+
+    If you wish to provide additional comments or information regarding this
+    issue, please don't open a new ticket. You can update or view this
+    ticket's progress online here: %{ticket.client_link}.
+
+    %{signature}
diff --git a/include/i18n/en_US/templates/email/ticket.overdue.yaml b/include/i18n/en_US/templates/email/ticket.overdue.yaml
new file mode 100644
index 000000000..874304904
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.overdue.yaml
@@ -0,0 +1,29 @@
+#
+# Email template: ticket.overdue.yaml
+#
+# Sent to staff members when a ticket transitions to overdue in the system.
+# Overdue tickets occur based on the ticket's due-date as well as the SLA
+# defined for the ticket.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to staff members when a ticket transitions to overdue in the system.
+    Overdue tickets occur based on the ticket's due-date as well as the SLA
+    defined for the ticket.
+
+subject: |
+    Stale Ticket Alert
+body: |
+    %{recipient},
+
+    A ticket, #%{ticket.number} assigned to you or in your department is
+    seriously overdue.
+
+    %{ticket.staff_link}
+
+    We should all work hard to guarantee that all tickets are being
+    addressed in a timely manner.
+
+    - Your friendly (although with limited patience) Support Ticket System -
+    powered by osTicket.
diff --git a/include/i18n/en_US/templates/email/ticket.overlimit.yaml b/include/i18n/en_US/templates/email/ticket.overlimit.yaml
new file mode 100644
index 000000000..51ca4e161
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.overlimit.yaml
@@ -0,0 +1,30 @@
+#
+# Email template: ticket.overlimit.yaml
+#
+# Sent to users when they have exceeded the maximum open ticket limit. The
+# limit is configurable in the Admin Panel, and is defined by the number of
+# tickets open by a particular email address.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to users when they have exceeded the maximum open ticket limit. The
+    limit is configurable in the Admin Panel, and is defined by the number
+    of tickets open by a particular email address.
+
+subject: |
+     Open Tickets Limit Reached
+body: |
+    %{ticket.name},
+
+    You have reached the maximum number of open tickets allowed.
+
+    To be able to open another ticket, one of your pending tickets must be
+    closed. To update or add comments to an open ticket simply login using
+    the link below.
+
+    %{url}/tickets.php?e=%{ticket.email}
+
+    Thank you.
+
+    Support Ticket System
diff --git a/include/i18n/en_US/templates/email/ticket.reply.yaml b/include/i18n/en_US/templates/email/ticket.reply.yaml
new file mode 100644
index 000000000..3a37ce49e
--- /dev/null
+++ b/include/i18n/en_US/templates/email/ticket.reply.yaml
@@ -0,0 +1,30 @@
+#
+# Email template: ticket.reply.yaml
+#
+# Sent to users when a staff members makes a reply to their ticket. Replies
+# are only generated by staff members.
+#
+%YAML 1.0
+---
+notes: |
+    Sent to users when a staff members makes a reply to their ticket.
+    Replies are only generated by staff members.
+
+subject: |
+    [#%{ticket.number}] %{ticket.subject}
+body: |
+    %{ticket.name},
+
+    A customer support staff member has replied to your support request,
+    #%{ticket.number} with the following response:
+
+    %{response}
+
+    We hope this response has sufficiently answered your questions. If not,
+    please do not send another email. Instead, reply to this email or login
+    to your account for a complete archive of all your support requests and
+    responses.
+
+    %{ticket.client_link}
+
+    %{signature}
diff --git a/include/i18n/en_US/templates/email/transfer.alert.yaml b/include/i18n/en_US/templates/email/transfer.alert.yaml
new file mode 100644
index 000000000..2f0a5a565
--- /dev/null
+++ b/include/i18n/en_US/templates/email/transfer.alert.yaml
@@ -0,0 +1,31 @@
+#
+# Email template: transfer.alert.yaml
+#
+# Sent to staff members when a ticket is assigned to them. Tickets can be
+# assigned automatically by the system or manually by another staff member.
+# Use %{assigner} to distinguish who made the assignment.
+#
+%YAML 1.0
+---
+notes: |
+
+subject: |
+    Ticket Transfer #%{ticket.number} - %{ticket.dept.name}
+body: |
+    %{recipient},
+
+    Ticket #%{ticket.number} has been transferred to the %{ticket.dept.name}
+    department by %{staff.name}
+
+    ----------------------
+
+    %{comments}
+
+    ----------------------
+
+    To view/respond to the ticket, please login to the support ticket
+    system.
+
+    %{ticket.staff_link}
+
+    - Your friendly Customer Support System - powered by osTicket.
diff --git a/include/i18n/en_US/templates/page/landing.yaml b/include/i18n/en_US/templates/page/landing.yaml
new file mode 100644
index 000000000..f18491098
--- /dev/null
+++ b/include/i18n/en_US/templates/page/landing.yaml
@@ -0,0 +1,23 @@
+#
+# Page template: landing.yaml
+#
+# The landing page is served on the front page of the customer portal above
+# the two links for creating new tickets and viewing ticket status.
+#
+%YAML 1.0
+---
+notes: |
+    The landing page is served on the front page of the customer portal
+    above the two links for creating new tickets and viewing ticket status.
+
+name: Landing
+body: |
+    <h1>Welcome to the Support Center</h1>
+    <p>
+    In order to streamline support requests and better serve you, we utilize
+    a support ticket system. Every support request is assigned a unique
+    ticket number which you can use to track the progress and responses
+    online. For your reference we provide complete archives and history of
+    all your support requests. A valid email address is required to submit a
+    ticket.
+    </p>
diff --git a/include/i18n/en_US/templates/page/offline.yaml b/include/i18n/en_US/templates/page/offline.yaml
new file mode 100644
index 000000000..c3f31e7da
--- /dev/null
+++ b/include/i18n/en_US/templates/page/offline.yaml
@@ -0,0 +1,21 @@
+#
+# Page template: offline.yaml
+#
+# The offline page is served to the customer portal when the help desk is
+# configured offline in the Admin Panel
+#
+%YAML 1.0
+---
+notes: |
+    The offline page is served to the customer portal when the help desk is
+    configured offline in the Admin Panel
+
+name: Offline
+body: |
+    <div><h1>
+    <span style="font-size: medium">Support Ticket System Offline</span>
+    </h1>
+    <p>Thank you for your interest in contacting us.</p>
+    <p>Our helpdesk is offline at the moment, please check back at a later
+    time.</p>
+    </div>
diff --git a/include/i18n/en_US/templates/page/thank-you.yaml b/include/i18n/en_US/templates/page/thank-you.yaml
new file mode 100644
index 000000000..96f048804
--- /dev/null
+++ b/include/i18n/en_US/templates/page/thank-you.yaml
@@ -0,0 +1,20 @@
+#
+# Page template: thank-you.yaml
+#
+# The thank-you page is served to the customer portal when a user submites a
+# new ticket via the customer portal.
+#
+%YAML 1.0
+---
+notes: |
+    The thank-you page is served to the customer portal when a user submites
+    a new ticket via the customer portal.
+
+name: Thank You
+body: |
+    <div>%{ticket.name},<br />
+    <p>Thank you for contacting us.</p>
+    <p>A support ticket request #%{ticket.number} has been created and a
+    representative will be getting back to you shortly if necessary.</p>
+    <p>Support Team</p>
+    </div>
diff --git a/include/i18n/en_US/templates/premade.yaml b/include/i18n/en_US/templates/premade.yaml
new file mode 100644
index 000000000..8483de8b9
--- /dev/null
+++ b/include/i18n/en_US/templates/premade.yaml
@@ -0,0 +1,24 @@
+#
+# Canned response templates
+#
+---
+- title: What is osTicket (sample)?
+  response: |
+    osTicket is a widely-used open source support ticket system, an
+    attractive alternative to higher-cost and complex customer support
+    systems - simple, lightweight, reliable, open source, web-based and easy
+    to setup and use.
+  notes: |
+
+  attachments:
+    - name: osTicket.txt
+      type: text/plain
+      data: Canned Attachments Rock!
+
+- title: Sample (with variables)
+  response: |
+    %{ticket.name},
+
+    Your ticket #%{ticket.number} created on %{ticket.create_date} is in
+    %{ticket.dept.name} department.
+  notes: |
diff --git a/include/staff/tpl.inc.php b/include/staff/tpl.inc.php
index c5954090d..efde7fa53 100644
--- a/include/staff/tpl.inc.php
+++ b/include/staff/tpl.inc.php
@@ -14,7 +14,7 @@ if (is_a($template, EmailTemplateGroup)) {
     // Attempt to lookup the default data if it is defined
     $default = @$template->getMsgTemplate($selected);
     if ($default) {
-        $info['subj'] = $default->getSubject();
+        $info['subject'] = $default->getSubject();
         $info['body'] = $default->getBody();
     }
 } else {
@@ -27,7 +27,7 @@ if (is_a($template, EmailTemplateGroup)) {
     $action = 'updatetpl';
     $extras = array();
     $msgtemplates=$template->getGroup()->all_names;
-    $info=array_merge(array('subj'=>$template->getSubject(), 'body'=>$template->getBody()),$info);
+    $info=array_merge(array('subject'=>$template->getSubject(), 'body'=>$template->getBody()),$info);
 }
 $info['tpl']=($info['tpl'] && $msgtemplates[$info['tpl']])?$info['tpl']:'ticket.autoresp';
 $tpl=$msgtemplates[$info['tpl']];
@@ -80,8 +80,8 @@ $tpl=$msgtemplates[$info['tpl']];
     <tbody>
         <tr>
             <td colspan=2>
-                <strong>Message Subject:</strong> <em>Email message subject</em> <font class="error">*&nbsp;<?php echo $errors['subj']; ?></font><br>
-                <input type="text" name="subj" size="60" value="<?php echo $info['subj']; ?>" >
+                <strong>Message Subject:</strong> <em>Email message subject</em> <font class="error">*&nbsp;<?php echo $errors['subject']; ?></font><br>
+                <input type="text" name="subject" size="60" value="<?php echo $info['subject']; ?>" >
             </td>
         </tr>
         <tr>
diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig
index 417c53845..3ab6cfb80 100644
--- a/include/upgrader/streams/core.sig
+++ b/include/upgrader/streams/core.sig
@@ -1 +1 @@
-16fcef4a13d6475a5f8bfef462b548e2
+43fbf5b9254787c93d049be0b607cf2d
diff --git a/include/upgrader/streams/core/16fcef4a-43fbf5b9.patch.sql b/include/upgrader/streams/core/16fcef4a-43fbf5b9.patch.sql
new file mode 100644
index 000000000..cb660f749
--- /dev/null
+++ b/include/upgrader/streams/core/16fcef4a-43fbf5b9.patch.sql
@@ -0,0 +1,25 @@
+/**
+ * @version v1.8.0
+ * @signature 43fbf5b9254787c93d049be0b607cf2d
+ *
+ * Make default data translatable. This patch also adds columns to database
+ * tables to introduce the concept of a language.
+ *
+ */
+
+ALTER TABLE `%TABLE_PREFIX%email_template_group`
+    ADD `lang` varchar(16) NOT NULL default 'en_US' AFTER `name`;
+
+ALTER TABLE `%TABLE_PREFIX%email_template`
+    ADD `notes` text AFTER `body`;
+
+ALTER TABLE `%TABLE_PREFIX%canned_response`
+    ADD `lang` varchar(16) NOT NULL default 'en_US' AFTER `response`;
+
+ALTER TABLE `%TABLE_PREFIX%page`
+    ADD `lang` varchar(16) NOT NULL default 'en_US' AFTER `body`;
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `value` = '43fbf5b9254787c93d049be0b607cf2d'
+    WHERE `key` = 'schema_signature' AND `namespace` = 'core';
diff --git a/main.inc.php b/main.inc.php
index be0b6bfcf..ca636616b 100644
--- a/main.inc.php
+++ b/main.inc.php
@@ -18,216 +18,13 @@
     #Disable direct access.
     if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!');
 
-    #Disable Globals if enabled....before loading config info
-    if(ini_get('register_globals')) {
-       ini_set('register_globals',0);
-       foreach($_REQUEST as $key=>$val)
-           if(isset($$key))
-               unset($$key);
-    }
-
-    #Disable url fopen && url include
-    ini_set('allow_url_fopen', 0);
-    ini_set('allow_url_include', 0);
-
-    #Disable session ids on url.
-    ini_set('session.use_trans_sid', 0);
-    #No cache
-    session_cache_limiter('nocache');
-
-    #Error reporting...Good idea to ENABLE error reporting to a file. i.e display_errors should be set to false
-    $error_reporting = E_ALL & ~E_NOTICE;
-    if (defined('E_STRICT')) # 5.4.0
-        $error_reporting &= ~E_STRICT;
-    if (defined('E_DEPRECATED')) # 5.3.0
-        $error_reporting &= ~(E_DEPRECATED | E_USER_DEPRECATED);
-    error_reporting($error_reporting); //Respect whatever is set in php.ini (sysadmin knows better??)
-
-    #Don't display errors
-    ini_set('display_errors', 1);
-    ini_set('display_startup_errors', 1);
-
-    //Default timezone
-    if (!ini_get('date.timezone')) {
-        if(function_exists('date_default_timezone_set')) {
-            if(@date_default_timezone_get()) //Let PHP determine the timezone.
-                @date_default_timezone_set(@date_default_timezone_get());
-            else //Default to EST - if PHP can't figure it out.
-                date_default_timezone_set('America/New_York');
-        } else { //Default when all fails. PHP < 5.
-            ini_set('date.timezone', 'America/New_York');
-        }
-    }
-
-    #Set Dir constants
-    $here = substr(realpath(dirname(__file__)),
-        strlen($_SERVER['DOCUMENT_ROOT']));
-    // Determine the path in the URI used as the base of the osTicket
-    // installation
-    if (!defined('ROOT_PATH'))
-        define('ROOT_PATH', str_replace('\\', '/', $here.'/')); //root path. Damn directories
-
-    define('ROOT_DIR',str_replace('\\\\', '/', realpath(dirname(__FILE__))).'/'); #Get real path for root dir ---linux and windows
-    define('INCLUDE_DIR',ROOT_DIR.'include/'); //Change this if include is moved outside the web path.
-    define('PEAR_DIR',INCLUDE_DIR.'pear/');
-    define('SETUP_DIR',INCLUDE_DIR.'setup/');
-
-    define('UPGRADE_DIR', INCLUDE_DIR.'upgrader/');
-    define('I18N_DIR', INCLUDE_DIR.'i18n/');
-
-    /*############## Do NOT monkey with anything else beyond this point UNLESS you really know what you are doing ##############*/
-
-    #Current version && schema signature (Changes from version to version)
-    define('THIS_VERSION','1.7.0+'); //Shown on admin panel
-    #load config info
-    $configfile='';
-    if(file_exists(ROOT_DIR.'ostconfig.php')) //Old installs prior to v 1.6 RC5
-        $configfile=ROOT_DIR.'ostconfig.php';
-    elseif(file_exists(INCLUDE_DIR.'settings.php')) { //OLD config file.. v 1.6 RC5
-        $configfile=INCLUDE_DIR.'settings.php';
-        //Die gracefully on upgraded v1.6 RC5 installation - otherwise script dies with confusing message.
-        if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']), 'settings.php'))
-            die('Please rename config file include/settings.php to include/ost-config.php to continue!');
-    } elseif(file_exists(INCLUDE_DIR.'ost-config.php')) //NEW config file v 1.6 stable ++
-        $configfile=INCLUDE_DIR.'ost-config.php';
-    elseif(file_exists(ROOT_DIR.'setup/'))
-        header('Location: '.ROOT_PATH.'setup/');
-
-    if(!$configfile || !file_exists($configfile)) die('<b>Error loading settings. Contact admin.</b>');
-
-    require($configfile);
-    define('CONFIG_FILE',$configfile); //used in admin.php to check perm.
-
-   //Path separator
-    if(!defined('PATH_SEPARATOR')){
-        if(strpos($_ENV['OS'],'Win')!==false || !strcasecmp(substr(PHP_OS, 0, 3),'WIN'))
-            define('PATH_SEPARATOR', ';' ); //Windows
-        else
-            define('PATH_SEPARATOR',':'); //Linux
-    }
-
-    //Set include paths. Overwrite the default paths.
-    ini_set('include_path', './'.PATH_SEPARATOR.INCLUDE_DIR.PATH_SEPARATOR.PEAR_DIR);
-
-
-    #include required files
-    require(INCLUDE_DIR.'class.osticket.php');
-    require(INCLUDE_DIR.'class.ostsession.php');
-    require(INCLUDE_DIR.'class.usersession.php');
-    require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
-    require(INCLUDE_DIR.'class.log.php');
-    require(INCLUDE_DIR.'class.crypto.php');
-    require(INCLUDE_DIR.'class.misc.php');
-    require(INCLUDE_DIR.'class.timezone.php');
-    require(INCLUDE_DIR.'class.http.php');
-    require(INCLUDE_DIR.'class.signal.php');
-    require(INCLUDE_DIR.'class.nav.php');
-    require(INCLUDE_DIR.'class.page.php');
-    require(INCLUDE_DIR.'class.format.php'); //format helpers
-    require(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
-    require(INCLUDE_DIR.'class.mailer.php');
-    if (extension_loaded('mysqli'))
-        require_once INCLUDE_DIR.'mysqli.php';
-    else
-        require(INCLUDE_DIR.'mysql.php');
-
-    #Cookies
-    session_set_cookie_params(86400, ROOT_PATH, $_SERVER['HTTP_HOST'],
-        osTicket::is_https());
+    require('bootstrap.php');
+    Bootstrap::loadConfig();
+    Bootstrap::defineTables(TABLE_PREFIX);
+    Bootstrap::connect();
 
-    #CURRENT EXECUTING SCRIPT.
-    define('THISPAGE', Misc::currentURL());
-    define('THISURI', $_SERVER['REQUEST_URI']);
-
-    # This is to support old installations. with no secret salt.
-    if(!defined('SECRET_SALT')) define('SECRET_SALT',md5(TABLE_PREFIX.ADMIN_EMAIL));
-
-    #Session related
-    define('SESSION_SECRET', MD5(SECRET_SALT)); //Not that useful anymore...
-    define('SESSION_TTL', 86400); // Default 24 hours
-
-    define('DEFAULT_MAX_FILE_UPLOADS',ini_get('max_file_uploads')?ini_get('max_file_uploads'):5);
-    define('DEFAULT_PRIORITY_ID',1);
-
-    define('EXT_TICKET_ID_LEN',6); //Ticket create. when you start getting collisions. Applies only on random ticket ids.
-
-    #Tables being used sytem wide
-    define('CONFIG_TABLE',TABLE_PREFIX.'config');
-    define('SYSLOG_TABLE',TABLE_PREFIX.'syslog');
-    define('SESSION_TABLE',TABLE_PREFIX.'session');
-    define('FILE_TABLE',TABLE_PREFIX.'file');
-    define('FILE_CHUNK_TABLE',TABLE_PREFIX.'file_chunk');
-
-    define('STAFF_TABLE',TABLE_PREFIX.'staff');
-    define('DEPT_TABLE',TABLE_PREFIX.'department');
-    define('TOPIC_TABLE',TABLE_PREFIX.'help_topic');
-    define('GROUP_TABLE',TABLE_PREFIX.'groups');
-    define('GROUP_DEPT_TABLE', TABLE_PREFIX.'group_dept_access');
-    define('TEAM_TABLE',TABLE_PREFIX.'team');
-    define('TEAM_MEMBER_TABLE',TABLE_PREFIX.'team_member');
-
-    define('PAGE_TABLE', TABLE_PREFIX.'page');
-
-    define('FAQ_TABLE',TABLE_PREFIX.'faq');
-    define('FAQ_ATTACHMENT_TABLE',TABLE_PREFIX.'faq_attachment');
-    define('FAQ_TOPIC_TABLE',TABLE_PREFIX.'faq_topic');
-    define('FAQ_CATEGORY_TABLE',TABLE_PREFIX.'faq_category');
-    define('CANNED_TABLE',TABLE_PREFIX.'canned_response');
-    define('CANNED_ATTACHMENT_TABLE',TABLE_PREFIX.'canned_attachment');
-
-    define('TICKET_TABLE',TABLE_PREFIX.'ticket');
-    define('TICKET_THREAD_TABLE',TABLE_PREFIX.'ticket_thread');
-    define('TICKET_ATTACHMENT_TABLE',TABLE_PREFIX.'ticket_attachment');
-    define('TICKET_PRIORITY_TABLE',TABLE_PREFIX.'ticket_priority');
-    define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
-    define('TICKET_LOCK_TABLE',TABLE_PREFIX.'ticket_lock');
-    define('TICKET_EVENT_TABLE',TABLE_PREFIX.'ticket_event');
-    define('TICKET_EMAIL_INFO_TABLE',TABLE_PREFIX.'ticket_email_info');
-
-    define('EMAIL_TABLE',TABLE_PREFIX.'email');
-    define('EMAIL_TEMPLATE_GRP_TABLE',TABLE_PREFIX.'email_template_group');
-    define('EMAIL_TEMPLATE_TABLE',TABLE_PREFIX.'email_template');
-
-    define('FILTER_TABLE',TABLE_PREFIX.'filter');
-    define('FILTER_RULE_TABLE',TABLE_PREFIX.'filter_rule');
-
-    define('BANLIST_TABLE',TABLE_PREFIX.'email_banlist'); //Not in use anymore....as of v 1.7
-
-    define('SLA_TABLE',TABLE_PREFIX.'sla');
-
-    define('API_KEY_TABLE',TABLE_PREFIX.'api_key');
-    define('TIMEZONE_TABLE',TABLE_PREFIX.'timezone');
-
-    #Global overwrite
-    if($_SERVER['HTTP_X_FORWARDED_FOR']) //Can contain multiple IPs - use the last one.
-        $_SERVER['REMOTE_ADDR'] =  array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
-
-    #Connect to the DB && get configuration from database
-    $ferror=null;
-    $options = array();
-    if (defined('DBSSLCA'))
-        $options['ssl'] = array(
-            'ca' => DBSSLCA,
-            'cert' => DBSSLCERT,
-            'key' => DBSSLKEY
-        );
-
-    if (!db_connect(DBHOST, DBUSER, DBPASS, $options)) {
-        $ferror='Unable to connect to the database -'.db_connect_error();
-    }elseif(!db_select_database(DBNAME)) {
-        $ferror='Unknown or invalid database '.DBNAME;
-    } elseif(!($ost=osTicket::start()) || !($cfg = $ost->getConfig())) {
-        $ferror='Unable to load config info from DB. Get tech support.';
-    }
-
-    if($ferror) { //Fatal error
-        //try alerting admin using email in config file
-        $msg=$ferror."\n\n".THISPAGE;
-        Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg, sprintf('"osTicket Alerts"<%s>', ADMIN_EMAIL));
-        //Display generic error to the user
-        die("<b>Fatal Error:</b> Contact system administrator.");
-        exit;
-    }
+    if(!($ost=osTicket::start()) || !($cfg = $ost->getConfig()))
+        Bootstrap::croak('Unable to load config info from DB. Get tech support.');
 
     //Init
     $session = $ost->getSession();
diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php
index 8a2b04a0d..78fd35849 100644
--- a/setup/inc/class.installer.php
+++ b/setup/inc/class.installer.php
@@ -15,6 +15,7 @@
 **********************************************************************/
 require_once INCLUDE_DIR.'class.migrater.php';
 require_once INCLUDE_DIR.'class.setup.php';
+require_once INCLUDE_DIR.'class.i18n.php';
 
 class Installer extends SetupWizard {
 
@@ -109,6 +110,7 @@ class Installer extends SetupWizard {
         /*************** We're ready to install ************************/
         define('ADMIN_EMAIL',$vars['admin_email']); //Needed to report SQL errors during install.
         define('PREFIX',$vars['prefix']); //Table prefix
+        Bootstrap::defineTables(PREFIX);
 
         $debug = true; // Change it to false to squelch SQL errors.
 
@@ -139,6 +141,10 @@ class Installer extends SetupWizard {
             }
         }
 
+        // TODO: Use language selected from install worksheet
+        $i18n = new Internationalization('en_US');
+        $i18n->loadDefaultData();
+
         $sql='SELECT `id` FROM '.PREFIX.'sla ORDER BY `id` LIMIT 1';
         $sla_id_1 = db_result(db_query($sql, false), 0);
 
diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql
index 9359cfae9..f560a201a 100644
--- a/setup/inc/streams/core/install-mysql.sql
+++ b/setup/inc/streams/core/install-mysql.sql
@@ -74,10 +74,6 @@ CREATE TABLE `%TABLE_PREFIX%sla` (
   UNIQUE KEY `name` (`name`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%sla` (`isactive`, `enable_priority_escalation`,
-  `disable_overdue_alerts`, `grace_period`, `name`, `notes`, `created`, `updated`)
-  VALUES (1, 1, 0, 48, 'Default SLA', NULL, NOW(), NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%config`;
 CREATE TABLE `%TABLE_PREFIX%config` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -91,7 +87,6 @@ CREATE TABLE `%TABLE_PREFIX%config` (
 
 INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES
   ('core', 'isonline', '0'),
-  ('core', 'enable_daylight_saving', '0'),
   ('core', 'staff_ip_binding', '0'),
   ('core', 'staff_max_logins', '4'),
   ('core', 'staff_login_timeout', '2'),
@@ -113,7 +108,6 @@ INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES
   ('core', 'default_sla_id', '0'),
   ('core', 'default_priority_id', '2'),
   ('core', 'default_template_id', '1'),
-  ('core', 'default_timezone_id', '0'),
   ('core', 'default_smtp_id', '0'),
   ('core', 'allow_email_spoofing', '0'),
   ('core', 'clickable_urls', '1'),
@@ -173,13 +167,6 @@ INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES
   ('core', 'random_ticket_ids', '1'),
   ('core', 'log_level', '2'),
   ('core', 'log_graceperiod', '12'),
-  ('core', 'upload_dir', ''),
-  ('core', 'allowed_filetypes', '.doc, .pdf'),
-  ('core', 'time_format', ' h:i A'),
-  ('core', 'date_format', 'm/d/Y'),
-  ('core', 'datetime_format', 'm/d/Y g:i a'),
-  ('core', 'daydatetime_format', 'D, M j Y g:ia'),
-  ('core', 'reply_separator', '-- do not edit --'),
   ('core', 'admin_email', ''),
   ('core', 'helpdesk_title', 'osTicket Support Ticket System'),
   ('core', 'helpdesk_url', ''),
@@ -208,10 +195,6 @@ CREATE TABLE `%TABLE_PREFIX%department` (
   KEY `tpl_id` (`tpl_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%department` (`sla_id`, `dept_name`, `dept_signature`, `ispublic`, `ticket_auto_response`, `message_auto_response`) VALUES
-  (0, 'Support', 'Support Dept', 1, 1, 1),
-  ((SELECT `id` FROM `%TABLE_PREFIX%sla` ORDER BY `id` LIMIT 1), 'Billing', 'Billing Dept', 1, 1, 1);
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%email`;
 CREATE TABLE `%TABLE_PREFIX%email` (
   `email_id` int(11) unsigned NOT NULL auto_increment,
@@ -276,11 +259,6 @@ CREATE TABLE `%TABLE_PREFIX%filter` (
   KEY `email_id` (`email_id`)
 ) DEFAULT CHARSET=utf8;
 
-
-INSERT INTO `%TABLE_PREFIX%filter` (
-`isactive`,`execorder`,`reject_ticket`,`name`,`notes`,`created`)
-VALUES (1, 99, 1, 'SYSTEM BAN LIST', 'Internal list for email banning. Do not remove', NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%filter_rule`;
 CREATE TABLE `%TABLE_PREFIX%filter_rule` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -297,25 +275,18 @@ CREATE TABLE `%TABLE_PREFIX%filter_rule` (
   UNIQUE `filter` (`filter_id`, `what`, `how`, `val`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%filter_rule` (
-  `filter_id`, `isactive`, `what`,`how`,`val`,`created`)
-  VALUES (LAST_INSERT_ID(), 1, 'email', 'equal', 'test@example.com',NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%email_template_group`;
 CREATE TABLE `%TABLE_PREFIX%email_template_group` (
   `tpl_id` int(11) NOT NULL auto_increment,
   `isactive` tinyint(1) unsigned NOT NULL default '0',
   `name` varchar(32) NOT NULL default '',
+  `lang` varchar(16) NOT NULL default 'en_US',
   `notes` text,
   `created` datetime NOT NULL,
   `updated` timestamp NOT NULL,
   PRIMARY KEY  (`tpl_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%email_template_group` SET
-    `isactive` = 1, `name` = 'osTicket Default Template',
-    `notes` = 'Default osTicket templates', `created` = NOW(), `updated` = NOW();
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%email_template`;
 CREATE TABLE `%TABLE_PREFIX%email_template` (
   `id` int(11) UNSIGNED NOT NULL auto_increment,
@@ -323,42 +294,13 @@ CREATE TABLE `%TABLE_PREFIX%email_template` (
   `code_name` varchar(32) NOT NULL,
   `subject` varchar(255) NOT NULL default '',
   `body` text NOT NULL,
+  `notes` text,
   `created` datetime NOT NULL,
   `updated` datetime NOT NULL,
   PRIMARY KEY  (`id`),
   UNIQUE KEY `template_lookup` (`tpl_id`, `code_name`)
 ) DEFAULT CHARSET=utf8;
 
--- TODO: Dump revised copy before release!!!
-INSERT INTO `%TABLE_PREFIX%email_template` (`code_name`, `subject`, `body`)
-    VALUES (
-    'ticket.autoresp', 'Support Ticket Opened [#%{ticket.number}]', '%{ticket.name}, \r\n\r\nA request for support has been created and assigned ticket #%{ticket.number}. A representative will follow-up with you as soon as possible.\r\n\r\nYou can view this ticket''s progress online here: %{ticket.client_link}.\r\n\r\nIf you wish to send additional comments or information regarding this issue, please don''t open a new ticket. Simply login using the link above and update the ticket.\r\n\r\n%{signature}'
-    ), (
-    'ticket.autoreply', 'Support Ticket Opened [#%{ticket.number}]', '%{ticket.name}, \r\n\r\nA request for support has been created and assigned ticket #%{ticket.number} with the following auto-reply:\r\n\r\n%{response}\r\n\r\n\r\nWe hope this response has sufficiently answered your questions. If not, please do not open another ticket. If need be, representative will follow-up with you as soon as possible.\r\n\r\nYou can view this ticket''s progress online here: %{ticket.client_link}.'
-    ), (
-    'ticket.notice', '[#%{ticket.number}] %{ticket.subject}', '%{ticket.name}, \r\n\r\nOur customer care team has created a ticket, #%{ticket.number} on your behalf, with the following message.\r\n\r\n%{message}\r\n\r\nIf you wish to provide additional comments or information regarding this issue, please don''t open a new ticket. You can update or view this ticket''s progress online here: %{ticket.client_link}.\r\n\r\n%{signature}'
-    ), (
-    'ticket.alert', 'New Ticket Alert', '%{recipient}, \r\n\r\nNew ticket #%{ticket.number} created.\r\n\r\n-----------------------\r\nName: %{ticket.name}\r\nEmail: %{ticket.email}\r\nDept: %{ticket.dept.name}\r\n\r\n%{message}\r\n-----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.'
-    ), (
-    'message.autoresp', '[#%{ticket.number}] Message Added', '%{ticket.name}, \r\n\r\nYour reply to support request #%{ticket.number} has been noted.\r\n\r\nYou can view this support request progress online here: %{ticket.client_link}.\r\n\r\n%{signature}'
-    ), (
-    'message.alert', 'New Message Alert', '%{recipient}, \r\n\r\nNew message appended to ticket #%{ticket.number}\r\n\r\n----------------------\r\nName: %{ticket.name}\r\nEmail: %{ticket.email}\r\nDept: %{ticket.dept.name}\r\n\r\n%{message}\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.'
-    ), (
-    'note.alert', 'New Internal Note Alert', '%{recipient}, \r\n\r\nInternal note appended to ticket #%{ticket.number}\r\n\r\n----------------------\r\n* %{note.title} *\r\n\r\n%{note.message}\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.'
-    ), (
-    'assigned.alert', 'Ticket #%{ticket.number} Assigned to you', '%{assignee}, \r\n\r\nTicket #%{ticket.number} has been assigned to you by %{assigner}\r\n\r\n----------------------\r\n\r\n%{comments}\r\n\r\n----------------------\r\n\r\nTo view complete details, simply login to the support system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Support Ticket System - powered by osTicket.'
-    ), (
-    'transfer.alert', 'Ticket Transfer #%{ticket.number} - %{ticket.dept.name}', '%{recipient}, \r\n\r\nTicket #%{ticket.number} has been transferred to %{ticket.dept.name} department by %{staff.name}\r\n\r\n----------------------\r\n\r\n%{comments}\r\n\r\n----------------------\r\n\r\nTo view/respond to the ticket, please login to the support ticket system.\r\n\r\n%{ticket.staff_link}\r\n\r\n- Your friendly Customer Support System - powered by osTicket.'
-    ), (
-    'ticket.overdue', 'Stale Ticket Alert', '%{recipient}, \r\n\r\nA ticket, #%{ticket.number} assigned to you or in your department is seriously overdue.\r\n\r\n%{ticket.staff_link}\r\n\r\nWe should all work hard to guarantee that all tickets are being addressed in a timely manner.\r\n\r\n- Your friendly (although with limited patience) Support Ticket System - powered by osTicket.'
-    ), (
-    'ticket.overlimit', 'Open Tickets Limit Reached', '%{ticket.name}\r\n\r\nYou have reached the maximum number of open tickets allowed.\r\n\r\nTo be able to open another ticket, one of your pending tickets must be closed. To update or add comments to an open ticket simply login using the link below.\r\n\r\n%{url}/tickets.php?e=%{ticket.email}\r\n\r\nThank you.\r\n\r\nSupport Ticket System'
-    ), (
-    'ticket.reply', '[#%{ticket.number}] %{ticket.subject}', '%{ticket.name}, \r\n\r\nA customer support staff member has replied to your support request, #%{ticket.number} with the following response:\r\n\r\n%{response}\r\n\r\nWe hope this response has sufficiently answered your questions. If not, please do not send another email. Instead, reply to this email or login to your account for a complete archive of all your support requests and responses.\r\n\r\n%{ticket.client_link}\r\n\r\n%{signature}'
-    );
-UPDATE `%TABLE_PREFIX%email_template` SET `created`=NOW(), `updated`=NOW(),
-       `tpl_id` = (SELECT `tpl_id` FROM `%TABLE_PREFIX%email_template_group`);
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%file`;
 CREATE TABLE `%TABLE_PREFIX%file` (
   `id` int(11) NOT NULL auto_increment,
@@ -373,10 +315,6 @@ CREATE TABLE `%TABLE_PREFIX%file` (
   KEY `hash` (`hash`)
 ) DEFAULT CHARSET=utf8;
 
-
-INSERT INTO `%TABLE_PREFIX%file` (`type`, `size`, `hash`, `name`, `created`) VALUES
-  ('text/plain', '25', '670c6cc1d1dfc97fad20e5470251b255', 'osTicket.txt', NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%file_chunk`;
 CREATE TABLE `%TABLE_PREFIX%file_chunk` (
   `file_id` int(11) NOT NULL,
@@ -385,9 +323,6 @@ CREATE TABLE `%TABLE_PREFIX%file_chunk` (
   PRIMARY KEY (`file_id`, `chunk_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%file_chunk` (`file_id`, `chunk_id`, `filedata`)
-  VALUES (LAST_INSERT_ID(), 0, 0x43616e6e6564206174746163686d656e747320726f636b210a);
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%groups`;
 CREATE TABLE `%TABLE_PREFIX%groups` (
   `group_id` int(10) unsigned NOT NULL auto_increment,
@@ -411,11 +346,6 @@ CREATE TABLE `%TABLE_PREFIX%groups` (
   KEY `group_active` (`group_enabled`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%groups` (`group_enabled`, `group_name`, `can_create_tickets`, `can_edit_tickets`, `can_delete_tickets`, `can_close_tickets`, `can_assign_tickets`, `can_transfer_tickets`, `can_ban_emails`, `can_manage_premade`, `can_manage_faq`, `notes`, `created`, `updated`) VALUES
-  (1, 'Admins', 1, 1, 1, 1, 1, 1, 1, 1, 1, 'overlords', NOW(), NOW()),
-  (1, 'Managers', 1, 1, 1, 1, 1, 1, 1, 1, 1, '', NOW(), NOW()),
-  (1, 'Staff', 1, 1, 0, 1, 1, 1, 0, 0, 0, '', NOW(), NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%group_dept_access`;
 CREATE TABLE `%TABLE_PREFIX%group_dept_access` (
   `group_id` int(10) unsigned NOT NULL default '0',
@@ -424,10 +354,6 @@ CREATE TABLE `%TABLE_PREFIX%group_dept_access` (
   KEY `dept_id`  (`dept_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%group_dept_access` (`group_id`, `dept_id`)
-  SELECT `%TABLE_PREFIX%groups`.`group_id`, `%TABLE_PREFIX%department`.`dept_id`
-  FROM `%TABLE_PREFIX%groups`, `%TABLE_PREFIX%department`;
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%help_topic`;
 CREATE TABLE `%TABLE_PREFIX%help_topic` (
   `topic_id` int(11) unsigned NOT NULL auto_increment,
@@ -455,10 +381,6 @@ CREATE TABLE `%TABLE_PREFIX%help_topic` (
   KEY `page_id` (`page_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%help_topic` (`isactive`, `ispublic`, `noautoresp`, `dept_id`, `sla_id`, `topic`, `notes`) VALUES
-  (1, 1, 0, (SELECT `dept_id` FROM `%TABLE_PREFIX%department` ORDER BY `dept_id` LIMIT 1), (SELECT `id` FROM `%TABLE_PREFIX%sla` ORDER BY `id` LIMIT 1), 'Support', NULL),
-  (1, 1, 0, (SELECT `dept_id` FROM `%TABLE_PREFIX%department` ORDER BY `dept_id` LIMIT 1), 0, 'Billing', NULL);
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%canned_response`;
 CREATE TABLE `%TABLE_PREFIX%canned_response` (
   `canned_id` int(10) unsigned NOT NULL auto_increment,
@@ -466,6 +388,7 @@ CREATE TABLE `%TABLE_PREFIX%canned_response` (
   `isenabled` tinyint(1) unsigned NOT NULL default '1',
   `title` varchar(255) NOT NULL default '',
   `response` text NOT NULL,
+  `lang` varchar(16) NOT NULL default 'en_US',
   `notes` text,
   `created` datetime NOT NULL,
   `updated` datetime NOT NULL,
@@ -475,10 +398,6 @@ CREATE TABLE `%TABLE_PREFIX%canned_response` (
   KEY `active` (`isenabled`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%canned_response` (`isenabled`, `title`, `response`) VALUES
-  (1, 'What is osTicket (sample)?', '\r\nosTicket is a widely-used open source support ticket system, an attractive alternative to higher-cost and complex customer support systems - simple, lightweight, reliable, open source, web-based and easy to setup and use.'),
-  (1, 'Sample (with variables)', '\r\n%{ticket.name},\r\n\r\nYour ticket #%{ticket.number} created on %{ticket.create_date} is in %{ticket.dept.name} department.\r\n\r\n');
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%canned_attachment`;
 CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%canned_attachment` (
   `canned_id` int(10) unsigned NOT NULL,
@@ -486,9 +405,6 @@ CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%canned_attachment` (
   PRIMARY KEY  (`canned_id`,`file_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%canned_attachment` (`canned_id`, `file_id`)
-  VALUES (LAST_INSERT_ID(), (SELECT `id` FROM `%TABLE_PREFIX%file` ORDER BY `id` LIMIT 1));
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%session`;
 CREATE TABLE `%TABLE_PREFIX%session` (
   `session_id` varchar(255) collate ascii_general_ci NOT NULL default '',
@@ -572,9 +488,6 @@ CREATE TABLE `%TABLE_PREFIX%team` (
   KEY `lead_id` (`lead_id`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%team` (`isenabled`, `noalerts`, `name`, `notes`, `created`, `updated`)
-  VALUES (1, 0, 'Level I Support', '', NOW(), NOW());
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%team_member`;
 CREATE TABLE `%TABLE_PREFIX%team_member` (
   `team_id` int(10) unsigned NOT NULL default '0',
@@ -688,12 +601,6 @@ CREATE TABLE `%TABLE_PREFIX%ticket_priority` (
   KEY `ispublic` (`ispublic`)
 ) DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%ticket_priority` (`priority`, `priority_desc`, `priority_color`, `priority_urgency`, `ispublic`) VALUES
-  ('low', 'Low', '#DDFFDD', 4, 1),
-  ('normal', 'Normal', '#FFFFF0', 3, 1),
-  ('high', 'High', '#FEE7E7', 2, 1),
-  ('emergency', 'Emergency', '#FEE7E7', 1, 0);
-
 DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket_thread`;
 CREATE TABLE `%TABLE_PREFIX%ticket_thread` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -761,20 +668,10 @@ CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%page` (
   `type` enum('landing','offline','thank-you','other') NOT NULL default 'other',
   `name` varchar(255) NOT NULL,
   `body` text NOT NULL,
+  `lang` varchar(16) NOT NULL default 'en_US',
   `notes` text,
   `created` datetime NOT NULL,
   `updated` datetime NOT NULL,
   PRIMARY KEY  (`id`),
   UNIQUE KEY `name` (`name`)
 ) DEFAULT CHARSET=utf8;
-
-
-INSERT INTO `%TABLE_PREFIX%page` (`id`, `isactive`, `type`, `name`, `body`, `notes`, `created`, `updated`) VALUES
-('', 1, 'offline', 'Offline', '<div>\r\n<h1><span style="font-size: medium">Support Ticket System Offline</span></h1>\r\n<p>Thank you for your interest in contacting us.</p>\r\n<p>Our helpdesk is offline at the moment, please check back at a later time.</p>\r\n</div>', 'Default offline page', NOW(), NOW()),
-('', 1, 'thank-you', 'Thank you', '<div>%{ticket.name},<br />\r\n    \r\n<p>\r\nThank you for contacting us.</p><p> A support ticket request #%{ticket.number} has been created and a representative will be getting back to you shortly if necessary.</p>\r\n          \r\n<p>Support Team </p>\r\n</div>', 'Default "thank you" page displayed after the end-user creates a web ticket.', NOW(), NOW()),
-('', 1, 'landing', 'Landing', '<h1>Welcome to the Support Center</h1>\r\n<p>In order to streamline support requests and better serve you, we utilize a support ticket system. Every support request is assigned a unique ticket number which you can use to track the progress and responses online. For your reference we provide complete archives and history of all your support requests. A valid email address is required to submit a ticket.\r\n</p>\r\n', 'Introduction text on the landing page.', NOW(), NOW());
-
-INSERT INTO `%TABLE_PREFIX%config` (`key`, `value`, `namespace`) VALUES
-  ('landing_page_id', (SELECT `id` FROM `%TABLE_PREFIX%page` WHERE `type` = 'landing'), 'core'),
-  ('offline_page_id', (SELECT `id` FROM `%TABLE_PREFIX%page` WHERE `type` = 'offline'), 'core'),
-  ('thank-you_page_id', (SELECT `id` FROM `%TABLE_PREFIX%page` WHERE `type` = 'thank-you'), 'core');
diff --git a/setup/setup.inc.php b/setup/setup.inc.php
index ab75b7219..addbb4fdd 100644
--- a/setup/setup.inc.php
+++ b/setup/setup.inc.php
@@ -39,26 +39,21 @@ if(ini_get('register_globals')) {
             unset($$key);
 }
 
-#start session
-session_start();
-
 #clear global vars
 $errors=array();
 $msg='';
 
 #define constants.
 define('SETUPINC',true);
-define('URL',rtrim('http'.(($_SERVER['HTTPS']=='on')?'s':'').'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']),'setup'));
+require('../bootstrap.php');
+
+#start session
+session_start();
+
+define('URL',rtrim((Bootstrap::https()?'https':'http').'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']),'setup'));
 
 #define paths
 define('INC_DIR',dirname(__file__).'/inc/'); //local include dir!
-if(!defined('INCLUDE_DIR')):
-define('ROOT_PATH',dirname(__file__).'/../');
-define('ROOT_DIR',dirname(__file__).'/../');
-define('INCLUDE_DIR',ROOT_DIR.'include/');
-define('PEAR_DIR',INCLUDE_DIR.'pear/');
-ini_set('include_path', './'.PATH_SEPARATOR.INC_DIR.PATH_SEPARATOR.INCLUDE_DIR.PATH_SEPARATOR.PEAR_DIR);
-endif;
 
 #required files
 require_once(INCLUDE_DIR.'class.setup.php');
-- 
GitLab