Compare commits

..

16 Commits

Author SHA1 Message Date
odain
a419914236 N°9412 - fix uninstall option and others when going to setup from extension mgt 2026-06-08 17:13:49 +02:00
jf-cbd
3426b92768 Fix unit test 2026-06-08 14:04:01 +02:00
jf-cbd
7c44c94de1 Fix unit and CS fixer tests 2026-06-08 13:50:14 +02:00
Purple Grape
4371ddfbbd N°9663 - improved translation for zh_cn (#913) 2026-06-08 13:21:12 +02:00
Timmy38
66bf1dc6fa N°9179 Fix tests for unattended install backward compatibility 2026-06-08 11:45:11 +02:00
Eric Espie
6999000d69 N°9179 - Fix CI 2026-06-08 09:01:20 +02:00
Eric Espié
eedcdf32fe N°9169 - adapt itsm designer connector to the new setup (#928)
* N°9169 - Adapt ITSM designer connector to the new setup - Button Back to designer

* N°9169 - Enhance ITSM designer connector with return button functionality

* N°9169 - Adapt ITSM designer connector to the new setup - Button Back to designer (removed URL in post params)

* N°9169 - Enhance ITSM designer connector with return button functionality and update button styles

---------

Co-authored-by: lenaick.moreira <lenaick.moreira@gmail.com>
2026-06-05 09:59:14 +02:00
Timmy38
2321d89981 N°9179 Fix missing optional steps when using older install-xxxx.xml file with unattended install 2026-06-04 09:38:48 +02:00
odain
3bf47d1e8c Merge branch 'support/3.2' into develop 2026-06-02 17:47:33 +02:00
odain
feb89650e4 curl_close deprecated in PHP 8.5 2026-06-02 17:47:10 +02:00
Eric Espie
b672dfc9f2 Fix PHPStan warning 2026-06-02 15:10:28 +02:00
lenaick.moreira
eef06ee032 Merge branch 'support/3.2.3' into support/3.2 2026-05-20 14:20:43 +02:00
Lenaick
d6ce202fa8 N°9614 - Add a specific route to display the icons for an EventNotificationNewsroom (#911)
* N°9614 - Add a specific route to display the icons for an EventNotificationNewsroom

* N°9614 - Display the icon in EventNotificationNewsroom only for events relating to the logged-in user

* N°9614 - Refactor icon download logic in EventNotificationNewsroomService and add unit tests

* Add unit test to verify icon download functionality for users without read access
2026-05-20 14:18:13 +02:00
Stephen Abello
1c38d989e4 N°9603 - Fix transitions applied when editing only caselog are not working (#908)
* N°9603 - Fix transitions applied when editing only caselog are not working

* Remove unused variable
2026-05-18 17:28:46 +02:00
Molkobain
e65542f978 Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-05-07 18:54:39 +02:00
Stephen Abello
829857ec85 N°9461 - Fix activity panel send options hidden by CKEditor 2026-05-07 15:55:02 +02:00
81 changed files with 2656 additions and 1681 deletions

View File

@@ -1917,7 +1917,9 @@ SQL;
$aResponseHeaders[$sName] = $sValue;
}
}
curl_close($ch);
if (PHP_VERSION_ID < 80000) {
curl_close($ch);
}
return $response;
}

View File

@@ -340,13 +340,14 @@ class ormDocument
* @param string $sContentDisposition Either 'inline' or 'attachment'
* @param string $sSecretField The attcode of the field containing a "secret" to be provided in order to retrieve the file
* @param string $sSecretValue The value of the secret to be compared with the value of the attribute $sSecretField
* @param bool $bAllowAllData If true, no rights filtering is applied
*
* @return void
*/
public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null)
public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment', $sSecretField = null, $sSecretValue = null, $bAllowAllData = false)
{
try {
$oObj = MetaModel::GetObject($sClass, $id, false, false);
$oObj = MetaModel::GetObject($sClass, $id, false, $bAllowAllData);
if (!is_object($oObj)) {
// If access to the document is not granted, check if the access to the host object is allowed
$oObj = MetaModel::GetObject($sClass, $id, false, true);

View File

@@ -22,5 +22,5 @@
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:darkmoon' => '暗月',
'theme:darkmoon' => 'Dark moon',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-high-contrast' => 'Fullmoon (High contrast)~~',
'theme:fullmoon-high-contrast' => 'Fullmoon (高对比度)',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (Protanopia & Deuteranopia)~~',
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (红绿色盲 & 绿色色盲)',
]);

View File

@@ -23,5 +23,5 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon-tritanopia' => 'Fullmoon (Tritanopia)~~',
'theme:fullmoon-tritanopia' => 'Fullmoon (蓝黄色盲)',
]);

View File

@@ -25,7 +25,9 @@ use CoreException;
use Dict;
use Exception;
use MetaModel;
use MFCompiler;
use RunTimeEnvironment;
use SecurityException;
use SetupUtils;
use utils;
@@ -83,10 +85,11 @@ class DataFeatureRemovalController extends Controller
{
$aParams = [];
if (SetupUtils::IsSessionSetupTokenValid()) {
try {
//from setup wizard/mtp
SetupUtils::CheckSetupToken();
SetupUtils::EraseSetupToken();
} else {
} catch (SecurityException $e) {
//from same module
$this->ValidateTransactionId();
}
@@ -100,6 +103,9 @@ class DataFeatureRemovalController extends Controller
'removed_extensions' => '[]',
'extensions_not_uninstallable' => '[]',
'copy_setup_files' => 1,
'force-uninstall' => "",
'use_symbolic_links' => MFCompiler::UseSymbolicLinks() ? 'on' : '',
'return_button_label' => '',
];
$aHiddenInputs = [];
@@ -108,6 +114,10 @@ class DataFeatureRemovalController extends Controller
}
$aParams['aHiddenInputs'] = $aHiddenInputs;
if ($aHiddenInputs['return_button_label'] !== '') {
$aParams['sReturnButtonURL'] = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php');
}
$aAddedExtensions = json_decode($aHiddenInputs['added_extensions'], true);
$aRemovedExtensions = json_decode($aHiddenInputs['removed_extensions'], true);
@@ -115,6 +125,7 @@ class DataFeatureRemovalController extends Controller
//it does not come from setup
// we get extensions from 1st screen uiblocks
$this->ReadExtensionsDiff();
$aHiddenInputs['force-uninstall'] = $this->bForcedUninstallation ? 'on' : '';
$aAddedExtensions = $this->aExtensionsToCheck['to_be_installed'];
$aHiddenInputs['added_extensions'] = $this->ConvertIntoSetupFormat($aAddedExtensions);
@@ -151,7 +162,7 @@ class DataFeatureRemovalController extends Controller
if ("[]" === $aHiddenInputs['selected_modules']) {
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
$oConfig = MetaModel::GetConfig();
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, $aAddedExtensions, $aRemovedExtensions);
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
$aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions);
$oRunTimeEnvironment = $this->GetRuntimeEnvironment($aRemovedExtensions);
@@ -179,6 +190,10 @@ class DataFeatureRemovalController extends Controller
$aParams['aSetupParams']["_params[$sInputName]"] = $sInputValue;
}
if ($aHiddenInputs['return_button_label'] !== '') {
$aParams['sReturnButtonURL'] = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php');
}
[$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses);
[$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable();
$aParams['bDeletionNeeded'] = ($aParams['iQueryCount'] > 0);
@@ -189,7 +204,12 @@ class DataFeatureRemovalController extends Controller
private function ConvertIntoSetupFormat(array $aData): string
{
return json_encode($aData);
$aNewData = [];
foreach ($aData as $k => $sVal) {
$aNewData[] = sprintf('"%s":"%s"', $k, $sVal);
}
return "{".implode(',', $aNewData)."}";
}
/**
@@ -415,7 +435,7 @@ class DataFeatureRemovalController extends Controller
$aExtensionData['extra_flags']['selected'] = false;
$sLabel = $aAvailableExtensions[$sCode]['label'];
$this->aExtensionsToCheck['to_be_removed'][$sCode] = $sLabel;
if (!$aExtensionData['extra_flags']['uninstallable'] || $aExtensionData['extra_flags']['remote']) {
if (! $this->bForcedUninstallation && $aExtensionData['extra_flags']['uninstallable']) {
$this->bForcedUninstallation = true;
}
} elseif (!$aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] === 'on') {

View File

@@ -87,11 +87,15 @@
{% endif %}
{% endif %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% if aHiddenInputs.return_button_label != '' %}
{% UIButton ForAlternativeSecondaryAction { sLabel:aHiddenInputs.return_button_label, OnClickJsCode: 'window.location.href="' ~ sReturnButtonURL ~ '"'} %}
{% else %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% endif %}
{% EndUIPanel %}

View File

@@ -4,7 +4,7 @@
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @license http://opensource.org/licenses/AGPL-3.0
*
* This file is part of iTop.
*
@@ -21,14 +21,15 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Database inconsistencies
Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Dictionary entries go here
'Menu:DBToolsMenu' => '数据库工具',
'Menu:DBToolsMenu' => '数据库完整性',
'DBTools:Class' => '类型',
'DBTools:Title' => '数据库维护工具',
'DBTools:Title' => '数据库完整性检查',
'DBTools:ErrorsFound' => '发现错误',
'DBTools:Indication' => '重要: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
'DBTools:Indication' => '重要提示: 修复数据库错误后, 可能会出现新的不一致, 您必须重新运行一次分析.',
'DBTools:Disclaimer' => '免责申明: 在应用修复之前, 应先备份数据库',
'DBTools:Error' => '错误',
'DBTools:Count' => '个数',
@@ -42,17 +43,20 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'DBTools:IntegrityCheck' => '完整性检查',
'DBTools:FetchCheck' => '提取检查 (耗时长)',
'DBTools:SelectAnalysisType' => '请选择分析类型',
'DBTools:Analyze' => '分析',
'DBTools:Details' => '显示详情',
'DBTools:ShowAll' => '显示所有错误',
'DBTools:Inconsistencies' => '数据库不一致',
'DBTools:DetailedErrorTitle' => '%2$s个错误在类型%1$s: %3$s',
'DBTools:DetailedErrorLimit' => '列表限制为%1$s错误',
'DBAnalyzer-Integrity-OrphanRecord' => '孤立记录位于 `%1$s`, 其应该有副本位于表 `%2$s`',
'DBAnalyzer-Integrity-InvalidExtKey' => '无效的外键%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-MissingExtKey' => '外键丢失%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-InvalidValue' => '无效的值%1$s (列: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-UsersWithoutProfile' => '一些用户账号没有角色',
'DBAnalyzer-Integrity-UsersWithoutProfile' => '有的账号没有角色',
'DBAnalyzer-Integrity-HKInvalid' => '损坏的层级链 `%1$s`',
'DBAnalyzer-Fetch-Count-Error' => '读取计数出错于 `%1$s`, %2$d个记录已读取 / %3$d已',
'DBAnalyzer-Integrity-FinalClass' => '字段 `%2$s`.`%1$s` 必须是相同的值, 而不是 `%3$s`.`%1$s`',
@@ -70,19 +74,24 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'DBTools:LostAttachments' => '附件缺失',
'DBTools:LostAttachments:Disclaimer' => '可以在此搜索数据库中丢失或错放的附件. 这不是数据恢复工具, 其无法恢复已删除的数据.',
'DBTools:LostAttachments:Button:Analyze' => '分析',
'DBTools:LostAttachments:Button:Restore' => '还原',
'DBTools:LostAttachments:Button:Restore:Confirm' => '此操作无法回退, 请确认是否继续还原.',
'DBTools:LostAttachments:Button:Busy' => '请稍候...',
'DBTools:LostAttachments:Step:Analyze' => '首先, 通过分析数据库来搜索丢失或误挪动的附件.',
'DBTools:LostAttachments:Step:AnalyzeResults' => '分析结果:',
'DBTools:LostAttachments:Step:AnalyzeResults:None' => '非常好! 所有附件都是正常的.',
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => '某些附件 (%1$d) 看起来放错了位置. 请检查下面的列表并选择要挪动的文件.',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => '文件名',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => '当前位置',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => '移动到...',
'DBTools:LostAttachments:Step:RestoreResults' => '还原结果:',
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d的附件被还原.',
'DBTools:LostAttachments:StoredAsInlineImage' => '存储为内嵌图像',
'DBTools:LostAttachments:History' => '附件 "%1$s" 已使用数据库工具还原',
]);

View File

@@ -1,15 +1,23 @@
<?php
/**
* Localized data
* Copyright (C) 2013-2024 Combodo SAS
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*
*/
/**
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Attachments:TabTitle_Count' => '附件 (%1$d)',
'Attachments:EmptyTabTitle' => '附件',
@@ -39,10 +47,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Attachment' => '附件',
'Class:Attachment+' => '',
'Class:Attachment+' => '文件: 链接到单一对象的文本或图片. 它无法被修改,只能被删除. 附件无法在编辑界面之外创建.',
'Class:Attachment/Attribute:expire' => '过期',
'Class:Attachment/Attribute:expire+' => '',
'Class:Attachment/Attribute:temp_id' => '临时编号',
'Class:Attachment/Attribute:temp_id' => '临时id',
'Class:Attachment/Attribute:temp_id+' => '',
'Class:Attachment/Attribute:item_class' => '项目类型',
'Class:Attachment/Attribute:item_class+' => '',
@@ -69,11 +77,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Attachment/Attribute:creation_date' => '创建日期',
'Class:Attachment/Attribute:creation_date+' => '~~',
'Class:Attachment/Attribute:user_id' => '用户编号',
'Class:Attachment/Attribute:user_id+' => '~~',
'Class:Attachment/Attribute:contact_id' => '联系人编号',
'Class:Attachment/Attribute:contact_id+' => '~~',
'Class:Attachment/Attribute:creation_date+' => '',
'Class:Attachment/Attribute:user_id' => '用户id',
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => '联系人id',
'Class:Attachment/Attribute:contact_id+' => '',
]);
//
@@ -81,15 +89,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnAttachmentDownload' => '触发器 (对象附件下载时)',
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
'Class:TriggerOnAttachmentCreate' => 'Trigger (on object\'s attachment creation)~~',
'Class:TriggerOnAttachmentCreate+' => 'Trigger on object\'s attachment creation~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => 'Add file in email~~',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => 'If checked, the file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete' => 'Trigger (on object\'s attachment deletion)~~',
'Class:TriggerOnAttachmentDelete+' => 'Trigger on object\'s attachment deletion~~',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => 'Add deleted file in email~~',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'If checked, the deleted file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Trigger on object is not allowed on class Attachment. Please use specific trigger~~',
'Class:TriggerOnAttachmentDownload' => '触发器 (对象附件下载时)',
'Class:TriggerOnAttachmentDownload+' => '触发器于指定类型 [子类型] 对象附件下载时',
'Class:TriggerOnAttachmentCreate' => '触发器 (对象附件被创建时)',
'Class:TriggerOnAttachmentCreate+' => '触发器 (对象附件被创建时)',
'Class:TriggerOnAttachmentDelete' => '触发器 (对象附件被删除时)',
'Class:TriggerOnAttachmentDelete+' => '触发器 (对象附件被删除时)',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email' => '在邮件里添加文件',
'Class:TriggerOnAttachmentCreate/Attribute:file_in_email+' => '如果勾选,文件将在触发邮件操作时自动附加到邮件中',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => '在邮件里添加已删除的文件',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => '如果勾选,已删除的文件将在触发邮件操作时自动附加到邮件中',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => '此触发器不允许用于附件. 请使用特定的触发器',
]);

View File

@@ -21,25 +21,28 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'bkp-backup-running' => '备份正在进行, 请稍候...',
'bkp-restore-running' => '还原正在进行, 请稍等...',
'Menu:BackupStatus' => '定时备份',
'bkp-status-title' => '定时备份',
'Menu:BackupStatus' => '备份',
'bkp-status-title' => '备份',
'bkp-status-checks' => '设置与检查',
'bkp-mysqldump-ok' => '已找到 mysqldump : %1$s',
'bkp-mysqldump-notfound' => 'mysqldump找不到: %1$s - 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数mysql_bindir.',
'bkp-mysqldump-issue' => 'mysqldump无法运行 (retcode=%1$d): 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数mysql_bindir',
'bkp-mysqldump-notfound' => 'mysqldump 找不到: %1$s - 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数 mysql_bindir.',
'bkp-mysqldump-issue' => 'mysqldump 无法运行 (retcode=%1$d): 请确认它安装在正确的路径, 或者调整'.ITOP_APPLICATION_SHORT.'配置文件的参数 mysql_bindir',
'bkp-missing-dir' => '目标目录<code>%1$s</code>找不到',
'bkp-free-disk-space' => '<b>%1$s可用空间</b>位于<code>%2$s</code>',
'bkp-dir-not-writeable' => '%1$s没有写入权限',
'bkp-wrong-format-spec' => '当前文件名格式错误 (%1$s). 默认格式应该是: %2$s',
'bkp-name-sample' => '备份文件将以数据库名, 日期和时间进行命名. 例如: %1$s',
'bkp-week-days' => '在每个<b>%1$s的%2$s</b>进行备份',
'bkp-retention' => '最多<b>%1$d份备份文件</b>在目标目录.',
'bkp-retention' => '在目标目录中最多保留<b>%1$d份备份文件</b>.',
'bkp-next-to-delete' => '当下一次备份时将被删除 (参阅设置 "retention_count")',
'bkp-table-file' => '文件',
'bkp-table-file+' => '只有扩展名是.zip的文件才被认为是备份文件',
'bkp-table-file+' => '只有扩展名是.zip的文件才被认为是有效的备份文件',
'bkp-table-size' => '大小',
'bkp-table-size+' => '',
'bkp-table-actions' => '操作',
@@ -47,7 +50,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'bkp-status-backups-auto' => '定时备份',
'bkp-status-backups-manual' => '手动备份',
'bkp-status-backups-none' => '尚未开始备份',
'bkp-next-backup' => '下一次备份将发生在<b>%1$s</b> (%2$s) 的%3$s',
'bkp-next-backup' => '下一次备份将发生在<b>%1$s</b> (%2$s) 的%3$s',
'bkp-next-backup-unknown' => '下一次备份<b>尚未被计划</b>.',
'bkp-button-backup-now' => '立即备份!',
'bkp-button-restore-now' => '还原!',

View File

@@ -17,10 +17,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -31,8 +32,9 @@
//
// Class: lnkFunctionalCIToProviderContract
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToProviderContract' => '关联功能配置项/供应商合同',
'Class:lnkFunctionalCIToProviderContract' => '链接 功能配置项/供应商合同',
'Class:lnkFunctionalCIToProviderContract+' => '',
'Class:lnkFunctionalCIToProviderContract/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => '供应商合同',
@@ -50,9 +52,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToService' => '关联 功能配置项/服务',
'Class:lnkFunctionalCIToService+' => '',
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s~~',
'Class:lnkFunctionalCIToService' => '链接 功能配置项/服务',
'Class:lnkFunctionalCIToService+' => 'This link models the functional CIs that are required to deliver a Service and whose malfunction would affect the quality of the Service.~~',
'Class:lnkFunctionalCIToService/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToService/Attribute:service_id' => '服务',
'Class:lnkFunctionalCIToService/Attribute:service_id+' => '',
'Class:lnkFunctionalCIToService/Attribute:service_name' => '服务名称',
@@ -80,7 +82,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Document/Attribute:contracts_list' => '合同',
'Class:Document/Attribute:contracts_list+' => '此文档关的所有合同',
'Class:Document/Attribute:contracts_list+' => '此文档关的所有合同',
'Class:Document/Attribute:services_list' => '服务',
'Class:Document/Attribute:services_list+' => '此文档关的所有服务',
'Class:Document/Attribute:services_list+' => '此文档关的所有服务',
]);

View File

@@ -17,10 +17,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @author Benjamin Planque <benjamin.planque@combodo.com>
*/
* @author Benjamin Planque <benjamin.planque@combodo.com>
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -28,19 +29,21 @@
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
//
// Class: lnkFunctionalCIToTicket
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToTicket' => '关联 功能配置项/工单',
'Class:lnkFunctionalCIToTicket+' => '',
'Class:lnkFunctionalCIToTicket' => '链接 功能配置项/工单',
'Class:lnkFunctionalCIToTicket+' => 'This link models the functional CIs that are concerned by a Ticket (such as a User Request, an Incident, a Change, ...)~~',
'Class:lnkFunctionalCIToTicket/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id' => '工单',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_id+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref' => '工单编号',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_ref+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title' => '工单标题',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title+' => '~~',
'Class:lnkFunctionalCIToTicket/Attribute:ticket_title+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id' => '配置项',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_id+' => '',
'Class:lnkFunctionalCIToTicket/Attribute:functionalci_name' => '配置项名称',
@@ -50,7 +53,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToTicket/Attribute:impact_code' => '影响',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:manual' => '手动添加',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:computed' => '自动添加',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => '不通知',
'Class:lnkFunctionalCIToTicket/Attribute:impact_code/Value:not_impacted' => '未被影响',
]);
//

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:ChangeManagement' => '变更管理',
'Menu:Change:Overview' => '概况',
@@ -125,7 +126,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Change/Attribute:parent_name' => '变更编号',
'Class:Change/Attribute:parent_name+' => '',
'Class:Change/Attribute:related_request_list' => '相关需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有用户需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有需求',
'Class:Change/Attribute:related_problems_list' => '相关问题',
'Class:Change/Attribute:related_problems_list+' => '此变更相关的所有问题',
'Class:Change/Attribute:related_incident_list' => '相关事件',

View File

@@ -109,7 +109,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Change/Attribute:fallback_plan' => '回滚计划',
'Class:Change/Attribute:fallback_plan+' => '',
'Class:Change/Attribute:related_request_list' => '相关需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有用户需求',
'Class:Change/Attribute:related_request_list+' => '此变更相关的所有需求',
'Class:Change/Attribute:related_incident_list' => '相关事件',
'Class:Change/Attribute:related_incident_list+' => '此变更相关的所有事件',
'Class:Change/Attribute:related_problems_list' => '相关问题',

View File

@@ -26,6 +26,7 @@ SetupWebPage::AddModule(
],
'data.struct' => [
'data/en_us.data.itop-brand.xml',
'data/en_us.data.itop-networkdevicetype.xml',
'data/en_us.data.itop-osfamily.xml',
'data/en_us.data.itop-osversion.xml',
],
@@ -101,8 +102,6 @@ if (!class_exists('ConfigMgmtInstaller')) {
*/
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
// load localized data for NetworkDeviceType
static::LoadLocalizedDataOnCrossingVersion($oConfiguration, $sPreviousVersion, $sCurrentVersion,'3.3.0',__DIR__."/data/{{language_code}}.data.itop-networkdevicetype.xml" );
}
}
}

View File

@@ -21,9 +21,10 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:ConfigFileEditor' => 'Plain text editor~~',
'Menu:ConfigEditor' => '编辑配置文件',
'Menu:ConfigFileEditor' => '纯文本编辑器',
'itop-config/Operation:Edit/Title' => '配置文件编辑器',
'config-edit-intro' => '编辑配置文件时请务必格外小心.',
'config-apply' => '应用',
@@ -34,7 +35,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'config-no-change' => '没有变化: 配置文件将保持不变.',
'config-reverted' => '配置文件已恢复.',
'config-parse-error' => '第%2$d行: %1$s.<br/>配置文件尚未更新.',
'config-current-line' => '正在编辑第%1$s行',
'config-current-line' => '正在编辑第 %1$s 行',
'config-saved-warning-db-password' => '保存成功, 但因为数据库密码中包含不支持的字符, 配置文件备份不会成功.',
'config-error-transaction' => '错误: 无效的事务编号. 配置<b>没有</b>被更新.',
'config-error-file-changed' => '错误: 配置文件在您打开以后已被更改, 无法保存. 请刷新并再次保存.',

View File

@@ -0,0 +1,173 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2013 XXXXX
* @license http://opensource.org/licenses/AGPL-3.0
*/
//
// Fieldsets for Container classes
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Container:baseinfo' => '基本信息',
'Container:moreinfo' => '容器详情',
'Container:otherinfo' => '日期和描述',
]);
//
// Class Container Image
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerImage/Name' => '%1$s %2$s',
'Class:ContainerImage/ComplementaryName' => '%1$s - %2$s',
'Class:ContainerImage' => '容器镜像',
'Class:ContainerImage+' => '准备作为容器启动的软件镜像',
'Class:ContainerImage/Attribute:name' => '名称',
'Class:ContainerImage/Attribute:name+' => '',
'Class:ContainerImage/Attribute:version' => '版本',
'Class:ContainerImage/Attribute:version+' => '',
'Class:ContainerImage/Attribute:description' => '描述',
'Class:ContainerImage/Attribute:description+' => '',
'Class:ContainerImage/Attribute:publisher' => '发布者',
'Class:ContainerImage/Attribute:publisher+' => '镜像的发布者. 例如: php, nginx, ...',
'Class:ContainerImage/Attribute:image' => '镜像',
'Class:ContainerImage/Attribute:image+' => '在对应的托管平台上检索镜像的详细信息',
'Class:ContainerImage/Attribute:type_id' => '类型',
'Class:ContainerImage/Attribute:type_id+' => 'Type d\image~~',
'Class:ContainerImage/Attribute:software_id' => '软件',
'Class:ContainerImage/Attribute:software_id+' => '',
'Class:ContainerImage/Attribute:containerapplications_list' => '容器化应用',
'Class:ContainerImage/Attribute:containerapplications_list+' => '此镜像所对应的应用程序',
]);
//
// Class Container Application
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerApplication/Name' => '%1$s',
'Class:ContainerApplication/ComplementaryName' => '%1$s',
'Class:ContainerApplication' => '容器化应用程序',
'Class:ContainerApplication+' => '部署在容器平台上的应用程序',
'Class:ContainerApplication/Attribute:descriptor' => 'Deployment file',
'Class:ContainerApplication/Attribute:descriptor+' => 'File describing how to deploy the application on the container platform (e.g., Docker Compose, Helm Chart, etc.)',
'Class:ContainerApplication/Attribute:containervirtualhost_id' => 'Container Host',
'Class:ContainerApplication/Attribute:containervirtualhost_id+' => 'Container Platform on which the application is running',
'Class:ContainerApplication/Attribute:logo' => 'Logo',
'Class:ContainerApplication/Attribute:logo+' => 'Used as object icon when this ContainerApplication is displayed within impact analysis graphs',
'Class:ContainerApplication/Attribute:containertype_id' => '容器类型',
'Class:ContainerApplication/Attribute:containertype_id+' => '容器化使用的技术',
'Class:ContainerApplication/Attribute:containerimages_list' => '容器镜像',
'Class:ContainerApplication/Attribute:containerimages_list+' => 'Software images used to build the containerized application',
]);
//
// Class: lnkContainerApplicationToImage
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContainerApplicationToImage' => '链接 容器应用/容器镜像',
'Class:lnkContainerApplicationToImage+' => '',
'Class:lnkContainerApplicationToImage/Name' => '%1$s / %2$s',
'Class:lnkContainerApplicationToImage/Name+' => '',
'Class:lnkContainerApplicationToImage/Attribute:containerapplication_id' => '容器化应用程序',
'Class:lnkContainerApplicationToImage/Attribute:containerapplication_id+' => '使用此镜像的应用程序',
'Class:lnkContainerApplicationToImage/Attribute:containerimage_id' => '容器镜像',
'Class:lnkContainerApplicationToImage/Attribute:containerimage_id+' => '用于构建容器化应用程序的软件镜像',
]);
//
// Class Container Virtual Host
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerVirtualHost/Name' => '%1$s',
'Class:ContainerVirtualHost/ComplementaryName' => '',
'Class:ContainerVirtualHost' => '容器平台',
'Class:ContainerVirtualHost+' => 'Platform on which applications run as containers',
'Class:ContainerVirtualHost/Attribute:containertype_id' => '容器类型',
'Class:ContainerVirtualHost/Attribute:containertype_id+' => '用于交付容器的技术',
'Class:ContainerVirtualHost/Attribute:status' => '状态',
'Class:ContainerVirtualHost/Attribute:status+' => '容器平台的状态',
'Class:ContainerVirtualHost/Attribute:containerapplications_list' => '应用程序',
'Class:ContainerVirtualHost/Attribute:containerapplications_list+' => '在此容器环境中运行的应用程序',
]);
//
// Class Container Host
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerHost/Name' => '%1$s',
'Class:ContainerHost/ComplementaryName' => '%1$s-%2$s',
'Class:ContainerHost' => '容器宿主机',
'Class:ContainerHost+' => '托管容器的宿主机. 它是容器平台的基本元素',
'Class:ContainerHost/Attribute:containercluster_id' => '容器集群',
'Class:ContainerHost/Attribute:containercluster_id+' => '',
'Class:ContainerHost/Attribute:role' => '角色',
'Class:ContainerHost/Attribute:role+' => '主机在集群中的角色:主节点或工作节点. 独立运行时不在集群中.',
'Class:ContainerHost/Attribute:system_id' => '系统',
'Class:ContainerHost/Attribute:system_id+' => '系统可以是物理机, 虚拟机, 云平台, ...',
'Class:ContainerHost/Attribute:role/Value:master' => '主节点',
'Class:ContainerHost/Attribute:role/Value:worker' => '工作节点',
'Class:ContainerHost/Attribute:role/Value:standalone' => '独立运行',
]);
//
// Class Container Cluster
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerCluster/Name' => '%1$s',
'Class:ContainerCluster/ComplementaryName' => '',
'Class:ContainerCluster' => '容器集群',
'Class:ContainerCluster+' => '由一组容器宿主机组成的容器平台',
'Class:ContainerCluster/Attribute:redundancy' => '冗余配置',
'Class:ContainerCluster/Attribute:redundancy/disabled' => '当所有主机都在运行时, 集群才是正常的',
'Class:ContainerCluster/Attribute:redundancy/count' => '当至少 %1$s 个主机在运行时, 集群才是正常的',
'Class:ContainerCluster/Attribute:redundancy/percent' => '当至少 %1$s %% 的在主机运行时,集群才是正常的',
'Class:ContainerCluster/Attribute:containerhosts_list' => '容器宿主机',
'Class:ContainerCluster/Attribute:containerhosts_list+' => '此集群的主机',
]);
//
// Class Container Type
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerType/Name' => '%1$s',
'Class:ContainerType/ComplementaryName' => '',
'Class:ContainerType' => '容器类型',
'Class:ContainerType+' => '用于交付容器的技术',
]);
//
// Class Container Type
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContainerImageType/Name' => '%1$s',
'Class:ContainerImageType/ComplementaryName' => '',
'Class:ContainerImageType' => '容器镜像类型',
'Class:ContainerImageType+' => '容器镜像的分类',
]);
//
// Class Cloud, Server and Virtual Machine
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Cloud/Attribute:containerhosts_list' => '容器宿主机',
'Class:Cloud/Attribute:containerhosts_list+' => '运行在此云平台上的容器宿主机列表',
'Class:Server/Attribute:containerhosts_list' => '容器宿主机',
'Class:Server/Attribute:containerhosts_list+' => '运行在此物理机上的容器宿主机列表',
'Class:VirtualMachine/Attribute:containerhosts_list' => '容器宿主机',
'Class:VirtualMachine/Attribute:containerhosts_list+' => '运行在此虚拟机上的容器宿主机列表',
'Class:Software/Attribute:containerimages_list' => '容器镜像',
'Class:Software/Attribute:containerimages_list+' => '运行此软件的容器镜像列表',
]);

