diff --git a/.gitignore b/.gitignore
index 3bdc4e066866d0433aafc3341fa4b43b0b420b58..6e7535b0b92c9fd5d8c741d3c95ba4fe7c19630e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,6 @@ Vagrantfile
 
 # Staging directory used for packaging script
 stage
+
+# Ignore packaged plugins and language packs
+*.phar
diff --git a/include/ajax.tips.php b/include/ajax.tips.php
index ed560403e945933600ad3390dea1aa508530ea8b..e81d1301b53622478520050bcd6e75528b28e36e 100644
--- a/include/ajax.tips.php
+++ b/include/ajax.tips.php
@@ -20,8 +20,13 @@ if(!defined('INCLUDE_DIR')) die('!');
 require_once(INCLUDE_DIR.'class.i18n.php');
 
 class HelpTipAjaxAPI extends AjaxController {
-    function getTipsJson($namespace, $lang='en_US') {
-        global $ost;
+    function getTipsJson($namespace, $lang=false) {
+        global $ost, $thisstaff;
+
+        if (!$lang)
+            $lang = ($thisstaff)
+                ? $thisstaff->getLanguage()
+                : Internationalization::getDefaultLanguage();
 
         $i18n = new Internationalization($lang);
         $tips = $i18n->getTemplate("help/tips/$namespace.yaml");
diff --git a/include/class.config.php b/include/class.config.php
index 06607fdc52393e084f8fdc9dde376b4c8108a1e1..f5c7077d7dcbe07cddca31d10e83d1e63a7cb32e 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -148,6 +148,7 @@ class OsticketConfig extends Config {
         'allow_online_attachments_onlogin' => false,
         'name_format' =>        'full', # First Last
         'auto_claim_tickets'=>  true,
+        'system_language' =>    'en_US',
     );
 
     function OsticketConfig($section=null) {
@@ -709,6 +710,10 @@ class OsticketConfig extends Config {
         return ($this->allowAttachments() && $this->get('allow_email_attachments'));
     }
 
+    function getSystemLanguage() {
+        return $this->get('system_language');
+    }
+
     //TODO: change db field to allow_api_attachments - which will include  email/json/xml attachments
     //       terminology changed on the UI
     function allowAPIAttachments() {
diff --git a/include/class.i18n.php b/include/class.i18n.php
index 7891d7ef937ecacf2bc148ae4a4e441801a8e003..fdb0061bb760da7e3cc8bd7364df70deff1cc0e1 100644
--- a/include/class.i18n.php
+++ b/include/class.i18n.php
@@ -16,7 +16,6 @@
 **********************************************************************/
 require_once INCLUDE_DIR.'class.error.php';
 require_once INCLUDE_DIR.'class.yaml.php';
-require_once INCLUDE_DIR.'class.config.php';
 
 class Internationalization {
 
@@ -43,7 +42,6 @@ class Internationalization {
     function loadDefaultData() {
         # notrans -- do not translate the contents of this array
         $models = array(
-            'email_template_group.yaml' => 'EmailTemplateGroup',
             'department.yaml' =>    'Dept',
             'sla.yaml' =>           'SLA',
             'form.yaml' =>          'DynamicForm',
@@ -77,6 +75,7 @@ class Internationalization {
         }
 
         // Configuration
+        require_once INCLUDE_DIR.'class.config.php';
         if (($tpl = $this->getTemplate('config.yaml'))
                 && ($data = $tpl->getData())) {
             foreach ($data as $section=>$items) {
@@ -101,6 +100,8 @@ class Internationalization {
             if (db_query($sql) && ($id = db_insert_id()))
                 $_config->set("{$type}_page_id", $id);
         }
+        // Default Language
+        $_config->set('system_language', $this->langs[0]);
 
         // Canned response examples
         if (($tpl = $this->getTemplate('templates/premade.yaml'))
@@ -118,6 +119,13 @@ class Internationalization {
 
         // Email templates
         // TODO: Lookup tpl_id
+        if ($objects = $this->getTemplate('email_template_group.yaml')->getData()) {
+            foreach ($objects as $o) {
+                $o['lang_id'] = $this->langs[0];
+                $tpl = EmailTemplateGroup::create($o, $errors);
+            }
+        }
+        // This shouldn't be necessary
         $tpl = EmailTemplateGroup::lookup(1);
         foreach ($tpl->all_names as $name=>$info) {
             if (($tp = $this->getTemplate("templates/email/$name.yaml"))
@@ -131,6 +139,120 @@ class Internationalization {
             }
         }
     }
+
+    static function availableLanguages($base=I18N_DIR) {
+        $langs = (include I18N_DIR . 'langs.php');
+
+        // Consider all subdirectories and .phar files in the base dir
+        $dirs = glob(I18N_DIR . '*', GLOB_ONLYDIR | GLOB_NOSORT);
+        $phars = glob(I18N_DIR . '*.phar', GLOB_NOSORT);
+
+        $installed = array();
+        foreach (array_merge($dirs, $phars) as $f) {
+            $base = basename($f, '.phar');
+            @list($code, $locale) = explode('_', $base);
+            if (isset($langs[$code])) {
+                $installed[strtolower($base)] =
+                    $langs[$code] + array(
+                    'lang' => $code,
+                    'locale' => $locale,
+                    'path' => $f,
+                    'code' => $base,
+                    'desc' => sprintf("%s%s (%s)",
+                        $langs[$code]['nativeName'],
+                        $locale ? sprintf(' - %s', $locale) : '',
+                        $langs[$code]['name']),
+                );
+            }
+        }
+
+        return $installed;
+    }
+
+    // TODO: Move this to the REQUEST class or some middleware when that
+    // exists.
+    // Algorithm borrowed from Drupal 7 (locale.inc)
+    static function getDefaultLanguage() {
+        global $cfg;
+
+        if (empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
+            return $cfg->getSystemLanguage();
+
+        $languages = self::availableLanguages();
+
+        // The Accept-Language header contains information about the
+        // language preferences configured in the user's browser / operating
+        // system. RFC 2616 (section 14.4) defines the Accept-Language
+        // header as follows:
+        //   Accept-Language = "Accept-Language" ":"
+        //                  1#( language-range [ ";" "q" "=" qvalue ] )
+        //   language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+        // Samples: "hu, en-us;q=0.66, en;q=0.33", "hu,en-us;q=0.5"
+        $browser_langcodes = array();
+        if (preg_match_all('@(?<=[, ]|^)([a-zA-Z-]+|\*)(?:;q=([0-9.]+))?(?:$|\s*,\s*)@',
+            trim($_SERVER['HTTP_ACCEPT_LANGUAGE']), $matches, PREG_SET_ORDER)) {
+          foreach ($matches as $match) {
+            // We can safely use strtolower() here, tags are ASCII.
+            // RFC2616 mandates that the decimal part is no more than three
+            // digits, so we multiply the qvalue by 1000 to avoid floating
+            // point comparisons.
+            $langcode = strtolower($match[1]);
+            $qvalue = isset($match[2]) ? (float) $match[2] : 1;
+            $browser_langcodes[$langcode] = (int) ($qvalue * 1000);
+          }
+        }
+
+        // We should take pristine values from the HTTP headers, but
+        // Internet Explorer from version 7 sends only specific language
+        // tags (eg. fr-CA) without the corresponding generic tag (fr)
+        // unless explicitly configured. In that case, we assume that the
+        // lowest value of the specific tags is the value of the generic
+        // language to be as close to the HTTP 1.1 spec as possible.
+        //
+        // References:
+        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
+        // http://blogs.msdn.com/b/ie/archive/2006/10/17/accept-language-header-for-internet-explorer-7.aspx
+        asort($browser_langcodes);
+        foreach ($browser_langcodes as $langcode => $qvalue) {
+          $generic_tag = strtok($langcode, '-');
+          if (!isset($browser_langcodes[$generic_tag])) {
+            $browser_langcodes[$generic_tag] = $qvalue;
+          }
+        }
+
+        // Find the enabled language with the greatest qvalue, following the rules
+        // of RFC 2616 (section 14.4). If several languages have the same qvalue,
+        // prefer the one with the greatest weight.
+        $best_match_langcode = FALSE;
+        $max_qvalue = 0;
+        foreach ($languages as $langcode => $language) {
+          // Language tags are case insensitive (RFC2616, sec 3.10).
+          // We use _ as the location separator
+          $langcode = str_replace('_','-',strtolower($langcode));
+
+          // If nothing matches below, the default qvalue is the one of the wildcard
+          // language, if set, or is 0 (which will never match).
+          $qvalue = isset($browser_langcodes['*']) ? $browser_langcodes['*'] : 0;
+
+          // Find the longest possible prefix of the browser-supplied language
+          // ('the language-range') that matches this site language ('the language tag').
+          $prefix = $langcode;
+          do {
+            if (isset($browser_langcodes[$prefix])) {
+              $qvalue = $browser_langcodes[$prefix];
+              break;
+            }
+          } while ($prefix = substr($prefix, 0, strrpos($prefix, '-')));
+
+          // Find the best match.
+          if ($qvalue > $max_qvalue) {
+            $best_match_langcode = $language['code'];
+            $max_qvalue = $qvalue;
+          }
+        }
+
+        return $best_match_langcode;
+    }
 }
 
 class DataTemplate {
@@ -153,6 +275,12 @@ class DataTemplate {
                 $this->filepath = realpath("{$this->base}/$l/$path");
                 break;
             }
+            elseif (Phar::isValidPharFilename("{$this->base}/$l.phar")
+                    && file_exists("phar://{$this->base}/$l.phar/$path")) {
+                $this->lang = $l;
+                $this->filepath = "phar://{$this->base}/$l.phar/$path";
+                break;
+            }
         }
     }
 
diff --git a/include/class.staff.php b/include/class.staff.php
index 3883ab3636b0d32dfb4b4b0108edb7e685cda6ce..efd4f341c03f40cb3fa79756cc038533b7c86c7f 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -65,6 +65,7 @@ class Staff extends AuthenticatedUser {
         $this->teams = $this->ht['teams'] = array();
         $this->group = $this->dept = null;
         $this->departments = $this->stats = array();
+        $this->config = new Config('staff.'.$this->id);
 
         //WE have to patch info here to support upgrading from old versions.
         if(($time=strtotime($this->ht['passwdreset']?$this->ht['passwdreset']:$this->ht['added'])))
@@ -91,7 +92,7 @@ class Staff extends AuthenticatedUser {
     }
 
     function getInfo() {
-        return $this->getHastable();
+        return $this->config->getInfo() + $this->getHastable();
     }
 
     /*compares user password*/
@@ -255,6 +256,17 @@ class Staff extends AuthenticatedUser {
         return $this->dept;
     }
 
+    function getLanguage() {
+        static $cached = false;
+        if (!$cached) $cached = &$_SESSION['staff:lang'];
+
+        if (!$cached) {
+            $cached = $this->config->get('lang');
+            if (!$cached)
+                $cached = Internationalization::getDefaultLanguage();
+        }
+        return $cached;
+    }
 
     function isManager() {
         return (($dept=$this->getDept()) && $dept->getManagerId()==$this->getId());
@@ -466,6 +478,9 @@ class Staff extends AuthenticatedUser {
 
         if($errors) return false;
 
+        $this->config->set('lang', $vars['lang']);
+        $_SESSION['staff:lang'] = null;
+
         $sql='UPDATE '.STAFF_TABLE.' SET updated=NOW() '
             .' ,firstname='.db_input($vars['firstname'])
             .' ,lastname='.db_input($vars['lastname'])
diff --git a/include/class.template.php b/include/class.template.php
index e135034cd4943d45190d70b710e9868f4df6a43f..70af7fce0d960ce494638398869ecfd34b858add 100644
--- a/include/class.template.php
+++ b/include/class.template.php
@@ -118,7 +118,7 @@ class EmailTemplateGroup {
     }
 
     function getLanguage() {
-        return 'en_US';
+        return $this->ht['lang'];
     }
 
     function isInUse(){
@@ -320,6 +320,10 @@ class EmailTemplateGroup {
             .' ,isactive='.db_input($vars['isactive'])
             .' ,notes='.db_input(Format::sanitize($vars['notes']));
 
+        if ($vars['lang_id'])
+            // TODO: Validation of lang_id
+            $sql .= ',lang='.db_input($vars['lang_id']);
+
         if($id) {
             $sql='UPDATE '.EMAIL_TEMPLATE_GRP_TABLE.' SET '.$sql.' WHERE tpl_id='.db_input($id);
             if(db_query($sql))
diff --git a/include/i18n/en_US/help/tips/install.yaml b/include/i18n/en_US/help/tips/install.yaml
index 2cb86b36dfeee5b7a282c2e797f4fd992fa06234..b65340da0096ba4152e4660bbc639b058a3b340f 100644
--- a/include/i18n/en_US/help/tips/install.yaml
+++ b/include/i18n/en_US/help/tips/install.yaml
@@ -20,6 +20,16 @@ system_email:
         <p>Default email address e.g support@yourcompany.com - you can add
         more later!</p>
 
+default_lang:
+    title: Default System Language
+    content: |
+        <p>Initial data for this language will be installed into the
+        database. For instance email templates and default system pages will
+        be installed for this language.</p>
+    links:
+      - title: osTicket Language Packs
+        href: http://osticket.com/download?product=langs
+
 first_name:
     title: First Name
     content: |
diff --git a/include/i18n/langs.php b/include/i18n/langs.php
new file mode 100644
index 0000000000000000000000000000000000000000..09957c42be514963c8d7a40f99051b996e728b42
--- /dev/null
+++ b/include/i18n/langs.php
@@ -0,0 +1,735 @@
+<?php
+/**
+ * @author Phil Teare
+ * using wikipedia data
+ */
+return array(
+    "ab" => array(
+        "name" => "Abkhaz",
+        "nativeName" => "аҧсуа"
+    ),
+    "aa" => array(
+        "name" => "Afar",
+        "nativeName" => "Afaraf"
+    ),
+    "af" => array(
+        "name" => "Afrikaans",
+        "nativeName" => "Afrikaans"
+    ),
+    "ak" => array(
+        "name" => "Akan",
+        "nativeName" => "Akan"
+    ),
+    "sq" => array(
+        "name" => "Albanian",
+        "nativeName" => "Shqip"
+    ),
+    "am" => array(
+        "name" => "Amharic",
+        "nativeName" => "አማርኛ"
+    ),
+    "ar" => array(
+        "name" => "Arabic",
+        "nativeName" => "العربية"
+    ),
+    "an" => array(
+        "name" => "Aragonese",
+        "nativeName" => "Aragonés"
+    ),
+    "hy" => array(
+        "name" => "Armenian",
+        "nativeName" => "Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶"
+    ),
+    "as" => array(
+        "name" => "Assamese",
+        "nativeName" => "অসমীয়া"
+    ),
+    "av" => array(
+        "name" => "Avaric",
+        "nativeName" => "авар мацӀ, магӀарул мацӀ"
+    ),
+    "ae" => array(
+        "name" => "Avestan",
+        "nativeName" => "avesta"
+    ),
+    "ay" => array(
+        "name" => "Aymara",
+        "nativeName" => "aymar aru"
+    ),
+    "az" => array(
+        "name" => "Azerbaijani",
+        "nativeName" => "azərbaycan dili"
+    ),
+    "bm" => array(
+        "name" => "Bambara",
+        "nativeName" => "bamanankan"
+    ),
+    "ba" => array(
+        "name" => "Bashkir",
+        "nativeName" => "башҡорт теле"
+    ),
+    "eu" => array(
+        "name" => "Basque",
+        "nativeName" => "euskara, euskera"
+    ),
+    "be" => array(
+        "name" => "Belarusian",
+        "nativeName" => "Беларуская"
+    ),
+    "bn" => array(
+        "name" => "Bengali",
+        "nativeName" => "বাংলা"
+    ),
+    "bh" => array(
+        "name" => "Bihari",
+        "nativeName" => "भोजपुरी"
+    ),
+    "bi" => array(
+        "name" => "Bislama",
+        "nativeName" => "Bislama"
+    ),
+    "bs" => array(
+        "name" => "Bosnian",
+        "nativeName" => "bosanski jezik"
+    ),
+    "br" => array(
+        "name" => "Breton",
+        "nativeName" => "brezhoneg"
+    ),
+    "bg" => array(
+        "name" => "Bulgarian",
+        "nativeName" => "български език"
+    ),
+    "my" => array(
+        "name" => "Burmese",
+        "nativeName" => "ဗမာစာ"
+    ),
+    "ca" => array(
+        "name" => "Catalan; Valencian",
+        "nativeName" => "Català"
+    ),
+    "ch" => array(
+        "name" => "Chamorro",
+        "nativeName" => "Chamoru"
+    ),
+    "ce" => array(
+        "name" => "Chechen",
+        "nativeName" => "нохчийн мотт"
+    ),
+    "ny" => array(
+        "name" => "Chichewa; Chewa; Nyanja",
+        "nativeName" => "chiCheŵa, chinyanja"
+    ),
+    "zh" => array(
+        "name" => "Chinese",
+        "nativeName" => "中文 (Zhōngwén), 汉语, 漢語"
+    ),
+    "cv" => array(
+        "name" => "Chuvash",
+        "nativeName" => "чӑваш чӗлхи"
+    ),
+    "kw" => array(
+        "name" => "Cornish",
+        "nativeName" => "Kernewek"
+    ),
+    "co" => array(
+        "name" => "Corsican",
+        "nativeName" => "corsu, lingua corsa"
+    ),
+    "cr" => array(
+        "name" => "Cree",
+        "nativeName" => "ᓀᐦᐃᔭᐍᐏᐣ"
+    ),
+    "hr" => array(
+        "name" => "Croatian",
+        "nativeName" => "hrvatski"
+    ),
+    "cs" => array(
+        "name" => "Czech",
+        "nativeName" => "česky, čeština"
+    ),
+    "da" => array(
+        "name" => "Danish",
+        "nativeName" => "dansk"
+    ),
+    "dv" => array(
+        "name" => "Divehi; Dhivehi; Maldivian;",
+        "nativeName" => "Þ‹Þ¨ÞˆÞ¬Þ€Þ¨"
+    ),
+    "nl" => array(
+        "name" => "Dutch",
+        "nativeName" => "Nederlands, Vlaams"
+    ),
+    "en" => array(
+        "name" => "English",
+        "nativeName" => "English"
+    ),
+    "eo" => array(
+        "name" => "Esperanto",
+        "nativeName" => "Esperanto"
+    ),
+    "et" => array(
+        "name" => "Estonian",
+        "nativeName" => "eesti, eesti keel"
+    ),
+    "ee" => array(
+        "name" => "Ewe",
+        "nativeName" => "Eʋegbe"
+    ),
+    "fo" => array(
+        "name" => "Faroese",
+        "nativeName" => "føroyskt"
+    ),
+    "fj" => array(
+        "name" => "Fijian",
+        "nativeName" => "vosa Vakaviti"
+    ),
+    "fi" => array(
+        "name" => "Finnish",
+        "nativeName" => "suomi, suomen kieli"
+    ),
+    "fr" => array(
+        "name" => "French",
+        "nativeName" => "français, langue française"
+    ),
+    "ff" => array(
+        "name" => "Fula; Fulah; Pulaar; Pular",
+        "nativeName" => "Fulfulde, Pulaar, Pular"
+    ),
+    "gl" => array(
+        "name" => "Galician",
+        "nativeName" => "Galego"
+    ),
+    "ka" => array(
+        "name" => "Georgian",
+        "nativeName" => "ქართული"
+    ),
+    "de" => array(
+        "name" => "German",
+        "nativeName" => "Deutsch"
+    ),
+    "el" => array(
+        "name" => "Greek, Modern",
+        "nativeName" => "Ελληνικά"
+    ),
+    "gn" => array(
+        "name" => "Guaraní",
+        "nativeName" => "Avañeẽ"
+    ),
+    "gu" => array(
+        "name" => "Gujarati",
+        "nativeName" => "ગુજરાતી"
+    ),
+    "ht" => array(
+        "name" => "Haitian; Haitian Creole",
+        "nativeName" => "Kreyòl ayisyen"
+    ),
+    "ha" => array(
+        "name" => "Hausa",
+        "nativeName" => "Hausa, هَوُسَ"
+    ),
+    "he" => array(
+        "name" => "Hebrew (modern)",
+        "nativeName" => "עברית"
+    ),
+    "hz" => array(
+        "name" => "Herero",
+        "nativeName" => "Otjiherero"
+    ),
+    "hi" => array(
+        "name" => "Hindi",
+        "nativeName" => "हिन्दी, हिंदी"
+    ),
+    "ho" => array(
+        "name" => "Hiri Motu",
+        "nativeName" => "Hiri Motu"
+    ),
+    "hu" => array(
+        "name" => "Hungarian",
+        "nativeName" => "Magyar"
+    ),
+    "ia" => array(
+        "name" => "Interlingua",
+        "nativeName" => "Interlingua"
+    ),
+    "id" => array(
+        "name" => "Indonesian",
+        "nativeName" => "Bahasa Indonesia"
+    ),
+    "ie" => array(
+        "name" => "Interlingue",
+        "nativeName" => "Originally called Occidental; then Interlingue after WWII"
+    ),
+    "ga" => array(
+        "name" => "Irish",
+        "nativeName" => "Gaeilge"
+    ),
+    "ig" => array(
+        "name" => "Igbo",
+        "nativeName" => "Asụsụ Igbo"
+    ),
+    "ik" => array(
+        "name" => "Inupiaq",
+        "nativeName" => "Iñupiaq, Iñupiatun"
+    ),
+    "io" => array(
+        "name" => "Ido",
+        "nativeName" => "Ido"
+    ),
+    "is" => array(
+        "name" => "Icelandic",
+        "nativeName" => "Íslenska"
+    ),
+    "it" => array(
+        "name" => "Italian",
+        "nativeName" => "Italiano"
+    ),
+    "iu" => array(
+        "name" => "Inuktitut",
+        "nativeName" => "ᐃᓄᒃᑎᑐᑦ"
+    ),
+    "ja" => array(
+        "name" => "Japanese",
+        "nativeName" => "日本語 (にほんご/にっぽんご)"
+    ),
+    "jv" => array(
+        "name" => "Javanese",
+        "nativeName" => "basa Jawa"
+    ),
+    "kl" => array(
+        "name" => "Kalaallisut, Greenlandic",
+        "nativeName" => "kalaallisut, kalaallit oqaasii"
+    ),
+    "kn" => array(
+        "name" => "Kannada",
+        "nativeName" => "ಕನ್ನಡ"
+    ),
+    "kr" => array(
+        "name" => "Kanuri",
+        "nativeName" => "Kanuri"
+    ),
+    "ks" => array(
+        "name" => "Kashmiri",
+        "nativeName" => "कश्मीरी, كشميري‎"
+    ),
+    "kk" => array(
+        "name" => "Kazakh",
+        "nativeName" => "Қазақ тілі"
+    ),
+    "km" => array(
+        "name" => "Khmer",
+        "nativeName" => "ភាសាខ្មែរ"
+    ),
+    "ki" => array(
+        "name" => "Kikuyu, Gikuyu",
+        "nativeName" => "Gĩkũyũ"
+    ),
+    "rw" => array(
+        "name" => "Kinyarwanda",
+        "nativeName" => "Ikinyarwanda"
+    ),
+    "ky" => array(
+        "name" => "Kirghiz, Kyrgyz",
+        "nativeName" => "кыргыз тили"
+    ),
+    "kv" => array(
+        "name" => "Komi",
+        "nativeName" => "коми кыв"
+    ),
+    "kg" => array(
+        "name" => "Kongo",
+        "nativeName" => "KiKongo"
+    ),
+    "ko" => array(
+        "name" => "Korean",
+        "nativeName" => "한국어 (韓國語), 조선말 (朝鮮語)"
+    ),
+    "ku" => array(
+        "name" => "Kurdish",
+        "nativeName" => "Kurdî, كوردی‎"
+    ),
+    "kj" => array(
+        "name" => "Kwanyama, Kuanyama",
+        "nativeName" => "Kuanyama"
+    ),
+    "la" => array(
+        "name" => "Latin",
+        "nativeName" => "latine, lingua latina"
+    ),
+    "lb" => array(
+        "name" => "Luxembourgish, Letzeburgesch",
+        "nativeName" => "Lëtzebuergesch"
+    ),
+    "lg" => array(
+        "name" => "Luganda",
+        "nativeName" => "Luganda"
+    ),
+    "li" => array(
+        "name" => "Limburgish, Limburgan, Limburger",
+        "nativeName" => "Limburgs"
+    ),
+    "ln" => array(
+        "name" => "Lingala",
+        "nativeName" => "Lingála"
+    ),
+    "lo" => array(
+        "name" => "Lao",
+        "nativeName" => "ພາສາລາວ"
+    ),
+    "lt" => array(
+        "name" => "Lithuanian",
+        "nativeName" => "lietuvių kalba"
+    ),
+    "lu" => array(
+        "name" => "Luba-Katanga",
+        "nativeName" => ""
+    ),
+    "lv" => array(
+        "name" => "Latvian",
+        "nativeName" => "latviešu valoda"
+    ),
+    "gv" => array(
+        "name" => "Manx",
+        "nativeName" => "Gaelg, Gailck"
+    ),
+    "mk" => array(
+        "name" => "Macedonian",
+        "nativeName" => "македонски јазик"
+    ),
+    "mg" => array(
+        "name" => "Malagasy",
+        "nativeName" => "Malagasy fiteny"
+    ),
+    "ms" => array(
+        "name" => "Malay",
+        "nativeName" => "bahasa Melayu, بهاس ملايو‎"
+    ),
+    "ml" => array(
+        "name" => "Malayalam",
+        "nativeName" => "മലയാളം"
+    ),
+    "mt" => array(
+        "name" => "Maltese",
+        "nativeName" => "Malti"
+    ),
+    "mi" => array(
+        "name" => "Māori",
+        "nativeName" => "te reo Māori"
+    ),
+    "mr" => array(
+        "name" => "Marathi (Marāṭhī)",
+        "nativeName" => "मराठी"
+    ),
+    "mh" => array(
+        "name" => "Marshallese",
+        "nativeName" => "Kajin M̧ajeļ"
+    ),
+    "mn" => array(
+        "name" => "Mongolian",
+        "nativeName" => "монгол"
+    ),
+    "na" => array(
+        "name" => "Nauru",
+        "nativeName" => "Ekakairũ Naoero"
+    ),
+    "nv" => array(
+        "name" => "Navajo, Navaho",
+        "nativeName" => "Diné bizaad, Dinékʼehǰí"
+    ),
+    "nb" => array(
+        "name" => "Norwegian Bokmål",
+        "nativeName" => "Norsk bokmål"
+    ),
+    "nd" => array(
+        "name" => "North Ndebele",
+        "nativeName" => "isiNdebele"
+    ),
+    "ne" => array(
+        "name" => "Nepali",
+        "nativeName" => "नेपाली"
+    ),
+    "ng" => array(
+        "name" => "Ndonga",
+        "nativeName" => "Owambo"
+    ),
+    "nn" => array(
+        "name" => "Norwegian Nynorsk",
+        "nativeName" => "Norsk nynorsk"
+    ),
+    "no" => array(
+        "name" => "Norwegian",
+        "nativeName" => "Norsk"
+    ),
+    "ii" => array(
+        "name" => "Nuosu",
+        "nativeName" => "ꆈꌠ꒿ Nuosuhxop"
+    ),
+    "nr" => array(
+        "name" => "South Ndebele",
+        "nativeName" => "isiNdebele"
+    ),
+    "oc" => array(
+        "name" => "Occitan",
+        "nativeName" => "Occitan"
+    ),
+    "oj" => array(
+        "name" => "Ojibwe, Ojibwa",
+        "nativeName" => "ᐊᓂᔑᓈᐯᒧᐎᓐ"
+    ),
+    "cu" => array(
+        "name" => "Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic",
+        "nativeName" => "ѩзыкъ словѣньскъ"
+    ),
+    "om" => array(
+        "name" => "Oromo",
+        "nativeName" => "Afaan Oromoo"
+    ),
+    "or" => array(
+        "name" => "Oriya",
+        "nativeName" => "ଓଡ଼ିଆ"
+    ),
+    "os" => array(
+        "name" => "Ossetian, Ossetic",
+        "nativeName" => "ирон æвзаг"
+    ),
+    "pa" => array(
+        "name" => "Panjabi, Punjabi",
+        "nativeName" => "ਪੰਜਾਬੀ, پنجابی‎"
+    ),
+    "pi" => array(
+        "name" => "Pāli",
+        "nativeName" => "पाऴि"
+    ),
+    "fa" => array(
+        "name" => "Persian",
+        "nativeName" => "فارسی"
+    ),
+    "pl" => array(
+        "name" => "Polish",
+        "nativeName" => "polski"
+    ),
+    "ps" => array(
+        "name" => "Pashto, Pushto",
+        "nativeName" => "پښتو"
+    ),
+    "pt" => array(
+        "name" => "Portuguese",
+        "nativeName" => "Português"
+    ),
+    "qu" => array(
+        "name" => "Quechua",
+        "nativeName" => "Runa Simi, Kichwa"
+    ),
+    "rm" => array(
+        "name" => "Romansh",
+        "nativeName" => "rumantsch grischun"
+    ),
+    "rn" => array(
+        "name" => "Kirundi",
+        "nativeName" => "kiRundi"
+    ),
+    "ro" => array(
+        "name" => "Romanian, Moldavian, Moldovan",
+        "nativeName" => "română"
+    ),
+    "ru" => array(
+        "name" => "Russian",
+        "nativeName" => "русский язык"
+    ),
+    "sa" => array(
+        "name" => "Sanskrit (Saṁskṛta)",
+        "nativeName" => "संस्कृतम्"
+    ),
+    "sc" => array(
+        "name" => "Sardinian",
+        "nativeName" => "sardu"
+    ),
+    "sd" => array(
+        "name" => "Sindhi",
+        "nativeName" => "सिन्धी, سنڌي، سندھی‎"
+    ),
+    "se" => array(
+        "name" => "Northern Sami",
+        "nativeName" => "Davvisámegiella"
+    ),
+    "sm" => array(
+        "name" => "Samoan",
+        "nativeName" => "gagana faa Samoa"
+    ),
+    "sg" => array(
+        "name" => "Sango",
+        "nativeName" => "yângâ tî sängö"
+    ),
+    "sr" => array(
+        "name" => "Serbian",
+        "nativeName" => "српски језик"
+    ),
+    "gd" => array(
+        "name" => "Scottish Gaelic; Gaelic",
+        "nativeName" => "Gàidhlig"
+    ),
+    "sn" => array(
+        "name" => "Shona",
+        "nativeName" => "chiShona"
+    ),
+    "si" => array(
+        "name" => "Sinhala, Sinhalese",
+        "nativeName" => "සිංහල"
+    ),
+    "sk" => array(
+        "name" => "Slovak",
+        "nativeName" => "slovenčina"
+    ),
+    "sl" => array(
+        "name" => "Slovene",
+        "nativeName" => "slovenščina"
+    ),
+    "so" => array(
+        "name" => "Somali",
+        "nativeName" => "Soomaaliga, af Soomaali"
+    ),
+    "st" => array(
+        "name" => "Southern Sotho",
+        "nativeName" => "Sesotho"
+    ),
+    "es" => array(
+        "name" => "Spanish; Castilian",
+        "nativeName" => "español, castellano"
+    ),
+    "su" => array(
+        "name" => "Sundanese",
+        "nativeName" => "Basa Sunda"
+    ),
+    "sw" => array(
+        "name" => "Swahili",
+        "nativeName" => "Kiswahili"
+    ),
+    "ss" => array(
+        "name" => "Swati",
+        "nativeName" => "SiSwati"
+    ),
+    "sv" => array(
+        "name" => "Swedish",
+        "nativeName" => "svenska"
+    ),
+    "ta" => array(
+        "name" => "Tamil",
+        "nativeName" => "தமிழ்"
+    ),
+    "te" => array(
+        "name" => "Telugu",
+        "nativeName" => "తెలుగు"
+    ),
+    "tg" => array(
+        "name" => "Tajik",
+        "nativeName" => "тоҷикӣ, toğikī, تاجیکی‎"
+    ),
+    "th" => array(
+        "name" => "Thai",
+        "nativeName" => "ไทย"
+    ),
+    "ti" => array(
+        "name" => "Tigrinya",
+        "nativeName" => "ትግርኛ"
+    ),
+    "bo" => array(
+        "name" => "Tibetan Standard, Tibetan, Central",
+        "nativeName" => "བོད་ཡིག"
+    ),
+    "tk" => array(
+        "name" => "Turkmen",
+        "nativeName" => "Türkmen, Түркмен"
+    ),
+    "tl" => array(
+        "name" => "Tagalog",
+        "nativeName" => "Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔"
+    ),
+    "tn" => array(
+        "name" => "Tswana",
+        "nativeName" => "Setswana"
+    ),
+    "to" => array(
+        "name" => "Tonga (Tonga Islands)",
+        "nativeName" => "faka Tonga"
+    ),
+    "tr" => array(
+        "name" => "Turkish",
+        "nativeName" => "Türkçe"
+    ),
+    "ts" => array(
+        "name" => "Tsonga",
+        "nativeName" => "Xitsonga"
+    ),
+    "tt" => array(
+        "name" => "Tatar",
+        "nativeName" => "татарча, tatarça, تاتارچا‎"
+    ),
+    "tw" => array(
+        "name" => "Twi",
+        "nativeName" => "Twi"
+    ),
+    "ty" => array(
+        "name" => "Tahitian",
+        "nativeName" => "Reo Tahiti"
+    ),
+    "ug" => array(
+        "name" => "Uighur, Uyghur",
+        "nativeName" => "Uyƣurqə, ئۇيغۇرچە‎"
+    ),
+    "uk" => array(
+        "name" => "Ukrainian",
+        "nativeName" => "українська"
+    ),
+    "ur" => array(
+        "name" => "Urdu",
+        "nativeName" => "اردو"
+    ),
+    "uz" => array(
+        "name" => "Uzbek",
+        "nativeName" => "zbek, Ўзбек, أۇزبېك‎"
+    ),
+    "ve" => array(
+        "name" => "Venda",
+        "nativeName" => "Tshivenḓa"
+    ),
+    "vi" => array(
+        "name" => "Vietnamese",
+        "nativeName" => "Tiếng Việt"
+    ),
+    "vo" => array(
+        "name" => "Volapük",
+        "nativeName" => "Volapük"
+    ),
+    "wa" => array(
+        "name" => "Walloon",
+        "nativeName" => "Walon"
+    ),
+    "cy" => array(
+        "name" => "Welsh",
+        "nativeName" => "Cymraeg"
+    ),
+    "wo" => array(
+        "name" => "Wolof",
+        "nativeName" => "Wollof"
+    ),
+    "fy" => array(
+        "name" => "Western Frisian",
+        "nativeName" => "Frysk"
+    ),
+    "xh" => array(
+        "name" => "Xhosa",
+        "nativeName" => "isiXhosa"
+    ),
+    "yi" => array(
+        "name" => "Yiddish",
+        "nativeName" => "ייִדיש"
+    ),
+    "yo" => array(
+        "name" => "Yoruba",
+        "nativeName" => "Yorùbá"
+    ),
+    "za" => array(
+        "name" => "Zhuang, Chuang",
+        "nativeName" => "Saɯ cueŋƅ, Saw cuengh"
+    )
+);
diff --git a/include/staff/profile.inc.php b/include/staff/profile.inc.php
index 8ceaca328452056ad3829a00ae69f64c85dae52e..116a39eab0617425965850687298f47999bfb77d 100644
--- a/include/staff/profile.inc.php
+++ b/include/staff/profile.inc.php
@@ -100,6 +100,24 @@ $info['id']=$staff->getId();
                 &nbsp;<span class="error">*&nbsp;<?php echo $errors['timezone_id']; ?></span>
             </td>
         </tr>
+        <tr>
+            <td width="180">
+                Preferred Language:
+            </td>
+            <td>
+        <?php
+        $langs = Internationalization::availableLanguages(); ?>
+                <select name="lang">
+                    <option value="">&mdash; Use Browser Preference &mdash;</option>
+<?php foreach($langs as $l) {
+    $selected = ($info['lang'] == $l['code']) ? 'selected="selected"' : ''; ?>
+                    <option value="<?php echo $l['code']; ?>" <?php echo $selected;
+                        ?>><?php echo $l['desc']; ?></option>
+<?php } ?>
+                </select>
+                <span class="error">&nbsp;<?php echo $errors['lang']; ?></span>
+            </td>
+        </tr>
         <tr>
             <td width="180">
                Daylight Saving:
diff --git a/include/staff/template.inc.php b/include/staff/template.inc.php
index 8fee6a2ce6a8bae63c9273b99eafa178c48d0214..2d05235eecb07d2a20c5d389fc58b1aaf763a022 100644
--- a/include/staff/template.inc.php
+++ b/include/staff/template.inc.php
@@ -15,6 +15,7 @@ if($template && $_REQUEST['a']!='add'){
     $action='add';
     $submit_text='Add Template';
     $info['isactive']=isset($info['isactive'])?$info['isactive']:0;
+    $info['lang_id'] = $cfg->getSystemLanguage();
     $qstr.='&a='.urlencode($_REQUEST['a']);
 }
 $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
@@ -54,19 +55,22 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">*&nbsp;<?php echo $errors['isactive']; ?></span>
             </td>
         </tr>
+        <?php
+        if($template){ ?>
         <tr>
             <td width="180" class="required">
                 Language:
             </td>
             <td>
-                <select name="lang_id">
-                    <option value="en" selected="selected">English (US)</option>
-                </select>
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['lang_id']; ?></span>
+                <?php
+            $langs = Internationalization::availableLanguages();
+            $lang = strtolower($info['lang']);
+            if (isset($langs[$lang]))
+                echo $langs[$lang]['desc'];
+            else
+                echo $info['lang']; ?>
             </td>
         </tr>
-        <?php
-        if($template){ ?>
         <tr>
             <th colspan="2">
                 <em><strong>Template Messages</strong>: Click on the message to edit.&nbsp;
@@ -100,6 +104,23 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             }
         }
         }else{ ?>
+        <tr>
+            <td width="180" class="required">
+                Language:
+            </td>
+            <td>
+        <?php
+        $langs = Internationalization::availableLanguages(); ?>
+                <select name="lang_id">
+<?php foreach($langs as $l) {
+    $selected = ($info['lang_id'] == $l['code']) ? 'selected="selected"' : ''; ?>
+                    <option value="<?php echo $l['code']; ?>" <?php echo $selected;
+                        ?>><?php echo $l['desc']; ?></option>
+<?php } ?>
+                </select>
+                &nbsp;<span class="error">*&nbsp;<?php echo $errors['lang_id']; ?></span>
+            </td>
+        </tr>
         <tr>
             <td width="180" class="required">
                 Template To Clone:
diff --git a/scp/ajax.php b/scp/ajax.php
index 01b41867dd53bc052d5a7b9c8765327b140e3739..7e990934b8abe59b1b9a1aecfd3ccd91cfb06271 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -101,8 +101,8 @@ $dispatcher = patterns('',
     )),
     url_post('^/upgrader', array('ajax.upgrader.php:UpgraderAjaxAPI', 'upgrade')),
     url('^/help/', patterns('ajax.tips.php:HelpTipAjaxAPI',
-        url_get('tips/(?P<namespace>[\w_.]+)$', 'getTipsJson'),
-        url_get('(?P<lang>\w{2}_\w{2})?/tips/(?P<namespace>[\w_.]+)$', 'getTipsForLangJson')
+        url_get('^tips/(?P<namespace>[\w_.]+)$', 'getTipsJson'),
+        url_get('^(?P<lang>[\w_]+)?/tips/(?P<namespace>[\w_.]+)$', 'getTipsJsonForLang')
     ))
 );
 
diff --git a/setup/ajax.php b/setup/ajax.php
index 9c2c7b282a325f135f3dde4e8e80491860666b31..97e45daddc88ece9cd65e24ea71dfb9f0d7ac8b9 100644
--- a/setup/ajax.php
+++ b/setup/ajax.php
@@ -23,8 +23,8 @@ require_once INCLUDE_DIR.'/class.ajax.php';
 
 $dispatcher = patterns('',
     url('^/help/', patterns('ajax.tips.php:HelpTipAjaxAPI',
-        url_get('tips/(?P<namespace>[\w_]+)$', 'getTipsJson'),
-        url_get('(?P<lang>\w{2}_\w{2})?/tips/(?P<namespace>[\w_]+)$', 'getTipsForLangJson')
+        url_get('^tips/(?P<namespace>[\w_.]+)$', 'getTipsJson'),
+        url_get('^(?P<lang>[\w_]+)?/tips/(?P<namespace>[\w_.]+)$', 'getTipsJsonForLang')
     ))
 );
 print $dispatcher->resolve(Osticket::get_path_info());
diff --git a/setup/cli/cli.inc.php b/setup/cli/cli.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..31bdbfe8993cdadadbc4896c1e9257b3909b8cc0
--- /dev/null
+++ b/setup/cli/cli.inc.php
@@ -0,0 +1,31 @@
+<?php
+/*********************************************************************
+    cli.inc.php
+
+    Master include file which must be included at the start of every file.
+    This is a modification of main.inc.php to support running cli scripts.
+
+    Peter Rotich <peter@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:
+**********************************************************************/
+
+#Disable direct access.
+if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!');
+
+define('ROOT_PATH', '/');
+define('INC_DIR',dirname(__file__).'/../inc/'); //local include dir!
+
+require_once(dirname(__file__).'/../../bootstrap.php');
+
+Bootstrap::loadConfig();
+Bootstrap::defineTables(TABLE_PREFIX);
+Bootstrap::loadCode();
+Bootstrap::i18n_prep();
+
+?>
diff --git a/setup/cli/modules/class.module.php b/setup/cli/modules/class.module.php
index 437f87c609eb6b63f6799978ce324f437a456ca5..421e49bd11a22f115af0e9d3c288099f07859e3f 100644
--- a/setup/cli/modules/class.module.php
+++ b/setup/cli/modules/class.module.php
@@ -227,6 +227,11 @@ class Module {
     function run($args, $options) {
     }
 
+    function fail($message) {
+        $this->stderr->write($message . "\n");
+        die();
+    }
+
     /* static */
     function register($action, $class) {
         global $registered_modules;
diff --git a/setup/cli/modules/i18n.php b/setup/cli/modules/i18n.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9a4117c4b15f59d6914dbd11edf741b1c5544b7
--- /dev/null
+++ b/setup/cli/modules/i18n.php
@@ -0,0 +1,130 @@
+<?php
+
+require_once dirname(__file__) . "/class.module.php";
+require_once dirname(__file__) . "/../cli.inc.php";
+require_once INCLUDE_DIR . 'class.format.php';
+
+class i18n_Compiler extends Module {
+
+    var $prologue = "Manages translation files from Crowdin";
+
+    var $arguments = array(
+        "command" => "Action to be performed.
+            list    - Show list of available translations"
+    );
+
+    var $options = array(
+        "key" => array('-k','--key','metavar'=>'API-KEY',
+            'help'=>'Crowdin project API key. This can be omitted if
+            CROWDIN_API_KEY is defined in the ost-config.php file'),
+        "lang" => array('-L', '--lang', 'metavar'=>'code',
+            'help'=>'Language code (used for building)'),
+    );
+
+    static $crowdin_api_url = 'http://i18n.osticket.com/api/project/osticket-official/{command}';
+
+    function _http_get($url) {
+        #curl post
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_USERAGENT, 'osTicket/'.THIS_VERSION);
+        curl_setopt($ch, CURLOPT_HEADER, FALSE);
+        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+        $result=curl_exec($ch);
+        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+        curl_close($ch);
+
+        return array($code, $result);
+    }
+
+    function _request($command, $args=array()) {
+
+        $url = str_replace('{command}', $command, self::$crowdin_api_url);
+
+        $args += array('key' => $this->key);
+        foreach ($args as &$a)
+            $a = urlencode($a);
+        unset($a);
+        $url .= '?' . Format::array_implode('=', '&', $args);
+
+        return $this->_http_get($url);
+    }
+
+    function run($args, $options) {
+        $this->key = $options['key'];
+        if (!$this->key && defined('CROWDIN_API_KEY'))
+            $this->key = CROWDIN_API_KEY;
+
+        switch (strtolower($args['command'])) {
+        case 'list':
+            if (!$this->key)
+                $this->fail('API key is required');
+            $this->_list();
+            break;
+        case 'build':
+            if (!$this->key)
+                $this->fail('API key is required');
+            if (!$options['lang'])
+                $this->fail('Language code is required. See `list`');
+            $this->_build($options['lang']);
+            break;
+        }
+    }
+
+    function _list() {
+        error_reporting(E_ALL);
+        list($code, $body) = $this->_request('status');
+        $d = new DOMDocument();
+        $d->loadXML($body);
+
+        $xp = new DOMXpath($d);
+        foreach ($xp->query('//language') as $c) {
+            $name = $code = '';
+            foreach ($c->childNodes as $n) {
+                switch (strtolower($n->nodeName)) {
+                case 'name':
+                    $name = $n->textContent;
+                    break;
+                case 'code':
+                    $code = $n->textContent;
+                    break;
+                }
+            }
+            if (!$code)
+                continue;
+            $this->stdout->write(sprintf("%s (%s)\n", $code, $name));
+        }
+    }
+
+    function _build($lang) {
+        list($code, $zip) = $this->_request("download/$lang.zip");
+
+        if ($code !== 200)
+            $this->fail('Language is not available'."\n");
+
+        $temp = tempnam('/tmp', 'osticket-cli');
+        $f = fopen($temp, 'w');
+        fwrite($f, $zip);
+        fclose($f);
+        $zip = new ZipArchive();
+        $zip->open($temp);
+        unlink($temp);
+
+        $lang = str_replace('-','_',$lang);
+        @unlink(I18N_DIR."$lang.phar");
+        $phar = new Phar(I18N_DIR."$lang.phar");
+
+        for ($i=0; $i<$zip->numFiles; $i++) {
+            $info = $zip->statIndex($i);
+            $phar->addFromString($info['name'], $zip->getFromIndex($i));
+        }
+
+        // TODO: Add i18n extras (like fonts)
+
+        // TODO: Sign files
+    }
+}
+
+Module::register('i18n', 'i18n_Compiler');
+?>
diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php
index d57fa0b449095e9bb88a1cb3b9004dd0a1325c5a..4ec86eee5479e8902871bc1081f407e19deb3bda 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 {
 
@@ -149,10 +150,9 @@ class Installer extends SetupWizard {
         }
 
         if(!$this->errors) {
-            // TODO: Use language selected from install worksheet
-            require_once INCLUDE_DIR.'class.i18n.php';
 
-            $i18n = new Internationalization('en_US');
+            // TODO: Use language selected from install worksheet
+            $i18n = new Internationalization($vars['lang_id']);
             $i18n->loadDefaultData();
 
             $sql='SELECT `id` FROM '.PREFIX.'sla ORDER BY `id` LIMIT 1';
diff --git a/setup/inc/install.inc.php b/setup/inc/install.inc.php
index e2d6a5a0f3b87b28f7466a91780b2d5d932956fb..f58943a2fc450022077fd2d1ba59f752b636c66f 100644
--- a/setup/inc/install.inc.php
+++ b/setup/inc/install.inc.php
@@ -1,8 +1,8 @@
-<?php 
+<?php
 if(!defined('SETUPINC')) die('Kwaheri!');
-$info=($_POST && $errors)?Format::htmlchars($_POST):array('prefix'=>'ost_','dbhost'=>'localhost');
+$info=($_POST && $errors)?Format::htmlchars($_POST):array('prefix'=>'ost_','dbhost'=>'localhost','lang_id'=>'en_US');
 ?>
-<div id="main" class="step2">        
+<div id="main" class="step2">
     <h1>osTicket Basic Installation</h1>
             <p>Please fill out the information below to continue your osTicket installation. All fields are required.</p>
             <font class="error"><strong><?php echo $errors['err']; ?></strong></font>
@@ -26,6 +26,19 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):array('prefix'=>'ost_','dbho
                     <a class="tip" href="#system_email"><i class="icon-question-sign help-tip"></i></a>
                     <font class="error"><?php echo $errors['email']; ?></font>
                 </div>
+                <div class="row">
+                    <label>Default Language:</label>
+<?php $langs = Internationalization::availableLanguages(); ?>
+                <select name="lang_id">
+<?php foreach($langs as $l) {
+    $selected = ($info['lang_id'] == $l['code']) ? 'selected="selected"' : ''; ?>
+                    <option value="<?php echo $l['code']; ?>" <?php echo $selected;
+                        ?>><?php echo $l['desc']; ?></option>
+<?php } ?>
+                </select>
+                <a class="tip" href="#default_lang"><i class="icon-question-sign help-tip"></i></a>
+                <font class="error">&nbsp;<?php echo $errors['lang_id']; ?></font>
+                </div>
 
                 <h4 class="head admin">Admin User</h4>
                 <span class="subhead">Your primary administrator account - you can add more users later.</span>