From 15ae2165165da813912300d223c50b74f44cc1e0 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 9 Nov 2018 14:25:57 +0000 Subject: [PATCH] ttOrgImportHelper class impoved to output conflicting login names. --- WEB-INF/lib/ttOrgImportHelper.class.php | 54 +++++++++---------------- WEB-INF/resources/ca.lang.php | 1 + WEB-INF/resources/cs.lang.php | 1 + WEB-INF/resources/da.lang.php | 2 + WEB-INF/resources/de.lang.php | 2 + WEB-INF/resources/en.lang.php | 1 + WEB-INF/resources/es.lang.php | 1 + WEB-INF/resources/et.lang.php | 2 + WEB-INF/resources/fa.lang.php | 1 + WEB-INF/resources/fi.lang.php | 2 + WEB-INF/resources/fr.lang.php | 2 + WEB-INF/resources/gr.lang.php | 2 + WEB-INF/resources/he.lang.php | 1 + WEB-INF/resources/hu.lang.php | 1 + WEB-INF/resources/it.lang.php | 2 + WEB-INF/resources/ja.lang.php | 1 + WEB-INF/resources/ko.lang.php | 1 + WEB-INF/resources/nl.lang.php | 2 + WEB-INF/resources/no.lang.php | 1 + WEB-INF/resources/pl.lang.php | 2 + WEB-INF/resources/pt-br.lang.php | 2 + WEB-INF/resources/pt.lang.php | 1 + WEB-INF/resources/ro.lang.php | 1 + WEB-INF/resources/ru.lang.php | 1 + WEB-INF/resources/sk.lang.php | 1 + WEB-INF/resources/sl.lang.php | 1 + WEB-INF/resources/sr.lang.php | 2 + WEB-INF/resources/sv.lang.php | 2 + WEB-INF/resources/tr.lang.php | 1 + WEB-INF/resources/zh-cn.lang.php | 1 + WEB-INF/resources/zh-tw.lang.php | 1 + 31 files changed, 61 insertions(+), 35 deletions(-) diff --git a/WEB-INF/lib/ttOrgImportHelper.class.php b/WEB-INF/lib/ttOrgImportHelper.class.php index c70d2580..b22c4fe3 100644 --- a/WEB-INF/lib/ttOrgImportHelper.class.php +++ b/WEB-INF/lib/ttOrgImportHelper.class.php @@ -27,28 +27,17 @@ // +----------------------------------------------------------------------+ import('ttUserHelper'); -import('ttProjectHelper'); -import('ttTaskHelper'); -import('ttInvoiceHelper'); -import('ttTimeHelper'); -import('ttClientHelper'); -import('ttCustomFieldHelper'); -import('ttFavReportHelper'); -import('ttExpenseHelper'); -import('ttRoleHelper'); // ttOrgImportHelper - this class is a future replacement for ttImportHelper. // Currently, it is work in progress. // When done, it should handle import of complex groups consisting of other groups. class ttOrgImportHelper { var $errors = null; // Errors go here. Set in constructor by reference. - - var $currentElement = array(); // Current element of the XML file we are parsing. - var $currentTag = ''; // XML tag of the current element. + var $cannotImport = null; // A comma-separated string of entity names that we cannot import. + // TODO: rename the above to something better. var $canImport = true; // False if we cannot import data due to a login collision. var $firstPass = true; // True during first pass through the file. - var $org_id = null; // Organization id (same as top group_id). var $current_parent_group_id = null; // Current parent group id as we parse the file. // Set when we create a new group. @@ -71,38 +60,32 @@ class ttOrgImportHelper { // startElement - callback handler for opening tag of an XML element in the file. function startElement($parser, $name, $attrs) { -/* - if ($name == 'GROUP' - || $name == 'USER') { - $this->currentElement = $attrs; - } - $this->currentTag = $name; -*/ + // First pass. We only check user logins for potential collisions with existing. if ($this->firstPass) { if ($name == 'USER' && $this->canImport) { - if ('' != $attrs['STATUS'] && ttUserHelper::getUserByLogin($attrs['LOGIN'])) { - // We have a login collision, cannot import any data. - $this->canImport = false; + $login = $attrs['LOGIN']; + if ('' != $attrs['STATUS'] && ttUserHelper::getUserByLogin($login)) { + // We have a login collision. Append colliding login to a list of things we cannot import. + $this->cannotImport .= ($this->cannotImport ? ", $login" : $login); } } - //$this->currentTag = ''; } // Second pass processing. We import data here, one tag at a time. if (!$this->firstPass && $this->canImport) { $mdb2 = getConnection(); - // We are in second pass through the XML file and can import data. + // We are in second pass and can import data. if ($name == 'GROUP') { // Create a new group. $group_id = $this->createGroup(array( 'parent_id' => $this->current_parent_group_id, 'org_id' => $this->org_id, - 'name' => $this->currentElement['NAME'], - 'currency' => $this->currentElement['CURRENCY'], - 'lang' => $this->currentElement['LANG'])); - // We only have 3 properties in export at the moment, while work is ongoing... + 'name' => $attrs['NAME'], + 'currency' => $attrs['CURRENCY'], + 'lang' => $attrs['LANG'])); + // We only have 3 properties at the moment, while work is ongoing... // Special handling for top group. if (!$this->org_id) { @@ -128,8 +111,7 @@ class ttOrgImportHelper { if ($name == 'ROLE') { // We get here when processing a tag for the current group. // Add new role to $this->currentGroupRoles and a mapping to $this->currentGroupRoleMap. - $this->currentGroupRoles[$this->currentElement['ID']] = $this->currentElement; - $this->currentElement = array(); + $this->currentGroupRoles[$attrs['ID']] = $attrs; } } } @@ -185,11 +167,13 @@ class ttOrgImportHelper { xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser))); } - if (!$this->canImport) { - $this->errors->add($i18n->get('error.user_exists')); - break; - } } + if ($this->cannotImport) { + $this->canImport = false; + $this->errors->add($i18n->get('error.user_exists')); + $this->errors->add(sprintf($i18n->get('error.cannot_import'), $this->cannotImport)); + } + $this->firstPass = false; // We are done with 1st pass. xml_parser_free($parser); if ($file) fclose($file); diff --git a/WEB-INF/resources/ca.lang.php b/WEB-INF/resources/ca.lang.php index 64a3b86a..2a74077e 100644 --- a/WEB-INF/resources/ca.lang.php +++ b/WEB-INF/resources/ca.lang.php @@ -116,6 +116,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Iniciar sessió', diff --git a/WEB-INF/resources/cs.lang.php b/WEB-INF/resources/cs.lang.php index 1cc0734d..4d593749 100644 --- a/WEB-INF/resources/cs.lang.php +++ b/WEB-INF/resources/cs.lang.php @@ -118,6 +118,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Přihlásit', diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 280c9945..914bba6d 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -108,6 +108,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Gå til uafsluttet registrering.', 'error.overlap' => 'Tidsinterval overlapper eksisterende poster.', 'error.future_date' => 'Datoen er ud i fremtiden.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Log ind', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index 48d5dcfa..9e118e4a 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -101,6 +101,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Zum unvollständigen Eintrag gehen.', 'error.overlap' => 'Der Zeitinterval überschneidet sich mit vorhandenen Einträgen.', 'error.future_date' => 'Datum ist in der Zukunft.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Anmelden', diff --git a/WEB-INF/resources/en.lang.php b/WEB-INF/resources/en.lang.php index a28c87cf..16f61f22 100644 --- a/WEB-INF/resources/en.lang.php +++ b/WEB-INF/resources/en.lang.php @@ -100,6 +100,7 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Go to uncompleted entry.', 'error.overlap' => 'Time interval overlaps with existing records.', 'error.future_date' => 'Date is in future.', +'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Login', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 28dbb500..2ee7de8c 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -114,6 +114,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Iniciar sesion', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index 85402163..86cde2a3 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -118,6 +118,8 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Login', diff --git a/WEB-INF/resources/fa.lang.php b/WEB-INF/resources/fa.lang.php index d220c13d..55625a88 100644 --- a/WEB-INF/resources/fa.lang.php +++ b/WEB-INF/resources/fa.lang.php @@ -116,6 +116,7 @@ $i18n_key_words = array( 'error.overlap' => 'بازه زمانی با سوابق موجود هم پوشانی دارد.', // TODO: translate the following. // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'ورود', diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 1e4b86a6..36b4d0bd 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -110,6 +110,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Siirry kesken olevaan syötteeseen.', 'error.overlap' => 'Aikavälillä on päällekkäisiä syötteitä.', 'error.future_date' => 'Aika on tulevaisuudessa.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Kirjaudu', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index 1e64e96d..6290479f 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -108,6 +108,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Aller à l\\\'entrée non terminée.', 'error.overlap' => 'Les heures des projets ne peuvent se chevaucher.', 'error.future_date' => 'Date ultérieure.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Connexion', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index 18040153..f2de6f51 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -102,6 +102,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Μεταβείτε στην μη ολοκληρωμένη καταχώρηση.', 'error.overlap' => 'Το χρονικό διάστημα επικαλύπτει υπάρχουσες καταχωρήσεις.', 'error.future_date' => 'Η ημερομηνία είναι στο μέλλον.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Σύνδεση', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index a44d82e5..66cbea76 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -126,6 +126,7 @@ $i18n_key_words = array( 'error.overlap' => 'טווח הזמן מתנגש עם רישומים קיימים.', // TODO: translate the following. // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'היכנס', diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index 9e59b544..b740fe35 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -115,6 +115,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Bejelentkezés', diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index ea2b2514..5d0600aa 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -106,6 +106,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Vai alle voce incompleta.', 'error.overlap' => 'Intervallo temporale sovrapposto a voci esistenti.', 'error.future_date' => 'La data è nel futuro.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Login', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index 23afc5d9..6149e7c4 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -120,6 +120,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'ログイン', diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index 6e0f59bd..fa41f2ca 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -119,6 +119,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => '로그인', diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index b1f76af7..8c4a5244 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -99,6 +99,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Ga naar onvolledige invoer.', 'error.overlap' => 'De huidige registratie overlapt een reeds bestaande registratie.', 'error.future_date' => 'Datum ligt in de toekomst.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Aanmelden', diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index 07026ae5..044a6f33 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -120,6 +120,7 @@ $i18n_key_words = array( // TODO: translate the following. // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Innlogging', diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index f88888fc..c94ae1c9 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -112,6 +112,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Przejdź do niedokończonego wpisu.', 'error.overlap' => 'Okres czasowy nakłada się z istniejącymi wpisami.', 'error.future_date' => 'Data jest w przyszłości.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons 'button.login' => 'Login', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index 79370ec6..f40b5f01 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -109,6 +109,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Ir até a entrada incompleta.', 'error.overlap' => 'O intervalo se sobrepõe com entradas já existentes.', 'error.future_date' => 'Data é no futuro.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Login', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index c9b24b34..4f7d748b 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -112,6 +112,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Login', diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 22341552..82d5d3e6 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -120,6 +120,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Autentifica', diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 4a5dbd62..3974d167 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -99,6 +99,7 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Посмотреть неоконченную запись.', 'error.overlap' => 'Интервал времени перекрывается с существующими записями.', 'error.future_date' => 'Дата в будущем.', +'error.cannot_import' => 'Невозможно импортировать: %s.', // Labels for buttons. 'button.login' => 'Войти', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 13992fe8..cfca9b0a 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -115,6 +115,7 @@ $i18n_key_words = array( // TODO: translate the following. // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Prihlásiť', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index df5ddf52..e07b2089 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -109,6 +109,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Prijava', diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index a35014c0..6bc886a0 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -109,6 +109,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Prikaži postojeći unos.', 'error.overlap' => 'Navedeni vremenski interval se podudara sa već unetim vremenom.', 'error.future_date' => 'Naveli ste budući datum.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Prijava', diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index fb4289a8..a646aab5 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -106,6 +106,8 @@ $i18n_key_words = array( 'error.goto_uncompleted' => 'Visa registrering.', 'error.overlap' => 'Tidsintervallet överlappar med en redan existerande tidsregistrering.', 'error.future_date' => 'Det går inte att registrera tider framåt i tiden.', +// TODO: translate the following. +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Logga in', diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index 4b167e88..eb488754 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -123,6 +123,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => 'Giriş', diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index 2d55378f..e37138ba 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -112,6 +112,7 @@ $i18n_key_words = array( // TODO: translate the following. // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => '登录', diff --git a/WEB-INF/resources/zh-tw.lang.php b/WEB-INF/resources/zh-tw.lang.php index 74d379fc..f46f4562 100644 --- a/WEB-INF/resources/zh-tw.lang.php +++ b/WEB-INF/resources/zh-tw.lang.php @@ -117,6 +117,7 @@ $i18n_key_words = array( // 'error.goto_uncompleted' => 'Go to uncompleted entry.', // 'error.overlap' => 'Time interval overlaps with existing records.', // 'error.future_date' => 'Date is in future.', +// 'error.cannot_import' => 'Cannot import: %s.', // Labels for buttons. 'button.login' => '登錄', -- 2.20.1