View File

@@ -26,12 +26,14 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'itop-core-update:UI:SelectUpdateFile' => '应用升级',
'itop-core-update:UI:ConfirmUpdate' => ' 升级',
'itop-core-update:UI:UpdateCoreFiles' => '应用升级',
'iTopUpdate:UI:MaintenanceModeActive' => '此应用当前维护中, 不允许任何用户访问. 必须运行安装或恢复归档来使其处于正常模式.',
'iTopUpdate:UI:MaintenanceModeActive' => '此应用当前维护中, 不允许任何用户访问. 必须运行安装向导或恢复归档来使其处于正常模式.',
'itop-core-update:UI:UpdateDone' => '应用升级',
'itop-core-update/Operation:SelectUpdateFile/Title' => '应用升级',
'itop-core-update/Operation:ConfirmUpdate/Title' => '请确认升级应用',
'itop-core-update/Operation:UpdateCoreFiles/Title' => '应用正在升级',
'itop-core-update/Operation:UpdateDone/Title' => '应用升级完毕',
'iTopUpdate:UI:SelectUpdateFile' => '请选择要上传的升级文件',
'iTopUpdate:UI:CheckUpdate' => '校验升级文件',
'iTopUpdate:UI:ConfirmInstallFile' => '即将安装 %1$s',
@@ -50,6 +52,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopUpdate:UI:UploadArchive' => '请选择要上传的软件包',
'iTopUpdate:UI:ServerFile' => '服务器上的软件包路径已存在',
'iTopUpdate:UI:WarningReadOnlyDuringUpdate' => '升级期间, 应用会变成只读状态.',
'iTopUpdate:UI:Status' => '状态',
'iTopUpdate:UI:Action' => '升级',
'iTopUpdate:UI:Setup' => ITOP_APPLICATION_SHORT.'安装',
@@ -61,8 +64,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopUpdate:UI:ItopDiskSpace' => ITOP_APPLICATION_SHORT.'的磁盘空间',
'iTopUpdate:UI:DBDiskSpace' => '数据库的磁盘空间',
'iTopUpdate:UI:FileUploadMaxSize' => '文件上传大小上限',
'iTopUpdate:UI:PostMaxSize' => 'PHP ini值post_max_size: %1$s',
'iTopUpdate:UI:UploadMaxFileSize' => 'PHP ini 值 upload_max_filesize: %1$s',
'iTopUpdate:UI:PostMaxSize' => 'PHP ini post_max_size: %1$s',
'iTopUpdate:UI:UploadMaxFileSize' => 'PHP ini 的值 upload_max_filesize: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Loading' => '正在检查文件',
'iTopUpdate:UI:CanCoreUpdate:Error' => '文件检查失败 (%1$s)',
'iTopUpdate:UI:CanCoreUpdate:ErrorFileNotExist' => '文件检查失败 (%1$s 文件不存在)',
@@ -70,11 +75,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopUpdate:UI:CanCoreUpdate:Yes' => '应用可以升级',
'iTopUpdate:UI:CanCoreUpdate:No' => '应用无法升级: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => '警告: 应用升级可能失败: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>检测到一些文件被修改</b>, 无法进行局部升级.</br>请按照<a target="_blank" href="%2$s">指南</a>一步步操作以手动升级系统. 您必须使用<a href="%1$s">安装</a>升级应用.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>检测到一些文件被修改</b>, 无法进行局部升级.</br>请按照<a target="_blank" href="%2$s">流程</a>一步步操作以手动升级系统. 您必须使用<a href="%1$s">安装向导</a>升级应用.',
'iTopUpdate:UI:CheckInProgress' => '完整性检查中, 请稍候',
'iTopUpdate:UI:SetupLaunch' => '启动'.ITOP_APPLICATION_SHORT.'安装',
'iTopUpdate:UI:SetupLaunchConfirm' => '启动'.ITOP_APPLICATION_SHORT.'安装, 确定吗?',
'iTopUpdate:UI:FastSetupLaunch' => 'Fast Setup~~',
'iTopUpdate:UI:SetupLaunch' => '启动'.ITOP_APPLICATION_SHORT.'安装向导',
'iTopUpdate:UI:SetupLaunchConfirm' => '即将启动'.ITOP_APPLICATION_SHORT.'安装向导, 请确定?',
'iTopUpdate:UI:FastSetupLaunch' => '快速安装',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => '准备开始',
@@ -101,6 +107,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopUpdate:Error:InvalidToken' => '无效的 token',
'iTopUpdate:Error:UpdateFailed' => '升级失败',
'iTopUpdate:Error:FileUploadMaxSizeTooSmall' => '上传上限太小. 请调整 PHP 配置.',
'iTopUpdate:UI:RestoreArchive' => '您可以从归档文件 \'%1$s\' 还原应用程序',
'iTopUpdate:UI:RestoreBackup' => '您可以从 \'%1$s\' 还原数据库',
'iTopUpdate:UI:UpdateDone' => '升级成功',

View File

@@ -4,7 +4,7 @@
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @license http://opensource.org/licenses/AGPL-3.0
*
* This file is part of iTop.
*
@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,10 +31,12 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -43,9 +46,11 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: FAQ
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:FAQ' => 'FAQ',
'Class:FAQ+' => '常见问题',

View File

@@ -0,0 +1,91 @@
<?php
/**
* Module combodo-flow-map
*
* @copyright Copyright (C) 2013 XXXXX
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Relation:dataflows/Description' => 'DataFlows between CIs~~',
'Relation:dataflows/DownStream' => 'Outbound flows...',
'Relation:dataflows/DownStream+' => 'Outbound flows map from',
'Relation:dataflows/UpStream' => 'Inbound flows...',
'Relation:dataflows/UpStream+' => 'Inbound flows map to',
'Class:FunctionalCI/Attribute:dataflows' => '数据流',
'Class:FunctionalCI/Attribute:dataflows+' => '该对象作为源或目标的数据流',
'FunctionalCI:DataFlow:Title' => '数据流',
'FunctionalCI:DataFlow:Inbound' => '入站数据流',
'FunctionalCI:DataFlow:Outbound' => '出站数据流',
'DataFlow:moreinfo' => '数据流详情',
'Class:DataFlow' => '数据流',
'Class:DataFlow+' => 'For application flow for example~~',
'Class:DataFlow/Name' => '%1$s',
'Class:DataFlow/Attribute:name' => '名称',
'Class:DataFlow/Attribute:name+' => '已传输的数据',
'Class:DataFlow/Attribute:source_id' => '数据源',
'Class:DataFlow/Attribute:source_id+' => '数据流的源头配置项',
'Class:DataFlow/Attribute:source_impact' => '数据源影响?',
'Class:DataFlow/Attribute:source_impact+' => '数据源是否影响数据流?',
'Class:DataFlow/Attribute:source_impact/Value:yes' => '是',
'Class:DataFlow/Attribute:source_impact/Value:yes+' => '如果数据源失效,数据流将受到影响',
'Class:DataFlow/Attribute:source_impact/Value:no' => '否',
'Class:DataFlow/Attribute:source_impact/Value:no+' => '如果数据源失效,数据流不受影响',
'Class:DataFlow/Attribute:destination_id' => '目标',
'Class:DataFlow/Attribute:destination_id+' => '数据流的目标配置项',
'Class:DataFlow/Attribute:destination_impact' => '目标影响',
'Class:DataFlow/Attribute:destination_impact+' => '目标是否受数据流影响?',
'Class:DataFlow/Attribute:destination_impact/Value:yes' => '是',
'Class:DataFlow/Attribute:destination_impact/Value:yes+' => '如果数据流停止,目标将受到影响',
'Class:DataFlow/Attribute:destination_impact/Value:no' => '否',
'Class:DataFlow/Attribute:destination_impact/Value:no+' => '如果数据流停止,目标不受影响',
'Class:DataFlow/Attribute:dataflowtype_id' => '数据流类型',
'Class:DataFlow/Attribute:dataflowtype_id+' => '数据流的分类',
'Class:DataFlow/Attribute:status' => '状态',
'Class:DataFlow/Attribute:status+' => '',
'Class:DataFlow/Attribute:status/Value:active' => '启用',
'Class:DataFlow/Attribute:status/Value:inactive' => '停用',
'Class:DataFlow/Attribute:execution_frequency' => '执行频率',
'Class:DataFlow/Attribute:execution_frequency+' => '数据流执行的频率',
'Class:DataFlow/Attribute:execution_frequency/Value:realtime' => '实时',
'Class:DataFlow/Attribute:execution_frequency/Value:realtime+' => '',
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand' => '按需',
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand+' => '即时执行,不按计划进行',
'Class:DataFlow/Attribute:execution_frequency/Value:hourly' => '每小时',
'Class:DataFlow/Attribute:execution_frequency/Value:hourly+' => '',
'Class:DataFlow/Attribute:execution_frequency/Value:daily' => '每天',
'Class:DataFlow/Attribute:execution_frequency/Value:daily+' => '',
'Class:DataFlow/Attribute:execution_frequency/Value:weekly' => '每周',
'Class:DataFlow/Attribute:execution_frequency/Value:weekly+' => '',
'Class:DataFlow/Attribute:execution_frequency/Value:monthly' => '每月',
'Class:DataFlow/Attribute:execution_frequency/Value:monthly+' => '',
'Class:DataFlow/Attribute:execution_frequency/Value:yearly' => '每年',
'Class:DataFlow/Attribute:execution_frequency/Value:yearly+' => '',
'Class:DataFlow/Attribute:documents_list+' => '例如: 技术规范, 操作手册等.',
'Class:DataFlow/Attribute:contacts_list+' => '例如: 数据流所有者, 技术支持等.',
'Class:DataFlow/Error:CheckSource' => 'The source of a data flow cannot be a data flow itself. Choose another source CI than %1$s~~',
'Class:DataFlow/Error:CheckDestination' => 'The destination of a data flow cannot be a data flow itself. Choose another destination CI than %1$s~~',
'Class:DataFlowType' => '数据流类型',
'Class:DataFlowType+' => '数据流的分类',
/*
'Class:DataFlow/Attribute:source_id_friendlyname' => 'source_id_friendlyname',
'Class:DataFlow/Attribute:source_id_friendlyname+' => 'Full name',
'Class:DataFlow/Attribute:source_id_finalclass_recall' => 'source_id->CI sub-class',
'Class:DataFlow/Attribute:source_id_finalclass_recall+' => 'Name of the final class',
'Class:DataFlow/Attribute:source_id_obsolescence_flag' => 'source_id->Obsolete',
'Class:DataFlow/Attribute:source_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
'Class:DataFlow/Attribute:destination_id_friendlyname' => 'destination_id_friendlyname',
'Class:DataFlow/Attribute:destination_id_friendlyname+' => 'Full name',
'Class:DataFlow/Attribute:destination_id_finalclass_recall' => 'destination_id->CI sub-class',
'Class:DataFlow/Attribute:destination_id_finalclass_recall+' => 'Name of the final class',
'Class:DataFlow/Attribute:destination_id_obsolescence_flag' => 'destination_id->Obsolete',
'Class:DataFlow/Attribute:destination_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
*/
]);

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Dictionary entries go here
'Menu:iTopHub' => 'iTop Hub',
@@ -39,6 +40,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopHub:AutoSubmit' => '不再询问. 下次自动进入iTop Hub.',
'UI:About:RemoteExtensionSource' => 'iTop Hub',
'iTopHub:Explanation' => '点击这个按钮您将被引导至iTop Hub.',
'iTopHub:BackupFreeDiskSpaceIn' => '%1$s 可用磁盘空间位于 %2$s.',
'iTopHub:FailedToCheckFreeDiskSpace' => '检查可用磁盘空间失败.',
'iTopHub:BackupOk' => '备份成功.',
@@ -48,6 +50,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopHub:CompiledOK' => '编译成功.',
'iTopHub:ConfigurationSafelyReverted' => '安装时发生错误!<br/>系统配置将不会改变.',
'iTopHub:FailAuthent' => '认证失败.',
'iTopHub:InstalledExtensions' => '本机已安装的扩展',
'iTopHub:ExtensionCategory:Manual' => '手动安装的扩展',
'iTopHub:ExtensionCategory:Manual+' => '下列已安装的扩展是手动将文件放置到 %1$s 目录的:',
@@ -57,6 +60,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopHub:NoExtensionInThisCategory+' => '浏览 iTop Hub, 去寻找符合您喜欢的扩展吧.',
'iTopHub:ExtensionNotInstalled' => '未安装',
'iTopHub:GetMoreExtensions' => '从 iTop Hub 获取扩展...',
'iTopHub:LandingWelcome' => '恭喜! 下列来自 iTop Hub 的扩展已被下载并安装到本机.',
'iTopHub:GoBackToITopBtn' => '返回'.ITOP_APPLICATION_SHORT,
'iTopHub:Uncompressing' => '扩展解压中...',
@@ -65,6 +69,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopHub:DBBackupSentence' => '在升级之前,备份数据库和'.ITOP_APPLICATION_SHORT.'配置文件',
'iTopHub:DeployBtn' => '安装!',
'iTopHub:DatabaseBackupProgress' => '实例备份...',
'iTopHub:InstallationEffect:Install' => '版本: %1$s 将被安装.',
'iTopHub:InstallationEffect:NoChange' => '版本: %1$s 已安装. 保持不变.',
'iTopHub:InstallationEffect:Upgrade' => '将从版本 %1$s <b>升级</b>到版本 %2$s.',
@@ -74,6 +79,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'iTopHub:InstallationEffect:MissingDependencies' => '扩展无法安装, 因为未知的依赖.',
'iTopHub:InstallationEffect:MissingDependencies_Details' => '此扩展依赖模块: %1$s',
'iTopHub:InstallationProgress:InstallationSuccessful' => '安装成功!',
'iTopHub:InstallationStatus:Installed_Version' => '%1$s 版本: %2$s.',
'iTopHub:InstallationStatus:Installed' => '已安装',
'iTopHub:InstallationStatus:Version_NotInstalled' => '版本 %1$s <b>未被</b> 安装.',

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:IncidentManagement' => '事件管理',
'Menu:IncidentManagement+' => '事件管理',
@@ -130,7 +131,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Attribute:servicesubcategory_id+' => '',
'Class:Incident/Attribute:servicesubcategory_name' => '子服务名称',
'Class:Incident/Attribute:servicesubcategory_name+' => '',
'Class:Incident/Attribute:escalation_flag' => '是否升级',
'Class:Incident/Attribute:escalation_flag' => '升级标识',
'Class:Incident/Attribute:escalation_flag+' => '',
'Class:Incident/Attribute:escalation_flag/Value:no' => '否',
'Class:Incident/Attribute:escalation_flag/Value:no+' => '否',
@@ -150,10 +151,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Attribute:tto+' => '响应时间',
'Class:Incident/Attribute:ttr' => 'TTR',
'Class:Incident/Attribute:ttr+' => '解决时限',
'Class:Incident/Attribute:tto_time_spent' => 'TTO time spent~~',
'Class:Incident/Attribute:tto_time_spent+' => '~~',
'Class:Incident/Attribute:ttr_time_spent' => 'TTR time spent~~',
'Class:Incident/Attribute:ttr_time_spent+' => '~~',
'Class:Incident/Attribute:tto_time_spent' => 'TTO 耗时',
'Class:Incident/Attribute:tto_time_spent+' => 'TTO 耗时',
'Class:Incident/Attribute:ttr_time_spent' => 'TTR 耗时',
'Class:Incident/Attribute:ttr_time_spent+' => 'TTR 耗时',
'Class:Incident/Attribute:tto_escalation_deadline' => 'TTO截止日期',
'Class:Incident/Attribute:tto_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_tto_passed' => 'SLA TTO合格',
@@ -169,7 +170,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Attribute:time_spent' => '耗时',
'Class:Incident/Attribute:time_spent+' => '',
'Class:Incident/Attribute:resolution_code' => '解决方式',
'Class:Incident/Attribute:resolution_code+' => '',
'Class:Incident/Attribute:resolution_code+' => '为解决这个事件而做了什么?',
'Class:Incident/Attribute:resolution_code/Value:assistance' => '外部支持',
'Class:Incident/Attribute:resolution_code/Value:assistance+' => '外部支持',
'Class:Incident/Attribute:resolution_code/Value:bug fixed' => '缺陷修复',
@@ -204,7 +205,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Attribute:related_request_list+' => '此事件相关的所有需求',
'Class:Incident/Attribute:child_incidents_list' => '子事件',
'Class:Incident/Attribute:child_incidents_list+' => '此事件相关的所有衍生事件',
'Class:Incident/Attribute:public_log' => '评论',
'Class:Incident/Attribute:public_log' => '公共日志',
'Class:Incident/Attribute:public_log+' => '',
'Class:Incident/Attribute:user_satisfaction' => '用户满意度',
'Class:Incident/Attribute:user_satisfaction+' => '',
@@ -218,7 +219,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Attribute:user_satisfaction/Value:4+' => '非常不满意',
'Class:Incident/Attribute:user_comment' => '用户评论',
'Class:Incident/Attribute:user_comment+' => '',
'Class:Incident/Attribute:parent_incident_id_friendlyname' => '父级事件称',
'Class:Incident/Attribute:parent_incident_id_friendlyname' => '父级事件称',
'Class:Incident/Attribute:parent_incident_id_friendlyname+' => '',
'Class:Incident/Stimulus:ev_assign' => '分配',
'Class:Incident/Stimulus:ev_assign+' => '',
@@ -239,6 +240,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Incident/Stimulus:ev_reopen' => '重新打开',
'Class:Incident/Stimulus:ev_reopen+' => '',
'Class:Incident/Error:CannotAssignParentIncidentIdToSelf' => '无法分配父级事件给自己',
'Class:Incident/Method:ResolveChildTickets' => '解决子工单',
'Class:Incident/Method:ResolveChildTickets+' => '递归解决子工单 (自动解决), 并调整相关字段与父级工单保持一致: 服务, 团队, 办理人, 解决方案',
'Tickets:Related:OpenIncidents' => '打开的事件',

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,10 +31,12 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -43,9 +46,11 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: KnownError
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:KnownError' => '已知错误',
'Class:KnownError+' => '记录一个已知错误',
@@ -96,8 +101,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkErrorToFunctionalCI' => '关联已知问题/功能配置项',
'Class:lnkErrorToFunctionalCI+' => '已知问题和功能配置项之间的关联',
'Class:lnkErrorToFunctionalCI' => '链接 已知问题/功能配置项',
'Class:lnkErrorToFunctionalCI+' => '已知问题和功能配置项之间的链接',
'Class:lnkErrorToFunctionalCI/Name' => '%1$s / %2$s',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id' => '配置项',
'Class:lnkErrorToFunctionalCI/Attribute:functionalci_id+' => '',
@@ -116,8 +121,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDocumentToError' => '关联文档/已知问题',
'Class:lnkDocumentToError+' => '文档和已知问题之间的关联',
'Class:lnkDocumentToError' => '链接 文档/已知问题',
'Class:lnkDocumentToError+' => '文档和已知问题之间的链接',
'Class:lnkDocumentToError/Name' => '%1$s / %2$s',
'Class:lnkDocumentToError/Attribute:document_id' => '文档',
'Class:lnkDocumentToError/Attribute:document_id+' => '',
@@ -127,7 +132,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDocumentToError/Attribute:error_id+' => '',
'Class:lnkDocumentToError/Attribute:error_name' => '已知问题名称',
'Class:lnkDocumentToError/Attribute:error_name+' => '',
'Class:lnkDocumentToError/Attribute:link_type' => '关联类型',
'Class:lnkDocumentToError/Attribute:link_type' => '链接类型',
'Class:lnkDocumentToError/Attribute:link_type+' => '',
]);

View File

@@ -6,13 +6,16 @@
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:CreateMailbox' => '创建邮箱...',
'Menu:OAuthClient' => 'OAuth Mail Access~~',
'Menu:OAuthClient+' => '',
'Menu:GenerateTokens' => '生成访问令牌...',
'Menu:RegenerateTokens' => '重新生成访问令牌...',
'itop-oauth-client/Operation:CreateMailBox/Title' => '邮箱创建',
'itop-oauth-client:UsedForSMTP' => '此OAuth客户端用户SMTP',
'itop-oauth-client:TestSMTP' => '发送测试邮件',
'itop-oauth-client:MissingOAuthClient' => '没有Oauth客户端给用户%1$s',
@@ -21,7 +24,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'itop-oauth-client:Message:TokenCreated' => '访问令牌已生成',
'itop-oauth-client:Message:TokenRecreated' => '访问令牌已重新生成',
'itop-oauth-client:Message:TokenError' => '由于服务错误没有生成访问令牌',
'OAuthClient:Name/UseForSMTPMustBeUnique' => '此组合登录 (%1$s) 和使用于SMTP (%2$s) 已经在OAuth客户端使用',
'OAuthClient:baseinfo' => '基本信息',
'OAuthClient:scope' => '范围',
]);
@@ -59,7 +64,6 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
This url must be copied in the OAuth2 configuration of the provider
Erase the field to recalculate default value
EOF
,
'Class:OAuthClient/Attribute:mailbox_list' => '邮箱列表',
'Class:OAuthClient/Attribute:mailbox_list+' => '~~',

View File

@@ -1,8 +1,7 @@
<?php
/**
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
@@ -18,6 +17,7 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Portal
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Page:DefaultTitle' => '%1$s 用户门户',
@@ -84,7 +84,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Brick:Portal:UserProfile:Password:ConfirmPassword' => '确认密码',
'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator' => '要修改密码, 请联系管理员',
'Brick:Portal:UserProfile:Password:CantChangeForUnknownReason' => '无法修改密码, 请联系管理员',
'Brick:Portal:UserProfile:PersonalInformations:Title' => '人员信息',
'Brick:Portal:UserProfile:PersonalInformations:Title' => '个体信息',
'Brick:Portal:UserProfile:Photo:Title' => '头像',
]);

View File

@@ -21,6 +21,7 @@
* @license https://opensource.org/licenses/AGPL-3.0
* @author Benjamin Planque <benjamin.planque@combodo.com>
*/
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -28,6 +29,7 @@
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'portal:itop-portal' => '标准门户', // This is the portal name that will be displayed in portal dispatcher (eg. URL in menus)
'Page:DefaultTitle' => '%1$s - 用户门户',

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,10 +31,12 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//////////////////////////////////////////////////////////////////////
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -43,6 +46,7 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:ProblemManagement' => '问题管理',
'Menu:ProblemManagement+' => '问题管理',

View File

@@ -4,6 +4,7 @@
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:RequestManagement' => '服务台',
'Menu:RequestManagement+' => '',
@@ -13,10 +14,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:UserRequest:Provider+' => '',
'Menu:UserRequest:Overview' => '概况',
'Menu:UserRequest:Overview+' => '',
'Menu:NewUserRequest' => '新建用户需求',
'Menu:NewUserRequest+' => '新建用户需求工单',
'Menu:SearchUserRequests' => '搜索用户需求',
'Menu:SearchUserRequests+' => '搜索用户需求',
'Menu:NewUserRequest' => '新建需求',
'Menu:NewUserRequest+' => '新建需求工单',
'Menu:SearchUserRequests' => '搜索需求',
'Menu:SearchUserRequests+' => '搜索需求',
'Menu:UserRequest:Shortcuts' => '快捷方式',
'Menu:UserRequest:Shortcuts+' => '',
'Menu:UserRequest:MyRequests' => '分配给我的需求',
@@ -53,7 +54,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest' => '用户需求',
'Class:UserRequest' => '需求',
'Class:UserRequest+' => '',
'Class:UserRequest/Attribute:status' => '状态',
'Class:UserRequest/Attribute:status+' => '',
@@ -135,7 +136,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:servicesubcategory_id+' => '',
'Class:UserRequest/Attribute:servicesubcategory_name' => '子服务名称',
'Class:UserRequest/Attribute:servicesubcategory_name+' => '',
'Class:UserRequest/Attribute:escalation_flag' => '升级标',
'Class:UserRequest/Attribute:escalation_flag' => '升级标',
'Class:UserRequest/Attribute:escalation_flag+' => '',
'Class:UserRequest/Attribute:escalation_flag/Value:no' => '否',
'Class:UserRequest/Attribute:escalation_flag/Value:no+' => '否',
@@ -211,7 +212,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:parent_incident_ref+' => '~~',
'Class:UserRequest/Attribute:related_request_list' => '子需求',
'Class:UserRequest/Attribute:related_request_list+' => '此父级需求相关的所有衍生需求',
'Class:UserRequest/Attribute:public_log' => '评论',
'Class:UserRequest/Attribute:public_log' => '公共日志',
'Class:UserRequest/Attribute:public_log+' => '',
'Class:UserRequest/Attribute:user_satisfaction' => '用户满意度',
'Class:UserRequest/Attribute:user_satisfaction+' => '',
@@ -225,7 +226,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:user_satisfaction/Value:4+' => '非常不满意',
'Class:UserRequest/Attribute:user_comment' => '用户评论',
'Class:UserRequest/Attribute:user_comment+' => '',
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => 'parent_request_id_friendlyname',
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => '父级需求昵称',
'Class:UserRequest/Attribute:parent_request_id_friendlyname+' => '',
'Class:UserRequest/Stimulus:ev_assign' => '分配',
'Class:UserRequest/Stimulus:ev_assign+' => '',
@@ -252,12 +253,13 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Stimulus:ev_wait_for_approval' => '等待批准',
'Class:UserRequest/Stimulus:ev_wait_for_approval+' => '',
'Class:UserRequest/Error:CannotAssignParentRequestIdToSelf' => '无法分配父级需求给自己',
'Class:UserRequest/Method:ResolveChildTickets' => '解决子工单',
'Class:UserRequest/Method:ResolveChildTickets+' => '递归解决子工单 (自动解决), 并调整相关字段与父级工单保持一致: 服务, 团队, 办理人, 解决方案信息',
]);
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Organization:Overview:UserRequests' => '此组织的所有用户需求',
'Organization:Overview:UserRequests' => '此组织的所有需求',
'Organization:Overview:MyUserRequests' => '我在此组织发起的需求',
'Organization:Overview:Tickets' => '此组织内的所有工单',
]);

View File

