diff --git a/interface/web/admin/form/software_repo.tform.php b/interface/web/admin/form/software_repo.tform.php
new file mode 100644
index 0000000000000000000000000000000000000000..cffcd0137a79abf3decde3d4f3c6e41f8ceb2eb0
--- /dev/null
+++ b/interface/web/admin/form/software_repo.tform.php
@@ -0,0 +1,153 @@
+ 0 id must match with id of current user
+$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user
+$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete
+$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete
+
+$form["tabs"]['software_repo'] = array (
+ 'title' => "Repository",
+ 'width' => 80,
+ 'template' => "templates/software_repo_edit.htm",
+ 'fields' => array (
+ ##################################
+ # Beginn Datenbankfelder
+ ##################################
+ 'repo_name' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'TEXT',
+ 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY',
+ 'errmsg'=> 'repo_name_empty'),
+ 1 => array ( 'type' => 'UNIQUE',
+ 'errmsg'=> 'repo_name_unique'),
+ ),
+ 'default' => '',
+ 'value' => '',
+ 'separator' => '',
+ 'width' => '40',
+ 'maxlength' => '40',
+ 'rows' => '',
+ 'cols' => ''
+ ),
+ 'repo_url' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'TEXT',
+ 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY',
+ 'errmsg'=> 'repo_name_empty'),
+ 1 => array ( 'type' => 'UNIQUE',
+ 'errmsg'=> 'repo_name_unique'),
+ ),
+ 'default' => '',
+ 'value' => '',
+ 'separator' => '',
+ 'width' => '40',
+ 'maxlength' => '40',
+ 'rows' => '',
+ 'cols' => ''
+ ),
+ 'repo_username' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'TEXT',
+ 'default' => '',
+ 'value' => '',
+ 'separator' => '',
+ 'width' => '30',
+ 'maxlength' => '30',
+ 'rows' => '',
+ 'cols' => ''
+ ),
+ 'repo_password' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'PASSWORD',
+ 'encryption' => 'CLEARTEXT',
+ 'default' => '',
+ 'value' => '',
+ 'separator' => '',
+ 'width' => '30',
+ 'maxlength' => '30',
+ 'rows' => '',
+ 'cols' => ''
+ ),
+ 'active' => array (
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'CHECKBOX',
+ 'default' => 'y',
+ 'value' => array(0 => 'n',1 => 'y')
+ ),
+ ##################################
+ # ENDE Datenbankfelder
+ ##################################
+ )
+);
+?>
\ No newline at end of file
diff --git a/interface/web/admin/language_complete.php b/interface/web/admin/language_complete.php
new file mode 100644
index 0000000000000000000000000000000000000000..4f45724cc21ef9866f7cf976d3a9d1b278de4742
--- /dev/null
+++ b/interface/web/admin/language_complete.php
@@ -0,0 +1,146 @@
+auth->check_module_permissions('admin');
+
+//* This is only allowed for administrators
+if(!$app->auth->is_admin()) die('only allowed for administrators.');
+
+$app->uses('tpl');
+
+$app->tpl->newTemplate('form.tpl.htm');
+$app->tpl->setInclude('content_tpl', 'templates/language_complete.htm');
+
+//* reading languages
+$language_option = '';
+$error = '';
+$msg = '';
+$selected_language = (isset($_REQUEST['lng_select']))?substr($_REQUEST['lng_select'],0,2):'en';
+if(!preg_match("/^[a-z]{2}$/i", $selected_language)) die('unallowed characters in selected language name.');
+
+$handle = opendir(ISPC_ROOT_PATH.'/lib/lang/');
+while ($file = readdir ($handle)) {
+ if ($file != '.' && $file != '..') {
+ $tmp_lng = substr($file,0,-4);
+ if($tmp_lng !='' && $tmp_lng != 'en') {
+ $selected = ($tmp_lng == $selected_language)?'SELECTED':'';
+ $language_option .= "";
+ //if(isset($_POST['lng_new']) && $_POST['lng_new'] == $tmp_lng) $error = 'Language exists already.';
+ }
+ }
+}
+$app->tpl->setVar('language_option',$language_option);
+$app->tpl->setVar('error',$error);
+
+// Export the language file
+if(isset($_POST['lng_select']) && $error == '') {
+
+ // complete the global langauge file
+ merge_langfile(ISPC_LIB_PATH."/lang/".$selected_language.".lng",ISPC_LIB_PATH."/lang/en.lng");
+
+ // Go trough all language files
+ $bgcolor = '#FFFFFF';
+ $language_files_list = array();
+ $handle = @opendir(ISPC_WEB_PATH);
+ while ($file = @readdir ($handle)) {
+ if ($file != '.' && $file != '..') {
+ if(@is_dir(ISPC_WEB_PATH.'/'.$file.'/lib/lang')) {
+ $handle2 = opendir(ISPC_WEB_PATH.'/'.$file.'/lib/lang');
+ while ($lang_file = @readdir ($handle2)) {
+ if ($lang_file != '.' && $lang_file != '..' && substr($lang_file,0,2) == 'en') {
+ $target_lang_file = $selected_language.substr($lang_file,2);
+ merge_langfile(ISPC_WEB_PATH.'/'.$file.'/lib/lang/'.$target_lang_file,ISPC_WEB_PATH.'/'.$file.'/lib/lang/'.$lang_file);
+ }
+ }
+ }
+ }
+ }
+}
+
+function merge_langfile($langfile,$masterfile) {
+ global $msg;
+
+ if(is_file($langfile)) {
+
+ // Load the english language file
+ include($masterfile);
+ if(isset($wb) && is_array($wb)) {
+ $wb_master = $wb;
+ unset($wb);
+ } else {
+ $wb_master = array();
+ }
+
+ // Load the incomplete language file
+ $wb = array();
+ include($langfile);
+
+ $n = 0;
+ foreach($wb_master as $key => $val) {
+ if(!isset($wb[$key])) {
+ $wb[$key] = $val;
+ $n++;
+ }
+ }
+
+ $file_content = " $val) {
+ $val = str_replace("'",'',$val);
+ $val = str_replace('"','',$val);
+ $file_content .= '$wb['."'$key'".'] = '."'$val';\n";
+ }
+ $file_content .= "?>\n";
+
+ $msg .= "Added $n lines to the file $langfile
";
+ file_put_contents($langfile ,$file_content);
+ } else {
+ $msg .= "File does not exist yet. Copied file $masterfile to $langfile
";
+ copy($masterfile,$langfile);
+ }
+}
+
+
+
+
+$app->tpl->setVar('msg',$msg);
+
+//* load language file
+$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_language_complete.lng';
+include($lng_file);
+$app->tpl->setVar($wb);
+
+$app->tpl_defaults();
+$app->tpl->pparse();
+
+
+?>
\ No newline at end of file
diff --git a/interface/web/admin/lib/lang/en_language_complete.lng b/interface/web/admin/lib/lang/en_language_complete.lng
new file mode 100644
index 0000000000000000000000000000000000000000..734e75c5fa1b4dfc21da233155aef37520cf6a8a
--- /dev/null
+++ b/interface/web/admin/lib/lang/en_language_complete.lng
@@ -0,0 +1,6 @@
+This adds missing strings from the english master language files to the selected language.';
+$wb["language_select_txt"] = 'Select language';
+$wb['btn_save_txt'] = 'Merge files now';
+$wb['btn_cancel_txt'] = 'Back';
+?>
\ No newline at end of file
diff --git a/interface/web/admin/lib/module.conf.php b/interface/web/admin/lib/module.conf.php
index a37dd96969e473e3b5a4e991ea024e5797c730ee..5b631553f26bca3673cd20d0cc6db2b235b7c4d4 100644
--- a/interface/web/admin/lib/module.conf.php
+++ b/interface/web/admin/lib/module.conf.php
@@ -136,6 +136,10 @@ $items[] = array( 'title' => 'New Language',
'target' => 'content',
'link' => 'admin/language_add.php');
+$items[] = array( 'title' => 'Merge',
+ 'target' => 'content',
+ 'link' => 'admin/language_complete.php');
+
$items[] = array( 'title' => 'Export',
'target' => 'content',
'link' => 'admin/language_export.php');
diff --git a/interface/web/admin/templates/language_complete.htm b/interface/web/admin/templates/language_complete.htm
new file mode 100644
index 0000000000000000000000000000000000000000..144e9ebcc163d1d5f38dbaeacde9455ac415f06f
--- /dev/null
+++ b/interface/web/admin/templates/language_complete.htm
@@ -0,0 +1,12 @@
+
+