@@ -4,6 +4,7 @@
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:RequestManagement' => '服务台',
'Menu:RequestManagement+' => '',
@@ -13,10 +14,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:UserRequest:Provider+' => '',
'Menu:UserRequest:Overview' => '概况',
'Menu:UserRequest:Overview+' => '',
'Menu:NewUserRequest' => '新建用户需求',
'Menu:NewUserRequest+' => '新建用户需求工单',
'Menu:SearchUserRequests' => '搜索用户需求',
'Menu:SearchUserRequests+' => '搜索用户需求',
'Menu:NewUserRequest' => '新建需求',
'Menu:NewUserRequest+' => '新建需求工单',
'Menu:SearchUserRequests' => '搜索需求',
'Menu:SearchUserRequests+' => '搜索需求',
'Menu:UserRequest:Shortcuts' => '快捷方式',
'Menu:UserRequest:Shortcuts+' => '',
'Menu:UserRequest:MyRequests' => '分配给我的需求',
@@ -57,7 +58,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest' => '用户需求',
'Class:UserRequest' => '需求',
'Class:UserRequest+' => '',
'Class:UserRequest/Attribute:status' => '状态',
'Class:UserRequest/Attribute:status+' => '',
@@ -141,7 +142,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:servicesubcategory_id+' => '',
'Class:UserRequest/Attribute:servicesubcategory_name' => '子服务名称',
'Class:UserRequest/Attribute:servicesubcategory_name+' => '',
'Class:UserRequest/Attribute:escalation_flag' => '是否升级',
'Class:UserRequest/Attribute:escalation_flag' => '升级标识',
'Class:UserRequest/Attribute:escalation_flag+' => '',
'Class:UserRequest/Attribute:escalation_flag/Value:no' => '否',
'Class:UserRequest/Attribute:escalation_flag/Value:no+' => '否',
@@ -151,7 +152,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:escalation_reason+' => '',
'Class:UserRequest/Attribute:assignment_date' => '分配日期',
'Class:UserRequest/Attribute:assignment_date+' => '',
'Class:UserRequest/Attribute:resolution_date' => '开始时间',
'Class:UserRequest/Attribute:resolution_date' => '解决日期',
'Class:UserRequest/Attribute:resolution_date+' => '',
'Class:UserRequest/Attribute:last_pending_date' => '最近待定日期',
'Class:UserRequest/Attribute:last_pending_date+' => '',
@@ -161,9 +162,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:tto+' => '响应时间',
'Class:UserRequest/Attribute:ttr' => 'TTR',
'Class:UserRequest/Attribute:ttr+' => '解决时限',
'Class:UserRequest/Attribute:tto_time_spent' => 'TTO time spent~~',
'Class:UserRequest/Attribute:tto_time_spent' => 'TTO 耗时',
'Class:UserRequest/Attribute:tto_time_spent+' => '~~',
'Class:UserRequest/Attribute:ttr_time_spent' => 'TTR time spent~~',
'Class:UserRequest/Attribute:ttr_time_spent' => 'TTR 耗时',
'Class:UserRequest/Attribute:ttr_time_spent+' => '~~',
'Class:UserRequest/Attribute:tto_escalation_deadline' => 'TTO截止日期',
'Class:UserRequest/Attribute:tto_escalation_deadline+' => '',
@@ -213,7 +214,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:parent_change_ref+' => '',
'Class:UserRequest/Attribute:related_request_list' => '衍生事件',
'Class:UserRequest/Attribute:related_request_list+' => '此事件相关的所有子事件',
'Class:UserRequest/Attribute:public_log' => '评论',
'Class:UserRequest/Attribute:public_log' => '公共日志',
'Class:UserRequest/Attribute:public_log+' => '',
'Class:UserRequest/Attribute:user_satisfaction' => '用户满意度',
'Class:UserRequest/Attribute:user_satisfaction+' => '',
@@ -227,7 +228,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:UserRequest/Attribute:user_satisfaction/Value:4+' => '',
'Class:UserRequest/Attribute:user_comment' => '用户留言',
'Class:UserRequest/Attribute:user_comment+' => '',
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => 'parent_request_id_friendlyname',
'Class:UserRequest/Attribute:parent_request_id_friendlyname' => '父级需求昵称',
'Class:UserRequest/Attribute:parent_request_id_friendlyname+' => '',
'Class:UserRequest/Stimulus:ev_assign' => '分配',
'Class:UserRequest/Stimulus:ev_assign+' => '',
@@ -271,20 +272,21 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Portal:UserRequest:MoreInfo' => '更多详细信息',
'Portal:Details-Service-Element' => '服务元素',
'Portal:NoClosedTicket' => '没有关闭的需求',
'Portal:NoService' => '',
'Portal:NoService' => '没有可用的服务',
'Portal:ListOpenProblems' => '处理中的问题',
'Portal:ShowProblem' => '问题',
'Portal:ShowFaqs' => 'FAQ',
'Portal:NoOpenProblem' => '没有打开的问题',
'Portal:SelectLanguage' => '更改您的语言',
'Portal:LanguageChangedTo_Lang' => '语言更改为',
'Portal:ChooseYourFavoriteLanguage' => '选择您喜欢的语言',
'Portal:ChooseYourFavoriteLanguage' => '选择您喜欢的语言',
'Class:UserRequest/Method:ResolveChildTickets' => '解决子工单',
'Class:UserRequest/Method:ResolveChildTickets+' => '递归解决子工单 (自动解决), 并调整相关字段与父级工单保持一致: 服务, 团队, 办理人, 解决方案',
]);
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Organization:Overview:UserRequests' => '来自此组织的用户需求',
'Organization:Overview:MyUserRequests' => '我在此组织的用户需求',
'Organization:Overview:UserRequests' => '来自此组织的需求',
'Organization:Overview:MyUserRequests' => '我在此组织的需求',
'Organization:Overview:Tickets' => '来自此组织的工单',
]);

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,6 +31,7 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Menu, fieldsets, UI, messages translations
//
@@ -41,6 +43,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI-ServiceManagementMenu-ContractsBySrvLevel' => '合同 (按服务等级)',
'UI-ServiceManagementMenu-ContractsByStatus' => '合同 (按状态)',
'UI-ServiceManagementMenu-ContractsEndingIn30Days' => '近30天内截止的合同',
'Menu:ProviderContract' => '供应商合同',
'Menu:ProviderContract+' => '供应商合同',
'Menu:CustomerContract' => '客户合同',
@@ -55,18 +58,18 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:SLT+' => '服务等级目标',
'Menu:DeliveryModel' => '交付模式',
'Menu:DeliveryModel+' => '交付模式',
'Menu:ServiceFamily' => '服务系列',
'Menu:ServiceFamily+' => '服务系列',
'Menu:ServiceCatalog' => 'Service catalog~~',
'Menu:ServiceCatalog+' => 'Define the service elements of your offering~~',
'UI-ServiceCatalogMenu-Title' => 'Service catalog~~',
'UI-ServiceCatalogMenu-NotInPortal' => 'Not displayed in User Portal~~',
'UI-ServiceCatalogMenu-OnlyProductionInPortal' => 'Only Service and Subcategory on production are visible in User Portal~~',
'UI-ServiceCatalogMenu-UnusedService' => 'Services not used by any Customers~~',
'UI-ServiceCatalogMenu-ServiceWithoutFamilyNotInPortal' => 'Services without Service Family are not visible in User Portal~~',
'UI-ServiceCatalogMenu-SLTBySLA' => 'Count SLTs on each SLA~~',
'UI-ServiceCatalogMenu-ContractByService' => 'Count Contracts using a Service~~',
'UI-ServiceCatalogMenu-ContractBySLA' => 'Count Contracts using an SLA~~',
'Menu:ServiceFamily' => '服务家族',
'Menu:ServiceFamily+' => '服务家族',
'Menu:ServiceCatalog' => '服务清单',
'Menu:ServiceCatalog+' => '定义所有提供的服务',
'UI-ServiceCatalogMenu-Title' => '服务清单',
'UI-ServiceCatalogMenu-NotInPortal' => '在用户门户中不可见',
'UI-ServiceCatalogMenu-OnlyProductionInPortal' => '只有生产状态的服务和子服务才会在用户门户中可见',
'UI-ServiceCatalogMenu-UnusedService' => '未被任何客户使用的服务',
'UI-ServiceCatalogMenu-ServiceWithoutFamilyNotInPortal' => '没有服务家族的服务在用户门户中不可见',
'UI-ServiceCatalogMenu-SLTBySLA' => '统计 SLA/SLT',
'UI-ServiceCatalogMenu-ContractByService' => '统计 服务/合同',
'UI-ServiceCatalogMenu-ContractBySLA' => '统计 SLA/合同',
'Contract:baseinfo' => '常规信息',
'Contract:moreinfo' => '合同信息',
@@ -90,7 +93,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContractType' => '合同类型',
'Class:ContractType+' => '',
'Class:ContractType+' => '用于对客户和供应商合同进行分类.',
]);
//
@@ -99,7 +102,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contract' => '合同',
'Class:Contract+' => '',
'Class:Contract+' => '用于处理不同合同类型的抽象类.',
'Class:Contract/Attribute:name' => '名称',
'Class:Contract/Attribute:name+' => '',
'Class:Contract/Attribute:org_id' => '组织',
@@ -138,8 +141,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contract/Attribute:provider_name+' => '',
'Class:Contract/Attribute:status' => '状态',
'Class:Contract/Attribute:status+' => '',
'Class:Contract/Attribute:status/Value:implementation' => '启用',
'Class:Contract/Attribute:status/Value:implementation+' => '启用',
'Class:Contract/Attribute:status/Value:implementation' => '生效',
'Class:Contract/Attribute:status/Value:implementation+' => '生效',
'Class:Contract/Attribute:status/Value:obsolete' => '废弃',
'Class:Contract/Attribute:status/Value:obsolete+' => '废弃',
'Class:Contract/Attribute:status/Value:production' => '正式',
@@ -154,7 +157,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:CustomerContract' => '客户合同',
'Class:CustomerContract+' => '',
'Class:CustomerContract+' => 'Agreement between a client and a provider for the delivery of services with an optional level of commitment (SLA, Coverage Window).~~',
'Class:CustomerContract/Attribute:services_list' => '服务',
'Class:CustomerContract/Attribute:services_list+' => '此合同包含的所有服务',
'Class:CustomerContract/Attribute:functionalcis_list' => '配置项',
@@ -169,7 +172,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ProviderContract' => '供应商合同',
'Class:ProviderContract+' => '',
'Class:ProviderContract+' => 'Agreement between an external provider and an internal organization.~~',
'Class:ProviderContract/Attribute:functionalcis_list' => '配置项',
'Class:ProviderContract/Attribute:functionalcis_list+' => '此合同包含的所有配置项',
'Class:ProviderContract/Attribute:sla' => 'SLA',
@@ -183,8 +186,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContactToContract' => '关联联系人/合同',
'Class:lnkContactToContract+' => '',
'Class:lnkContactToContract' => '链接 联系人/合同',
'Class:lnkContactToContract+' => 'Manages key contacts on each Customer or Provider Contract.~~',
'Class:lnkContactToContract/Name' => '%1$s / %2$s',
'Class:lnkContactToContract/Attribute:contract_id' => '合同',
'Class:lnkContactToContract/Attribute:contract_id+' => '',
@@ -201,8 +204,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContractToDocument' => '关联合同/文档',
'Class:lnkContractToDocument+' => '',
'Class:lnkContractToDocument' => '链接 合同/文档',
'Class:lnkContractToDocument+' => 'Link used when a Document is applicable to a Contract.~~',
'Class:lnkContractToDocument/Name' => '%1$s / %2$s',
'Class:lnkContractToDocument/Attribute:contract_id' => '合同',
'Class:lnkContractToDocument/Attribute:contract_id+' => '',
@@ -220,7 +223,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkFunctionalCIToProviderContract' => '关联功能配置项/供应商合同',
'Class:lnkFunctionalCIToProviderContract+' => '',
'Class:lnkFunctionalCIToProviderContract+' => 'This link models the Functional CIs that are supported by an external company through a Provider Contract.~~',
'Class:lnkFunctionalCIToProviderContract/Name' => '%1$s / %2$s',
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id' => '供应商合同',
'Class:lnkFunctionalCIToProviderContract/Attribute:providercontract_id+' => '',
@@ -237,8 +240,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceFamily' => '服务系列',
'Class:ServiceFamily+' => '',
'Class:ServiceFamily' => '服务家族',
'Class:ServiceFamily+' => '服务架构的最高层级.在用户门户中对外提供服务时需要.',
'Class:ServiceFamily/Attribute:name' => '名称',
'Class:ServiceFamily/Attribute:name+' => '',
'Class:ServiceFamily/Attribute:icon' => '图标',
@@ -253,7 +256,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Service' => '服务',
'Class:Service+' => '',
'Class:Service+' => '服务由组织提供,并通过客户合同订阅. 它必须包含至少一个子服务.',
'Class:Service/ComplementaryName' => '%1$s - %2$s',
'Class:Service/Attribute:name' => '名称',
'Class:Service/Attribute:name+' => '',
@@ -263,18 +266,18 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Service/Attribute:organization_name+' => '',
'Class:Service/Attribute:description' => '描述',
'Class:Service/Attribute:description+' => '',
'Class:Service/Attribute:servicefamily_id' => '服务系列',
'Class:Service/Attribute:servicefamily_id' => '服务家族',
'Class:Service/Attribute:servicefamily_id+' => 'Required for this service to be visible on User Portal~~',
'Class:Service/Attribute:servicefamily_name' => '服务系列名称',
'Class:Service/Attribute:servicefamily_name' => '服务家族名称',
'Class:Service/Attribute:servicefamily_name+' => '',
'Class:Service/Attribute:documents_list' => '文档',
'Class:Service/Attribute:documents_list+' => '此服务相关的所有文档',
'Class:Service/Attribute:contacts_list' => '联系人',
'Class:Service/Attribute:contacts_list+' => '此服务相关的所有联系人',
'Class:Service/Attribute:status' => '状态',
'Class:Service/Attribute:status+' => 'By default only Service in production are visible by Portal users~~',
'Class:Service/Attribute:status/Value:implementation' => '启用',
'Class:Service/Attribute:status/Value:implementation+' => '启用',
'Class:Service/Attribute:status+' => '默认情况下,只有生产状态的服务才会在用户门户中可见',
'Class:Service/Attribute:status/Value:implementation' => '生效',
'Class:Service/Attribute:status/Value:implementation+' => '生效',
'Class:Service/Attribute:status/Value:obsolete' => '废弃',
'Class:Service/Attribute:status/Value:obsolete+' => '',
'Class:Service/Attribute:status/Value:production' => '生产',
@@ -292,8 +295,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDocumentToService' => '关联文档/服务',
'Class:lnkDocumentToService+' => '',
'Class:lnkDocumentToService' => '链接 文档/服务',
'Class:lnkDocumentToService+' => 'Link used when a Document is applicable to a Service.~~',
'Class:lnkDocumentToService/Name' => '%1$s / %2$s',
'Class:lnkDocumentToService/Attribute:service_id' => '服务',
'Class:lnkDocumentToService/Attribute:service_id+' => '',
@@ -310,8 +313,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContactToService' => '关联联系人/服务',
'Class:lnkContactToService+' => '',
'Class:lnkContactToService' => '链接 联系人/服务',
'Class:lnkContactToService+' => 'Ideal for defining the Team to which Tickets created on the related Service will be assigned (automatically or manually).~~',
'Class:lnkContactToService/Name' => '%1$s / %2$s',
'Class:lnkContactToService/Attribute:service_id' => '服务',
'Class:lnkContactToService/Attribute:service_id+' => '',
@@ -329,7 +332,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceSubcategory' => '子服务',
'Class:ServiceSubcategory+' => '',
'Class:ServiceSubcategory+' => '服务架构的最低层级. 用户需求通常与某个子服务相关联.',
'Class:ServiceSubcategory/ComplementaryName' => '%1$s - %2$s',
'Class:ServiceSubcategory/Attribute:name' => '名称',
'Class:ServiceSubcategory/Attribute:name+' => '',
@@ -341,8 +344,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceSubcategory/Attribute:service_name+' => '',
'Class:ServiceSubcategory/Attribute:status' => '状态',
'Class:ServiceSubcategory/Attribute:status+' => '',
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => '启用',
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => '启用',
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => '生效',
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => '生效',
'Class:ServiceSubcategory/Attribute:status/Value:obsolete' => '废弃',
'Class:ServiceSubcategory/Attribute:status/Value:obsolete+' => '废弃',
'Class:ServiceSubcategory/Attribute:status/Value:production' => '生产',
@@ -363,7 +366,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLA' => 'SLA',
'Class:SLA+' => '',
'Class:SLA+' => 'Service Level Agreement (SLA) 适用于客户订阅的服务,并通过 SLT 进行衡量和考核.',
'Class:SLA/Attribute:name' => '名称',
'Class:SLA/Attribute:name+' => '',
'Class:SLA/Attribute:description' => '描述',
@@ -385,7 +388,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLT' => 'SLT',
'Class:SLT+' => '',
'Class:SLT+' => '服务水平目标位于服务水平协议(SLA)之下. 它定义了(TTO 或 TTR)指标的最大时限, 需求类型 (事件或服务需求) 和优先级.',
'Class:SLT/Attribute:name' => '名称',
'Class:SLT/Attribute:name+' => '',
'Class:SLT/Attribute:priority' => '优先级',
@@ -425,8 +428,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkSLAToSLT' => '关联 SLA / SLT',
'Class:lnkSLAToSLT+' => '',
'Class:lnkSLAToSLT' => '链接 SLA/SLT',
'Class:lnkSLAToSLT+' => 'This link indicates that an SLT is included in the Service Level Agreement (SLA). An SLA usually contains several SLTs. An SLT can be reused as is by several SLAs (seldom).~~',
'Class:lnkSLAToSLT/Name' => '%1$s / %2$s',
'Class:lnkSLAToSLT/Attribute:sla_id' => 'SLA',
'Class:lnkSLAToSLT/Attribute:sla_id+' => '',
@@ -453,8 +456,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToService' => '关联客户合同/服务',
'Class:lnkCustomerContractToService+' => '',
'Class:lnkCustomerContractToService' => '链接 客户合同/服务',
'Class:lnkCustomerContractToService+' => 'A single line of a Customer Contract, specifying the Service provided and, for this service, the subscribed commitment levels (Service Level Agreement and Coverage Window).~~',
'Class:lnkCustomerContractToService/Name' => '%1$s / %2$s',
'Class:lnkCustomerContractToService/Attribute:customercontract_id' => '客户合同',
'Class:lnkCustomerContractToService/Attribute:customercontract_id+' => '',
@@ -477,8 +480,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToProviderContract' => '关联 客户合同/供应商合同',
'Class:lnkCustomerContractToProviderContract+' => '',
'Class:lnkCustomerContractToProviderContract' => '链接 客户合同/供应商合同',
'Class:lnkCustomerContractToProviderContract+' => 'This link models when a Provider Contract contributes to the delivery of a Customer Contract.~~',
'Class:lnkCustomerContractToProviderContract/Name' => '%1$s / %2$s',
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_id' => '客户合同',
'Class:lnkCustomerContractToProviderContract/Attribute:customercontract_id+' => '',
@@ -495,8 +498,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToFunctionalCI' => '关联客户合同/功能配置项',
'Class:lnkCustomerContractToFunctionalCI+' => '',
'Class:lnkCustomerContractToFunctionalCI' => '链接 客户合同/功能配置项',
'Class:lnkCustomerContractToFunctionalCI+' => 'This link models the equipment (Functional CI) covered by a Customer Contract.~~',
'Class:lnkCustomerContractToFunctionalCI/Name' => '%1$s / %2$s',
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_id' => '客户合同',
'Class:lnkCustomerContractToFunctionalCI/Attribute:customercontract_id+' => '',
@@ -514,7 +517,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DeliveryModel' => '交付模式',
'Class:DeliveryModel+' => '',
'Class:DeliveryModel+' => '交付模式指定了可以分配工单的团队;它必须在联系人选项卡中包含至少一个团队.
每个客户组织都必须有定义好的交付模式.',
'Class:DeliveryModel/Attribute:name' => '名称',
'Class:DeliveryModel/Attribute:name+' => '',
'Class:DeliveryModel/Attribute:org_id' => '组织',
@@ -524,7 +528,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DeliveryModel/Attribute:description' => '描述',
'Class:DeliveryModel/Attribute:description+' => '',
'Class:DeliveryModel/Attribute:contacts_list' => '联系人',
'Class:DeliveryModel/Attribute:contacts_list+' => '此交付模式的所有联系人 (包括团队和人员)',
'Class:DeliveryModel/Attribute:contacts_list+' => '此交付模式的所有联系人 (包括团队和个体)',
'Class:DeliveryModel/Attribute:customers_list' => '客户',
'Class:DeliveryModel/Attribute:customers_list+' => '使用此交付模式的所有客户',
]);
@@ -534,8 +538,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDeliveryModelToContact' => '关联 交付模式/联系人',
'Class:lnkDeliveryModelToContact+' => '',
'Class:lnkDeliveryModelToContact' => '链接 交付模式/联系人',
'Class:lnkDeliveryModelToContact+' => 'This link specifies the role of a Team (more rarely a Person) within a Delivery Model.~~',
'Class:lnkDeliveryModelToContact/Name' => '%1$s / %2$s',
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id' => '交付模式',
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id+' => '',

View File

@@ -88,7 +88,13 @@ if (!class_exists('ServiceMgmtProviderInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
// Load localized structural data: contract types
static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contracttype.xml");
static::LoadLocalizedData(
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contracttype.xml"
);
}
}
}

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,7 +31,10 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Menu, fieldsets, UI, messages translations
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:ServiceManagement' => '服务管理',
'Menu:ServiceManagement+' => '服务管理概况',
@@ -39,6 +43,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI-ServiceManagementMenu-ContractsBySrvLevel' => '合同 (按服务等级)',
'UI-ServiceManagementMenu-ContractsByStatus' => '合同 (按状态)',
'UI-ServiceManagementMenu-ContractsEndingIn30Days' => '未来30天内截止的合同',
'Menu:ProviderContract' => '供应商合同',
'Menu:ProviderContract+' => '供应商合同',
'Menu:CustomerContract' => '客户合同',
@@ -53,18 +58,18 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:SLT+' => '服务等级目标',
'Menu:DeliveryModel' => '交付模式',
'Menu:DeliveryModel+' => '交付模式',
'Menu:ServiceFamily' => '服务系列',
'Menu:ServiceFamily+' => '服务系列',
'Menu:ServiceCatalog' => 'Service catalog~~',
'Menu:ServiceCatalog+' => 'Define the service elements of your offering~~',
'UI-ServiceCatalogMenu-Title' => 'Service catalog~~',
'UI-ServiceCatalogMenu-NotInPortal' => 'Not displayed in User Portal~~',
'UI-ServiceCatalogMenu-OnlyProductionInPortal' => 'Only Service and Subcategory on production are visible in User Portal~~',
'UI-ServiceCatalogMenu-UnusedService' => 'Services not used by any Customers~~',
'UI-ServiceCatalogMenu-ServiceWithoutFamilyNotInPortal' => 'Services without Service Family are not visible in User Portal~~',
'UI-ServiceCatalogMenu-SLTBySLA' => 'Count SLTs on each SLA~~',
'UI-ServiceCatalogMenu-ContractByService' => 'Count Contracts using a Service~~',
'UI-ServiceCatalogMenu-ContractBySLA' => 'Count Contracts using an SLA~~',
'Menu:ServiceFamily' => '服务家族',
'Menu:ServiceFamily+' => '服务家族',
'Menu:ServiceCatalog' => '服务清单',
'Menu:ServiceCatalog+' => '定义可提供的服务',
'UI-ServiceCatalogMenu-Title' => '服务清单',
'UI-ServiceCatalogMenu-NotInPortal' => '在用户门户中不可见',
'UI-ServiceCatalogMenu-OnlyProductionInPortal' => '只有生产状态的服务和子服务才会在用户门户中可见',
'UI-ServiceCatalogMenu-UnusedService' => '未被任何客户使用的服务',
'UI-ServiceCatalogMenu-ServiceWithoutFamilyNotInPortal' => '没有服务家族的服务在用户门户中不可见',
'UI-ServiceCatalogMenu-SLTBySLA' => '统计 SLA/SLT',
'UI-ServiceCatalogMenu-ContractByService' => '统计 服务/合同',
'UI-ServiceCatalogMenu-ContractBySLA' => '统计 SLA/合同',
'Menu:Procedure' => '流程清单',
'Menu:Procedure+' => '所有流程清单',
@@ -79,8 +84,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Organization/Attribute:deliverymodel_id' => '交付模式',
'Class:Organization/Attribute:deliverymodel_id+' => 'This is required for Tickets handling.
The delivery model specifies the teams to which tickets can be assigned.~~',
'Class:Organization/Attribute:deliverymodel_id+' => '工单处理必备.
交付模式指定了工单可以分配到的团队.',
'Class:Organization/Attribute:deliverymodel_name' => '交付模式名称',
]);
@@ -90,7 +95,7 @@ The delivery model specifies the teams to which tickets can be assigned.~~',
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContractType' => '合同类型',
'Class:ContractType+' => '',
'Class:ContractType+' => '用于对客户和供应商合同进行分类.',
]);
//
@@ -99,7 +104,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contract' => '合同',
'Class:Contract+' => '',
'Class:Contract+' => '用于处理不同合同类型的抽象类.',
'Class:Contract/Attribute:name' => '名称',
'Class:Contract/Attribute:name+' => '',
'Class:Contract/Attribute:org_id' => '客户',
@@ -138,8 +143,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contract/Attribute:provider_name+' => '通用名称',
'Class:Contract/Attribute:status' => '状态',
'Class:Contract/Attribute:status+' => '',
'Class:Contract/Attribute:status/Value:implementation' => '启用',
'Class:Contract/Attribute:status/Value:implementation+' => '启用',
'Class:Contract/Attribute:status/Value:implementation' => '生效',
'Class:Contract/Attribute:status/Value:implementation+' => '生效',
'Class:Contract/Attribute:status/Value:obsolete' => '废弃',
'Class:Contract/Attribute:status/Value:obsolete+' => '废弃',
'Class:Contract/Attribute:status/Value:production' => '生产',
@@ -153,7 +158,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:CustomerContract' => '客户合同',
'Class:CustomerContract+' => '',
'Class:CustomerContract+' => 'Agreement between a client and a provider for the delivery of services with an optional level of commitment (SLA, Coverage Window).~~',
'Class:CustomerContract/Attribute:services_list' => '服务',
'Class:CustomerContract/Attribute:services_list+' => '此合同包含的所有服务',
]);
@@ -164,7 +169,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ProviderContract' => '供应商合同',
'Class:ProviderContract+' => '',
'Class:ProviderContract+' => 'Agreement between an external provider and an internal organization.~~',
'Class:ProviderContract/Attribute:functionalcis_list' => '配置项',
'Class:ProviderContract/Attribute:functionalcis_list+' => '此供应商合同包含的所有配置项',
'Class:ProviderContract/Attribute:sla' => 'SLA',
@@ -184,8 +189,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContactToContract' => '关联 联系人/合同',
'Class:lnkContactToContract+' => '',
'Class:lnkContactToContract' => '链接 联系人/合同',
'Class:lnkContactToContract+' => 'Manages key contacts on each customer or provider contract.~~',
'Class:lnkContactToContract/Name' => '%1$s / %2$s',
'Class:lnkContactToContract/Attribute:contract_id' => '合同',
'Class:lnkContactToContract/Attribute:contract_id+' => '',
@@ -202,8 +207,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContractToDocument' => '关联合同/文档',
'Class:lnkContractToDocument+' => '',
'Class:lnkContractToDocument' => '链接 合同/文档',
'Class:lnkContractToDocument+' => 'Link used when a Document is applicable to a Contract.~~',
'Class:lnkContractToDocument/Name' => '%1$s / %2$s',
'Class:lnkContractToDocument/Attribute:contract_id' => '合同',
'Class:lnkContractToDocument/Attribute:contract_id+' => '',
@@ -220,8 +225,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceFamily' => '服务系列',
'Class:ServiceFamily+' => '',
'Class:ServiceFamily' => '服务家族',
'Class:ServiceFamily+' => '服务架构的最高层级.在用户门户中对外提供服务时需要.',
'Class:ServiceFamily/Attribute:name' => '名称',
'Class:ServiceFamily/Attribute:name+' => '',
'Class:ServiceFamily/Attribute:icon' => '图标',
@@ -236,7 +241,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Service' => '服务',
'Class:Service+' => '',
'Class:Service+' => '服务由组织提供并通过客户合同订阅.它必须包含至少一个子服务.',
'Class:Service/ComplementaryName' => '%1$s - %2$s',
'Class:Service/Attribute:name' => '名称',
'Class:Service/Attribute:name+' => '',
@@ -244,9 +249,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Service/Attribute:org_id+' => '',
'Class:Service/Attribute:organization_name' => '供应商名称',
'Class:Service/Attribute:organization_name+' => '',
'Class:Service/Attribute:servicefamily_id' => '服务系列',
'Class:Service/Attribute:servicefamily_id' => '服务家族',
'Class:Service/Attribute:servicefamily_id+' => 'Required for this service to be visible on User Portal~~',
'Class:Service/Attribute:servicefamily_name' => '服务系列名称',
'Class:Service/Attribute:servicefamily_name' => '服务家族名称',
'Class:Service/Attribute:servicefamily_name+' => '',
'Class:Service/Attribute:description' => '描述',
'Class:Service/Attribute:description+' => '',
@@ -255,9 +260,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Service/Attribute:contacts_list' => '联系人',
'Class:Service/Attribute:contacts_list+' => '此服务相关的所有联系人',
'Class:Service/Attribute:status' => '状态',
'Class:Service/Attribute:status+' => 'By default only Service in production are visible by Portal users~~',
'Class:Service/Attribute:status/Value:implementation' => '启用',
'Class:Service/Attribute:status/Value:implementation+' => '启用',
'Class:Service/Attribute:status+' => '默认情况下,只有生产状态的服务才会在用户门户中可见',
'Class:Service/Attribute:status/Value:implementation' => '生效',
'Class:Service/Attribute:status/Value:implementation+' => '生效',
'Class:Service/Attribute:status/Value:obsolete' => '废弃',
'Class:Service/Attribute:status/Value:obsolete+' => '',
'Class:Service/Attribute:status/Value:production' => '生产',
@@ -279,8 +284,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDocumentToService' => '关联文档/服务',
'Class:lnkDocumentToService+' => '',
'Class:lnkDocumentToService' => '链接 文档/服务',
'Class:lnkDocumentToService+' => 'Link used when a Document is applicable to a Service.~~',
'Class:lnkDocumentToService/Name' => '%1$s / %2$s',
'Class:lnkDocumentToService/Attribute:service_id' => '服务',
'Class:lnkDocumentToService/Attribute:service_id+' => '',
@@ -297,8 +302,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContactToService' => '关联联系人/服务',
'Class:lnkContactToService+' => '',
'Class:lnkContactToService' => '链接 联系人/服务',
'Class:lnkContactToService+' => 'Ideal for defining the team to which Tickets created on the related Service will be assigned (automatically or manually).~~',
'Class:lnkContactToService/Name' => '%1$s / %2$s',
'Class:lnkContactToService/Attribute:service_id' => '服务',
'Class:lnkContactToService/Attribute:service_id+' => '',
@@ -316,7 +321,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceSubcategory' => '子服务',
'Class:ServiceSubcategory+' => '',
'Class:ServiceSubcategory+' => '服务架构的最低层级. 用户需求通常与某个子服务相关联.',
'Class:ServiceSubcategory/ComplementaryName' => '%1$s - %2$s',
'Class:ServiceSubcategory/Attribute:name' => '名称',
'Class:ServiceSubcategory/Attribute:name+' => '',
@@ -334,8 +339,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ServiceSubcategory/Attribute:request_type/Value:service_request+' => '服务需求',
'Class:ServiceSubcategory/Attribute:status' => '状态',
'Class:ServiceSubcategory/Attribute:status+' => '',
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => '启用',
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => '启用',
'Class:ServiceSubcategory/Attribute:status/Value:implementation' => '生效',
'Class:ServiceSubcategory/Attribute:status/Value:implementation+' => '生效',
'Class:ServiceSubcategory/Attribute:status/Value:obsolete' => '废弃',
'Class:ServiceSubcategory/Attribute:status/Value:obsolete+' => '废弃',
'Class:ServiceSubcategory/Attribute:status/Value:production' => '生产',
@@ -348,7 +353,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLA' => 'SLA',
'Class:SLA+' => '',
'Class:SLA+' => 'Service Level Agreement (SLA) 适用于客户订阅的服务,并通过 SLT 进行衡量和考核.',
'Class:SLA/Attribute:name' => '名称',
'Class:SLA/Attribute:name+' => '',
'Class:SLA/Attribute:description' => '描述',
@@ -361,7 +366,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLA/Attribute:slts_list+' => '此SLA包含的所有服务等级目标',
'Class:SLA/Attribute:customercontracts_list' => '客户合同',
'Class:SLA/Attribute:customercontracts_list+' => '使用此SLA的所有客户合同',
'Class:SLA/Error:UniqueLnkCustomerContractToService' => '不能保存客户合同%1$s与服务%2$s的关联: SLA已存在',
'Class:SLA/Error:UniqueLnkCustomerContractToService' => '无法保存客户合同%1$s与服务%2$s的链接: SLA已存在',
]);
//
@@ -370,7 +375,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLT' => 'SLT',
'Class:SLT+' => '',
'Class:SLT+' => '服务水平目标(SLT)位于服务水平协议(SLA)之下. 它定义了(TTO 或 TTR)指标的最大时限, 需求类型 (事件或服务需求) 和优先级.',
'Class:SLT/Attribute:name' => '名称',
'Class:SLT/Attribute:name+' => '',
'Class:SLT/Attribute:priority' => '优先级',
@@ -404,7 +409,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SLT/Attribute:unit/Value:minutes' => '分钟',
'Class:SLT/Attribute:unit/Value:minutes+' => '分钟',
'Class:SLT/Attribute:slas_list' => 'SLA',
'Class:SLT/Attribute:slas_list+' => '所有使用此 SLT 的 SLA',
'Class:SLT/Attribute:slas_list+' => '使用此 SLT 的所有 SLA',
]);
//
@@ -412,8 +417,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkSLAToSLT' => '关联SLA/SLT',
'Class:lnkSLAToSLT+' => '',
'Class:lnkSLAToSLT' => '链接 SLA/SLT',
'Class:lnkSLAToSLT+' => 'This link indicates that an SLT is included in the Service Level Agreement (SLA). An SLA usually contains several SLTs. An SLT can be reused as is by several SLAs (seldom).~~',
'Class:lnkSLAToSLT/Name' => '%1$s / %2$s',
'Class:lnkSLAToSLT/Attribute:sla_id' => 'SLA',
'Class:lnkSLAToSLT/Attribute:sla_id+' => '',
@@ -440,8 +445,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToService' => '关联客户合同/服务',
'Class:lnkCustomerContractToService+' => '',
'Class:lnkCustomerContractToService' => '链接 客户合同/服务',
'Class:lnkCustomerContractToService+' => 'A single line of a customer contract, specifying the Service provided and, for this service, the subscribed commitment levels (Service Level Aggrement and Coverage Window).~~',
'Class:lnkCustomerContractToService/Name' => '%1$s / %2$s',
'Class:lnkCustomerContractToService/Attribute:customercontract_id' => '客户合同',
'Class:lnkCustomerContractToService/Attribute:customercontract_id+' => '',
@@ -455,6 +460,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToService/Attribute:sla_id+' => '',
'Class:lnkCustomerContractToService/Attribute:sla_name' => 'SLA名称',
'Class:lnkCustomerContractToService/Attribute:sla_name+' => '',
'Class:lnkCustomerContractToService/Attribute:provider_id' => 'Provider id~~',
'Class:lnkCustomerContractToService/Attribute:provider_id+' => '',
]);
//
@@ -462,8 +469,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkProviderContractToService' => '关联供应商合同/服务',
'Class:lnkProviderContractToService+' => '',
'Class:lnkProviderContractToService' => '链接 供应商合同/服务',
'Class:lnkProviderContractToService+' => 'This link can model that a provider contract enables the delivery of a Service.~~',
'Class:lnkProviderContractToService/Name' => '%1$s / %2$s',
'Class:lnkProviderContractToService/Attribute:service_id' => '服务',
'Class:lnkProviderContractToService/Attribute:service_id+' => '',
@@ -473,6 +480,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkProviderContractToService/Attribute:providercontract_id+' => '',
'Class:lnkProviderContractToService/Attribute:providercontract_name' => '供应商合同名称',
'Class:lnkProviderContractToService/Attribute:providercontract_name+' => '',
'Class:lnkProviderContractToService/Attribute:provider_id' => 'Provider id~~',
'Class:lnkProviderContractToService/Attribute:provider_id+' => '',
]);
//
@@ -481,7 +490,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DeliveryModel' => '交付模式',
'Class:DeliveryModel+' => '',
'Class:DeliveryModel+' => '交付模式指定了可以分配工单的团队;它必须在联系人选项卡中包含至少一个团队.
每个客户组织都必须有定义好的交付模式.',
'Class:DeliveryModel/Attribute:name' => '名称',
'Class:DeliveryModel/Attribute:name+' => 'Don\'t forget to add teams to this delivery model~~',
'Class:DeliveryModel/Attribute:org_id' => '组织',
@@ -491,9 +501,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DeliveryModel/Attribute:description' => '描述',
'Class:DeliveryModel/Attribute:description+' => '',
'Class:DeliveryModel/Attribute:contacts_list' => '联系人',
'Class:DeliveryModel/Attribute:contacts_list+' => '此交付模式相关的所有联系人 (包括团队和人员)',
'Class:DeliveryModel/Attribute:contacts_list+' => '此交付模式相关的所有联系人 (包括团队和个体)',
'Class:DeliveryModel/Attribute:customers_list' => '客户',
'Class:DeliveryModel/Attribute:customers_list+' => '所有使用此交付模式的客户',
'Class:DeliveryModel/Attribute:customers_list+' => '使用此交付模式的所有客户',
]);
//
@@ -501,8 +511,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkDeliveryModelToContact' => '关联交付模式/联系人',
'Class:lnkDeliveryModelToContact+' => '',
'Class:lnkDeliveryModelToContact' => '链接 交付模式/联系人',
'Class:lnkDeliveryModelToContact+' => 'This link specifies the role of a Team (more rarely a Person) within a Delivery Model.~~',
'Class:lnkDeliveryModelToContact/Name' => '%1$s / %2$s',
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id' => '交付模式',
'Class:lnkDeliveryModelToContact/Attribute:deliverymodel_id+' => '',
@@ -539,21 +549,3 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContractToDocument/Attribute:provider_id' => 'Provider id~~',
'Class:lnkContractToDocument/Attribute:provider_id+' => '~~',
]);
//
// Class: lnkCustomerContractToService
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkCustomerContractToService/Attribute:provider_id' => 'Provider id~~',
'Class:lnkCustomerContractToService/Attribute:provider_id+' => '~~',
]);
//
// Class: lnkProviderContractToService
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkProviderContractToService/Attribute:provider_id' => 'Provider id~~',
'Class:lnkProviderContractToService/Attribute:provider_id+' => '~~',
]);

View File

@@ -85,7 +85,13 @@ if (!class_exists('ServiceMgmtInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
// Load localized structural data: contact types and document types
static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contracttype.xml");
static::LoadLocalizedData(
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contracttype.xml"
);
}
}
}

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Dictionary entries go here
]);
@@ -30,12 +31,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:NASFileSystem/Attribute:org_id' => 'Org id~~',
'Class:NASFileSystem/Attribute:org_id+' => '~~',
'Class:NASFileSystem/Attribute:location_id' => 'Location id~~',
'Class:NASFileSystem/Attribute:location_id+' => '~~',
'Class:NASFileSystem/Attribute:location_name' => 'Location name~~',
'Class:NASFileSystem/Attribute:location_name+' => '~~',
'Class:NASFileSystem/Attribute:org_id' => '组织 ID',
'Class:NASFileSystem/Attribute:org_id+' => '',
'Class:NASFileSystem/Attribute:location_id' => '位置 ID',
'Class:NASFileSystem/Attribute:location_id+' => '',
'Class:NASFileSystem/Attribute:location_name' => '位置名称',
'Class:NASFileSystem/Attribute:location_name+' => '',
]);
//
@@ -43,10 +44,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:FiberChannelInterface/Attribute:org_id' => 'Org id~~',
'Class:FiberChannelInterface/Attribute:org_id+' => '~~',
'Class:FiberChannelInterface/Attribute:location_id' => 'Location id~~',
'Class:FiberChannelInterface/Attribute:location_id+' => '~~',
'Class:FiberChannelInterface/Name' => '%2$s %1$s',
'Class:FiberChannelInterface/Attribute:org_id' => '组织 ID',
'Class:FiberChannelInterface/Attribute:org_id+' => '',
'Class:FiberChannelInterface/Attribute:location_id' => '位置 ID',
'Class:FiberChannelInterface/Attribute:location_id+' => '',
]);
//
@@ -54,10 +56,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:LogicalVolume/Attribute:org_id' => 'Org id~~',
'Class:LogicalVolume/Attribute:org_id+' => '~~',
'Class:LogicalVolume/Attribute:location_id' => 'Location id~~',
'Class:LogicalVolume/Attribute:location_id+' => '~~',
'Class:LogicalVolume/Attribute:location_name' => 'Location name~~',
'Class:LogicalVolume/Attribute:location_name+' => '~~',
'Class:LogicalVolume/Attribute:org_id' => '组织 ID',
'Class:LogicalVolume/Attribute:org_id+' => '',
'Class:LogicalVolume/Attribute:location_id' => '位置 ID',
'Class:LogicalVolume/Attribute:location_id+' => '',
'Class:LogicalVolume/Attribute:location_name' => '位置名称',
'Class:LogicalVolume/Attribute:location_name+' => '',
]);

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnary conventions
// Class:<class_name>
// Class:<class_name>+
@@ -32,6 +33,7 @@
// Class:<class_name>/Stimulus:<stimulus_code>+
// Class:<class_name>/UniquenessRule:<rule_code>
// Class:<class_name>/UniquenessRule:<rule_code>+
//////////////////////////////////////////////////////////////////////
// Note: The classes have been grouped by categories: bizmodel
//////////////////////////////////////////////////////////////////////
@@ -39,12 +41,14 @@
// Classes in 'bizmodel'
//////////////////////////////////////////////////////////////////////
//
//
// Class: Organization
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Organization' => '组织',
'Class:Organization+' => '',
'Class:Organization+' => 'It can be a customer, a provider, your company or departments within your company. Organizations can be structured hierarchically. Users can be limited to objects belonging to some organizations only.~~',
'Class:Organization/Attribute:name' => '名称',
'Class:Organization/Attribute:name+' => '常用名称',
'Class:Organization/Attribute:code' => '编码',
@@ -91,7 +95,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Location/Attribute:org_name' => '所属组织名称',
'Class:Location/Attribute:org_name+' => '',
'Class:Location/Attribute:address' => '地址',
'Class:Location/Attribute:address+' => '地址',
'Class:Location/Attribute:address+' => '邮政地址',
'Class:Location/Attribute:postal_code' => '邮编',
'Class:Location/Attribute:postal_code+' => '邮政编码',
'Class:Location/Attribute:city' => '城市',
@@ -110,7 +114,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contact' => '联系人',
'Class:Contact+' => '',
'Class:Contact+' => '抽象类. 联系人可以与工单和功能配置项关联,用于不同的目的,例如事件分配和通知.',
'Class:Contact/ComplementaryName' => '%1$s - %2$s',
'Class:Contact/Attribute:name' => '名称',
'Class:Contact/Attribute:name+' => '',
@@ -129,7 +133,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contact/Attribute:phone' => '电话',
'Class:Contact/Attribute:phone+' => '',
'Class:Contact/Attribute:notify' => '通知',
'Class:Contact/Attribute:notify+' => '',
'Class:Contact/Attribute:notify+' => 'Flag which can be used by each notification~~',
'Class:Contact/Attribute:notify/Value:no' => '否',
'Class:Contact/Attribute:notify/Value:no+' => '否',
'Class:Contact/Attribute:notify/Value:yes' => '是',
@@ -137,7 +141,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Contact/Attribute:function' => '职责',
'Class:Contact/Attribute:function+' => '',
'Class:Contact/Attribute:cis_list' => '配置项',
'Class:Contact/Attribute:cis_list+' => '此联系人关的所有配置项',
'Class:Contact/Attribute:cis_list+' => '此联系人关的所有配置项',
'Class:Contact/Attribute:finalclass' => '联系人类型',
'Class:Contact/Attribute:finalclass+' => '根本属性的名称',
]);
@@ -147,9 +151,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Person' => '人员',
'Class:Person+' => '',
'Class:Person/ComplementaryName' => '%1$s - %2$s~~',
'Class:Person' => '个体',
'Class:Person+' => 'A type of Contact used to describe physical persons. Persons can be grouped into Teams. Persons can be linked to other configuration items (eg. to describe who to contact in case of incident with an application).
Other usage: the caller of a User request is a Person as well as the agent assigned to resolve it.~~',
'Class:Person/ComplementaryName' => '%1$s - %2$s',
'Class:Person/Attribute:name' => '姓',
'Class:Person/Attribute:name+' => '',
'Class:Person/Attribute:first_name' => '名',
@@ -167,11 +172,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Person/Attribute:manager_name' => '名称',
'Class:Person/Attribute:manager_name+' => '',
'Class:Person/Attribute:team_list' => '团队',
'Class:Person/Attribute:team_list+' => '这人员归属的所有团队',
'Class:Person/Attribute:team_list+' => '这个体归属的所有团队',
'Class:Person/Attribute:tickets_list' => '工单',
'Class:Person/Attribute:tickets_list+' => '此人发起的所有工单',
'Class:Person/Attribute:tickets_list/UI:Links:Create:Modal:Title' => 'Create a %4$s for %2$s~~',
'Class:Person/Attribute:user_list' => '用户',
'Class:Person/Attribute:user_list+' => '所有关联到此人员的用户',
'Class:Person/Attribute:user_list+' => '此个体相关的所有用户',
'Class:Person/Attribute:manager_id_friendlyname' => '直属上级姓名',
'Class:Person/Attribute:manager_id_friendlyname+' => '',
'Class:Person/Attribute:picture' => '头像',
@@ -180,7 +186,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Person/UniquenessRule:employee_number' => '\'$this->org_name$\' 内已经有人占用了这个员工号',
'Class:Person/UniquenessRule:name+' => '同一组织内的员工姓名必须唯一',
'Class:Person/UniquenessRule:name' => '\'$this->org_name$\' 内已经有人叫这个名字',
'Class:Person/Error:ChangingOrgDenied' => '无法移动此人员到组织 \'%1$s\' 因为这将终端其用户门户的访问, 其关联的用户没有被授权访问此组织',
'Class:Person/Error:ChangingOrgDenied' => '无法移动此个体到组织 \'%1$s\' 因为这将终端其用户门户的访问, 其关联的用户没有被授权访问此组织',
]);
//
@@ -189,19 +195,19 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Team' => '团队',
'Class:Team+' => '',
'Class:Team+' => 'A type of Contact. Often used to group Persons, but not only. Teams are expected to watch Tickets dispatched to them, and assign it to an agent, usually a member of that team.~~',
'Class:Team/ComplementaryName' => '%1$s - %2$s',
'Class:Team/Attribute:persons_list' => '成员',
'Class:Team/Attribute:persons_list+' => '此团队包含的所有成员',
'Class:Team/Attribute:overview' => 'Overview~~',
'Team:Overview' => 'Tickets and CIs managed by the team~~',
'Team:Overview:ActiveTickets' => 'Active tickets~~',
'Team:Overview:FunctionalCIs-ByType' => 'Functional CIs~~',
'Team:Overview:UserRequest-ByStatus' => 'User requests by status~~',
'Team:Overview:UserRequest-ClosedByMonth' => 'User requests closed in last 12 months~~',
'Team:Overview:UserRequest-ClosedByAgent' => 'User requests closed by agent in last 12 months~~',
'Class:Team/Attribute:overview' => '概览',
'Team:Overview' => '此团队管理的工单和配置项',
'Team:Overview:ActiveTickets' => '活跃的工单',
'Team:Overview:FunctionalCIs-ByType' => '功能配置项',
'Team:Overview:UserRequest-ByStatus' => '用户请求状态',
'Team:Overview:UserRequest-ClosedByMonth' => '过去12个月关闭的需求',
'Team:Overview:UserRequest-ClosedByAgent' => '过去12个月由办理人关闭的需求',
'Class:Team/Attribute:tickets_list' => '工单',
'Class:Team/Attribute:tickets_list+' => '此团队的所有工单',
'Class:Team/Attribute:tickets_list+' => '此团队分配到的所有工单',
]);
//
@@ -210,7 +216,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Document' => '文档',
'Class:Document+' => '',
'Class:Document+' => 'Abstract class. A document that can be shared across multiple objects, making it easy and quick to retrieve from all relevant locations.~~',
'Class:Document/ComplementaryName' => '%1$s - %2$s - %3$s',
'Class:Document/Attribute:name' => '名称',
'Class:Document/Attribute:name+' => '',
@@ -235,7 +241,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Document/Attribute:status/Value:published' => '正式',
'Class:Document/Attribute:status/Value:published+' => '',
'Class:Document/Attribute:cis_list' => '配置项',
'Class:Document/Attribute:cis_list+' => '此文档关的所有配置项',
'Class:Document/Attribute:cis_list+' => '此文档关的所有配置项',
'Class:Document/Attribute:finalclass' => '文档类型',
'Class:Document/Attribute:finalclass+' => '根本属性的名称',
]);
@@ -246,7 +252,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DocumentFile' => '文档文件',
'Class:DocumentFile+' => '',
'Class:DocumentFile+' => 'It\'s a type of Document which includes an uploaded file (in any format: Word, PDF, Spreadsheet, etc.).~~',
'Class:DocumentFile/Attribute:file' => '文件',
'Class:DocumentFile/Attribute:file+' => '',
]);
@@ -257,7 +263,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DocumentNote' => '文档笔记',
'Class:DocumentNote+' => '',
'Class:DocumentNote+' => 'Used to store a text document. HTML formatting is supported using the WYSIWYG editor. Search can be performed on its content.~~',
'Class:DocumentNote/Attribute:text' => '正文',
'Class:DocumentNote/Attribute:text+' => '',
]);
@@ -268,7 +274,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DocumentWeb' => '文档网页',
'Class:DocumentWeb+' => '',
'Class:DocumentWeb+' => 'Hyperlinks to external applications or documents, acting as pointers to external resources. You cannot search in their content from '.ITOP_APPLICATION_SHORT,
'Class:DocumentWeb/Attribute:url' => 'URL',
'Class:DocumentWeb/Attribute:url+' => '',
]);
@@ -279,10 +285,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Typology' => '拓扑',
'Class:Typology+' => '',
'Class:Typology+' => 'Abstract class. ExternalKeyAttribute to a Typology subclass are used in place of an EnumAttribute, to have more dynamic values.~~',
'Class:Typology/Attribute:name' => '名称',
'Class:Typology/Attribute:name+' => '',
'Class:Typology/Attribute:finalclass' => '拓扑类型',
'Class:Typology/Attribute:finalclass' => '拓扑类型',
'Class:Typology/Attribute:finalclass+' => '根本属性的名称',
]);
@@ -292,7 +298,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DocumentType' => '文档类型',
'Class:DocumentType+' => '',
'Class:DocumentType+' => 'Typology. A classification system used to organize and logically group documents~~',
]);
//
@@ -301,7 +307,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ContactType' => '联系人类型',
'Class:ContactType+' => '',
'Class:ContactType+' => 'Typology to organize your Contacts and group them logically for you.~~',
]);
//
@@ -309,15 +315,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkPersonToTeam' => '关联 人员/团队',
'Class:lnkPersonToTeam+' => '',
'Class:lnkPersonToTeam' => '链接 个体/团队',
'Class:lnkPersonToTeam+' => 'This link indicates when a Person is a member of a Team.~~',
'Class:lnkPersonToTeam/Name' => '%1$s / %2$s',
'Class:lnkPersonToTeam/Name+' => '',
'Class:lnkPersonToTeam/Attribute:team_id' => '团队',
'Class:lnkPersonToTeam/Attribute:team_id+' => '',
'Class:lnkPersonToTeam/Attribute:team_name' => '团队名称',
'Class:lnkPersonToTeam/Attribute:team_name+' => '',
'Class:lnkPersonToTeam/Attribute:person_id' => '人员',
'Class:lnkPersonToTeam/Attribute:person_id' => '个体',
'Class:lnkPersonToTeam/Attribute:person_id+' => '',
'Class:lnkPersonToTeam/Attribute:person_name' => '姓名',
'Class:lnkPersonToTeam/Attribute:person_name+' => '',
@@ -338,7 +344,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:Catalogs+' => '数据类型',
'Menu:Audit' => '审计',
'Menu:Audit+' => '审计',
'Menu:CSVImport' => 'CSV导入',
'Menu:CSVImport' => 'CSV 导入',
'Menu:CSVImport+' => '批量创建或更新',
'Menu:Organization' => '组织',
'Menu:Organization+' => '所有组织',
@@ -351,8 +357,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Menu:Contact' => '联系人',
'Menu:Contact+' => '联系人',
'Menu:Contact:Count' => '%1$d 个联系人',
'Menu:Person' => '人员',
'Menu:Person+' => '所有人员',
'Menu:Person' => '个体',
'Menu:Person+' => '所有个体',
'Menu:Team' => '团队',
'Menu:Team+' => '所有团队',
'Menu:Document' => '文档',
@@ -383,6 +389,6 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Themes
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:fullmoon' => '满月',
'theme:test-red' => '测试 (红色)',
'theme:fullmoon' => 'Full moon',
'theme:test-red' => 'Test instance (Red)',
]);

View File

@@ -100,8 +100,20 @@ if (!class_exists('StructureInstaller')) {
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
// Load localized structural data: contact types and document types
static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-contacttype.xml");
static::LoadLocalizedDataOnNewInstall($oConfiguration, $sPreviousVersion, __DIR__."/data/{{language_code}}.data.itop-documenttype.xml");
static::LoadLocalizedData(
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-contacttype.xml"
);
static::LoadLocalizedData(
$oConfiguration,
$sPreviousVersion,
$sCurrentVersion,
'3.3.0',
__DIR__."/data/{{language_code}}.data.itop-documenttype.xml"
);
// Default language will be used for actions
// Note: There is a issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk

View File

@@ -7,5 +7,5 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'theme:light-grey' => '淡灰 (废弃)',
'theme:light-grey' => 'Light Grey (废弃)',
]);

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
// Dictionnay conventions
// Class:<class_name>
// Class:<class_name>+
@@ -30,12 +31,14 @@
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
// Class:<class_name>/Stimulus:<stimulus_code>
// Class:<class_name>/Stimulus:<stimulus_code>+
//
// Class: Ticket
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Ticket' => '工单',
'Class:Ticket+' => '',
'Class:Ticket+' => '抽象类',
'Class:Ticket/Attribute:ref' => '编号',
'Class:Ticket/Attribute:ref+' => '',
'Class:Ticket/Attribute:org_id' => '组织',
@@ -66,7 +69,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Ticket/Attribute:last_update+' => '',
'Class:Ticket/Attribute:close_date' => '关闭日期',
'Class:Ticket/Attribute:close_date+' => '',
'Class:Ticket/Attribute:private_log' => '私',
'Class:Ticket/Attribute:private_log' => '私有日志',
'Class:Ticket/Attribute:private_log+' => '',
'Class:Ticket/Attribute:contacts_list' => '联系人',
'Class:Ticket/Attribute:contacts_list+' => '此工单相关的所有联系人',
@@ -92,8 +95,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkContactToTicket' => '关联联系人/工单',
'Class:lnkContactToTicket+' => '',
'Class:lnkContactToTicket' => '链接 联系人/工单',
'Class:lnkContactToTicket+' => 'Allows linking several Contacts to notify them about the progress of Tickets, in addition to the requester and the agent.~~',
'Class:lnkContactToTicket/Name' => '%1$s / %2$s',
'Class:lnkContactToTicket/Attribute:ticket_id' => '工单',
'Class:lnkContactToTicket/Attribute:ticket_id+' => '',
@@ -119,7 +122,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:WorkOrder' => '工作任务',
'Class:WorkOrder+' => '',
'Class:WorkOrder+' => 'A task required for the resolution of a Ticket, assigned to a Team or even an agent.~~',
'Class:WorkOrder/Attribute:name' => '名称',
'Class:WorkOrder/Attribute:name+' => '',
'Class:WorkOrder/Attribute:status' => '状态',
@@ -154,95 +157,95 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Fieldset translation
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Ticket:baseinfo' => '基本信息',
'Ticket:date' => '日期信息',
'Ticket:contact' => '联系人',
'Ticket:moreinfo' => '更多信息',
'Ticket:relation' => '相关信息',
'Ticket:log' => '日志',
'Ticket:Type' => '风险评估',
'Ticket:support' => '支持信息',
'Ticket:resolution' => '解决方案',
'Ticket:SLA' => 'SLA 报告',
'WorkOrder:Details' => '详情',
'WorkOrder:Moreinfo' => '更多信息',
'Tickets:ResolvedFrom' => '由%1$s自动解决',
'Class:cmdbAbstractObject/Method:Set' => '设置',
'Class:cmdbAbstractObject/Method:Set+' => '填写固定值',
'Class:cmdbAbstractObject/Method:Set/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Set/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Set/Param:2' => '值',
'Class:cmdbAbstractObject/Method:Set/Param:2+' => '要设置的值',
'Class:cmdbAbstractObject/Method:SetCurrentDate' => '设置为当前日期',
'Class:cmdbAbstractObject/Method:SetCurrentDate+' => '填写当前日期和时间',
'Class:cmdbAbstractObject/Method:SetCurrentDate/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentDate/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull' => '为空则设置为当前日期',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull+' => '设置空字段为当前日期和时间',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull/Param:1' => '目标字段',
'Ticket:baseinfo' => '基本信息',
'Ticket:date' => '日期信息',
'Ticket:contact' => '联系人',
'Ticket:moreinfo' => '更多信息',
'Ticket:relation' => '相关信息',
'Ticket:log' => '日志',
'Ticket:Type' => '风险评估',
'Ticket:support' => '支持信息',
'Ticket:resolution' => '解决方案',
'Ticket:SLA' => 'SLA 报告',
'WorkOrder:Details' => '详情',
'WorkOrder:Moreinfo' => '更多信息',
'Tickets:ResolvedFrom' => '由%1$s自动解决',
'Class:cmdbAbstractObject/Method:Set' => '设置',
'Class:cmdbAbstractObject/Method:Set+' => '填写固定值',
'Class:cmdbAbstractObject/Method:Set/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Set/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Set/Param:2' => '值',
'Class:cmdbAbstractObject/Method:Set/Param:2+' => '要设置的值',
'Class:cmdbAbstractObject/Method:SetCurrentDate' => '设置为当前日期',
'Class:cmdbAbstractObject/Method:SetCurrentDate+' => '填写当前日期和时间',
'Class:cmdbAbstractObject/Method:SetCurrentDate/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentDate/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull' => '为空则设置为当前日期',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull+' => '设置空字段为当前日期和时间',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentDateIfNull/Param:1+' => '当前对象中要设置的字段',
'Class:cmdbAbstractObject/Method:SetCurrentUser' => '设置为当前用户',
'Class:cmdbAbstractObject/Method:SetCurrentUser+' => '填写当前登录用户',
'Class:cmdbAbstractObject/Method:SetCurrentUser/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentUser/Param:1+' => '当前对象中要设置的字段. 如果此字段为字符串则使用显示名称, 否则将使用标识符. 显示名称为关联用户的人员的姓名, 如果没有关联人员则为登录名.',
'Class:cmdbAbstractObject/Method:SetCurrentPerson' => '设置为当前人员',
'Class:cmdbAbstractObject/Method:SetCurrentPerson+' => '设置字段为当前登录的人员 (此 "人员" 关联到当前登录的 "用户").',
'Class:cmdbAbstractObject/Method:SetCurrentPerson/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentPerson/Param:1+' => '填写当前对象, 如果填写字符串则是昵称.',
'Class:cmdbAbstractObject/Method:SetElapsedTime' => '设置已过时间',
'Class:cmdbAbstractObject/Method:SetElapsedTime+' => '设置字段为当前时间针对另一个字段设置的日期所用时长 (秒)',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:1+' => '当前对象中要设置的字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:2' => '参考字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:2+' => '此字段来自获取相关日期的字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:3' => '工作时间',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:3+' => '若留空则取决于标准工作时间场景, 或者设置为 "DefaultWorkingTimeComputer" 来强制要求24x7场景',
'Class:cmdbAbstractObject/Method:SetIfNull' => '为空时设置',
'Class:cmdbAbstractObject/Method:SetIfNull+' => '仅当字段为空时设置, 使用此固定值',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:1+' => '当前对象里要设置的字段',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:2' => '值',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:2+' => '要设置的值',
'Class:cmdbAbstractObject/Method:AddValue' => '加上值',
'Class:cmdbAbstractObject/Method:AddValue+' => '给字段加上一个固定值',
'Class:cmdbAbstractObject/Method:AddValue/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:AddValue/Param:1+' => '当前对象里要修改的字段',
'Class:cmdbAbstractObject/Method:AddValue/Param:2' => '值',
'Class:cmdbAbstractObject/Method:AddValue/Param:2+' => '要加上的数值, 可以为负',
'Class:cmdbAbstractObject/Method:SetComputedDate' => '设置计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDate+' => '设置字段为按规则根据另一个字段计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:1+' => '当前对象里要设置的字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:2' => '修饰符',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:2+' => '要修改源日期的文本修饰符, 例如 "+3 days"',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:3' => '源字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:3+' => '作为源值应用修饰符逻辑的字段',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull' => '若空则设置计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull+' => '为空时设置字段为按规则根据另一个字段计算的日期',
'Class:cmdbAbstractObject/Method:SetCurrentUser' => '设置为当前用户',
'Class:cmdbAbstractObject/Method:SetCurrentUser+' => '填写当前登录用户',
'Class:cmdbAbstractObject/Method:SetCurrentUser/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentUser/Param:1+' => '当前对象中要设置的字段. 如果此字段为字符串则使用称, 否则将使用标识符. 称为关联用户的名称, 否则会使用登录名.',
'Class:cmdbAbstractObject/Method:SetCurrentPerson' => '设置为当前用户',
'Class:cmdbAbstractObject/Method:SetCurrentPerson+' => '设置字段为当前登录的用户 (此 "个体" 关联到当前登录的 "用户").',
'Class:cmdbAbstractObject/Method:SetCurrentPerson/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetCurrentPerson/Param:1+' => '填写当前对象, 如果填写字符串则是昵称.',
'Class:cmdbAbstractObject/Method:SetElapsedTime' => '设置已过时间',
'Class:cmdbAbstractObject/Method:SetElapsedTime+' => '设置字段为当前时间针对另一个字段设置的日期所用时长 (秒)',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:1+' => '当前对象中要设置的字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:2' => '参考字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:2+' => '此字段来自获取相关日期的字段',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:3' => '工作时间',
'Class:cmdbAbstractObject/Method:SetElapsedTime/Param:3+' => '若留空则取决于标准工作时间场景, 或者设置为 "DefaultWorkingTimeComputer" 来强制要求24x7场景',
'Class:cmdbAbstractObject/Method:SetIfNull' => '为空时设置',
'Class:cmdbAbstractObject/Method:SetIfNull+' => '仅当字段为空时设置, 使用此固定值',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:1+' => '当前对象里要设置的字段',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:2' => '值',
'Class:cmdbAbstractObject/Method:SetIfNull/Param:2+' => '要设置的值',
'Class:cmdbAbstractObject/Method:AddValue' => '加上值',
'Class:cmdbAbstractObject/Method:AddValue+' => '给字段加上一个固定值',
'Class:cmdbAbstractObject/Method:AddValue/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:AddValue/Param:1+' => '当前对象里要修改的字段',
'Class:cmdbAbstractObject/Method:AddValue/Param:2' => '值',
'Class:cmdbAbstractObject/Method:AddValue/Param:2+' => '要加上的数值, 可以为负',
'Class:cmdbAbstractObject/Method:SetComputedDate' => '设置计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDate+' => '设置字段为按规则根据另一个字段计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:1+' => '当前对象里要设置的字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:2' => '修饰符',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:2+' => '要修改源日期的文本修饰符, 例如 "+3 days"',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:3' => '源字段',
'Class:cmdbAbstractObject/Method:SetComputedDate/Param:3+' => '作为源值应用修饰符逻辑的字段',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull' => '若空则设置计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull+' => '为空时设置字段为按规则根据另一个字段计算的日期',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:1+' => '当前对象中要设置的字段',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:2' => '修饰符',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:2+' => '要修改源日期的文本修饰符, 例如 "+3 days"',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:3' => '源字段',
'Class:cmdbAbstractObject/Method:SetComputedDateIfNull/Param:3+' => '作为源值应用修饰符逻辑的字段',
'Class:cmdbAbstractObject/Method:Reset' => '重置',
'Class:cmdbAbstractObject/Method:Reset+' => '重置为默认值',
'Class:cmdbAbstractObject/Method:Reset/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Reset/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Copy' => '复制',
'Class:cmdbAbstractObject/Method:Copy+' => '复制当前值到另外一个地方',
'Class:cmdbAbstractObject/Method:Copy/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Copy/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Copy/Param:2' => '源字段',
'Class:cmdbAbstractObject/Method:Copy/Param:2+' => '此字段从当前对象获取值',
'Class:cmdbAbstractObject/Method:ApplyStimulus' => '使用调整',
'Class:cmdbAbstractObject/Method:ApplyStimulus+' => '当前对象中要应用的特定调整',
'Class:cmdbAbstractObject/Method:Reset' => '重置',
'Class:cmdbAbstractObject/Method:Reset+' => '重置为默认值',
'Class:cmdbAbstractObject/Method:Reset/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Reset/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Copy' => '复制',
'Class:cmdbAbstractObject/Method:Copy+' => '复制当前值到另外一个地方',
'Class:cmdbAbstractObject/Method:Copy/Param:1' => '目标字段',
'Class:cmdbAbstractObject/Method:Copy/Param:1+' => '填写当前对象',
'Class:cmdbAbstractObject/Method:Copy/Param:2' => '源字段',
'Class:cmdbAbstractObject/Method:Copy/Param:2+' => '此字段从当前对象获取值',
'Class:cmdbAbstractObject/Method:ApplyStimulus' => '使用调整',
'Class:cmdbAbstractObject/Method:ApplyStimulus+' => '当前对象中要应用的特定调整',
'Class:cmdbAbstractObject/Method:ApplyStimulus/Param:1' => '调整编码',
'Class:cmdbAbstractObject/Method:ApplyStimulus/Param:1+' => '当前对象的有效调整编码',
'Class:ResponseTicketTTO/Interface:iMetricComputer' => 'TTO',
'Class:ResponseTicketTTO/Interface:iMetricComputer+' => '响应时限',
'Class:ResponseTicketTTR/Interface:iMetricComputer' => 'TTR',
'Class:ResponseTicketTTR/Interface:iMetricComputer+' => '解决时限',
'Class:ResponseTicketTTO/Interface:iMetricComputer' => 'TTO',
'Class:ResponseTicketTTO/Interface:iMetricComputer+' => '响应时限',
'Class:ResponseTicketTTR/Interface:iMetricComputer' => 'TTR',
'Class:ResponseTicketTTR/Interface:iMetricComputer+' => '解决时限',
]);
//
@@ -251,5 +254,5 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Ticket/Attribute:team_email' => 'Team email~~',
'Class:Ticket/Attribute:team_email+' => '~~',
'Class:Ticket/Attribute:team_email+' => '',
]);

View File

@@ -61,6 +61,6 @@ class TicketsInstaller extends ModuleInstallerAPI
}
}
// Load localized structural data: predefined query phrases for notifications
static::LoadLocalizedDataOnCrossingVersion($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', __DIR__."/data/{{language_code}}.data.itop-tickets.xml");
static::LoadLocalizedData($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', __DIR__."/data/{{language_code}}.data.itop-tickets.xml");
}
}

View File

@@ -21,14 +21,15 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
//
// Fieldsets for Virtualization classes
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Virtualization:baseinfo' => 'General~~',
'Virtualization:moreinfo' => 'Virtualization specifics~~',
'Virtualization:otherinfo' => 'Dates and description~~',
'Virtualization:baseinfo' => '基本信息',
'Virtualization:moreinfo' => '虚拟化详情',
'Virtualization:otherinfo' => '日期和描述',
]);
//
@@ -38,13 +39,14 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Cloud/Name' => '%1$s',
'Class:Cloud/ComplementaryName' => '%1$s-%2$s',
'Class:Cloud' => 'Cloud~~',
'Class:Cloud+' => 'A Virtual Host operated by a Cloud provider. It can host Virtual Machines and Container Hosts.~~',
'Class:Cloud/Attribute:logo' => 'Logo~~',
'Class:Cloud/Attribute:logo+' => 'Used as object icon when this Cloud is displayed within impact analysis graphs~~',
'Class:Cloud/Attribute:provider_id+' => 'Who provides the cloud~~',
'Class:Cloud/Attribute:location_id' => 'Location~~',
'Class:Cloud/Attribute:location_id+' => 'Where is located the cloud~~',
'Class:Cloud' => '云平台',
'Class:Cloud+' => '由云供应商运营的虚拟化主机. 它可以托管虚拟机和容器宿主机.',
'Class:Cloud/Attribute:provider_id' => '供应商',
'Class:Cloud/Attribute:logo' => 'Logo',
'Class:Cloud/Attribute:logo+' => '在影响分析图中显示此云平台时用作对象图标',
'Class:Cloud/Attribute:provider_id+' => '谁提供云平台',
'Class:Cloud/Attribute:location_id' => '位置',
'Class:Cloud/Attribute:location_id+' => '云平台的位置',
]);
//
@@ -52,6 +54,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:LogicalInterface/Attribute:org_id' => 'Organization~~',
'Class:LogicalInterface/Attribute:org_id+' => '~~',
'Class:LogicalInterface/Name' => '%2$s %1$s',
'Class:LogicalInterface/Attribute:org_id' => '组织',
'Class:LogicalInterface/Attribute:org_id+' => '',
]);

View File

@@ -4,7 +4,7 @@
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @license http://opensource.org/licenses/AGPL-3.0
*
* This file is part of iTop.
*
@@ -21,7 +21,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Core:ormValue:ormDocument:DownloadsCount' => '%1s~~',
'Core:ormValue:ormDocument:DownloadsCount' => '%1s',
'Core:ormValue:ormDocument:DownloadsCount+' => '已下载%1$s次',
]);

View File

@@ -21,6 +21,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:cmdbAbstractObject/UniquenessRule:no_duplicate' => '%1$s: %2$s 已关联至 %3$s: %4$s, 不允许重复关联.',
'Class:cmdbAbstractObject/UniquenessRule:no_duplicate' => '%1$s: %2$s 已链接到 %3$s: %4$s, 不允许重复链接.',
]);

View File

@@ -17,58 +17,60 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Placeholders
// $%1s : host object class name
// $%2s : host object friendlyname
// $%3s : current tab name
// $%4s : remote object class name
// $%5s : remote object friendlyname
'UI:Links:Object:New:Modal:Title' => '创建对象',
// $%1s : host object class name
// $%2s : host object friendlyname
// $%3s : current tab name
// $%4s : remote object class name
// $%5s : remote object friendlyname
'UI:Links:Object:New:Modal:Title' => '创建对象',
// Create
'UI:Links:Create:Button' => '创建',
'UI:Links:Create:Button+' => '创建一个 %4$s',
'UI:Links:Create:Modal:Title' => '创建一个 %4$s 至 %2$s',
'UI:Links:Create:Button' => '创建',
'UI:Links:Create:Button+' => '创建一个 %4$s',
'UI:Links:Create:Modal:Title' => '创建一个 %4$s 至 %2$s',
// Add
'UI:Links:Add:Button' => '添加',
'UI:Links:Add:Button+' => '添加一个 %4$s',
'UI:Links:Add:Modal:Title' => '添加一个 %4$s 至 %2$s',
'UI:Links:Add:Button' => '添加',
'UI:Links:Add:Button+' => '添加一个 %4$s',
'UI:Links:Add:Modal:Title' => '添加一个 %4$s 至 %2$s',
// Modify link
'UI:Links:ModifyLink:Button' => '修改',
'UI:Links:ModifyLink:Button+' => '修改此关联',
'UI:Links:ModifyLink:Modal:Title' => '修改 %2$s %5$s 的关联',
'UI:Links:ModifyLink:Button' => '修改',
'UI:Links:ModifyLink:Button+' => '修改这个链接',
'UI:Links:ModifyLink:Modal:Title' => '修改 %2$s %5$s 之间的链接',
// Modify object
'UI:Links:ModifyObject:Button' => '修改',
'UI:Links:ModifyObject:Button+' => '修改对象',
'UI:Links:ModifyObject:Button' => '修改',
'UI:Links:ModifyObject:Button+' => '修改这个对象',
'UI:Links:ModifyObject:Modal:Title' => '%5$s',
// Remove
'UI:Links:Remove:Button' => '移除',
'UI:Links:Remove:Button+' => '移除 %4$s',
'UI:Links:Remove:Modal:Title' => '从%1$s 移除 %4$s',
'UI:Links:Remove:Modal:Message' => '请确认从 %2$s 移除 %5$s ?',
'UI:Links:Remove:Button' => '移除',
'UI:Links:Remove:Button+' => '移除这个 %4$s',
'UI:Links:Remove:Modal:Title' => '从%1$s 移除 %4$s',
'UI:Links:Remove:Modal:Message' => '请确认从 %2$s 移除 %5$s ?',
// Delete
'UI:Links:Delete:Button' => '删除',
'UI:Links:Delete:Button+' => '删除此 %4$s',
'UI:Links:Delete:Modal:Title' => '删除 %4$s',
'UI:Links:Delete:Modal:Message' => '请确认删除 %5$s?',
'UI:Links:Delete:Button' => '删除',
'UI:Links:Delete:Button+' => '删除此 %4$s',
'UI:Links:Delete:Modal:Title' => '删除 %4$s',
'UI:Links:Delete:Modal:Message' => '请确认删除 %5$s?',
// Bulk
'UI:Links:Bulk:LinkWillBeCreatedForAllObjects' => '添加至所有对象',
'UI:Links:Bulk:LinkWillBeCreatedForAllObjects' => '添加至所有对象',
'UI:Links:Bulk:LinkWillBeDeletedFromAllObjects' => '从所有对象删除',
'UI:Links:Bulk:LinkWillBeCreatedFor1Object' => '添加至一个对象',
'UI:Links:Bulk:LinkWillBeDeletedFrom1Object' => '从一个对象移除',
'UI:Links:Bulk:LinkWillBeCreatedForXObjects' => '添加 {count} 个对象',
'UI:Links:Bulk:LinkWillBeDeletedFromXObjects' => '移除 {count} 个对象',
'UI:Links:Bulk:LinkExistForAllObjects' => '已关联所有对象',
'UI:Links:Bulk:LinkExistForOneObject' => '已关联一个对象',
'UI:Links:Bulk:LinkExistForXObjects' => '已关联 {count} 个对象',
'UI:Links:Bulk:LinkWillBeCreatedFor1Object' => '添加至一个对象',
'UI:Links:Bulk:LinkWillBeDeletedFrom1Object' => '从一个对象移除',
'UI:Links:Bulk:LinkWillBeCreatedForXObjects' => '添加 {count} 个对象',
'UI:Links:Bulk:LinkWillBeDeletedFromXObjects' => '移除 {count} 个对象',
'UI:Links:Bulk:LinkExistForAllObjects' => '已关联所有对象',
'UI:Links:Bulk:LinkExistForOneObject' => '已关联一个对象',
'UI:Links:Bulk:LinkExistForXObjects' => '已关联 {count} 个对象',
// New item
'UI:Links:NewItem' => '新建条目',

View File

@@ -17,25 +17,27 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Newsroom:iTopNotification:Label' => ITOP_APPLICATION_SHORT,
'UI:Newsroom:iTopNotification:ViewAllPage:Title' => 'Your '.ITOP_APPLICATION_SHORT.' news~~',
'UI:Newsroom:iTopNotification:ViewAllPage:SubTitle' => 'Manage your news, flag them as read or unread, delete them, etc.~~',
'UI:Newsroom:iTopNotification:ViewAllPage:Title' => '您的 '.ITOP_APPLICATION_SHORT.' 消息',
'UI:Newsroom:iTopNotification:ViewAllPage:SubTitle' => '管理您的消息,将它们标记为已读或未读,甚至删除等等.',
'UI:Newsroom:iTopNotification:ViewAllPage:Read:Label' => '已读',
'UI:Newsroom:iTopNotification:ViewAllPage:Unread:Label' => '未读',
'UI:Newsroom:iTopNotification:SelectMode:Label' => 'Select mode~~',
'UI:Newsroom:iTopNotification:SelectMode:Label' => '请选择模式',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAllAsRead:Label' => '全部标记为已读',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAllAsUnread:Label' => '全部标记为未读',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteAll:Label' => '全部删除',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteAll:Success:Message' => '全部 %1$s 条消息已被删除',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteAll:Confirmation:Title' => '删除全部消息',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteAll:Confirmation:Message' => 'Are you sure you want to delete all news?~~',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteAll:Confirmation:Message' => '您确定要删除所有消息吗?',
'UI:Newsroom:iTopNotification:ViewAllPage:Empty:Title' => '没有消息, 已是最新!',
// Actions
// - Unitary buttons
// - Unitary buttons
'UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label' => '删除这条消息',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label' => 'Go to the news url~~',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label' => '转到消息的链接',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label' => '标记为已读',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label' => '标记为未读',
// - Bulk buttons
@@ -43,7 +45,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkSelectedAsUnread:Label' => '标记已选为未读',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteSelected:Label' => '删除已选择',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteSelected:Confirmation:Title' => '删除已选的消息',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteSelected:Confirmation:Message' => 'Are you sure you want to delete selected news?~~',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:DeleteSelected:Confirmation:Message' => '您确定要删除选中的消息吗?',
// Feedback messages
'UI:Newsroom:iTopNotification:ViewAllPage:Action:InvalidAction:Message' => '无效操作: "%1$s"',

View File

@@ -4,6 +4,7 @@
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
// UI elements
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:WelcomePopup:Button:RemindLater' => '以后再提醒我',
@@ -14,42 +15,42 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
// Message
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:WelcomePopup:Message:320_01_Welcome:Title' => '欢迎使用 '.ITOP_APPLICATION_SHORT.' 3.2',
'UI:WelcomePopup:Message:320_01_Welcome:Description' => '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
'UI:WelcomePopup:Message:320_01_Welcome:Description' => '<div>恭喜, 您已登录 '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<br>
<div>We\'re excited to announce this new release. </div>
<div>In addition to introducing new features such as Newsroom, '.ITOP_APPLICATION_SHORT.' 3.2 includes critical security patches, enhanced accessibility and other significant improvements focused on providing you with stability and security.</div>
<div>很高兴向你宣布这个新版本. </div>
<div>新增了新闻室等新功能, '.ITOP_APPLICATION_SHORT.' 3.2 还包含了关键的安全补丁, 增强的可访问性以及其它重要的改进,旨在为您提供更好的稳定性和安全性.</div>
<br>
<div>Discover all of '.ITOP_APPLICATION_SHORT.'\'s exciting new features and stay up-to-date with important notifications with our new welcome pop-up!</div>
<div>We hope you\'ll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>发现 '.ITOP_APPLICATION_SHORT.' 所有令人兴奋的新功能,并通过我们的新欢迎弹窗保持与重要通知的同步!</div>
<div>我们希望你能像我们一样,从构思到创造,全程享受这个版本!</div>
<br>
<div>Customize your '.ITOP_APPLICATION_SHORT.' preferences for a personalized experience.</div>~~',
'UI:WelcomePopup:Message:320_02_Newsroom:Title' => 'Say "Hello" to the newsroom~~',
'UI:WelcomePopup:Message:320_02_Newsroom:Description' => '<div>Say goodbye to cluttered inboxes and hello to personalized alerts with <a href="%1$s" target="_blank">'.ITOP_APPLICATION_SHORT.'\'s Newsroom</a>!</div>
<div>Newsroom allows you to easily manage notifications within the platform, so you can stay on top of important updates without constantly checking your email. With the ability to mark messages as read or unread, and automatically delete old notifications, you have complete control over your notifications. </div>
<div>定制您的 '.ITOP_APPLICATION_SHORT.' 偏好设置,可以获得个性化的使用体验.</div>',
'UI:WelcomePopup:Message:320_02_Newsroom:Title' => '向新闻室说 "Hello" ',
'UI:WelcomePopup:Message:320_02_Newsroom:Description' => '<div>告别杂乱的收件箱,用 <a href="%1$s" target="_blank">'.ITOP_APPLICATION_SHORT.' 新闻室</a>迎接个性化的告警!</div>
<div>新闻室允许您轻松管理平台内的通知,因此您可以掌握重要更新而无需频繁查收电子邮件.通过将消息标记为已读或未读,并自动删除旧通知,您可以完全控制您的通知.</div>
<br>
<div>Try it out today and streamline your '.ITOP_APPLICATION_SHORT.'\'s communication experience!</div>~~',
'UI:WelcomePopup:Message:320_03_NotificationsCenter:Title' => 'Notifications center~~',
'UI:WelcomePopup:Message:320_03_NotificationsCenter:Description' => '<div>As we know your information intake is already at its max, you can now easily choose how you receive your notifications - via email, chat, or even the Newsroom feature</div>
<div>You don\'t want to receive a certain type of alerts? Nothing easier with these advanced customization capabilities giving you the flexibility to tailor your experience to your needs. </div>
<div>今天就试试,简化您的 '.ITOP_APPLICATION_SHORT.' 沟通体验!</div>',
'UI:WelcomePopup:Message:320_03_NotificationsCenter:Title' => '通知中心',
'UI:WelcomePopup:Message:320_03_NotificationsCenter:Description' => '<div>由于我们知道您的信息摄入量已经达到最大限度,现在您可以轻松选择如何接收通知 - 通过电子邮件、聊天,甚至新闻室功能</div>
<div>您不想接收某种类型的警报?使用这些高级自定义功能,您可以根据需要轻松定制体验.</div>
<br>
<div>Access your <a href="%1$s" target="_blank">notifications center</a> through the newsroom or through your preferences and avoid information overload on all your communication channels!</div>~~',
'UI:WelcomePopup:Message:320_05_A11yThemes:Title' => 'Accessibility for '.ITOP_APPLICATION_SHORT.'\'s UI~~',
'UI:WelcomePopup:Message:320_05_A11yThemes:Description' => '<div>To ensure '.ITOP_APPLICATION_SHORT.'\'s accessibility, our team has been working on <a href="%1$s" target="_blank">new back-office themes</a>. WCAG compliants, those UI focus on making it easier for users with visual impairments to use the solution:
<div>通过新闻室或您的偏好设置访问您的<a href="%1$s" target="_blank">通知中心</a>,避免所有通信渠道的信息过载!</div>',
'UI:WelcomePopup:Message:320_05_A11yThemes:Title' => ITOP_APPLICATION_SHORT.' UI 的可访问性',
'UI:WelcomePopup:Message:320_05_A11yThemes:Description' => '<div>为了确保 '.ITOP_APPLICATION_SHORT.' 的可访问性,我们的团队一直在开发<a href="%1$s" target="_blank">新的后台主题</a>.符合 WCAG 标准,这些 UI 主题可以帮助视力障碍用户更容易的使用:
<ul>
<li><b>Color-blind theme:</b> Designed to help users with colorblindness, this theme actually breaks down in two sub-themes to adapt to specific cases: </li>
<li><b>色盲主题:</b> 设计用于帮助色盲用户,此主题实际上分为两个子主题以适应特定情况:</li>
<ul>
<li>One adapted to protanopia and deuteranopia</li>
<li>And another one for tritanopia</li>
<li>一个适用于红绿色盲和绿色色盲</li>
<li>另一个适用于黄蓝色盲</li>
</ul>
<br>
<li><b>High-contrast theme:</b> Increased contrast to allow users an easier distinction between different elements on screen and avoid to rely on color schema to convey information. It can be helpful for users with different pathology from colorblindness to low vision issues.</li>
<li><b>高对比度主题:</b> 增加对比度以允许用户更容易区分屏幕上的不同元素,并避免依赖颜色方案传递信息.它可以帮助从色盲到弱视等不同病理的用户.</li>
</ul>
</div>~~',
'UI:WelcomePopup:Message:320_04_PowerfulNotifications_AdminOnly:Title' => 'Powerful notifications~~',
'UI:WelcomePopup:Message:320_04_PowerfulNotifications_AdminOnly:Description' => '<div>'.ITOP_APPLICATION_SHORT.'\'s Newsroom gives you a new way to <a href="%1$s" target="_blank"><b>automate</b> your alerts based on events</a> with recurrence, so you can easily set up rules that work for you. </div>
<div>Our <b>priority-based notifications sorting</b> ensures that important messages are displayed first, while our URL customization options allow you to direct recipients to the right place. </div>
</div>',
'UI:WelcomePopup:Message:320_04_PowerfulNotifications_AdminOnly:Title' => '强大的通知',
'UI:WelcomePopup:Message:320_04_PowerfulNotifications_AdminOnly:Description' => '<div>'.ITOP_APPLICATION_SHORT.' 的新闻室为您提供了一种新的方法,可以 <a href="%1$s" target="_blank"><b>自动化</b> 基于事件的告警</a> 并支持重复设置, 因此您可以轻松设置适合您的规则. </div>
<div>我们的<b>基于优先级的通知排序</b>确保重要消息优先展示,同时,我们的 URL 自定义选项允许您将收件人引导到正确的位置.</div>
<br>
<div>With support for <b>multiple languages</b>, you have now complete control over your notifications display.</div>
<div>支持<b>多语言</b>,您现在可以完全控制通知显示.</div>
<br>
<div>Configure it today and see how much more efficient your alerts process can be!</div>~~',
<div>现在就配置它,看看您的警报流程可以变得多么高效!</div>',
]);

View File

@@ -17,13 +17,14 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Activity panel
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Layout:ActivityPanel:SizeToggler:Expand:Tooltip' => '展开',
'UI:Layout:ActivityPanel:SizeToggler:Reduce:Tooltip' => '减少',
'UI:Layout:ActivityPanel:SizeToggler:Reduce:Tooltip' => '还原',
'UI:Layout:ActivityPanel:DisplayToggler:Close:Tooltip' => '关闭',
'UI:Layout:ActivityPanel:LoadMoreEntries:Tooltip' => '加载更多',
'UI:Layout:ActivityPanel:LoadAllEntries:Tooltip' => '全部加载',
'UI:Layout:ActivityPanel:LoadMoreEntries:Tooltip' => '加载更多条目',
'UI:Layout:ActivityPanel:LoadAllEntries:Tooltip' => '加载之前全部的条目',
// Tabs
'UI:Layout:ActivityPanel:Tab:Activity:Title' => '活动',
@@ -54,6 +55,6 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Layout:ActivityPanel:NoEntry:Placeholder:Hint' => '暂无任何活动',
// Closed cover
'UI:Layout:ActivityPanel:ClosedCover:Title' => '活动面板',
'UI:Layout:ActivityPanel:ClosedCover:Tooltip' => '点击打开活动面板',
'UI:Layout:ActivityPanel:ClosedCover:Title' => '面板',
'UI:Layout:ActivityPanel:ClosedCover:Tooltip' => '点击打开面板',
]);

View File

@@ -17,17 +17,18 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Navigation menu
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Layout:NavigationMenu:CompanyLogo:AltText' => '公司标志',
'UI:Layout:NavigationMenu:CompanyLogo:AltText' => '公司 logo',
'UI:Layout:NavigationMenu:Silo:Label' => '请选择要筛选的组织',
'UI:Layout:NavigationMenu:Toggler:Tooltip' => '展开/折叠',
'UI:Layout:NavigationMenu:Toggler:TooltipWithSiloLabel' => '展开/折叠 (筛选%1$s)',
'UI:Layout:NavigationMenu:Toggler:Tooltip' => '展开 / 折叠',
'UI:Layout:NavigationMenu:Toggler:TooltipWithSiloLabel' => '展开 / 折叠 (筛选 %1$s)',
'UI:Layout:NavigationMenu:MenuFilter:Input:Placeholder' => '筛选器...',
'UI:Layout:NavigationMenu:MenuFilter:Input:Tooltip' => '请输入要筛选的关键字',
'UI:Layout:NavigationMenu:MenuFilter:Input:Hint' => '将会显示所有匹配的菜单',
'UI:Layout:NavigationMenu:MenuFilter:Placeholder:Hint' => '此菜单暂无筛选结果',
'UI:Layout:NavigationMenu:UserInfo:WelcomeMessage:Text' => '您好, %1$s!',
'UI:Layout:NavigationMenu:UserInfo:WelcomeMessage:Text' => 'Hi, %1$s!',
'UI:Layout:NavigationMenu:UserInfo:Picture:AltText' => '%1$s 的联系人头像',
'UI:Layout:NavigationMenu:UserMenu:Toggler:Label' => '打开用户菜单',
'UI:Layout:NavigationMenu:KeyboardShortcut:FocusFilter' => '筛选菜单',

View File

@@ -23,7 +23,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:ResetPwd-Error-WrongLogin' => '\'%1$s\' 用户名无效',
'UI:ResetPwd-Error-NotPossible' => '外部账号不允许重置密码.',
'UI:ResetPwd-Error-FixedPwd' => '此账号不允许重置密码.',
'UI:ResetPwd-Error-NoContact' => '此账号没有关联到人员.',
'UI:ResetPwd-Error-NoContact' => '此账号没有关联到个体.',
'UI:ResetPwd-Error-NoEmailAtt' => '此账号未关联邮箱地址,请联系管理员.',
'UI:ResetPwd-Error-NoEmail' => '缺少邮箱地址. 请联系管理员.',
'UI:ResetPwd-Error-Send' => '邮件发送存在技术原因. 请联系管理员.',

View File

@@ -19,15 +19,15 @@
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:NotificationsCenter:Page:Title' => 'Notifications center~~',
'UI:NotificationsCenter:Panel:Title' => 'Notifications center~~',
'UI:NotificationsCenter:Panel:SubTitle' => 'Manage Notifications that you have received : unsubscribe or limit them to a single channel~~',
'UI:NotificationsCenter:Panel:Toolbar:ViewAllNews:Title' => 'View all my news~~',
'UI:NotificationsCenter:Panel:Table:Channels' => 'Channels~~',
'UI:NotificationsCenter:Unsubscribe:Success' => 'You have been successfully unsubscribed from the selected notifications.~~',
'UI:NotificationsCenter:Unsubscribe:Error' => 'An error occurred while unsubscribing from the selected notifications.~~',
'UI:NotificationsCenter:Subscribe:Success' => 'You have been successfully subscribed to the selected notifications.~~',
'UI:NotificationsCenter:Subscribe:Error' => 'An error occurred while subscribing to the selected notifications.~~',
'UI:NotificationsCenter:Channel:OutOf:Text' => '%1$s out of %2$s~~',
'UI:NotificationsCenter:Advanced:Input:Label' => '%1$s: %2$s~~',
'UI:NotificationsCenter:Page:Title' => '通知中心',
'UI:NotificationsCenter:Panel:Title' => '通知中心',
'UI:NotificationsCenter:Panel:SubTitle' => '管理收到的通知 : 取消订阅或限制到单一频道',
'UI:NotificationsCenter:Panel:Toolbar:ViewAllNews:Title' => '查看所有新闻',
'UI:NotificationsCenter:Panel:Table:Channels' => '频道',
'UI:NotificationsCenter:Unsubscribe:Success' => '您已成功取消订阅所选通知.',
'UI:NotificationsCenter:Unsubscribe:Error' => '取消订阅所选通知时发生错误.',
'UI:NotificationsCenter:Subscribe:Success' => '您已成功订阅所选通知.',
'UI:NotificationsCenter:Subscribe:Error' => '订阅所选通知时发生错误.',
'UI:NotificationsCenter:Channel:OutOf:Text' => '%1$s / %2$s',
'UI:NotificationsCenter:Advanced:Input:Label' => '%1$s: %2$s',
]);

View File

@@ -17,42 +17,43 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Navigation menu
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'UI:Preferences:Title' => '首选项',
'UI:Preferences:UserInterface:Title' => '用户界面',
'UI:Preferences:General:Title' => '概况',
'UI:Preferences:General:Theme' => '主题',
'UI:Preferences:General:Theme:DefaultThemeLabel' => '%1$s (默认)',
'UI:Favorites:General:ShowSummaryCards' => '显示汇总卡片',
'UI:Favorites:General:ShowSummaryCards+' => '当鼠标移动到对象链接时, 显示此对象的简要汇总信息, 如果该类型支持',
'UI:Preferences:Lists:Title' => '列表',
'UI:Preferences:RichText:Title' => '富文本编辑器',
'UI:Preferences:RichText:ToolbarState' => '工具栏默认状态',
'UI:Preferences:RichText:ToolbarState:Expanded' => '展开',
'UI:Preferences:RichText:ToolbarState:Collapsed' => '折叠',
'UI:Preferences:ActivityPanel:Title' => '活动面板',
'UI:Preferences:ActivityPanel:EntryFormOpened' => '默认打开录入表单',
'UI:Preferences:ActivityPanel:EntryFormOpened+' => '在显示对象时是否打开录入表单. 如果不选择, 仍可以点击新建按钮打开录入表单',
'UI:Preferences:PersonalizeKeyboardShortcuts:Title' => '键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Input:Hint' => '请输入键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Tooltip' => '录制键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset' => '重置',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset:Tooltip' => '还原到默认的键盘快捷键',
'UI:Preferences:Tabs:Title' => '标签栏',
'UI:Preferences:Tabs:Layout:Label' => '布局',
'UI:Preferences:Tabs:Layout:Horizontal' => '水平',
'UI:Preferences:Tabs:Layout:Vertical' => '垂直',
'UI:Preferences:Tabs:Scrollable:Label' => '导航',
'UI:Preferences:Tabs:Scrollable:Classic' => '经典',
'UI:Preferences:Tabs:Scrollable:Scrollable' => '可滚动',
'UI:Preferences:General:Toasts' => 'Toast notifications position~~',
'UI:Preferences:General:Toasts:Bottom' => 'Bottom~~',
'UI:Preferences:General:Toasts:Top' => 'Top~~',
'UI:Preferences:ChooseAPlaceholder' => '用户的默认头像',
'UI:Preferences:ChooseAPlaceholder+' => '选择一个占位图片, 将在用户联系人没有设定头像图片时显示',
'UI:Preferences:ChooseAPlaceholder:Success:Message' => 'Your placeholder image has been successfully updated~~',
'UI:Preferences:Notifications' => 'Notifications~~',
'UI:Preferences:Notifications+' => 'Configure the notifications you want to receive <a href="%1$s">on this page</a>.~~',
'UI:Preferences:Title' => '偏好设置',
'UI:Preferences:UserInterface:Title' => '用户界面',
'UI:Preferences:General:Title' => '概况',
'UI:Preferences:General:Theme' => '主题',
'UI:Preferences:General:Theme:DefaultThemeLabel' => '%1$s (默认)',
'UI:Favorites:General:ShowSummaryCards' => '显示汇总卡片',
'UI:Favorites:General:ShowSummaryCards+' => '当鼠标移动到对象链接时, 显示此对象的简要汇总信息, 如果该类型支持',
'UI:Preferences:Lists:Title' => '列表',
'UI:Preferences:RichText:Title' => '富文本编辑器',
'UI:Preferences:RichText:ToolbarState' => '工具栏默认状态',
'UI:Preferences:RichText:ToolbarState:Expanded' => '展开',
'UI:Preferences:RichText:ToolbarState:Collapsed' => '折叠',
'UI:Preferences:ActivityPanel:Title' => '面板',
'UI:Preferences:ActivityPanel:EntryFormOpened' => '默认打开侧面板',
'UI:Preferences:ActivityPanel:EntryFormOpened+' => '在显示对象时是否打开侧面板. 如果不选择, 仍可以点击按钮打开侧面板',
'UI:Preferences:PersonalizeKeyboardShortcuts:Title' => '键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Input:Hint' => '请输入键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Tooltip' => '录制键盘快捷键',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset' => '重置',
'UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset:Tooltip' => '还原到默认的键盘快捷键',
'UI:Preferences:Tabs:Title' => '标签栏',
'UI:Preferences:Tabs:Layout:Label' => '布局',
'UI:Preferences:Tabs:Layout:Horizontal' => '水平',
'UI:Preferences:Tabs:Layout:Vertical' => '垂直',
'UI:Preferences:Tabs:Scrollable:Label' => '导航',
'UI:Preferences:Tabs:Scrollable:Classic' => '经典',
'UI:Preferences:Tabs:Scrollable:Scrollable' => '可滚动',
'UI:Preferences:General:Toasts' => '通知位置',
'UI:Preferences:General:Toasts:Bottom' => '底部',
'UI:Preferences:General:Toasts:Top' => '顶部',
'UI:Preferences:ChooseAPlaceholder' => '用户的默认头像',
'UI:Preferences:ChooseAPlaceholder+' => '选择一个占位图片, 将在用户联系人没有设定头像图片时显示',
'UI:Preferences:ChooseAPlaceholder:Success:Message' => '您的占位图片已成功更新',
'UI:Preferences:Notifications' => '通知',
'UI:Preferences:Notifications+' => '在 <a href="%1$s">这里</a>配置您想要收到的通知.',
]);

View File

@@ -4,52 +4,79 @@
* Localized data
*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license https://opensource.org/licenses/AGPL-3.0
* @license http://opensource.org/licenses/AGPL-3.0
*
*/
/**
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Core:DeletedObjectLabel' => '%1s (已删除)',
'Core:DeletedObjectTip' => '对象已被删除于 %1$s (%2$s)',
'Core:UnknownObjectLabel' => '找不到对象 (类型: %1$s, 编号: %2$d)',
'Core:UnknownObjectTip' => '对象没有找到. 其可能已经被删除并且日志已经被清除.',
'Core:UniquenessDefaultError' => '唯一性规则 \'%1$s\' 错误',
'Core:CheckConsistencyError' => '一致性规则没有被遵守: %1$s',
'Core:CheckValueError' => '属性 \'%1$s\' (%2$s)的未知值: %3$s',
'Core:AttributeLinkedSet' => '对象数组',
'Core:AttributeLinkedSet+' => '任何相同类型或子类型的对象',
'Core:AttributeLinkedSetDuplicatesFound' => '字段 \'%1$s\' 内容重复: %2$s',
'Core:AttributeDashboard' => '仪表盘',
'Core:AttributeDashboard+' => '',
'Core:AttributePhoneNumber' => '电话号码',
'Core:AttributePhoneNumber+' => '',
'Core:AttributeObsolescenceDate' => '报废日期',
'Core:AttributeObsolescenceDate+' => '',
'Core:AttributeTagSet' => '清单',
'Core:AttributeTagSet+' => '',
'Core:AttributeSet:placeholder' => '请点击这里添加',
'Core:Placeholder:CannotBeResolved' => '(%1$s : cannot be resolved)~~',
'Core:Placeholder:CannotBeResolved' => '(%1$s : 无法解析)',
'Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromClass' => '%1$s (%2$s)',
'Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromOneChildClass' => '%1$s (%2$s来自%3$s)',
'Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromSeveralChildClasses' => '%1$s (%2$s来自子类型',
'Core:AttributeCaseLog' => '日志',
'Core:AttributeCaseLog+' => '',
'Core:AttributeMetaEnum' => '计算枚举',
'Core:AttributeMetaEnum+' => '~~',
'Core:AttributeMetaEnum' => '计算的数字',
'Core:AttributeMetaEnum+' => '',
'Core:AttributeLinkedSetIndirect' => '对象数组 (N-N)',
'Core:AttributeLinkedSetIndirect+' => '相同类型的任何对象 [子类型]',
'Core:AttributeInteger' => '整数',
'Core:AttributeInteger+' => '整数(可以为负)',
'Core:AttributeDecimal' => '小数',
'Core:AttributeDecimal+' => '小数(可以为负)',
'Core:AttributeBoolean' => '布尔',
'Core:AttributeBoolean+' => '',
'Core:AttributeBoolean/Value:null' => '',
'Core:AttributeBoolean/Value:yes' => '是',
'Core:AttributeBoolean/Value:no' => '否',
'Core:AttributeArchiveFlag' => '是否归档',
'Core:AttributeArchiveFlag' => '归档标识',
'Core:AttributeArchiveFlag/Value:yes' => '是',
'Core:AttributeArchiveFlag/Value:yes+' => '该对象仅在归档模式可见',
'Core:AttributeArchiveFlag/Value:no' => '否',
@@ -57,46 +84,63 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Core:AttributeArchiveFlag/Label+' => '',
'Core:AttributeArchiveDate/Label' => '归档日期',
'Core:AttributeArchiveDate/Label+' => '',
'Core:AttributeObsolescenceFlag' => '是否废弃',
'Core:AttributeObsolescenceFlag' => '废弃标识',
'Core:AttributeObsolescenceFlag/Value:yes' => '是',
'Core:AttributeObsolescenceFlag/Value:yes+' => '该对象排除在影响分析中, 并且在搜索结果中隐藏',
'Core:AttributeObsolescenceFlag/Value:no' => '否',
'Core:AttributeObsolescenceFlag/Label' => '是否废弃',
'Core:AttributeObsolescenceFlag/Label' => '废弃标识',
'Core:AttributeObsolescenceFlag/Label+' => '基于其他属性动态计算',
'Core:AttributeObsolescenceDate/Label' => '废弃时间',
'Core:AttributeObsolescenceDate/Label+' => '该对象被废弃的大概日期',
'Core:AttributeString' => '字符串',
'Core:AttributeString+' => '字符串',
'Core:AttributeClass' => '类',
'Core:AttributeClass+' => '',
'Core:AttributeApplicationLanguage' => '用户语言',
'Core:AttributeApplicationLanguage+' => '语言和国家/地区(EN US)',
'Core:AttributeFinalClass' => '类型 (自动)',
'Core:AttributeFinalClass+' => '对象真实的类型 (内核自动创建)',
'Core:AttributePassword' => '密码',
'Core:AttributePassword+' => '外部设备的密码',
'Core:AttributeEncryptedString' => '加密字符串',
'Core:AttributeEncryptedString+' => '使用本地密钥加密的字符串',
'Core:AttributeEncryptUnknownLibrary' => '未知的加密库 (%1$s)',
'Core:AttributeEncryptFailedToDecrypt' => '** 解密错误 **',
'Core:AttributeText' => '文本',
'Core:AttributeText+' => '多行字符串',
'Core:AttributeHTML' => 'HTML',
'Core:AttributeHTML+' => 'HTML字符串',
'Core:AttributeEmailAddress' => '邮箱地址',
'Core:AttributeEmailAddress+' => 'Email 地址',
'Core:AttributeIPAddress' => 'IP 地址',
'Core:AttributeIPAddress+' => 'IP 地址',
'Core:AttributeOQL' => 'OQL',
'Core:AttributeOQL+' => '对象查询语言表达式',
'Core:AttributeEnum' => '枚举',
'Core:AttributeEnum+' => '预定义的字符串列表',
'Core:AttributeEnum' => '数字',
'Core:AttributeEnum+' => '预定义的数字列表',
'Core:AttributeTemplateString' => '字符模板',
'Core:AttributeTemplateString+' => '包含占位符的字符串',
'Core:AttributeTemplateText' => '文本模板',
'Core:AttributeTemplateText+' => '包含占位符的文本',
'Core:AttributeTemplateHTML' => 'HTML模板',
'Core:AttributeTemplateHTML+' => '含有占位符的HTML',
'Core:AttributeDateTime' => '日期/时间',
'Core:AttributeDateTime+' => '日期和时间 (年-月-日 时:分:秒)',
'Core:AttributeDateTime?SmartSearch' => '
@@ -112,8 +156,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
<b>[</b><em>日期</em>,<em>日期</em><b>]</b>
</p>
<p>
如果不写具体时间,则默认00:00:00
如果省略时间,则默认00:00:00
</p>',
'Core:AttributeDate' => '日期',
'Core:AttributeDate+' => '日期 (年-月-日)',
'Core:AttributeDate?SmartSearch' => '
@@ -128,34 +173,47 @@ Operators:<br/>
<b>&lt;</b><em>日期</em><br/>
<b>[</b><em>日期</em>,<em>日期</em><b>]</b>
</p>',
'Core:AttributeDeadline' => '截止日期',
'Core:AttributeDeadline+' => '日期, 显示与当前的相对时间',
'Core:AttributeExternalKey' => '外键',
'Core:AttributeExternalKey+' => '外部关联键',
'Core:AttributeHierarchicalKey' => '层级键',
'Core:AttributeHierarchicalKey+' => '关联到父级的外键',
'Core:AttributeExternalKey+' => '外面(或外部)的键',
'Core:AttributeHierarchicalKey' => 'Hierarchical Key~~',
'Core:AttributeHierarchicalKey+' => 'External (or foreign) key to the parent~~',
'Core:AttributeExternalField' => '外部字段',
'Core:AttributeExternalField+' => '映射到外键的字段',
'Core:AttributeExternalField+' => 'Field mapped to an external key~~',
'Core:AttributeURL' => 'URL',
'Core:AttributeURL+' => '绝对或相对的URL字符串',
'Core:AttributeBlob' => 'Blob',
'Core:AttributeBlob+' => '任何二进制内容(文档)',
'Core:AttributeOneWayPassword' => '单向密码',
'Core:AttributeOneWayPassword+' => '单向加密 (或哈希) 的密码',
'Core:AttributeTable' => '表',
'Core:AttributeTable+' => '带索引的二维数组',
'Core:AttributePropertySet' => '属性',
'Core:AttributePropertySet+' => '非类型化的属性列表 (名称和值)',
'Core:AttributeFriendlyName' => '通用名称',
'Core:AttributeFriendlyName' => '昵称',
'Core:AttributeFriendlyName+' => '自动创建的属性; 显示名称基于多个属性计算',
'Core:FriendlyName-Label' => '全称',
'Core:FriendlyName-Description' => '全称',
'Core:AttributeTag' => '标签',
'Core:AttributeTag+' => '标签',
'Core:AttributeTag+' => '',
'Core:Context=REST/JSON' => 'REST',
'Core:Context=Synchro' => '同步',
'Core:Context=Setup' => '安装向导',
'Core:Context=GUI:Console' => '命令行',
'Core:Context=GUI:Console' => '终端',
'Core:Context=CRON' => '定时任务',
'Core:Context=GUI:Portal' => '门户',
]);
@@ -315,12 +373,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:EventNotification' => '通知事件',
'Class:EventNotification+' => '已发送通知的追踪',
'Class:EventNotification/Attribute:trigger_id' => '触发器',
'Class:EventNotification/Attribute:trigger_id+' => '用户账号',
'Class:EventNotification/Attribute:object_class' => 'Object class~~',
'Class:EventNotification/Attribute:object_class+' => 'Object class (Same as trigger)~~',
'Class:EventNotification/Attribute:trigger_id+' => '账号',
'Class:EventNotification/Attribute:object_class' => '对象类型',
'Class:EventNotification/Attribute:object_class+' => '对象类型 (与触发器相同)',
'Class:EventNotification/Attribute:action_id' => '用户',
'Class:EventNotification/Attribute:action_id+' => '用户账号',
'Class:EventNotification/Attribute:object_id' => '对象编号',
'Class:EventNotification/Attribute:action_id+' => '账号',
'Class:EventNotification/Attribute:object_id' => '对象id',
'Class:EventNotification/Attribute:object_id+' => '对象编号 (类型由触发器定义?)',
]);
@@ -428,7 +486,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:EventNotificationNewsroom' => 'News sent~~',
'Class:EventNotificationNewsroom' => '已发送的新闻',
'Class:EventNotificationNewsroom+' => '',
'Class:EventNotificationNewsroom/Attribute:title' => '标题',
'Class:EventNotificationNewsroom/Attribute:title+' => '',
@@ -456,6 +514,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:EventNotificationNewsroom/Attribute:read_date+' => '',
'Class:EventNotificationNewsroom/Attribute:contact_id' => '联系人',
'Class:EventNotificationNewsroom/Attribute:contact_id+' => '',
'Core:EventNotificationNewsroom:ErrorNotificationNotSent' => '通知未发送',
'Core:EventNotificationNewsroom:ErrorOnDBInsert' => '保存通知时发生错误',
]);
//
@@ -463,23 +523,23 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Action' => '自定义操作',
'Class:Action+' => '用户定义的操作',
'Class:Action/ComplementaryName' => '%1$s: %2$s',
'Class:Action/Attribute:name' => '名称',
'Class:Action/Attribute:name+' => 'Any value that is meaningful to distinguish this action from the others',
'Class:Action/Attribute:description' => '描述',
'Class:Action/Attribute:description+' => 'A longer explanation about the purpose of this action. For information only.',
'Class:Action/Attribute:status' => '状态',
'Class:Action/Attribute:status+' => '是否正式环境?',
'Class:Action/Attribute:status/Value:test' => '正在测试',
'Class:Action/Attribute:status/Value:test+' => '',
'Class:Action/Attribute:status/Value:enabled' => '正式',
'Class:Action/Attribute:status/Value:enabled+' => '',
'Class:Action/Attribute:status/Value:disabled' => '停用',
'Class:Action' => '自定义操作',
'Class:Action+' => '用户定义的操作',
'Class:Action/ComplementaryName' => '%1$s: %2$s',
'Class:Action/Attribute:name' => '名称',
'Class:Action/Attribute:name+' => 'Any value that is meaningful to distinguish this action from the others',
'Class:Action/Attribute:description' => '描述',
'Class:Action/Attribute:description+' => 'A longer explanation about the purpose of this action. For information only.',
'Class:Action/Attribute:status' => '状态',
'Class:Action/Attribute:status+' => '是否正式环境?',
'Class:Action/Attribute:status/Value:test' => '正在测试',
'Class:Action/Attribute:status/Value:test+' => '',
'Class:Action/Attribute:status/Value:enabled' => '正式',
'Class:Action/Attribute:status/Value:enabled+' => '',
'Class:Action/Attribute:status/Value:disabled' => '停用',
'Class:Action/Attribute:status/Value:disabled+' => '',
'Class:Action/Attribute:trigger_list' => '相关的触发器',
'Class:Action/Attribute:trigger_list+' => '此操作关的触发器',
'Class:Action/Attribute:trigger_list+' => '此操作关的触发器',
'Class:Action/Attribute:asynchronous' => 'Asynchronous~~',
'Class:Action/Attribute:asynchronous+' => 'Whether this action should be executed in the background or not~~',
'Class:Action/Attribute:asynchronous/Value:use_global_setting' => '使用全局设置',
@@ -499,10 +559,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ActionNotification' => '通知',
'Class:ActionNotification+' => '通知 (抽象)',
'Class:ActionNotification' => '通知操作',
'Class:ActionNotification+' => '通知操作 (抽象)',
'Class:ActionNotification/Attribute:language' => '语言',
'Class:ActionNotification/Attribute:language+' => '',
'Class:ActionNotification/Attribute:language+' => 'Language to use for placeholders ($xxx$) inside the message (state, importance, priority, etc)~~',
]);
//
@@ -510,15 +570,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkActionNotificationToContact' => 'Link ActionNotification / Contact~~',
'Class:lnkActionNotificationToContact' => '链接 操作通知/联系人',
'Class:lnkActionNotificationToContact+' => 'Contact subscription to Notification Action~~',
'Class:lnkActionNotificationToContact/Attribute:contact_id' => 'Contact~~',
'Class:lnkActionNotificationToContact/Attribute:contact_id' => '联系人',
'Class:lnkActionNotificationToContact/Attribute:contact_id+' => 'Contact who subscribed (or not) to the notification~~',
'Class:lnkActionNotificationToContact/Attribute:action_id' => 'Action~~',
'Class:lnkActionNotificationToContact/Attribute:action_id' => '操作',
'Class:lnkActionNotificationToContact/Attribute:action_id+' => 'The notification that the contact received at least once, and to which he can subscribe or unsubscribe~~',
'Class:lnkActionNotificationToContact/Attribute:trigger_id' => 'Trigger~~',
'Class:lnkActionNotificationToContact/Attribute:trigger_id' => '触发器',
'Class:lnkActionNotificationToContact/Attribute:trigger_id+' => 'The trigger that fired the notification~~',
'Class:lnkActionNotificationToContact/Attribute:subscribed' => 'Subscribed~~',
'Class:lnkActionNotificationToContact/Attribute:subscribed' => '已订阅',
'Class:lnkActionNotificationToContact/Attribute:subscribed+' => 'If the contact unsubscribed (no) or is subscribed (yes and default) to the notification~~',
]);
@@ -527,41 +587,43 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ActionEmail' => '邮件通知',
'Class:ActionEmail+' => '',
'Class:ActionEmail/Attribute:status+' => '此状态将决定提醒谁:
'Class:ActionEmail' => '邮件通知',
'Class:ActionEmail+' => '',
'Class:ActionEmail/Attribute:status+' => '此状态将决定提醒谁:
- 测试中: 仅测试者,
- 生产的: 所有人 (收件人, 抄送和密送)
- 禁用的: 没有人',
'Class:ActionEmail/Attribute:status/Value:test+' => '仅测试收件人会被通知',
'Class:ActionEmail/Attribute:status/Value:enabled+' => '通知所有人, 包含抄送和秘抄',
'Class:ActionEmail/Attribute:status/Value:disabled+' => '不发送邮件通知',
'Class:ActionEmail/Attribute:test_recipient' => '测试收件人',
'Class:ActionEmail/Attribute:test_recipient+' => '通知为测试中时将使用此邮件地址, 而不是收件人, 抄送和密送',
'Class:ActionEmail/Attribute:from' => '发件人 (邮箱)',
'Class:ActionEmail/Attribute:from+' => '固定的邮箱地址或者类似$this->agent_id->email$的占位符.
'Class:ActionEmail/Attribute:status/Value:test+' => '仅测试收件人会被通知',
'Class:ActionEmail/Attribute:status/Value:enabled+' => '通知所有人, 包含抄送和秘抄',
'Class:ActionEmail/Attribute:status/Value:disabled+' => '不发送邮件通知',
'Class:ActionEmail/Attribute:test_recipient' => '测试收件人',
'Class:ActionEmail/Attribute:test_recipient+' => '通知为测试中时将使用此邮件地址, 而不是收件人, 抄送和密送',
'Class:ActionEmail/Attribute:from' => '发件人 (邮箱)',
'Class:ActionEmail/Attribute:from+' => '固定的邮箱地址或者类似$this->agent_id->email$的占位符.
有些邮件服务器可能不接收占位符.',
'Class:ActionEmail/Attribute:from_label' => '发件人 (显示名)',
'Class:ActionEmail/Attribute:from_label+' => '固定的显示名或者类似 $this->agent_id->friendlyname$ 的占位符',
'Class:ActionEmail/Attribute:reply_to' => '回复至 (邮箱)',
'Class:ActionEmail/Attribute:reply_to+' => '固定的邮箱地址或者类似$this->team_id->email$的占位符.
'Class:ActionEmail/Attribute:from_label' => '发件人 (显示名)',
'Class:ActionEmail/Attribute:from_label+' => '固定的显示名或者类似 $this->agent_id->friendlyname$ 的占位符',
'Class:ActionEmail/Attribute:reply_to' => '回复至 (邮箱)',
'Class:ActionEmail/Attribute:reply_to+' => '固定的邮箱地址或者类似$this->team_id->email$的占位符.
如果忽略则使用发件人 (邮箱).',
'Class:ActionEmail/Attribute:reply_to_label' => '回复至 (显示名)',
'Class:ActionEmail/Attribute:reply_to_label+' => '固定的显示名或者类似$this->team_id->friendlyname$的占位符.
如果忽略则使用发件人 (显示名).',
'Class:ActionEmail/Attribute:to' => '收件人',
'Class:ActionEmail/Attribute:to+' => '收件人: 返回含有邮箱字段对象的OQL查询.
'Class:ActionEmail/Attribute:reply_to_label' => '回复至 (显示名)',
'Class:ActionEmail/Attribute:reply_to_label+' => '固定的显示名或者类似$this->team_id->friendlyname$的占位符.
如果忽略则使用发件人 (显示名).',
'Class:ActionEmail/Attribute:to' => '收件人',
'Class:ActionEmail/Attribute:to+' => 'To: an OQL query returning objects having an email field.
While editing, click on the magnifier to get pertinent examples.
You can use in the OQL :this->attribute_code with an attribute code of the object which triggered the Notification. Then test your OQL syntax using the play icon.~~',
'Class:ActionEmail/Attribute:cc' => '抄送',
'Class:ActionEmail/Attribute:cc+' => 'Carbon Copy: an OQL query returning objects having an email field.
While editing, click on the magnifier to get pertinent examples.
You can use in the OQL :this->attribute_code with an attribute code of the object which triggered the Notification. Then test your OQL syntax using the play icon.~~',
'Class:ActionEmail/Attribute:bcc' => '密抄',
'Class:ActionEmail/Attribute:bcc+' => '密送: 返回含有邮箱字段对象的OQL查询.
编辑时可点击放大镜图标获取参考示例',
'Class:ActionEmail/Attribute:cc' => '抄送',
'Class:ActionEmail/Attribute:cc+' => '抄送: 返回含有邮箱字段对象的OQL查询.
编辑时可点击放大镜图标获取参考示例',
'Class:ActionEmail/Attribute:bcc' => '密抄',
'Class:ActionEmail/Attribute:bcc+' => '密送: 返回含有邮箱字段对象的OQL查询.
编辑时可点击放大镜图标获取参考示例',
'Class:ActionEmail/Attribute:subject' => '主题',
'Class:ActionEmail/Attribute:subject+' => '邮件主题. 可包含类似$this->attribute_code$的占位符',
'Class:ActionEmail/Attribute:body' => '正文',
'Class:ActionEmail/Attribute:body+' => '邮件正文. 可包含以下占位符:
'Class:ActionEmail/Attribute:subject' => '主题',
'Class:ActionEmail/Attribute:subject+' => '邮件主题. 可包含类似$this->attribute_code$的占位符',
'Class:ActionEmail/Attribute:body' => '正文',
'Class:ActionEmail/Attribute:body+' => '邮件正文. 可包含以下占位符:
- $this->attribute_code$ 触发通知的对象的任何属性,
- $this->html(attribute_code)$ 内容同上但是使用html格式,
- $this->hyperlink()$ 触发通知的对象的控制台链接,
@@ -569,30 +631,30 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
- $this->head_html(case_log_attribute)$ 事例日志中的最新一条html格式的回复,
- $this->attribute_external_key->attribute$ 任何远程属性的递归语法,
- $current_contact->attribute$ 触发通知的用户的属性',
'Class:ActionEmail/Attribute:importance' => '重要性',
'Class:ActionEmail/Attribute:importance+' => '生成邮件的重要性标签设置',
'Class:ActionEmail/Attribute:importance/Value:low' => '低',
'Class:ActionEmail/Attribute:importance/Value:low+' => '',
'Class:ActionEmail/Attribute:importance/Value:normal' => '普通',
'Class:ActionEmail/Attribute:importance/Value:normal+' => '',
'Class:ActionEmail/Attribute:importance/Value:high' => '高',
'Class:ActionEmail/Attribute:importance/Value:high+' => '',
'Class:ActionEmail/Attribute:language' => '语言',
'Class:ActionEmail/Attribute:language+' => '在邮件中 (状态, 重要性, 优先级, 等等) 所使用的占位符 ($xxx$) 的语言',
'Class:ActionEmail/Attribute:html_template' => 'HTML模板',
'Class:ActionEmail/Attribute:html_template+' => '绑定在以下 \'正文\' 属性内容上的可选HTML模板, 用于定制邮件布局 (在模板中, \'正文\' 属性的内容将被占位符 $content$ 替换)',
'Class:ActionEmail/Attribute:ignore_notify' => '忽略通知标记',
'Class:ActionEmail/Attribute:ignore_notify+' => '如果设置为 \'是\' 则联系人的 \'通知\' 标记将不生效.',
'Class:ActionEmail/Attribute:ignore_notify/Value:no' => '否',
'Class:ActionEmail/Attribute:ignore_notify/Value:yes' => '是',
'ActionEmail:main' => '消息',
'ActionEmail:trigger' => '触发器',
'ActionEmail:recipients' => '联系人',
'ActionEmail:preview_tab' => '预览',
'ActionEmail:preview_tab+' => '预览邮件模板',
'ActionEmail:preview_warning' => '实际收到的邮件在客户端中可能与当前在浏览器中的预览有所不同.',
'ActionEmail:preview_more_info' => '若需更多不同邮件客户端支持的CSS特性信息, 请参阅%1$s',
'ActionEmail:content_placeholder_missing' => '标识符 "%1$s" 在HTML中不存在. 字段 "%2$s" 的内容将不会包含在生成的邮件中.',
'Class:ActionEmail/Attribute:importance' => '重要性',
'Class:ActionEmail/Attribute:importance+' => '生成邮件的重要性标签设置',
'Class:ActionEmail/Attribute:importance/Value:low' => '低',
'Class:ActionEmail/Attribute:importance/Value:low+' => '',
'Class:ActionEmail/Attribute:importance/Value:normal' => '普通',
'Class:ActionEmail/Attribute:importance/Value:normal+' => '',
'Class:ActionEmail/Attribute:importance/Value:high' => '高',
'Class:ActionEmail/Attribute:importance/Value:high+' => '',
'Class:ActionEmail/Attribute:language' => '语言',
'Class:ActionEmail/Attribute:language+' => '在邮件中 (状态, 重要性, 优先级, 等等) 所使用的占位符 ($xxx$) 的语言',
'Class:ActionEmail/Attribute:html_template' => 'HTML模板',
'Class:ActionEmail/Attribute:html_template+' => '绑定在以下 \'正文\' 属性内容上的可选HTML模板, 用于定制邮件布局 (在模板中, \'正文\' 属性的内容将被占位符 $content$ 替换)',
'Class:ActionEmail/Attribute:ignore_notify' => '忽略通知标记',
'Class:ActionEmail/Attribute:ignore_notify+' => '如果设置为 \'是\' 则联系人的 \'通知\' 标记将不生效.',
'Class:ActionEmail/Attribute:ignore_notify/Value:no' => '否',
'Class:ActionEmail/Attribute:ignore_notify/Value:yes' => '是',
'ActionEmail:main' => '消息',
'ActionEmail:trigger' => '触发器',
'ActionEmail:recipients' => '联系人',
'ActionEmail:preview_tab' => '预览',
'ActionEmail:preview_tab+' => '预览邮件模板',
'ActionEmail:preview_warning' => '实际收到的邮件在客户端中可能与当前在浏览器中的预览有所不同.',
'ActionEmail:preview_more_info' => '若需更多不同邮件客户端支持的CSS特性信息, 请参阅%1$s',
'ActionEmail:content_placeholder_missing' => '标识符 "%1$s" 在HTML中不存在. 字段 "%2$s" 的内容将不会包含在生成的邮件中.',
]);
//
@@ -603,7 +665,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'ActionNewsroom:trigger' => '触发器',
'ActionNewsroom:content' => '消息',
'ActionNewsroom:settings' => '设置',
'Class:ActionNewsroom' => ITOP_APPLICATION_SHORT.'通知',
'Class:ActionNewsroom' => '新闻室的通知',
'Class:ActionNewsroom+' => '',
'Class:ActionNewsroom/Attribute:title' => '标题',
'Class:ActionNewsroom/Attribute:title+' => 'Title of the news. Can contain placeholders like $this->attribute_code$~~',
@@ -620,8 +682,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
- Otherwise, the application compact logo will be used~~',
'Class:ActionNewsroom/Attribute:priority' => '优先级',
'Class:ActionNewsroom/Attribute:priority+' => 'News will be ordered by decreasing priority, when displayed in the Newsroom popup',
'Class:ActionNewsroom/Attribute:priority/Value:1' => '严',
'Class:ActionNewsroom/Attribute:priority/Value:1+' => '严',
'Class:ActionNewsroom/Attribute:priority/Value:1' => '严',
'Class:ActionNewsroom/Attribute:priority/Value:1+' => '严',
'Class:ActionNewsroom/Attribute:priority/Value:2' => '紧急',
'Class:ActionNewsroom/Attribute:priority/Value:2+' => '紧急',
'Class:ActionNewsroom/Attribute:priority/Value:3' => '重要',
@@ -641,21 +703,21 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:Trigger' => '触发器',
'Class:Trigger+' => '自定义事件处理',
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
'Class:Trigger/Attribute:description' => '描述',
'Class:Trigger/Attribute:description+' => '简短描述',
'Class:Trigger/Attribute:action_list' => '触发的操作',
'Class:Trigger/Attribute:action_list+' => '此触发器激活后要执行的操作',
'Class:Trigger/Attribute:finalclass' => '触发器类型',
'Class:Trigger/Attribute:finalclass+' => '根本属性的名称',
'Class:Trigger/Attribute:context' => '上下文',
'Class:Trigger/Attribute:context+' => '允许此触发器开启的上下文',
'Class:Trigger/Attribute:complement' => '其它信息',
'Class:Trigger/Attribute:complement+' => '此触发器提供的更多信息, 使用英文',
'Class:Trigger/Attribute:subscription_policy' => 'Subscription policy~~',
'Class:Trigger/Attribute:subscription_policy+' => 'Allows users to unsubscribe from the trigger~~',
'Class:Trigger' => '触发器',
'Class:Trigger+' => '自定义事件处理',
'Class:Trigger/ComplementaryName' => '%1$s, %2$s',
'Class:Trigger/Attribute:description' => '描述',
'Class:Trigger/Attribute:description+' => '简短描述',
'Class:Trigger/Attribute:action_list' => '触发的操作',
'Class:Trigger/Attribute:action_list+' => '此触发器激活后要执行的操作',
'Class:Trigger/Attribute:finalclass' => '触发器类型',
'Class:Trigger/Attribute:finalclass+' => '根本属性的名称',
'Class:Trigger/Attribute:context' => '上下文',
'Class:Trigger/Attribute:context+' => '允许此触发器开启的上下文',
'Class:Trigger/Attribute:complement' => '其它信息',
'Class:Trigger/Attribute:complement+' => '此触发器提供的更多信息, 使用英文',
'Class:Trigger/Attribute:subscription_policy' => 'Subscription policy~~',
'Class:Trigger/Attribute:subscription_policy+' => 'Allows users to unsubscribe from the trigger~~',
'Class:Trigger/Attribute:subscription_policy/Value:allow_no_channel' => 'Allow complete unsubscription~~',
'Class:Trigger/Attribute:subscription_policy/Value:force_at_least_one_channel' => 'Force at least one channel (News or Email)~~',
'Class:Trigger/Attribute:subscription_policy/Value:force_all_channels' => 'Deny unsubscription~~',
@@ -666,14 +728,14 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnObject' => '触发器 (类型依赖的)',
'Class:TriggerOnObject+' => '在指定类型对象上的触发器',
'Class:TriggerOnObject/Attribute:target_class' => '目标类型',
'Class:TriggerOnObject/Attribute:target_class+' => '',
'Class:TriggerOnObject/Attribute:filter' => '筛选器',
'Class:TriggerOnObject/Attribute:filter+' => '限定将激活触发器的对象 (目标类型的)',
'TriggerOnObject:WrongFilterQuery' => '错误的筛选查询: %1$s',
'TriggerOnObject:WrongFilterClass' => '筛选查询返回的对象必须是类型 "%1$s"',
'Class:TriggerOnObject' => '触发器 (类型依赖的)',
'Class:TriggerOnObject+' => '在指定类型对象上的触发器',
'Class:TriggerOnObject/Attribute:target_class' => '目标类型',
'Class:TriggerOnObject/Attribute:target_class+' => 'Objects in this class will activate the trigger~~',
'Class:TriggerOnObject/Attribute:filter' => '筛选器',
'Class:TriggerOnObject/Attribute:filter+' => '限定将激活触发器的对象 (目标类型的)',
'TriggerOnObject:WrongFilterQuery' => '错误的筛选查询: %1$s',
'TriggerOnObject:WrongFilterClass' => '筛选查询返回的对象必须是类型 "%1$s"',
]);
//
@@ -681,7 +743,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnPortalUpdate' => '触发器 (工单更新时)',
'Class:TriggerOnPortalUpdate' => '触发器 (工单更新时)',
'Class:TriggerOnPortalUpdate+' => '终端用户更新工单时触发',
]);
@@ -719,7 +781,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnObjectCreate' => '触发器 (对象创建时)',
'Class:TriggerOnObjectCreate' => '触发器 (对象创建时)',
'Class:TriggerOnObjectCreate+' => '对象创建时触发',
]);
@@ -728,7 +790,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnObjectDelete' => '触发器 (对象删除时)',
'Class:TriggerOnObjectDelete' => '触发器 (对象删除时)',
'Class:TriggerOnObjectDelete+' => '指定类型或子类型对象删除时的触发器',
]);
@@ -737,7 +799,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnObjectUpdate' => '触发器 (对象更新时)',
'Class:TriggerOnObjectUpdate' => '触发器 (对象更新时)',
'Class:TriggerOnObjectUpdate+' => '指定类型或子类型对象更新时的触发器',
'Class:TriggerOnObjectUpdate/Attribute:filter+' => 'This filter is computed after the object update in database. It restricts the objects which can trigger the actions~~',
'Class:TriggerOnObjectUpdate/Attribute:target_attcodes' => '目标字段',
@@ -749,7 +811,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnObjectMention' => '触发器 (对象提及时)',
'Class:TriggerOnObjectMention' => '触发器 (对象提及时)',
'Class:TriggerOnObjectMention+' => '指定类型或子类型对象在属性日志中提及 (@xxx) 时的触发器',
'Class:TriggerOnObjectMention/Attribute:mentioned_filter' => '提及筛选',
'Class:TriggerOnObjectMention/Attribute:mentioned_filter+' => '限丁将激活此触发器的提及对象. 如果为空则任何类的提及对象将激活此触发器.',
@@ -760,7 +822,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TriggerOnAttributeBlobDownload' => '触发器 (对象文档下载时)',
'Class:TriggerOnAttributeBlobDownload' => '触发器 (对象文档下载时)',
'Class:TriggerOnAttributeBlobDownload+' => '指定类型或子类型对象的文档下载时的触发器',
'Class:TriggerOnAttributeBlobDownload/Attribute:target_attcodes' => '目标字段',
'Class:TriggerOnAttributeBlobDownload/Attribute:target_attcodes+' => '',
@@ -784,8 +846,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:lnkTriggerAction' => '操作/触发器',
'Class:lnkTriggerAction+' => '关联触发器和操作',
'Class:lnkTriggerAction' => '链接 操作/触发器',
'Class:lnkTriggerAction+' => '链接触发器和操作',
'Class:lnkTriggerAction/Attribute:action_id' => '操作',
'Class:lnkTriggerAction/Attribute:action_id+' => '要执行的操作',
'Class:lnkTriggerAction/Attribute:action_name' => '操作',
@@ -870,6 +932,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SynchroDataSource/Attribute:user_delete_policy/Value:administrators' => '仅管理员',
'Class:SynchroDataSource/Attribute:user_delete_policy/Value:everybody' => '所有允许删除此类型对象的用户',
'Class:SynchroDataSource/Attribute:user_delete_policy/Value:nobody' => '没有人',
'SynchroDataSource:Description' => '描述',
'SynchroDataSource:Reconciliation' => '搜索 &amp; 使一致',
'SynchroDataSource:Deletion' => '删除规则',
@@ -996,7 +1059,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SynchroLog/Attribute:stats_nb_obj_new_unchanged' => '未更改对象数量',
'Class:SynchroLog/Attribute:last_error' => '最新错误',
'Class:SynchroLog/Attribute:traces' => '跟踪',
'Class:SynchroReplica' => '同步复制',
'Class:SynchroReplica' => '同步副本',
'Class:SynchroReplica/Attribute:sync_source_id' => '同步数据源',
'Class:SynchroReplica/Attribute:dest_id' => '目标对象 (编号)',
'Class:SynchroReplica/Attribute:dest_class' => '目标类型',
@@ -1014,18 +1077,22 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:SynchroReplica/Attribute:info_last_modified' => '最后修改日期',
'Class:appUserPreferences' => '用户偏好',
'Class:appUserPreferences/Attribute:userid' => '用户',
'Class:appUserPreferences/Attribute:preferences' => '首选项',
'Class:appUserPreferences/Attribute:preferences' => '偏好设置',
'Core:ExecProcess:Code1' => '命令错误或命令执行出错 (例如错误的脚本名称)',
'Core:ExecProcess:Code255' => 'PHP错误 (解析, 或运行时)',
// Attribute Duration
'Core:Duration_Seconds' => '%1$ds',
'Core:EventNotificationNewsroom:ErrorNotificationNotSent' => 'Notification not sent~~',
'Core:EventNotificationNewsroom:ErrorOnDBInsert' => 'An error occurred while saving the notification~~',
'Core:Duration_Minutes_Seconds' => '%1$dmin %2$ds',
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds',
// Explain working time computing
'Core:ExplainWTC:ElapsedTime' => '耗时 (储存为 "%1$s")',
'Core:ExplainWTC:StopWatch-TimeSpent' => '在 "%1$s" 上消耗的时间',
'Core:ExplainWTC:StopWatch-Deadline' => '"%1$s" 的期限截止于%2$d%%',
// Bulk export
'Core:BulkExport:MissingParameter_Param' => '缺少参数 "%1$s"',
'Core:BulkExport:InvalidParameter_Query' => '参数 "query" 的值无效. 在查询薄中没有找到对应编号: "%1$s" 的记录.',
'Core:BulkExport:ExportFormatPrompt' => '导出格式:',
@@ -1072,7 +1139,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Core:BulkExportCanRunNonInteractive' => '点击这里运行非交互式导出.',
'Core:BulkExportLegacyExport' => '点击这里进入旧版导出.',
'Core:BulkExport:XLSXOptions' => 'Excel 选项',
'Core:BulkExport:TextFormat' => '文本中包含一些HTML 标',
'Core:BulkExport:TextFormat' => '文本中包含一些 HTML 标',
'Core:BulkExport:DateTimeFormat' => '日期和时间格式',
'Core:BulkExport:DateTimeFormatDefault_Example' => '默认格式 (%1$s), e.g. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => '自定义格式: %1$s',
@@ -1095,7 +1162,6 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Core:Validator:Mandatory' => '这里必填',
'Core:Validator:MustBeInteger' => '必须是整数',
'Core:Validator:MustSelectOne' => '请选择',
'INTERNAL:JQuery-DatePicker:LangCode' => 'zh-CN',
]);
//
@@ -1103,7 +1169,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TagSetFieldData' => '类型%1$s的%2$s',
'Class:TagSetFieldData+' => '~~',
'Class:TagSetFieldData+' => '',
'Class:TagSetFieldData/Attribute:code' => '代码',
'Class:TagSetFieldData/Attribute:code+' => '内部代码. 必须至少包含3个数字或字母',
'Class:TagSetFieldData/Attribute:label' => '标签',
@@ -1113,6 +1180,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:TagSetFieldData/Attribute:finalclass' => '标签类型',
'Class:TagSetFieldData/Attribute:obj_class' => '对象类型',
'Class:TagSetFieldData/Attribute:obj_attcode' => '字段编码',
'Core:TagSetFieldData:ErrorDeleteUsedTag' => '已使用的标签无法删除',
'Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel' => '标签编码或名称必须唯一',
'Core:TagSetFieldData:ErrorTagCodeSyntax' => '标签编码必须介于3到%1$d个字符, 以字母开头.',
@@ -1130,7 +1198,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
//
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:DBProperty' => '数据库属性',
'Class:DBProperty+' => '~~',
'Class:DBProperty+' => '',
'Class:DBProperty/Attribute:name' => '名称',
'Class:DBProperty/Attribute:name+' => '',
'Class:DBProperty/Attribute:description' => '描述',
@@ -1238,3 +1306,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
'Class:ResourceSystemMenu' => '资源系统菜单',
'Class:ResourceSystemMenu+' => '',
]);
// additional translation for zh_cn
Dict::Add('ZH CN', 'Chinese', '简体中文', [
'INTERNAL:JQuery-DatePicker:LangCode' => 'zh-CN',
]);

File diff suppressed because it is too large Load Diff

View File

@@ -736,7 +736,6 @@ class iTopExtensionsMap
public function GetSelectedExtensions(Config $oConfig, array $aAddedExtensions, array $aRemovedExtensions): array
{
$aDbChoices = self::GetChoicesFromDatabase($oConfig);
foreach ($aDbChoices as $i => $sChoice) {
if (in_array($sChoice, $aRemovedExtensions)) {
unset($aDbChoices[$i]);

View File

@@ -311,7 +311,7 @@ abstract class ModuleInstallerAPI
/**
* @param \Config $oConfiguration
* @param string $sPreviousVersion The previous version of the module (empty string in case of first install)
* @param string $sPreviousVersion The previous version of the module (empty string will force the loading)
* @param string $sCurrentVersion The current version of the module
* @param string $sFirstLoadingVersion The first module version for which the data loading should be performed (e.g. '3.0.0')
* @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
@@ -321,51 +321,74 @@ abstract class ModuleInstallerAPI
* @throws \CoreException
* @throws \CoreUnexpectedValue
*/
public static function LoadLocalizedDataOnCrossingVersion(Config $oConfiguration, ?string $sPreviousVersion, ?string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
public static function LoadLocalizedData(Config $oConfiguration, string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
{
self::AssertLoadLocalizedDataParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion);
self::AssertLoadLocalizedDataParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sFilePattern);
// The loading is done only if
// - it's a first install of the module
// - or it's an upgrade of that module (PreviousVersion is less than the CurrentVersion), which means that we are really upgrading (and not reinstalling the same version or downgrading), and
// - either the FirstLoadingVersion is between the PreviousVersion and the CurrentVersion
// - or the FirstLoadingVersion is empty, forcing the loading on all upgrades,
// It's not very clear if it makes sense to test a particular version,
// as the loading mechanism checks object existence using reconc_keys
// and do not recreate them, nor update existing.
// Without test, new entries added to the data files, would be automatically loaded
if (($sPreviousVersion === '') ||
(version_compare($sPreviousVersion, $sCurrentVersion, '<')
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<')
&& version_compare($sFirstLoadingVersion, $sCurrentVersion, '<='))) {
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<'))) {
self::LoadLocalizedData($oConfiguration, $sFilePattern);
// Note: There is an issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
// Fresh install
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage();
} else {
// Upgrade
$sDefaultLanguage = utils::GetConfig(true)->GetDefaultLanguage();
}
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern);
if ($sFileName !== '') {
self::XMLFileLoad($sFileName);
}
}
}
/**
* @param \Config $oConfiguration
* @param string $sPreviousVersion The previous version of the module (empty string in case of first install)
* @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
*
* @return void
*/
public static function LoadLocalizedDataOnNewInstall(Config $oConfiguration, ?string $sPreviousVersion, string $sFilePattern): void
* @throws \CoreUnexpectedValue
*/
private static function AssertLoadLocalizedDataParametersAreValid(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
{
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
self::LoadLocalizedData($oConfiguration, $sFilePattern);
if (($sPreviousVersion !== '') && !self::IsValidLocalizedDataVersion($sPreviousVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sCurrentVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sFirstLoadingVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
}
if (utils::IsNullOrEmptyString($sFilePattern)) {
throw new CoreUnexpectedValue('LoadLocalizedData expects sFilePattern to be a non-empty string');
}
if (substr_count($sFilePattern, '{{language_code}}') !== 1) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFilePattern to contain the exact placeholder '{{language_code}}' exactly once");
}
}
private static function IsValidLocalizedDataVersion(string $sVersion): bool
{
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
}
/**
* @param \Config $oConfiguration
* @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
* @param array|string $sFileName
* @param \XMLDataLoader $oDataLoader
*
* @return void
* @throws \Exception
*/
protected static function LoadLocalizedData(Config $oConfiguration, string $sFilePattern): void
public static function XMLFileLoad(string $sFileName): void
{
if (substr_count($sFilePattern, '{{language_code}}') !== 1) {
throw new CoreUnexpectedValue("LoadLocalizedData expects $sFilePattern to contain the exact placeholder '{{language_code}}' exactly once");
}
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage();
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern);
if (!file_exists($sFileName)) {
throw new Exception("File $sFileName not found");
}
@@ -378,39 +401,19 @@ abstract class ModuleInstallerAPI
$oDataLoader->EndSession();
}
/**
* @throws \CoreUnexpectedValue
*/
private static function AssertLoadLocalizedDataParametersAreValid(?string $sPreviousVersion, ?string $sCurrentVersion, string $sFirstLoadingVersion): void
{
if (($sPreviousVersion !== '') && !self::IsValidLocalizedDataVersion($sPreviousVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
}
if (!self::IsValidLocalizedDataVersion($sCurrentVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
}
if (($sFirstLoadingVersion !== '') && !self::IsValidLocalizedDataVersion($sFirstLoadingVersion)) {
throw new CoreUnexpectedValue("LoadLocalizedData expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
}
}
private static function IsValidLocalizedDataVersion(string $sVersion): bool
{
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
}
/**
* @param string $sLanguage The language code to use for localization (e.g. 'EN US')
* @param string $sFilePattern The full path+name of the file to localize, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
*
* @return string The localized file name if found, or an empty string if not found
* @throws \ConfigException
* @throws \CoreException
*/
private static function GetLocalizedFileName($sLanguage, string $sFilePattern): string
public static function GetLocalizedFileName($sLanguage, string $sFilePattern): string
{
$sLang = str_replace(' ', '_', strtolower($sLanguage));
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
if (!file_exists($sFileName)) {
SetupLog::Debug("No data file found matching the pattern $sFilePattern and language_code $sLang. Trying with 'en_us' as fallback.");
$sLang = 'en_us';
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
}

View File

@@ -81,13 +81,13 @@ class ApplicationInstallSequencer extends StepSequencer
return $this->ComputeNextStep($sStep);
case 'log-parameters':
if (array_key_exists($sStep, $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep($sStep)) {
$this->DoLogParameters();
}
return $this->ComputeNextStep($sStep);
case 'backup':
if (array_key_exists($sStep, $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep($sStep, false)) {
$aBackupOptions = $this->oParams->Get('optional_steps')['backup'];
// __DB__-%Y-%m-%d
$sDestination = $aBackupOptions['destination'];
@@ -100,7 +100,7 @@ class ApplicationInstallSequencer extends StepSequencer
case 'migrate-before':
$this->oRunTimeEnvironment->EnterMaintenanceMode($this->GetConfig());
if (array_key_exists($sStep, $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep($sStep)) {
$this->oRunTimeEnvironment->MigrateDataBeforeUpdateStructure($this->oParams->Get('mode'), $this->GetConfig());
}
return $this->ComputeNextStep($sStep);
@@ -111,7 +111,7 @@ class ApplicationInstallSequencer extends StepSequencer
return $this->ComputeNextStep($sStep);
case 'migrate-after':
if (array_key_exists($sStep, $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep($sStep)) {
$this->oRunTimeEnvironment->MigrateDataAfterUpdateStructure($this->oParams->Get('mode'), $this->GetConfig());
}
return $this->ComputeNextStep($sStep);
@@ -191,13 +191,17 @@ class ApplicationInstallSequencer extends StepSequencer
public function GetStepNames(): array
{
$aStepNames = [ ''];
foreach (['log-parameters', 'backup', 'migrate-before'] as $sStepName) {
if (array_key_exists($sStepName, $this->oParams->Get('optional_steps', []))) {
$aStepNames [] = $sStepName;
}
if ($this->HasOptionalStep('log-parameters')) {
$aStepNames [] = 'log-parameters';
}
if ($this->HasOptionalStep('backup', false)) {
$aStepNames [] = 'backup';
}
if ($this->HasOptionalStep('migrate-before')) {
$aStepNames [] = 'migrate-before';
}
$aStepNames [] = 'db-schema';
if (array_key_exists('migrate-after', $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep('migrate-after')) {
$aStepNames [] = 'migrate-after';
}

View File

@@ -102,7 +102,7 @@ class DataAuditSequencer extends StepSequencer
protected function IsDataAuditRequired(): bool
{
if (! array_key_exists('setup-audit', $this->oParams->Get('optional_steps', []))) {
if (!$this->HasOptionalStep('setup-audit', false)) {
return false;
}
@@ -124,7 +124,7 @@ class DataAuditSequencer extends StepSequencer
public function GetStepNames(): array
{
$aStepNames = [''];
if (array_key_exists('copy', $this->oParams->Get('optional_steps', []))) {
if ($this->HasOptionalStep('copy')) {
$aStepNames[] = 'copy';
}
$aStepNames[] = 'compile';

View File

@@ -29,6 +29,9 @@ abstract class StepSequencer
protected RunTimeEnvironment $oRunTimeEnvironment;
protected string $sSourceDesc;
protected const LABELS = [];
protected const SUCCESS_LABELS = [];
/**
* @param \Parameters $oParams
* @param \RunTimeEnvironment|null $oRunTimeEnvironment
@@ -233,4 +236,26 @@ abstract class StepSequencer
* @return array (status => , message => , percentage-completed => , next-step => , next-step-label => )
*/
abstract public function ExecuteStep($sStep = '', $sInstallComment = null): array;
/**
* Check whether an optional step is enabled in the "optional_steps" parameters. If optional_steps is not set, use $bDefaultValue as its default value
*
* @param $sStep
* @param bool $bDefaultValue
*
* @return bool
* @throws \Exception
*/
protected function HasOptionalStep($sStep, bool $bDefaultValue = true)
{
$aOptionalSteps = $this->oParams->Get('optional_steps', null);
if (is_null($aOptionalSteps)) {
return $bDefaultValue;
}
if (is_array($aOptionalSteps)) {
return array_key_exists($sStep, $aOptionalSteps);
}
throw new Exception('Incorrect value for parameter optional_steps');
}
}

View File

@@ -26,17 +26,17 @@ function WizardAsyncAction(sActionCode, oParams, OnErrorFunction)
function WizardUpdateButtons()
{
if (CanMoveForward()) {
$("#btn_next").prop('disabled', false);
$("#btn_next").removeClass('ibo-is-hidden');
}
else {
$("#btn_next").prop('disabled', true);
$("#btn_next").addClass('ibo-is-hidden');
}
if (CanMoveBackward()) {
$("#btn_back").prop('disabled', false);
$("#btn_back").removeClass('ibo-is-hidden');
}
else {
$("#btn_back").prop('disabled', true);
$("#btn_back").addClass('ibo-is-hidden');
}
}

View File

@@ -13,10 +13,10 @@
<target_env>production</target_env>
<workspace_dir></workspace_dir>
<database>
<server></server>
<user></user>
<pwd></pwd>
<name></name>
<server>localhost</server>
<user>iTop</user>
<pwd>blob99</pwd>
<name>configcomments</name>
<db_tls_enabled></db_tls_enabled>
<db_tls_ca></db_tls_ca>
<prefix></prefix>
@@ -24,9 +24,9 @@
<url></url>
<graphviz_path>/usr/bin/dot</graphviz_path>
<admin_account>
<user></user>
<pwd></pwd>
<language></language>
<user>admin</user>
<pwd>admin</pwd>
<language>FR FR</language>
</admin_account>
<language></language>
<selected_modules type="array">

View File

@@ -151,10 +151,10 @@ class WizardController
$sCurrentState = utils::ReadParam('_state', $this->sInitialState);
$oStep = $this->GetWizardStep($sCurrentStepClass, $sCurrentState);
if ($oStep->ValidateParams()) {
if ($oStep->CanComeBack()) {
$aPossibleSteps = $oStep->GetPossibleSteps();
if ($oStep->CanMoveBackward()) {
$this->PushStep(['class' => $sCurrentStepClass, 'state' => $sCurrentState]);
}
$aPossibleSteps = $oStep->GetPossibleSteps();
$oWizardState = $oStep->UpdateWizardStateAndGetNextStep(true); // true => moving forward
if (in_array($oWizardState->GetNextStep(), $aPossibleSteps)) {
$oNextStep = $this->GetWizardStep($oWizardState->GetNextStep(), $oWizardState->GetState());
@@ -237,8 +237,12 @@ HTML;
$oPage->add('<input type="hidden" name="_steps" value="'.utils::EscapeHtml(json_encode($this->aWizardSteps)).'"/>');
$oPage->add('<table style="width:100%;" class="ibo-setup--wizard--buttons-container"><tr>');
if ((count($this->aWizardSteps) > 0) && ($oStep->CanMoveBackward())) {
$oPage->add('<td style="text-align: left"><button id="btn_back" class="ibo-button ibo-is-alternative ibo-is-neutral" type="submit" name="operation" value="back"><span class="ibo-button--label">Back</span></button></td>');
if (count($this->aWizardSteps) > 0) {
if ($oStep->CanMoveBackward()) {
$oPage->add('<td style="text-align: left"><button id="btn_back" class="ibo-button ibo-is-alternative ibo-is-neutral" type="submit" name="operation" value="back"><span class="ibo-button--label">Back</span></button></td>');
} else {
$oPage->add('<td style="text-align: left"><button id="btn_back" class="ibo-button ibo-is-alternative ibo-is-neutral ibo-is-hidden" type="submit" name="operation" value="back"><span class="ibo-button--label">Back</span></button></td>');
}
}
if ($oStep->CanMoveForward()) {
$oPage->add('<td style="text-align:right;"><button id="btn_next" class="default ibo-button ibo-is-regular ibo-is-primary" type="submit" name="operation" value="next"><span class="ibo-button--label">'.utils::EscapeHtml($oStep->GetNextButtonLabel()).'</span></button></td>');

View File

@@ -54,16 +54,20 @@ class WizStepDataAudit extends WizStepInstall
}
}
/**
* Tells whether this step/state allows to go back or not
* @return boolean True if the '<< Back' button should be displayed
*/
public function CanMoveBackward()
{
return false;
}
public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState
{
return new WizardState(WizStepSummary::class);
}
public function CanComeBack()
{
return false;
}
public function Display(SetupPage $oPage): void
{
@@ -108,6 +112,9 @@ JS);
'removed_extensions' => '[]',
'extensions_not_uninstallable' => '[]',
'copy_setup_files' => 1,
'return_button_label' => '',
'force-uninstall' => "",
'use_symbolic_links' => "",
];
$aHiddenInputs = '';
foreach ($aParams as $sParamName => $defaultValue) {
@@ -123,23 +130,43 @@ INPUT;
<<<HTML
<form id="data-feature-removal" class="ibo-setup--wizard ibo-is-hidden" method="post" action="$sApplicationUrl">
<input type="hidden" name="operation" value="AnalysisResult"/>
<input type="hidden" name="setup_token" value="$sUID"/>
<input type="hidden" name="authent" value="$sUID"/>
$aHiddenInputs
</form>
HTML
);
$sButtonLabel = $this->oWizard->GetParameter('return_button_label', '');
if ($sButtonLabel !== '') {
$sButtonLabel = utils::HtmlEntities($sButtonLabel);
$sButtonUrl = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php');
$sButtonUrl = utils::HtmlEntities($sButtonUrl);
$oPage->add_ready_script(
<<<JS
$('.ibo-setup--wizard--buttons-container tr td:nth-child(1)').after('<td style="text-align:center;"><button id="return-button" class="ibo-button ibo-is-alternative ibo-is-neutral ibo-is-hidden" type="button" onclick="window.location.href=\'$sButtonUrl\'"><span class="ibo-button--label">$sButtonLabel</span></button></td>');
JS
);
}
}
protected function AddProgressErrorScript($oPage, $aRes)
{
$oPage->add_ready_script(
<<<JS
if ($('#return-button').length > 0) {
$('#return-button').removeClass('ibo-is-hidden');
}
JS
);
if (isset($aRes['error_code']) && $aRes['error_code'] === DataAuditSequencer::DATA_AUDIT_FAILED) {
$oPage->add_ready_script(
<<<EOF
$('.ibo-setup--wizard--buttons-container tr td:nth-child(2)').before('<td style="text-align:center;"><button class="ibo-button ibo-is-alternative ibo-is-neutral" type="submit" name="operation" value="next" id="ignore_and_continue"><span class="ibo-button--label">Ignore and continue</span></button></td>');
<<<JS
$('.ibo-setup--wizard--buttons-container tr td:nth-child(2)').after('<td style="text-align:center;"><button class="ibo-button ibo-is-alternative ibo-is-neutral" type="submit" name="operation" value="next" id="ignore_and_continue"><span class="ibo-button--label">Ignore and continue</span></button></td>');
$('#ignore_and_continue').on('click', function() {
return confirm("If you skip the cleanup you won't be able to run the process later. You'll have to migrate or delete unconsistent data manually.");
});
$('.ibo-setup--wizard--buttons-container tr td:nth-child(2)').after('<td style="text-align:center;"><span id="submit-wait" class="ibo-spinner ibo-is-inline ibo-is-hidden ibo-spinner ibo-block" data-role="ibo-spinner"><i class="ibo-spinner--icon fas fa-sync-alt fa-spin" aria-hidden="true"></i></span>&nbsp;<button id="goto-data-feature-removal" class="default ibo-button ibo-is-regular ibo-is-primary" type="button"><span class="ibo-button--label">Cleanup my data</span></button></td>');
$('.ibo-setup--wizard--buttons-container tr td:nth-child(3)').after('<td style="text-align:center;"><span id="submit-wait" class="ibo-spinner ibo-is-inline ibo-is-hidden ibo-spinner ibo-block" data-role="ibo-spinner"><i class="ibo-spinner--icon fas fa-sync-alt fa-spin" aria-hidden="true"></i></span>&nbsp;<button id="goto-data-feature-removal" class="default ibo-button ibo-is-regular ibo-is-primary" type="button"><span class="ibo-button--label">Cleanup my data</span></button></td>');
$('#goto-data-feature-removal').on("click", function() {
$('#goto-data-feature-removal').prop('disabled', true);
$('#submit-wait').removeClass("ibo-is-hidden");
@@ -148,7 +175,7 @@ HTML
$("#wiz_form").data("installation_status", "cleanup_needed");
$('#btn_next').hide();
EOF
JS
);
}
@@ -161,6 +188,10 @@ EOF
public function JSCanMoveBackward()
{
if ($this->oWizard->GetParameter('return_button_label', '') !== '') {
return 'return false;';
}
return 'return ["not started", "error", "cleanup_needed"].indexOf($("#wiz_form").data("installation_status")) !== -1;';
}
}

View File

@@ -144,6 +144,11 @@ class WizStepDone extends WizardStep
return false;
}
public function JSCanMoveBackward()
{
return 'return false;';
}
/**
* Tells whether this step of the wizard requires that the configuration file be writable
* @return bool True if the wizard will possibly need to modify the configuration at some point

View File

@@ -54,6 +54,13 @@ class WizStepInstall extends AbstractWizStepInstall
}
}
public function CanMoveBackward()
{
$sLabel = $this->oWizard->GetParameter('return_button_label', '');
SetupLog::Info(__METHOD__.": return_button_label [$sLabel]");
return $sLabel === '';
}
public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState
{
return new WizardState(WizStepDone::class);
@@ -109,6 +116,20 @@ JS);
JS);
}
public function PostFormDisplay(SetupPage $oPage)
{
$sButtonLabel = $this->oWizard->GetParameter('return_button_label', '');
SetupLog::Info(__METHOD__.": return_button_label [$sButtonLabel]");
if ($sButtonLabel !== '') {
$sButtonUrl = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php');
$oPage->add_ready_script(
<<<JS
$('.ibo-setup--wizard--buttons-container tr td:nth-child(1)').after('<td style="text-align:center;"><button id="return-button" class="ibo-button ibo-is-alternative ibo-is-neutral ibo-is-hidden" type="button" onclick="window.location.href=\'$sButtonUrl\'"><span class="ibo-button--label">$sButtonLabel</span></button></td>');
JS
);
}
}
/**
* @throws \Exception
*/
@@ -125,27 +146,25 @@ JS);
// Tell the web page to move the progress bar and to launch the next step
$sMessage = addslashes(utils::EscapeHtml($aRes['next-step-label']));
$oPage->add_ready_script(
<<<EOF
$("#wiz_form").data("installation_status", "running");
WizardUpdateButtons();
$('#setup_msg').html('$sMessage');
$('#progress').progression( {Current:{$aRes['percentage-completed']}, Maximum: 100} );
//$("#percentage").html('{$aRes['percentage-completed']} % completed<br/>{$aRes['next-step-label']}');
ExecuteStep('{$aRes['next-step']}');
EOF
<<<JS
$("#wiz_form").data("installation_status", "running");
WizardUpdateButtons();
$('#setup_msg').html('$sMessage');
$('#progress').progression( {Current:{$aRes['percentage-completed']}, Maximum: 100} );
//$("#percentage").html('{$aRes['percentage-completed']} % completed<br/>{$aRes['next-step-label']}');
ExecuteStep('{$aRes['next-step']}');
JS
);
static::AddPrevStepSuccessMessage($oPage, $aRes['prev-step-success-message']);
} elseif ($aRes['status'] !== StepSequencer::ERROR) {
// Installation complete, move to the next step of the wizard
$oPage->add_ready_script(
<<<EOF
$("#wiz_form").data("installation_status", "completed");
$('#progress').progression( {Current:100, Maximum: 100} );
WizardUpdateButtons();
$("#btn_next").off("click.install");
$("#btn_next").trigger('click');
EOF
<<<JS
$('#progress').progression( {Current:100, Maximum: 100} );
$("#wiz_form").data("installation_status", "completed");
$("#btn_next").trigger('click');
JS
);
static::AddPrevStepSuccessMessage($oPage, $aRes['prev-step-success-message']);
} else {
@@ -153,12 +172,12 @@ EOF
$sMessage = addslashes(utils::EscapeHtml($aRes['message']));
$sMessage = str_replace("\n", '<br>', $sMessage);
$oPage->add_ready_script(
<<<EOF
$("#wiz_form").data("installation_status", "error");
$("#progress .progress").addClass('progress-error');
WizardUpdateButtons();
$('#setup_error').html('$sMessage').show();
EOF
<<<JS
$("#wiz_form").data("installation_status", "error");
$("#progress .progress").addClass('progress-error');
WizardUpdateButtons();
$('#setup_error').html('$sMessage').show();
JS
);
$this->AddProgressErrorScript($oPage, $aRes);
}
@@ -166,7 +185,13 @@ EOF
protected function AddProgressErrorScript($oPage, $aRes)
{
$oPage->add_ready_script(
<<<JS
if ($('#return-button').length > 0) {
$('#return-button').removeClass('ibo-is-hidden');
}
JS
);
}
/**

View File

@@ -21,9 +21,6 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
$oWizard->SetParameter('datamodel_version', ITOP_CORE_VERSION);
$oWizard->SetParameter('upgrade_type', 'use-compatible');
$oWizard->SaveParameter('use_symbolic_links', MFCompiler::UseSymbolicLinks());
$oWizard->SaveParameter('force-uninstall', '');
// should be done at the end
parent::__construct($oWizard, $sCurrentState, false);
}
@@ -84,7 +81,7 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
return 'Next';
}
public function CanComeBack()
public function CanMoveBackward()
{
return false;
}

View File

@@ -57,6 +57,14 @@ class WizStepSummary extends AbstractWizStepInstall
}
}
public function CanMoveBackward()
{
$sLabel = $this->oWizard->GetParameter('return_button_label', '');
SetupLog::Info(__METHOD__.": return_button_label [$sLabel]");
return $sLabel === '';
}
public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState
{
$this->oWizard->SaveParameter('db_backup', false);
@@ -242,6 +250,19 @@ JS
);
}
public function PostFormDisplay(SetupPage $oPage)
{
$sButtonLabel = $this->oWizard->GetParameter('return_button_label', '');
if ($sButtonLabel !== '') {
$sButtonUrl = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php');
$oPage->add_ready_script(
<<<JS
$('.ibo-setup--wizard--buttons-container tr td:nth-child(1)').after('<td style="text-align:center;"><button id="return-button" class="ibo-button ibo-is-alternative ibo-is-neutral" type="button" onclick="window.location.href=\'$sButtonUrl\'"><span class="ibo-button--label">$sButtonLabel</span></button></td>');
JS
);
}
}
/**
* Tells whether the "Next" button should be enabled interactively
* @return string A piece of javascript code returning either true or false
@@ -257,7 +278,11 @@ JS
*/
public function JSCanMoveBackward()
{
return 'return true;';
if ($this->oWizard->GetParameter('return_button_label', '') === '') {
return 'return true;';
}
return 'return false;';
}
}

View File

@@ -18,8 +18,6 @@
* You should have received a copy of the GNU Affero General Public License
*/
use Combodo\iTop\Application\WebPage\WebPage;
/**
* First step of the iTop Installation Wizard: Welcome screen, requirements
*/
@@ -98,7 +96,7 @@ EOF
$sStyle = 'style="display:none;overflow:auto;"';
$sToggleButtons = '<button type="button" id="show_details" class="ibo-button ibo-is-alternative ibo-is-neutral" onclick="$(\'#details\').toggle(); $(this).toggle(); $(\'#hide_details\').toggle();"><span class="ibo-button--icon fa fa-caret-down"></span><span class="ibo-button--label">Show details</span></button><button type="button" id="hide_details" class="ibo-button ibo-is-alternative ibo-is-neutral" style="display:none;" onclick="$(\'#details\').toggle(); $(this).toggle(); $(\'#show_details\').toggle();"><span class="ibo-button--icon fa fa-caret-up"></span><span class="ibo-button--label">Hide details</span></button>';
if (count($aErrors) > 0) {
$sStyle = 'overflow:auto;"';
$sStyle = 'style="overflow:auto;"';
$sTitle = count($aErrors).' Error(s), '.count($aWarnings).' Warning(s).';
$sH2Class = 'text-error';
} elseif (count($aWarnings) > 0) {

View File

@@ -151,15 +151,6 @@ abstract class WizardStep
return true;
}
/**
* Tells whether the user will come back to this step/state if he click on "Back"
* @return boolean True if the 'Back' button should display this step
*/
public function CanComeBack()
{
return true;
}
/**
* Tells whether the "Next" button should be enabled interactively
* @return string A piece of javascript code returning either true or false

View File

@@ -13,7 +13,6 @@ use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItemFactory;
use Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\CaseLogEntryForm\CaseLogEntryForm;
use DBObject;
use DBObjectSet;
use Dict;
@@ -39,7 +38,9 @@ class CaseLogEntryFormFactory
->AddMainActionButtons(static::PrepareCancelButton());
$oSaveButton = static::PrepareSaveButton();
$oTransitionsMenu = static::PrepareTransitionsSelectionPopoverMenu($oObject, $sCaseLogAttCode);
$oTransitionsMenu = static::PrepareTransitionsSelectionPopoverMenu($oObject, $sCaseLogAttCode, $oCaseLogEntryForm->GetId());
// Prevent popover menu from landing behind caselog editor
$oTransitionsMenu->SetContainer(PopoverMenu::ENUM_CONTAINER_BODY);
if (true === $oTransitionsMenu->HasItems()) {
$oButtonGroup = ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu($oSaveButton, $oTransitionsMenu);
$oCaseLogEntryForm->AddMainActionButtons($oButtonGroup);
@@ -69,7 +70,16 @@ class CaseLogEntryFormFactory
return $oButton;
}
protected static function PrepareTransitionsSelectionPopoverMenu(DBObject $oObject, string $sCaseLogAttCode): PopoverMenu
/**
* @param DBObject $oObject
* @param string $sCaseLogAttCode
* @param string $sCaseLogEntryFormId
* @since 3.2.3 Add mandatory $sCaseLogEntryFormId parameter
* @return PopoverMenu
* @throws \ArchivedObjectException
* @throws \CoreException
*/
protected static function PrepareTransitionsSelectionPopoverMenu(DBObject $oObject, string $sCaseLogAttCode, string $sCaseLogEntryFormId): PopoverMenu
{
$sObjClass = get_class($oObject);
@@ -77,8 +87,6 @@ class CaseLogEntryFormFactory
$sSectionId = 'send-actions';
$oMenu->AddSection($sSectionId);
$sCaseLogEntryFormDataRole = CaseLogEntryForm::BLOCK_CODE;
// Note: This code is inspired from cmdbAbstract::DisplayModifyForm(), it might be better to factorize it
$aTransitions = $oObject->EnumTransitions();
if (!isset($aExtraParams['custom_operation']) && count($aTransitions)) {
@@ -97,7 +105,7 @@ class CaseLogEntryFormFactory
CaseLogEntryForm::BLOCK_CODE.'--add-action--'.$sCaseLogAttCode.'--stimulus--'.$sStimulusCode,
Dict::Format('UI:Button:SendAnd', $aStimuli[$sStimulusCode]->GetLabel()),
<<<JS
$(this).closest('[data-role="{$sCaseLogEntryFormDataRole}"]').trigger('save_entry.caselog_entry_form.itop', {stimulus_code: '{$sStimulusCode}'});
$('#$sCaseLogEntryFormId').trigger('save_entry.caselog_entry_form.itop', {stimulus_code: '{$sStimulusCode}'});
JS
)
);

View File

@@ -16,10 +16,12 @@ use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
use Combodo\iTop\Application\WebPage\DownloadPage;
use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\JsonPage;
use Combodo\iTop\Application\WebPage\JsonPPage;
use Combodo\iTop\Controller\Notifications\NotificationsCenterController;
use Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService;
use Combodo\iTop\Service\Notification\NotificationsRepository;
use Combodo\iTop\Service\Router\Router;
use CoreException;
@@ -27,6 +29,7 @@ use DBObjectSearch;
use DBObjectSet;
use Dict;
use EventNotificationNewsroom;
use Exception;
use MetaModel;
use SecurityException;
use UserRights;
@@ -379,9 +382,10 @@ JS
$oEventBlock->SetCSSColorClass($sReadColor);
$oEventBlock->SetSubTitle($sReadLabel);
$oEventBlock->SetClassLabel('');
/** @var \ormDocument $oImage */
$oImage = $oEvent->Get('icon');
if (!$oImage->IsEmpty()) {
$sIconUrl = $oImage->GetDisplayURL(get_class($oEvent), $iEventId, 'icon');
$sIconUrl = self::GetDisplayIconUrl($iEventId, $oImage->GetSignature());
$oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER, true);
}
@@ -545,7 +549,7 @@ $sMessage
HTML;
$sIcon = $oMessage->Get('icon') !== null ?
$oMessage->Get('icon')->GetDisplayURL(EventNotificationNewsroom::class, $oMessage->GetKey(), 'icon') :
$this->GetDisplayIconUrl($oMessage->GetKey(), $oMessage->Get('icon')->GetSignature()) :
Branding::GetCompactMainLogoAbsoluteUrl();
$aMessages[] = [
'id' => $oMessage->GetKey(),
@@ -692,6 +696,35 @@ HTML;
return $oPage;
}
/**
* Display the icon of an EventNotificationNewsroom
* (copy of ajax.render.php?operation=display_document but with the bAllowAllData parameter set to true in order to bypass the data access restrictions since the icon is not a critical information)
* @return void
* @throws \ConfigException
* @throws \CoreException
*/
public function OperationViewIcon(): void
{
$sId = utils::ReadParam('id', '');
if (!empty($sId)) {
$oPage = new DownloadPage('');
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$iCacheSec = (int)utils::ReadParam('cache', 0);
$oPage->set_cache($iCacheSec);
// N°4129 - Prevent XSS attacks & other script executions
if (utils::GetConfig()->Get('security.disable_inline_documents_sandbox') === false) {
$oPage->add_header('Content-Security-Policy: sandbox;');
}
if (EventNotificationNewsroomService::DownloadIcon($oPage, $sId, UserRights::GetContactId()) === true) {
$oPage->Output();
}
}
}
/**
* @param string $sAction
*
@@ -784,4 +817,9 @@ HTML;
return $aReturnData;
}
protected function GetDisplayIconUrl(string $sId, string $sSignature): string
{
return utils::GetAbsoluteUrlAppRoot()."pages/UI.php?route=itopnewsroom.view_icon&id=$sId&s=$sSignature&cache=86400";
}
}

View File

@@ -4,8 +4,10 @@ namespace Combodo\iTop\Service\Notification\Event;
use Action;
use Combodo\iTop\Application\Branding;
use Combodo\iTop\Application\WebPage\WebPage;
use EventNotificationNewsroom;
use MetaModel;
use ormDocument;
use utils;
/**
@@ -71,4 +73,31 @@ class EventNotificationNewsroomService
return $oEvent;
}
/**
* @param \Combodo\iTop\Application\WebPage\WebPage $oPage
* @param string $sId
* @param int $iContactId
*
* @return bool Returns true if the download has been launched, false otherwise (e.g. if the event doesn't exist or doesn't belong to the current user)
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public static function DownloadIcon(WebPage $oPage, string $sId, int $iContactId): bool
{
$oEvent = MetaModel::GetObject(EventNotificationNewsroom::class, $sId, false, true);
if (($oEvent !== null) && ($oEvent->Get('contact_id') === $iContactId)) {
ormDocument::DownloadDocument(
$oPage,
EventNotificationNewsroom::class,
$sId,
'icon',
ormDocument::ENUM_CONTENT_DISPOSITION_INLINE,
bAllowAllData: true
);
return true;
}
return false;
}
}

View File

@@ -706,7 +706,9 @@ abstract class ItopTestCase extends KernelTestCase
$this->aLastCurlGetInfo = $info;
$sErrorMsg = curl_error($ch);
$iErrorCode = curl_errno($ch);
curl_close($ch);
if (PHP_VERSION_ID < 80000) {
curl_close($ch);
}
\IssueLog::Info(__METHOD__, null, ['url' => $sUrl, 'error' => $sErrorMsg, 'error_code' => $iErrorCode, 'post_fields' => $aPostFields, 'info' => $info]);

View File

@@ -306,6 +306,21 @@ class ormDocumentTest extends ItopDataTestCase
$this->assertStringNotContainsString('the object does not exist or you are not allowed to view it', $sAllowedHtml, 'Unexpected error message when rights are sufficient.');
}
/**
* @dataProvider DownloadDocumentRightsProvider
*/
public function testAllowsDownloadingDocumentWhenBypassingRightsChecksWithAllowAllData(string $sTargetClass, string $sAttCode, string $sData, string $sFileName, ?string $sHostClass)
{
$iDeniedDocumentId = $this->CreateDownloadTargetInOrg($sTargetClass, $sAttCode, $this->iOrgDifferentFromUser, $sData, $sFileName, $sHostClass);
$oPageAllowed = new CaptureWebPage();
ormDocument::DownloadDocument($oPageAllowed, $sTargetClass, $iDeniedDocumentId, $sAttCode, ormDocument::ENUM_CONTENT_DISPOSITION_INLINE, bAllowAllData: true);
$sAllowedHtml = $oPageAllowed->GetHtml();
$this->assertStringContainsString($sData, $sAllowedHtml, 'Expected file data present when bypassing rights checks.');
$this->assertStringNotContainsString("Invalid id ($iDeniedDocumentId) for class '$sTargetClass' - the object does not exist or you are not allowed to view it", $sAllowedHtml, 'Unexpected invalid id error message when bypassing rights checks.');
}
public function DownloadDocumentRightsProvider(): array
{
return [

View File

@@ -0,0 +1,35 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Module\DataFeatureRemoval\Service;
use Combodo\iTop\DataFeatureRemoval\Controller\DataFeatureRemovalController;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
/**
* @see DataFeatureController
*/
class DataFeatureControllerTest extends ItopDataTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->RequireOnceItopFile('env-production/combodo-data-feature-removal/vendor/autoload.php');
}
public function testConvertIntoSetupFormat()
{
$oController = new DataFeatureRemovalController();
$aExtensions = [
'itop-container-mgmt',
'combodo-monitoring',
];
$expected = '{"0":"itop-container-mgmt","1":"combodo-monitoring"}';
$this->assertEquals($expected, $this->InvokeNonPublicMethod(DataFeatureRemovalController::class, 'ConvertIntoSetupFormat', $oController, [ $aExtensions]));
}
}

View File

@@ -34,7 +34,9 @@ function GetLastestInstallFile(): ?string
return $sLastFilePath;
}
$aRemovedExtensions = ['itop-container-mgmt' => 'Containerization'];
$aRemovedExtensions = [
'itop-container-mgmt' => 'Containerization',
];
$sPath = GetLastestInstallFile();
if (is_null($sPath)) {
@@ -56,10 +58,12 @@ $aPostParams = [
"auth_pwd" => 'admin',
'login_mode' => 'form',
'operation' => 'AnalysisResult',
'setup_token' => $sToken,
'authent' => $sToken,
'selected_modules' => utils::HtmlEntities(json_encode($aSelectedModules)),
'selected_extensions' => utils::HtmlEntities(json_encode($aSelectedExtensions)),
'removed_extensions' => utils::HtmlEntities(json_encode($aRemovedExtensions)),
'force-uninstall' => "on",
'use_symbolic_links' => "",
];
$sHiddenPostedInput = "";

View File

@@ -285,89 +285,61 @@ SQL
}
/**
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_RequiredLanguageProvider
* @covers \ModuleInstallerAPI::LoadLocalizedData
*/
public function testLoadLocalizedData_LoadRequiredLanguageOnFirstInstall(string $sRequiredLanguage, array $aAvailableLanguages, array $aExpectedCountByLanguage): void
public function testLoadLocalizedData_LoadsOnFirstInstall(): void
{
// Given
[$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_RequiredLanguage_', $sRequiredLanguage, $aAvailableLanguages);
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_FirstInstall_', 'fr_fr');
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
$this->GivenLocalizedDataFile($sTmpDir, "fr_fr", $sOrgName);
// When no previous version, and current version higher than the first loading version
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.3.0', '3.0.0', $sPattern);
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern);
// Then data loaded
foreach ($aExpectedCountByLanguage as $sLanguage => $iExpectedCount) {
$this->AssertOrganizationCountByName($sOrgName, $sLanguage, $iExpectedCount);
}
}
public function LoadLocalizedData_RequiredLanguageProvider(): array
{
return [
'Required fr_fr and file exists' => [
'required language' => 'fr_fr',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 0, 'fr_fr' => 1],
],
'Required en_us and file exists' => [
'required language' => 'en_us',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0],
],
'Required fr_fr but fallback to en_us' => [
'required language' => 'fr_fr',
'available languages' => ['en_us'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0],
],
'Required de_de and file exists' => [
'required language' => 'de_de',
'available languages' => ['en_us', 'fr_fr', 'de_de'],
'expected counts' => ['en_us' => 0, 'fr_fr' => 0, 'de_de' => 1],
],
'Required de_de but fallback to en_us' => [
'required language' => 'de_de',
'available languages' => ['en_us', 'fr_fr'],
'expected counts' => ['en_us' => 1, 'fr_fr' => 0, 'de_de' => 0],
],
];
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 1);
}
/**
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_VersionConditionNotMetProvider
* @covers \ModuleInstallerAPI::LoadLocalizedData
*/
public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion): void
public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(): void
{
// Given
[$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us', ['en_us']);
// When version gate conditions are not met
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, $sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us');
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
// When a previous version that is lower than the first loading version, but higher or equal to the current version
ModuleInstallerAPI::LoadLocalizedData($oConfig, '3.0.0', '3.1.0', '3.0.0', $sPattern);
// Then no data loaded
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
}
public function LoadLocalizedData_VersionConditionNotMetProvider(): array
/**
* @covers \ModuleInstallerAPI::LoadLocalizedData
*/
public function testLoadLocalizedData_FallbacksToEnUsWhenLanguageFileIsMissing(): void
{
return [
'Equal versions (reinstall)' => ['3.1.0', '3.1.0', '3.0.0'],
'Downgrade attempt' => ['3.2.0', '3.1.0', '3.0.0'],
'Upgrade but first loading version already passed' => ['3.1.0', '3.2.0', '3.0.0'],
'Upgrade with boundary equality on first loading version' => ['3.0.0', '3.1.0', '3.0.0'],
'Upgrade but first loading version empty' => ['3.1.0', '3.2.0', ''],
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_Fallback_', 'fr_fr');
// Intentionally create ONLY en_us file
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
// When loading localized data in fr_fr, but only en_us file exists
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern);
];
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 0);
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
}
/**
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @covers \ModuleInstallerAPI::LoadLocalizedData
* @dataProvider LoadLocalizedData_ValidVersionFormatsProvider
*/
public function testLoadLocalizedData_AcceptsSupportedVersionFormats(string $sCurrentVersion, string $sFirstLoadingVersion): void
{
[$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_ValidVersion_', 'en_us', ['en_us']);
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_ValidVersion_', 'en_us');
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
}
@@ -376,39 +348,11 @@ SQL
{
return [
'Current version with suffix' => ['3.2-dev', '3.0.0'],
'Current version x.y.z' => ['10.12.140-Tagada34', '1.0'],
'Current version x.y.z-suffix' => ['2.3.3-beta', '2.3.3-alpha'],
'Current version x.y.z' => ['1.2.4', '1.0'],
'Current version x.y.z-suffix' => ['2.3.3-beta', '2.0.0'],
'Current version x.y.z-1' => ['1.2.4-1', '1.0.3-2'],
];
}
// Test when a file is loaded twice because of the version conditions, it doesn't create duplicates (idempotent loading)
public function testLoadLocalizedData_IdempotentLoading(): void
{
// Given
[$oConfig, $sOrgName, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_Idempotent_', 'en_us', ['en_us']);
// When LoadLocalizedData is called twice with conditions that would load the file both times
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.1.0', '3.0.0', $sPattern);
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '3.1.0', '3.2.0', '', $sPattern);
// Then no duplicate data loaded
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
}
/**
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
* @dataProvider LoadLocalizedData_InvalidParametersProvider
*/
public function testLoadLocalizedData_ThrowsOnInvalidParameters(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sPattern, string $sExpectedMessage): void
{
$oConfig = MetaModel::GetConfig();
$this->assertNotNull($oConfig);
$this->expectException(\CoreUnexpectedValue::class);
$this->expectExceptionMessage($sExpectedMessage);
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, $sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
}
public function LoadLocalizedData_InvalidParametersProvider(): array
{
@@ -444,6 +388,13 @@ SQL
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{LANGUAGE_CODE}}.xml',
'message' => "{{language_code}}",
],
'Parent directory does not exist' => [
'previous' => '',
'current' => '3.2.0',
'first' => '3.0.0',
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'missing'.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
'message' => 'parent directory',
],
];
}
@@ -452,7 +403,7 @@ SQL
*
* @return array{0: Config, 1: string, 2: string, 3: string, 4: string}
*/
private function GivenLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage, array $aAvailableLanguages = []): array
private function GivenLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage): array
{
$oConfig = MetaModel::GetConfig();
$oConfig->SetDefaultLanguage($sLanguage);
@@ -464,11 +415,7 @@ SQL
$this->aFileToClean[] = $sTmpDir;
$sPattern = $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml';
foreach ($aAvailableLanguages as $sAvailableLanguage) {
$this->GivenLocalizedDataFile($sTmpDir, $sAvailableLanguage, $sOrgName);
}
return [$oConfig, $sOrgName, $sPattern];
return [$oConfig, $sOrgName, $sTmpDir, $sPattern];
}
private function GivenLocalizedDataFile(string $sDir, string $sLang, string $sOrgName): string

View File

@@ -101,10 +101,10 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
$aExpected = [
'status' => 1,
'message' => '',
'next-step' => 'db-schema',
'next-step-label' => 'Updating database schema',
'next-step' => 'migrate-before',
'next-step-label' => 'Migrate data before database upgrade',
'prev-step-success-message' => 'Parameters logged',
'percentage-completed' => 16,
'percentage-completed' => 22,
];
$this->assertEquals($aExpected, $aRes);
}
@@ -284,7 +284,7 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
'next-step' => 'load-data',
'next-step-label' => 'Loading data',
'prev-step-success-message' => 'Post-creation data loaded',
'percentage-completed' => 50,
'percentage-completed' => 66,
];
$this->assertEquals($aExpected, $aRes);
}
@@ -306,7 +306,7 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
'next-step' => 'create-config',
'next-step-label' => 'Creating the configuration File',
'prev-step-success-message' => 'Data loaded',
'percentage-completed' => 66,
'percentage-completed' => 77,
'status' => 1,
];
$this->assertEquals($aExpected, $aRes);
@@ -330,7 +330,7 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
'next-step' => 'commit',
'next-step-label' => 'Finalize',
'prev-step-success-message' => 'Configuration file created',
'percentage-completed' => 83,
'percentage-completed' => 88,
'status' => 1,
];
$this->assertEquals($aExpected, $aRes);
@@ -439,6 +439,27 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
$this->assertEquals($expected, $this->oSequencer->GetStepNames());
}
public function testDefaultOptionalStepsWhenUsingOldParameters()
{
$aAdditionalParams = [
'optional_steps' => null,
];
$this->GivenApplicationInstallSequencer($aAdditionalParams, true);
$expected = [
'',
'log-parameters',
'migrate-before',
'db-schema',
'migrate-after',
'after-db-create',
'load-data',
'create-config',
'commit',
];
$this->assertEquals($expected, $this->oSequencer->GetStepNames());
}
public static function WithoutOneStepProvider()
{
return [
@@ -482,7 +503,10 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
public function testGetStepNamesWithOnlyMandatorySteps()
{
$this->GivenApplicationInstallSequencer([], true);
$aAdditionalParams = [
'optional_steps' => [],
];
$this->GivenApplicationInstallSequencer($aAdditionalParams, true);
$expected = [
'',
'db-schema',
@@ -497,11 +521,11 @@ class ApplicationInstallerSequencerTest extends ItopTestCase
public function testGetStepAfterWithPercent()
{
$this->GivenApplicationInstallSequencer([], true);
$this->assertEquals(['db-schema', 16], $this->oSequencer->GetStepAfterWithPercent(''));
$this->assertEquals(['after-db-create', 33], $this->oSequencer->GetStepAfterWithPercent('db-schema'));
$this->assertEquals(['load-data', 50], $this->oSequencer->GetStepAfterWithPercent('after-db-create'));
$this->assertEquals(['create-config', 66], $this->oSequencer->GetStepAfterWithPercent('load-data'));
$this->assertEquals(['commit', 83], $this->oSequencer->GetStepAfterWithPercent('create-config'));
$this->assertEquals(['log-parameters', 11], $this->oSequencer->GetStepAfterWithPercent(''));
$this->assertEquals(['migrate-after', 44], $this->oSequencer->GetStepAfterWithPercent('db-schema'));
$this->assertEquals(['load-data', 66], $this->oSequencer->GetStepAfterWithPercent('after-db-create'));
$this->assertEquals(['create-config', 77], $this->oSequencer->GetStepAfterWithPercent('load-data'));
$this->assertEquals(['commit', 88], $this->oSequencer->GetStepAfterWithPercent('create-config'));
$this->assertEquals(['', 100], $this->oSequencer->GetStepAfterWithPercent('commit'));
}

View File

@@ -290,6 +290,22 @@ class DataAuditSequencerTest extends ItopTestCase
$this->assertEquals($expected, $oSequencer->GetStepNames());
}
public function testDefaultOptionalStepsWhenUsingOldParameters()
{
$oRunTimeEnvironment = $this->createMock(\RunTimeEnvironment::class);
$oParams = $this->GivenParams();
$oParams->Set('optional_steps', null);
$oSequencer = new DataAuditSequencer($oParams, $oRunTimeEnvironment);
$expected = [
'',
'copy',
'compile',
'complete',
];
$this->assertEquals($expected, $oSequencer->GetStepNames());
}
private function GivenParams(array $aAdditionalParams = []): PHPParameters
{
$oParams = new PHPParameters();

View File

@@ -39,7 +39,9 @@ class UnattendedInstallTest extends ItopDataTestCase
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$sJson = curl_exec($ch);
curl_close($ch);
if (PHP_VERSION_ID < 80000) {
curl_close($ch);
}
return $sJson;
}
public function testCallUnattendedInstallFromHttp()

View File

@@ -0,0 +1,154 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Service\Notification\Event;
use Action;
use ActionNewsroom;
use Combodo\iTop\Application\WebPage\CaptureWebPage;
use Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use Contact;
use EventNotificationNewsroom;
use Person;
use Ticket;
use Trigger;
use TriggerOnObjectMention;
use UserRequest;
use UserRights;
class EventNotificationNewsroomServiceTest extends ItopDataTestCase
{
public const CREATE_TEST_ORG = true;
private Contact $oContact;
private Trigger $oTrigger;
private Action $oAction;
private Ticket $oTicket;
private EventNotificationNewsroom $oEvent;
protected function setUp(): void
{
parent::setUp();
/** @var Contact $oContact */
$oContact = $this->createObject(Person::class, [
'name' => 'Khalo',
'first_name' => 'Frida',
'org_id' => $this->getTestOrgId(),
]);
$this->oContact = $oContact;
/** @var Trigger $oTrigger */
$oTrigger = $this->createObject(TriggerOnObjectMention::class, [
'description' => 'Person mentioned on Ticket',
'target_class' => 'Ticket',
]);
$this->oTrigger = $oTrigger;
/** @var Action $oAction */
$oAction = $this->createObject(ActionNewsroom::class, [
'name' => 'Notification to persons mentioned in logs',
'status' => 'enabled',
'title' => '$this->friendlyname$',
'message' => 'You have been mentioned by $current_contact->friendlyname$',
'recipients' => 'SELECT Person WHERE id = :mentioned->id',
]);
$this->oAction = $oAction;
/** @var Ticket $oTicket */
$oTicket = $this->createObject(UserRequest::class, [
'org_id' => $this->getTestOrgId(),
'title' => 'Houston, got a problem',
'description' => 'Test description',
]);
$this->oTicket = $oTicket;
}
protected function tearDown(): void
{
parent::tearDown();
$this->oEvent->DBDelete();
}
public function testDownloadIsTriggeredWhenDownloaderIsNotificationRecipient(): void
{
$this->oEvent = EventNotificationNewsroomService::MakeEventFromAction(
oAction: $this->oAction,
iContactId: $this->oContact->GetKey(),
iTriggerId: $this->oTrigger->GetKey(),
sMessage: 'Test message',
sTitle: 'Test event',
sUrl: 'https://localhost/itop/pages/UI.php?operation=details&class=UserRequest&id=1',
iObjectId: $this->oTicket->GetKey(),
sObjectClass: UserRequest::class,
);
$this->oEvent->DBInsert();
$oPage = new CaptureWebPage();
$bDownloadIcon = EventNotificationNewsroomService::DownloadIcon($oPage, $this->oEvent->GetKey(), $this->oContact->GetKey());
$sHtml = $oPage->GetHtml();
$this->assertTrue($bDownloadIcon);
$this->assertNotEquals('', $sHtml);
}
public function testDownloadIsNotTriggeredWhenDownloaderIsNotNotificationRecipient(): void
{
$oContact = $this->createObject(Person::class, [
'name' => 'Doe',
'first_name' => 'John',
'org_id' => $this->getTestOrgId(),
]);
$this->oEvent = EventNotificationNewsroomService::MakeEventFromAction(
oAction: $this->oAction,
iContactId: $oContact->GetKey(),
iTriggerId: $this->oTrigger->GetKey(),
sMessage: 'Test message',
sTitle: 'Test event',
sUrl: 'https://localhost/itop/pages/UI.php?operation=details&class=UserRequest&id=1',
iObjectId: $this->oTicket->GetKey(),
sObjectClass: UserRequest::class,
);
$this->oEvent->DBInsert();
$oPage = new CaptureWebPage();
$bDownloadIcon = EventNotificationNewsroomService::DownloadIcon($oPage, $this->oEvent->GetKey(), $this->oContact->GetKey());
$sHtml = $oPage->GetHtml();
$this->assertFalse($bDownloadIcon);
$this->assertEquals('', $sHtml);
}
public function testDownloadIconIsTriggeredEvenWhenUserCannotReadIconAttribute(): void
{
// Create a user with Support Agent Profile
$sLogin = uniqid('EventNotificationNewsroomServiceTest');
$oUser = $this->CreateContactlessUser($sLogin, self::$aURP_Profiles['Support Agent'], '1234@Abcdefg');
$oUser->Set('contactid', $this->oContact->GetKey());
UserRights::Login($sLogin);
$this->oEvent = EventNotificationNewsroomService::MakeEventFromAction(
oAction: $this->oAction,
iContactId: $this->oContact->GetKey(),
iTriggerId: $this->oTrigger->GetKey(),
sMessage: 'Test message',
sTitle: 'Test event',
sUrl: 'https://localhost/itop/pages/UI.php?operation=details&class=UserRequest&id=1',
iObjectId: $this->oTicket->GetKey(),
sObjectClass: UserRequest::class,
);
$this->oEvent->DBInsert();
$iURValue = UserRights::IsActionAllowedOnAttribute(EventNotificationNewsroom::class, 'icon', UR_ACTION_READ, $this->oEvent, $oUser);
$this->assertEquals(UR_ALLOWED_NO, $iURValue);
$oPage = new CaptureWebPage();
$bDownloadIcon = EventNotificationNewsroomService::DownloadIcon($oPage, $this->oEvent->GetKey(), $this->oContact->GetKey());
$sHtml = $oPage->GetHtml();
$this->assertTrue($bDownloadIcon);
$this->assertNotEquals('', $sHtml);
$this->assertStringNotContainsString('the object does not exist or you are not allowed to view it', $sHtml);
}
}