Compare commits

...

83 Commits

Author SHA1 Message Date
Bryan
9280884c1c Merge pull request #16056 from jumpserver/dev
v4.10.8-lts
2025-09-18 16:52:13 +08:00
wangruidong
c593f91d77 fix: Account backup: when sending to the mailbox fails, the task status also shows the success problem. 2025-09-18 15:44:35 +08:00
feng
46da05652a fix: Fixed the issue where the final connection verification failed when the domain name contains . 2025-09-18 14:08:00 +08:00
feng
9249aba1a9 perf: Video player version 2025-09-18 11:03:58 +08:00
fit2bot
eca637c120 perf: Translate msg template (#16050)
* fix: Correct translation for device and user limits in django.po

* perf: Translate msg template

---------

Co-authored-by: wangruidong <940853815@qq.com>
2025-09-17 19:04:06 +08:00
feng
ddacd5fce1 fix: Ticket direct approval 2025-09-17 18:58:16 +08:00
wangruidong
3ca5c04099 fix: Add ignore_https_errors option to browser context 2025-09-17 16:30:54 +08:00
wangruidong
6603a073ec fix: Case 2025-09-17 15:32:23 +08:00
wangruidong
d745f7495a fix: Conflict 2025-09-17 15:32:23 +08:00
wangruidong
76f1667c89 perf: Restore msg template default value config 2025-09-17 15:32:23 +08:00
wangruidong
1ab1954299 fix: reset password msg error 2025-09-17 15:32:23 +08:00
wangruidong
c8335999a4 perf: Translate msg template 2025-09-17 15:32:23 +08:00
feng
5b4a67362d perf: Translate 2025-09-17 15:10:54 +08:00
fit2bot
e025073da2 fix: The number of exported data is incorrect (#16043)
Co-authored-by: wangruidong <940853815@qq.com>
2025-09-16 18:52:24 +08:00
feng
2155bc6862 perf: Migrate 2025-09-16 16:46:30 +08:00
wangruidong
953b515817 perf: Add is_alive filter to TerminalFilterSet 2025-09-16 16:30:57 +08:00
ibuler
7f7a354b2d fix: get obj error on queryset limit 2025-09-16 16:28:54 +08:00
Eric
2b2f7ea3f0 perf: add rdp true color 24 bit 2025-09-16 16:28:14 +08:00
feng
529123e1b5 perf: Translate 2025-09-16 16:15:09 +08:00
ibuler
e156ab6ad8 fix: force page limit 2025-09-16 13:48:06 +08:00
wangruidong
3c1fd134ae fix: There is something wrong with the format of the site message 2025-09-16 13:33:43 +08:00
Bai
b15f663c87 fix: AK/SK remained valid after the user expired. 2025-09-16 13:32:25 +08:00
wangruidong
93906dff0a fix: Export report pdf failed 2025-09-16 11:36:42 +08:00
Bai
307befdacd fix: login acl action reject > reviewers 500 2025-09-16 11:17:42 +08:00
feng626
dbfc4d3981 Revert "perf: User acl 500"
This reverts commit 849edd33c1.
2025-09-16 11:15:51 +08:00
feng
849edd33c1 perf: User acl 500 2025-09-16 10:50:41 +08:00
feng
37cceec8fe perf: get protocols error 500 2025-09-16 10:40:42 +08:00
feng
d2494c25cc perf: Translate 2025-09-15 19:19:01 +08:00
feng
023952582e fix: Push account failed 2025-09-15 15:32:27 +08:00
halo
863fe95100 perf: client version 2025-09-12 18:53:16 +08:00
wangruidong
4b0bdb18c9 perf: Template msg example error 2025-09-12 18:47:47 +08:00
Eric
10da053a95 perf: change applet-hosts view default limit 2025-09-12 18:43:38 +08:00
mikebofs
c40bc46520 fix: asset permission exclude accounts with -action 2025-09-12 11:16:27 +08:00
feng
a732cc614e perf: Asset user login notify 2025-09-11 14:16:00 +08:00
ibuler
bb29d519c6 perf: exclude accounts date expired 2025-09-11 11:42:44 +08:00
ibuler
b56c3a76a7 fix: user option error 2025-09-11 11:21:59 +08:00
fit2bot
ab908d24a7 perf: add i18n (#16001)
* perf: change some api view default limit

* perf: add i18n

---------

Co-authored-by: mikebofs <mikebofs@gmail.com>
2025-09-10 18:18:18 +08:00
fit2bot
79cabe1b3c feat: setting email template content (#15974)
* feat: setting email template content

* perf: tempale list

* perf: custom template render to string

* perf: content serialize valid

* perf: Custom msg template base class

* perf: Template content reset

* perf: Update templates config

* perf: Remove useless code

---------

Co-authored-by: wangruidong <940853815@qq.com>
2025-09-10 16:49:52 +08:00
feng
231b7287c1 perf: Notify info css optimization 2025-09-10 14:04:19 +08:00
feng
be7a4c0d6e perf: Create account unique message 2025-09-09 17:39:18 +08:00
feng
009da19050 perf: Change secret windows password cannot contain > ^ 2025-09-09 16:41:45 +08:00
feng
dfda6b1e08 perf: Change secret del over report 2025-09-09 15:48:03 +08:00
fit2bot
59b40578d8 fix: adhoc SQL Server 2008 (#15984)
* fix: Resolve the issue of errors occurring during automated execution with SQL Server 2008

* fix: adhoc SQL Server 2008

* perf: add todo information

---------

Co-authored-by: halo <wuyihuangw@gmail.com>
2025-09-09 14:26:42 +08:00
Eric
e5db28c014 perf: user add has_public_keys 2025-09-09 14:23:39 +08:00
Eric
6d1f26b0f8 perf: add redis cluster mode setting 2025-09-09 13:51:53 +08:00
Ewall555
2333dbbe33 fix: avoid AttributeError when default_limit is missing 2025-09-09 13:32:52 +08:00
Bryan
f31994fdcd Merge pull request #15899 from jumpserver/dev 2025-08-21 19:03:18 +08:00
Bryan
71766418bb Merge pull request #15742 from jumpserver/dev
merge: v4.10.4-lts
2025-07-17 15:12:58 +08:00
Bryan
a9399dd709 Merge pull request #15608 from jumpserver/dev
v4.10.2
2025-06-19 20:14:21 +08:00
Bryan
d0cb9e5432 Merge pull request #15412 from jumpserver/dev
v4.10.0
2025-05-15 17:11:43 +08:00
老广
558188da90 merge: dev to master
Ready to relase
2025-04-17 20:24:45 +08:00
Bryan
ad5460dab8 Merge pull request #15086 from jumpserver/dev
v4.8.0
2025-03-20 18:44:44 +08:00
Bryan
4d37dca0de Merge pull request #14901 from jumpserver/dev
v4.7.0
2025-02-20 10:21:16 +08:00
Bryan
2ca4002624 Merge pull request #14813 from jumpserver/dev
v4.6.0
2025-01-15 14:38:17 +08:00
Bryan
053d640e4c Merge pull request #14699 from jumpserver/dev
v4.5.0
2024-12-19 16:04:45 +08:00
Bryan
f3acc28ded Merge pull request #14697 from jumpserver/dev
v4.5.0
2024-12-19 15:57:11 +08:00
Bryan
25987545db Merge pull request #14511 from jumpserver/dev
v4.4.0
2024-11-21 19:00:35 +08:00
Bryan
6720ecc6e0 Merge pull request #14319 from jumpserver/dev
v4.3.0
2024-10-17 14:55:38 +08:00
老广
0b3a7bb020 Merge pull request #14203 from jumpserver/dev
merge: from dev to master
2024-09-19 19:37:19 +08:00
Bryan
56373e362b Merge pull request #13988 from jumpserver/dev
v4.1.0
2024-08-16 18:40:35 +08:00
Bryan
02fc045370 Merge pull request #13600 from jumpserver/dev
v4.0.0
2024-07-03 19:04:35 +08:00
Bryan
e4ac73896f Merge pull request #13452 from jumpserver/dev
v3.10.11-lts
2024-06-19 16:01:26 +08:00
Bryan
1518f792d6 Merge pull request #13236 from jumpserver/dev
v3.10.10-lts
2024-05-16 16:04:07 +08:00
Bai
67277dd622 fix: 修复仪表盘会话排序数量都是 1 的问题 2024-04-22 19:42:33 +08:00
Bryan
82e7f020ea Merge pull request #13094 from jumpserver/dev
v3.10.9 (dev to master)
2024-04-22 19:39:53 +08:00
Bryan
f20b9e01ab Merge pull request #13062 from jumpserver/dev
v3.10.8 dev to master
2024-04-18 18:01:20 +08:00
Bryan
8cf8a3701b Merge pull request #13059 from jumpserver/dev
v3.10.8
2024-04-18 17:16:37 +08:00
Bryan
7ba24293d1 Merge pull request #12736 from jumpserver/pr@dev@master_fix
fix: 解决冲突
2024-02-29 16:38:43 +08:00
Bai
f10114c9ed fix: 解决冲突 2024-02-29 16:37:10 +08:00
Bryan
cf31cbfb07 Merge pull request #12729 from jumpserver/dev
v3.10.4
2024-02-29 16:19:59 +08:00
wangruidong
0edad24d5d fix: 资产过期消息提示发送失败 2024-02-04 11:41:48 +08:00
ibuler
1f1c1a9157 fix: 修复定时检测用户是否活跃任务无法执行的问题 2024-01-23 09:28:38 +00:00
feng
6c9d271ae1 fix: redis 密码有特殊字符celery beat启动失败 2024-01-22 06:18:34 +00:00
Bai
6ff852e225 perf: 修复 Count 时没有去重的问题 2024-01-22 06:16:25 +00:00
Bryan
baa75dc735 Merge pull request #12566 from jumpserver/master
v3.10.2
2024-01-17 07:34:28 -04:00
Bryan
8a9f0436b8 Merge pull request #12565 from jumpserver/dev
v3.10.2
2024-01-17 07:23:30 -04:00
Bryan
a9620a3cbe Merge pull request #12461 from jumpserver/master
v3.10.1
2023-12-29 11:33:05 +05:00
Bryan
769e7dc8a0 Merge pull request #12460 from jumpserver/dev
v3.10.1
2023-12-29 11:20:36 +05:00
Bryan
2a70449411 Merge pull request #12458 from jumpserver/dev
v3.10.1
2023-12-29 11:01:13 +05:00
Bryan
8df720f19e Merge pull request #12401 from jumpserver/dev
v3.10
2023-12-21 15:14:19 +05:00
老广
dabbb45f6e Merge pull request #12144 from jumpserver/dev
v3.9.0
2023-11-16 18:23:05 +08:00
Bryan
ce24c1c3fd Merge pull request #11914 from jumpserver/dev
v3.8.0
2023-10-19 03:37:39 -05:00
Bryan
3c54c82ce9 Merge pull request #11636 from jumpserver/dev
v3.7.0
2023-09-21 17:02:48 +08:00
107 changed files with 20442 additions and 3022 deletions

View File

@@ -235,8 +235,8 @@ class AccountBackupHandler:
except Exception as e:
error = str(e)
print(f'\033[31m>>> {error}\033[0m')
self.execution.status = Status.error
self.execution.summary['error'] = error
self.manager.status = Status.error
self.manager.summary['error'] = error
def backup_by_obj_storage(self):
object_id = self.execution.snapshot.get('id')

View File

@@ -113,6 +113,16 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
if host.get('error'):
return host
inventory_hosts = []
if asset.type == HostTypes.WINDOWS:
if self.secret_type == SecretType.SSH_KEY:
host['error'] = _("Windows does not support SSH key authentication")
return host
new_secret = self.get_secret(account)
if '>' in new_secret or '^' in new_secret:
host['error'] = _("Windows password cannot contain special characters like > ^")
return host
host['ssh_params'] = {}
accounts = self.get_accounts(account)
@@ -130,11 +140,6 @@ class BaseChangeSecretPushManager(AccountBasePlaybookManager):
if asset.type == HostTypes.WINDOWS:
accounts = accounts.filter(secret_type=SecretType.PASSWORD)
inventory_hosts = []
if asset.type == HostTypes.WINDOWS and self.secret_type == SecretType.SSH_KEY:
print(f'Windows {asset} does not support ssh key push')
return inventory_hosts
for account in accounts:
h = deepcopy(host)
h['name'] += '(' + account.username + ')' # To distinguish different accounts

View File

@@ -5,12 +5,14 @@
tasks:
- name: Test SQLServer connection
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version
register: db_info
@@ -23,45 +25,53 @@
var: info
- name: Check whether SQLServer User exist
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "SELECT 1 from sys.sql_logins WHERE name='{{ account.username }}';"
when: db_info is succeeded
register: user_exist
- name: Change SQLServer password
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}', DEFAULT_DATABASE = {{ jms_asset.spec_info.db_name }}; select @@version"
ignore_errors: true
when: user_exist.query_results[0] | length != 0
- name: Add SQLServer user
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "CREATE LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}', DEFAULT_DATABASE = {{ jms_asset.spec_info.db_name }}; CREATE USER {{ account.username }} FOR LOGIN {{ account.username }}; select @@version"
ignore_errors: true
when: user_exist.query_results[0] | length == 0
- name: Verify password
community.general.mssql_script:
mssql_script:
login_user: "{{ account.username }}"
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version
when: check_conn_after_change

View File

@@ -9,7 +9,7 @@ from accounts.const import (
AutomationTypes, SecretStrategy, ChangeSecretRecordStatusChoice
)
from accounts.models import ChangeSecretRecord
from accounts.notifications import ChangeSecretExecutionTaskMsg, ChangeSecretReportMsg
from accounts.notifications import ChangeSecretExecutionTaskMsg
from accounts.serializers import ChangeSecretRecordBackUpSerializer
from common.utils import get_logger
from common.utils.file import encrypt_and_compress_zip_file
@@ -94,10 +94,6 @@ class ChangeSecretManager(BaseChangeSecretPushManager):
if not recipients:
return
context = self.get_report_context()
for user in recipients:
ChangeSecretReportMsg(user, context).publish()
if not records:
return

View File

@@ -5,12 +5,14 @@
tasks:
- name: Test SQLServer connection
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT
l.name,

View File

@@ -5,12 +5,14 @@
tasks:
- name: Test SQLServer connection
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version
register: db_info
@@ -23,47 +25,55 @@
var: info
- name: Check whether SQLServer User exist
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "SELECT 1 from sys.sql_logins WHERE name='{{ account.username }}';"
when: db_info is succeeded
register: user_exist
- name: Change SQLServer password
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}', DEFAULT_DATABASE = {{ jms_asset.spec_info.db_name }}; select @@version"
ignore_errors: true
when: user_exist.query_results[0] | length != 0
register: change_info
- name: Add SQLServer user
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "CREATE LOGIN [{{ account.username }}] WITH PASSWORD = '{{ account.secret }}'; CREATE USER [{{ account.username }}] FOR LOGIN [{{ account.username }}]; select @@version"
ignore_errors: true
when: user_exist.query_results[0] | length == 0
register: change_info
- name: Verify password
community.general.mssql_script:
mssql_script:
login_user: "{{ account.username }}"
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version
when: check_conn_after_change

View File

@@ -5,11 +5,13 @@
tasks:
- name: "Remove account"
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: "{{ jms_asset.spec_info.db_name }}"
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: "DROP LOGIN {{ account.username }}; select @@version"

View File

@@ -5,11 +5,13 @@
tasks:
- name: Verify account
community.general.mssql_script:
mssql_script:
login_user: "{{ account.username }}"
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version

View File

@@ -253,6 +253,8 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize
'source_id': {'required': False, 'allow_null': True},
}
fields_unimport_template = ['params']
# 手动判断唯一性校验
validators = []
@classmethod
def setup_eager_loading(cls, queryset):
@@ -263,6 +265,21 @@ class AccountSerializer(AccountCreateUpdateSerializerMixin, BaseAccountSerialize
)
return queryset
def validate(self, attrs):
instance = getattr(self, "instance", None)
if instance:
return super().validate(attrs)
field_errors = {}
for _fields in Account._meta.unique_together:
lookup = {field: attrs.get(field) for field in _fields}
if Account.objects.filter(**lookup).exists():
verbose_names = ', '.join([str(Account._meta.get_field(f).verbose_name) for f in _fields])
msg_template = _('Account already exists. Field(s): {fields} must be unique.')
field_errors[_fields[0]] = msg_template.format(fields=verbose_names)
raise serializers.ValidationError(field_errors)
return attrs
class AccountDetailSerializer(AccountSerializer):
has_secret = serializers.BooleanField(label=_("Has secret"), read_only=True)

View File

@@ -1,36 +0,0 @@
{% load i18n %}
<h3>{% trans 'Task name' %}: {{ name }}</h3>
<h3>{% trans 'Task execution id' %}: {{ execution_id }}</h3>
<p>{% trans 'Respectful' %} {{ recipient }}</p>
<p>{% trans 'Hello! The following is the failure of changing the password of your assets or pushing the account. Please check and handle it in time.' %}</p>
<table style="width: 100%; border-collapse: collapse; max-width: 100%; text-align: left; margin-top: 20px;">
<caption></caption>
<thead>
<tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Asset' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Account' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Error' %}</th>
</tr>
</thead>
<tbody>
{% for asset_name, account_username, error in asset_account_errors %}
<tr>
<td style="border: 1px solid #ddd; padding: 10px;">{{ asset_name }}</td>
<td style="border: 1px solid #ddd; padding: 10px;">{{ account_username }}</td>
<td style="border: 1px solid #ddd; padding: 10px;">
<div style="
max-width: 90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;"
title="{{ error }}"
>
{{ error }}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -1,30 +1,52 @@
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from accounts.models import Account
from acls.models import LoginACL, LoginAssetACL
from assets.models import Asset
from audits.models import UserLoginLog
from common.views.template import custom_render_to_string
from notifications.notifications import UserMessage
from users.models import User
class UserLoginReminderMsg(UserMessage):
subject = _('User login reminder')
template_name = 'acls/user_login_reminder.html'
contexts = [
{"name": "city", "label": _('Login city'), "default": "Shanghai"},
{"name": "username", "label": _('User'), "default": "john"},
{"name": "ip", "label": "IP", "default": "192.168.1.1"},
{"name": "recipient_name", "label": _("Recipient name"), "default": "John"},
{"name": "recipient_username", "label": _("Recipient username"), "default": "john"},
{"name": "user_agent", "label": _('User agent'), "default": "Mozilla/5.0"},
{"name": "acl_name", "label": _('ACL name'), "default": "login acl"},
{"name": "login_from", "label": _('Login from'), "default": "web"},
{"name": "time", "label": _('Login time'), "default": "2025-01-01 12:00:00"},
]
def __init__(self, user, user_log: UserLoginLog):
def __init__(self, user, user_log: UserLoginLog, acl: LoginACL):
self.user_log = user_log
self.acl_name = str(acl)
self.login_from = user_log.get_type_display()
now = timezone.localtime(user_log.datetime)
self.time = now.strftime('%Y-%m-%d %H:%M:%S')
super().__init__(user)
def get_html_msg(self) -> dict:
user_log = self.user_log
context = {
'ip': user_log.ip,
'time': self.time,
'city': user_log.city,
'acl_name': self.acl_name,
'login_from': self.login_from,
'username': user_log.username,
'recipient': self.user,
'recipient_name': self.user.name,
'recipient_username': self.user.username,
'user_agent': user_log.user_agent,
}
message = render_to_string('acls/user_login_reminder.html', context)
message = custom_render_to_string(self.template_name, context)
return {
'subject': str(self.subject),
@@ -40,24 +62,54 @@ class UserLoginReminderMsg(UserMessage):
class AssetLoginReminderMsg(UserMessage):
subject = _('User login alert for asset')
template_name = 'acls/asset_login_reminder.html'
contexts = [
{"name": "city", "label": _('Login city'), "default": "Shanghai"},
{"name": "username", "label": _('User'), "default": "john"},
{"name": "name", "label": _('Name'), "default": "John"},
{"name": "asset", "label": _('Asset'), "default": "dev server"},
{"name": "recipient_name", "label": _('Recipient name'), "default": "John"},
{"name": "recipient_username", "label": _('Recipient username'), "default": "john"},
{"name": "account", "label": _('Account Input username'), "default": "root"},
{"name": "account_name", "label": _('Account name'), "default": "root"},
{"name": "acl_name", "label": _('ACL name'), "default": "login acl"},
{"name": "ip", "label": "IP", "default": "192.168.1.1"},
{"name": "login_from", "label": _('Login from'), "default": "web"},
{"name": "time", "label": _('Login time'), "default": "2025-01-01 12:00:00"}
]
def __init__(self, user, asset: Asset, login_user: User, account: Account, input_username):
def __init__(
self, user, asset: Asset, login_user: User,
account: Account, acl: LoginAssetACL,
ip, input_username, login_from
):
self.ip = ip
self.asset = asset
self.login_user = login_user
self.account = account
self.acl_name = str(acl)
self.login_from = login_from
self.login_user = login_user
self.input_username = input_username
now = timezone.localtime(timezone.now())
self.time = now.strftime('%Y-%m-%d %H:%M:%S')
super().__init__(user)
def get_html_msg(self) -> dict:
context = {
'ip': self.ip,
'time': self.time,
'login_from': self.login_from,
'recipient': self.user,
'username': self.login_user.username,
'name': self.login_user.name,
'asset': str(self.asset),
'account': self.input_username,
'account_name': self.account.name,
'acl_name': self.acl_name,
}
message = render_to_string('acls/asset_login_reminder.html', context)
message = custom_render_to_string(self.template_name, context)
return {
'subject': str(self.subject),

View File

@@ -90,7 +90,7 @@ class BaseACLSerializer(ActionAclSerializer, serializers.Serializer):
fields_small = fields_mini + [
"is_active", "priority", "action",
"date_created", "date_updated",
"comment", "created_by", "org_id",
"comment", "created_by"
]
fields_m2m = ["reviewers", ]
fields = fields_small + fields_m2m
@@ -100,6 +100,20 @@ class BaseACLSerializer(ActionAclSerializer, serializers.Serializer):
'reviewers': {'label': _('Recipients')},
}
class BaseUserACLSerializer(BaseACLSerializer):
users = JSONManyToManyField(label=_('User'))
class Meta(BaseACLSerializer.Meta):
fields = BaseACLSerializer.Meta.fields + ['users']
class BaseUserAssetAccountACLSerializer(BaseUserACLSerializer):
assets = JSONManyToManyField(label=_('Asset'))
accounts = serializers.ListField(label=_('Account'))
class Meta(BaseUserACLSerializer.Meta):
fields = BaseUserACLSerializer.Meta.fields + ['assets', 'accounts', 'org_id']
def validate_reviewers(self, reviewers):
action = self.initial_data.get('action')
if not action and self.instance:
@@ -119,18 +133,3 @@ class BaseACLSerializer(ActionAclSerializer, serializers.Serializer):
)
raise serializers.ValidationError(error)
return valid_reviewers
class BaseUserACLSerializer(BaseACLSerializer):
users = JSONManyToManyField(label=_('User'))
class Meta(BaseACLSerializer.Meta):
fields = BaseACLSerializer.Meta.fields + ['users']
class BaseUserAssetAccountACLSerializer(BaseUserACLSerializer):
assets = JSONManyToManyField(label=_('Asset'))
accounts = serializers.ListField(label=_('Account'))
class Meta(BaseUserACLSerializer.Meta):
fields = BaseUserACLSerializer.Meta.fields + ['assets', 'accounts']

View File

@@ -17,7 +17,7 @@ class LoginACLSerializer(BaseUserACLSerializer, CommonBulkModelSerializer):
class Meta(BaseUserACLSerializer.Meta):
model = LoginACL
fields = list((set(BaseUserACLSerializer.Meta.fields) | {'rules'}) - {'org_id'})
fields = list((set(BaseUserACLSerializer.Meta.fields) | {'rules'}))
action_choices_exclude = [
ActionChoices.warning,
ActionChoices.notify_and_warn,

View File

@@ -1,13 +1,17 @@
{% load i18n %}
<h3>{% trans 'Dear' %}: {{ recipient.name }}[{{ recipient.username }}]</h3>
<h3>{% trans 'Dear' %}: {{ recipient_name }}[{{ recipient_username }}]</h3>
<hr>
<p>{% trans 'We would like to inform you that a user has recently logged into the following asset:' %}<p>
<p><strong>{% trans 'Asset details' %}:</strong></p>
<ul>
<li><strong>{% trans 'User' %}:</strong> [{{ name }}({{ username }})]</li>
<li><strong>IP:</strong> [{{ ip }}]</li>
<li><strong>{% trans 'Assets' %}:</strong> [{{ asset }}]</li>
<li><strong>{% trans 'Account' %}:</strong> [{{ account_name }}({{ account }})]</li>
<li><strong>{% trans 'Login asset acl' %}:</strong> [{{ acl_name }}]</li>
<li><strong>{% trans 'Login from' %}:</strong> [{{ login_from }}]</li>
<li><strong>{% trans 'Time' %}:</strong> [{{ time }}]</li>
</ul>
<hr>

View File

@@ -1,6 +1,6 @@
{% load i18n %}
<h3>{% trans 'Dear' %}: {{ recipient.name }}[{{ recipient.username }}]</h3>
<h3>{% trans 'Dear' %}: {{ recipient_name }}[{{ recipient_username }}]</h3>
<hr>
<p>{% trans 'We would like to inform you that a user has recently logged:' %}<p>
<p><strong>{% trans 'User details' %}:</strong></p>
@@ -8,7 +8,10 @@
<li><strong>{% trans 'User' %}:</strong> [{{ username }}]</li>
<li><strong>IP:</strong> [{{ ip }}]</li>
<li><strong>{% trans 'Login city' %}:</strong> [{{ city }}]</li>
<li><strong>{% trans 'Login from' %}:</strong> [{{ login_from }}]</li>
<li><strong>{% trans 'User agent' %}:</strong> [{{ user_agent }}]</li>
<li><strong>{% trans 'Login acl' %}:</strong> [{{ acl_name }}]</li>
<li><strong>{% trans 'Time' %}:</strong> [{{ time }}]</li>
</ul>
<hr>

View File

@@ -16,7 +16,6 @@ class CategoryViewSet(ListModelMixin, JMSGenericViewSet):
'types': TypeSerializer,
}
permission_classes = (IsValidUser,)
default_limit = None
def get_queryset(self):
return AllTypes.categories()

View File

@@ -14,7 +14,7 @@ class FavoriteAssetViewSet(BulkModelViewSet):
serializer_class = FavoriteAssetSerializer
permission_classes = (IsValidUser,)
filterset_fields = ['asset']
default_limit = None
page_no_limit = True
def dispatch(self, request, *args, **kwargs):
with tmp_to_root_org():

View File

@@ -43,7 +43,7 @@ class AssetPlatformViewSet(JMSModelViewSet):
'ops_methods': 'assets.view_platform',
'filter_nodes_assets': 'assets.view_platform',
}
default_limit = None
page_no_limit = True
def get_queryset(self):
# 因为没有走分页逻辑,所以需要这里 prefetch

View File

@@ -1,8 +1,8 @@
from rest_framework.generics import ListAPIView
from assets import serializers
from assets.const import Protocol
from common.permissions import IsValidUser
from assets.models import Protocol
__all__ = ['ProtocolListApi']

View File

@@ -6,11 +6,13 @@
tasks:
- name: Test SQLServer connection
community.general.mssql_script:
mssql_script:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: '{{ jms_asset.spec_info.db_name }}'
encryption: "{{ jms_asset.encryption | default(None) }}"
tds_version: "{{ jms_asset.tds_version | default(None) }}"
script: |
SELECT @@version

View File

@@ -250,6 +250,12 @@ class Protocol(ChoicesMixin, models.TextChoices):
'default': False,
'label': _('Auth username')
},
'enable_cluster_mode': {
'type': 'bool',
'default': False,
'label': _('Enable cluster mode'),
'help_text': _('Enable if this Redis instance is part of a cluster')
},
}
},
}

View File

@@ -116,7 +116,7 @@ def send_login_info_to_reviewers(instance: UserLoginLog | str, auth_acl_id):
reviewers = acl.reviewers.all()
for reviewer in reviewers:
UserLoginReminderMsg(reviewer, instance).publish_async()
UserLoginReminderMsg(reviewer, instance, acl).publish_async()
@receiver(post_auth_success)

View File

@@ -431,7 +431,7 @@ class ConnectionTokenViewSet(AuthFaceMixin, ExtraActionApiMixin, RootOrgViewMixi
if account.username != AliasAccount.INPUT:
data['input_username'] = ''
ticket = self._validate_acl(user, asset, account, connect_method)
ticket = self._validate_acl(user, asset, account, connect_method, protocol)
if ticket:
data['from_ticket'] = ticket
@@ -470,7 +470,7 @@ class ConnectionTokenViewSet(AuthFaceMixin, ExtraActionApiMixin, RootOrgViewMixi
after=after, object_name=object_name
)
def _validate_acl(self, user, asset, account, connect_method):
def _validate_acl(self, user, asset, account, connect_method, protocol):
from acls.models import LoginAssetACL
kwargs = {'user': user, 'asset': asset, 'account': account}
if account.username == AliasAccount.INPUT:
@@ -523,9 +523,15 @@ class ConnectionTokenViewSet(AuthFaceMixin, ExtraActionApiMixin, RootOrgViewMixi
return
self._record_operate_log(acl, asset)
os = get_request_os(self.request) if self.request else 'windows'
method = ConnectMethodUtil.get_connect_method(
connect_method, protocol=protocol, os=os
)
login_from = method['label'] if method else connect_method
for reviewer in reviewers:
AssetLoginReminderMsg(
reviewer, asset, user, account, self.input_username
reviewer, asset, user, account, acl,
ip, self.input_username, login_from
).publish_async()
def create_face_verify(self, response):

View File

@@ -136,7 +136,7 @@ class SignatureAuthentication(signature.SignatureAuthentication):
# example implementation:
try:
key = AccessKey.objects.get(id=key_id)
if not key.is_active:
if not key.is_valid:
return None, None
user, secret = key.user, str(key.secret)
after_authenticate_update_date(user, key)

View File

@@ -25,6 +25,10 @@ class AccessKey(models.Model):
date_last_used = models.DateTimeField(null=True, blank=True, verbose_name=_('Date last used'))
date_created = models.DateTimeField(auto_now_add=True)
@property
def is_valid(self):
return self.is_active and self.user.is_valid
def get_id(self):
return str(self.id)

View File

@@ -1,14 +1,24 @@
from django.template.loader import render_to_string
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy as _
from common.utils import get_logger
from common.utils.timezone import local_now_display
from common.views.template import custom_render_to_string
from notifications.notifications import UserMessage
logger = get_logger(__file__)
class DifferentCityLoginMessage(UserMessage):
subject = _('Different city login reminder')
template_name = 'authentication/_msg_different_city.html'
contexts = [
{"name": "city", "label": _('Login city'), "default": "Shanghai"},
{"name": "username", "label": _('User'), "default": "john"},
{"name": "name", "label": _('Name'), "default": "John"},
{"name": "ip", "label": "IP", "default": "192.168.1.1"},
{"name": "time", "label": _('Login Date'), "default": "2025-01-01 12:00:00"},
]
def __init__(self, user, ip, city):
self.ip = ip
self.city = city
@@ -16,18 +26,16 @@ class DifferentCityLoginMessage(UserMessage):
def get_html_msg(self) -> dict:
now = local_now_display()
subject = _('Different city login reminder')
context = dict(
subject=subject,
name=self.user.name,
username=self.user.username,
ip=self.ip,
time=now,
city=self.city,
)
message = render_to_string('authentication/_msg_different_city.html', context)
message = custom_render_to_string(self.template_name, context)
return {
'subject': subject,
'subject': str(self.subject),
'message': message
}
@@ -41,6 +49,16 @@ class DifferentCityLoginMessage(UserMessage):
class OAuthBindMessage(UserMessage):
subject = _('OAuth binding reminder')
template_name = 'authentication/_msg_oauth_bind.html'
contexts = [
{"name": "username", "label": _('User'), "default": "john"},
{"name": "name", "label": _('Name'), "default": "John"},
{"name": "ip", "label": "IP", "default": "192.168.1.1"},
{"name": "oauth_name", "label": _('OAuth name'), "default": "WeCom"},
{"name": "oauth_id", "label": _('OAuth ID'), "default": "000001"},
]
def __init__(self, user, ip, oauth_name, oauth_id):
super().__init__(user)
self.ip = ip
@@ -51,7 +69,6 @@ class OAuthBindMessage(UserMessage):
now = local_now_display()
subject = self.oauth_name + ' ' + _('binding reminder')
context = dict(
subject=subject,
name=self.user.name,
username=self.user.username,
ip=self.ip,
@@ -59,9 +76,9 @@ class OAuthBindMessage(UserMessage):
oauth_name=self.oauth_name,
oauth_id=self.oauth_id
)
message = render_to_string('authentication/_msg_oauth_bind.html', context)
message = custom_render_to_string(self.template_name, context)
return {
'subject': subject,
'subject': str(subject),
'message': message
}

View File

@@ -11,8 +11,6 @@
<b>{% trans 'Time' %}:</b> {{ time }}<br>
<b>{% trans 'IP' %}:</b> {{ ip }}
</p>
-
<p>
{% trans 'If the operation is not your own, unbind and change the password.' %}
</p>

View File

@@ -13,5 +13,5 @@
<br>
<p>
{% trans 'This link is valid for 1 hour. After it expires' %}
<a href="{{ forget_password_url }}?email={{ user.email }}">{% trans 'request new one' %}</a>
<a href="{{ forget_password_url }}?email={{ email }}">{% trans 'request new one' %}</a>
</p>

View File

@@ -5,6 +5,7 @@ from contextlib import nullcontext
from itertools import chain
from typing import Callable
from django.conf import settings
from django.db import models
from django.db.models.signals import m2m_changed
from rest_framework.request import Request
@@ -16,6 +17,7 @@ from common.drf.filters import (
IDNotFilterBackend, NotOrRelFilterBackend, LabelFilterBackend
)
from common.utils import get_logger, lazyproperty
from common.utils import is_uuid
from orgs.utils import tmp_to_org, tmp_to_root_org
from .action import RenderToJsonMixin
from .serializer import SerializerMixin
@@ -95,9 +97,33 @@ class QuerySetMixin:
request: Request
get_serializer_class: Callable
get_queryset: Callable
slug_field = 'name'
def get_queryset(self):
return super().get_queryset()
def get_object(self):
pk = self.kwargs.get(self.lookup_field)
if not pk or is_uuid(pk) or pk.isdigit():
return super().get_object()
return self.get_queryset().get(**{self.slug_field: pk})
def limit_queryset_if_no_page(self, queryset):
if self.request.query_params.get('format') in ['csv', 'xlsx']:
return queryset
action = getattr(self, 'action', None)
if action != 'list':
return queryset
# 如果分页器有设置 limit则不限制
if self.paginator and self.paginator.get_limit(self.request):
return queryset
# 如果分页器没有设置 limit则不限制
if getattr(self, 'page_no_limit', False):
return queryset
if not settings.DEFAULT_PAGE_SIZE:
return queryset
return queryset[:settings.DEFAULT_PAGE_SIZE]
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
@@ -106,6 +132,7 @@ class QuerySetMixin:
if self.action == 'metadata':
queryset = queryset.none()
queryset = self.setup_eager_loading(queryset)
queryset = self.limit_queryset_if_no_page(queryset)
return queryset
def setup_eager_loading(self, queryset, is_paginated=False):

View File

@@ -77,6 +77,7 @@ class Language(models.TextChoices):
es = 'es', 'Español'
ru = 'ru', 'Русский'
ko = 'ko', '한국어'
vi = 'vi', 'Tiếng Việt'
@classmethod
def get_code_mapper(cls):

View File

@@ -97,10 +97,7 @@ def send_mail_attachment_async(subject, message, recipient_list, attachment_list
for attachment in attachment_list:
email.attach_file(attachment)
os.remove(attachment)
try:
return email.send()
except Exception as e:
logger.error("Sending mail attachment error: {}".format(e))
@shared_task(

View File

@@ -0,0 +1,47 @@
import logging
import os
from django.conf import settings
from django.template import Context
from django.template import Engine, TemplateSyntaxError
from django.template.loader import render_to_string
from django.utils._os import safe_join
logger = logging.getLogger(__name__)
def safe_render_to_string(template_name, context=None, request=None, using=None):
with open(template_name, encoding="utf-8") as f:
template_code = f.read()
safe_engine = Engine(
debug=False,
libraries={}, # 禁用自定义 tag 库
builtins=[], # 不自动加载内置标签
)
try:
template = safe_engine.from_string(template_code)
except TemplateSyntaxError as e:
logger.error(e)
return template_code
return template.render(Context(context or {}))
def _get_data_template_path(template_name: str):
# 保存到 data/template/<原路径>.html
# 例如 template_name users/_msg_x.html -> data/template/users/_msg_x.html
rel_path = template_name.replace('/', os.sep)
return safe_join(settings.DATA_DIR, 'template', rel_path)
def _get_edit_template_path(template_name: str):
return _get_data_template_path(template_name) + '.edit'
def custom_render_to_string(template_name, context=None, request=None, using=None):
# 如果自定的义模板存在,则使用自定义模板,否则使用系统模板
custom_template = _get_data_template_path(template_name)
if os.path.exists(custom_template):
template = safe_render_to_string(custom_template, context=context, request=request, using=using)
else:
template = render_to_string(template_name, context=context, request=request, using=using)
return template

View File

@@ -16,6 +16,7 @@ class BaseTranslateManager:
'es': 'Spanish',
'ru': 'Russian',
'ko': 'Korean',
'vi': 'Vietnamese',
}
def __init__(self, dir_path, oai_trans_instance):

85
apps/i18n/chen/vi.json Normal file
View File

@@ -0,0 +1,85 @@
{
"ACLRejectError": "Lệnh này không được phép thực hiện",
"AffectedRows": "Trình duyệt cơ sở dữ liệu",
"AlreadyFirstPageError": "Đã là trang đầu tiên",
"AlreadyLastPageError": "Đã đến trang cuối cùng",
"Cancel": "Hủy bỏ",
"ChangeContextError": "Chuyển đổi ngữ cảnh thất bại",
"CommandReview": "Xác nhận lệnh",
"CommandReviewMessage": "Lệnh bạn nhập cần được xác nhận trước khi thực thi, có muốn gửi yêu cầu xác nhận không?",
"CommandReviewRejectBy": "Lệnh xác nhận bị %s từ chối",
"CommandReviewTimeoutError": "Thời gian xác nhận lệnh đã hết",
"CommandWarningDialogMessage": "Lệnh bạn thực hiện có nguy cơ, thông báo cảnh báo sẽ được gửi đến quản lý. Bạn có muốn tiếp tục không?< -SEP->Chạy (Ctrl + Enter)",
"Confirm": "Xác nhận",
"ConnectError": "Kết nối thất bại",
"ConnectSuccess": "Kết nối thành công",
"Connected": "Đã kết nối",
"Copy": "Sao chép",
"CopyFailed": "Sao chép thất bại",
"CopyNotAllowed": "Không được phép sao chép, hãy liên hệ với quản trị viên để mở quyền!",
"CopySucceeded": "Sao chép thành công",
"Current": "Hiện tại",
"DatabaseExplorer": "Người dùng",
"DatabaseProperties": "Thuộc tính nguồn dữ liệu",
"DownloadNotAllowed": "Không cho phép tải về, vui lòng liên hệ với quản lý để mở quyền!",
"DriverClass": "Điều khiển",
"DriverVersion": "Phiên bản lái",
"ErrorMessage": "Thông báo lỗi",
"ExecuteError": "Thực hiện thành công",
"ExecuteSuccess": "Thực hiện thành công",
"ExecutionCanceled": "Thực hiện đã bị hủy",
"ExportALL": "Xuất tất cả dữ liệu",
"ExportAll": "Xuất toàn bộ",
"ExportCurrent": "Xuất trang hiện tại",
"ExportData": "Xuất dữ liệu",
"FetchError": "Lấy dữ liệu thất bại",
"Format": "Định dạng",
"FormatHotKey": "Định dạng (Ctrl + L)",
"InitializeDatasource": "Khởi tạo nguồn dữ liệu",
"InitializeDatasourceFailed": "Khởi tạo nguồn dữ liệu thất bại",
"InitializingDatasourceMessage": "Đang khởi tạo nguồn dữ liệu, xin vui lòng chờ...",
"InsertStatement": "Câu lệnh chèn",
"JDBCURL": "JDBC URL",
"LogOutput": "Xuất nhật ký",
"Name": "Tên",
"NewQuery": "Tạo mới truy vấn",
"NoPermissionError": "Không có quyền thực hiện thao tác này",
"NumRow": "{num} dòng",
"Open": "Mở",
"OverMaxIdleTimeError": "Do phiên này quá thời gian rỗi vượt quá %d phút, đã bị đóng",
"OverMaxSessionTimeError": "Do vì cuộc trò chuyện này kéo dài hơn %d giờ, nó đã bị đóng. \nThuộc tính \nKết nối thành công \nPhiên đã kết thúc \nSao chép thất bại \nLàm mới \nSao chép thành công \nKết nối thất bại \nQuyền đã hết hạn, phiên sẽ hết hạn sau mười phút, vui lòng liên hệ với quản lý để gia hạn kịp thời \nKhông được phép dán, vui lòng liên hệ với quản lý để mở quyền! \nKhông có quyền thực hiện thao tác này \nJDBC URL \nChuyển đổi ngữ cảnh thất bại \nQuyền đã hết hạn \nChọn SQL",
"ParseError": "Phân tích thất bại",
"PasteNotAllowed": "Không cho phép dán, vui lòng liên hệ với quản trị viên để mở quyền!",
"PermissionAlreadyExpired": "Quyền đã hết hạn",
"PermissionExpiredDialogMessage": "- Quyền hạn đã hết hạn, phiên làm việc sẽ hết hạn sau mười phút, xin vui lòng liên hệ với quản lý để gia hạn.\n- Phiên làm việc đã kết thúc.\n- Không cho phép dán, xin vui lòng liên hệ với quản lý để mở quyền!\n- Thuộc tính.\n- Chuyển đổi ngữ cảnh thất bại.\n- Sao chép không thành công.\n- Kết nối thất bại.\n- Làm mới.\n- Chọn SQL.\n- Thực hiện thành công.\n- Kết nối thành công.\n- Sao chép thành công.\n- Quyền hạn đã hết hạn.\n- JDBC URL.\n- Không có quyền thực hiện thao tác này.",
"PermissionExpiredDialogTitle": "Số dòng bị ảnh hưởng",
"PermissionsExpiredOn": "Quyền liên kết với phiên này đã hết hạn vào %s",
"Properties": "Thuộc tính",
"Refresh": "Làm mới",
"Run": "Chạy",
"RunHotKey": "Quyền đã hết hạn",
"RunSelected": "Chạy đã chọn",
"Save": "Lưu",
"SaveSQL": "Lưu SQL",
"SaveSucceed": "Lưu thành công",
"Scope": "Phạm vi",
"SelectSQL": "Chọn SQL",
"SessionClosedBy": "Phiên đã bị %s đóng",
"SessionFinished": "Phiên làm việc đã kết thúc",
"SessionLockedError": "Phiên hiện tại đã bị khóa, không thể tiếp tục thực hiện lệnh",
"SessionLockedMessage": "Phiên này đã bị %s khóa, không thể tiếp tục thực hiện lệnh",
"SessionUnlockedMessage": "Phiên này đã được %s mở khóa, có thể tiếp tục thực hiện lệnh",
"ShowProperties": "Thuộc tính",
"StopHotKey": "Dừng (Ctrl + D)",
"Submit": "Gửi",
"Total": "Tổng cộng",
"Type": "Loại",
"UpdateStatement": "Câu lệnh cập nhật",
"User": "Thực hiện thất bại",
"UserCancelCommandReviewError": "Người dùng hủy lệnh duyệt lại",
"Version": "Phiên bản",
"ViewData": "Xem dữ liệu",
"WaitCommandReviewMessage": "Yêu cầu xem xét đã được gửi đi, xin vui lòng chờ kết quả xem xét.",
"Warning": "Cảnh báo",
"initializingDatasourceFailedMessage": "Kết nối thất bại, vui lòng kiểm tra cấu hình kết nối cơ sở dữ liệu có chính xác hay không."
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-24 14:25+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/js/jumpserver.js:267
msgid "Update is successful!"
msgstr "Cập nhật thành công"
#: static/js/jumpserver.js:269
msgid "An unknown error occurred while updating.."
msgstr "Đã xảy ra lỗi không xác định khi cập nhật"
#: static/js/jumpserver.js:342
msgid "Not found"
msgstr "Không tìm thấy"
#: static/js/jumpserver.js:344
msgid "Server error"
msgstr "Lỗi máy chủ"
#: static/js/jumpserver.js:346 static/js/jumpserver.js:384
#: static/js/jumpserver.js:386
msgid "Error"
msgstr "Lỗi"
#: static/js/jumpserver.js:352 static/js/jumpserver.js:393
msgid "Delete the success"
msgstr "Xóa thành công"
#: static/js/jumpserver.js:359
msgid "Are you sure about deleting it?"
msgstr "Bạn có chắc chắn muốn xóa không?"
#: static/js/jumpserver.js:363 static/js/jumpserver.js:404
msgid "Cancel"
msgstr "Hủy"
#: static/js/jumpserver.js:365 static/js/jumpserver.js:406
msgid "Confirm"
msgstr "Xác nhận"
#: static/js/jumpserver.js:384
msgid ""
"The organization contains undeleted information. Please try again after deleting"
msgstr "Tổ chức còn chứa thông tin chưa được xóa, vui lòng xóa rồi thử lại"
#: static/js/jumpserver.js:386
msgid ""
"Do not perform this operation under this organization. Try again after switching to another organization"
msgstr "Đừng thực hiện thao tác này trong tổ chức hiện tại, hãy chuyển sang tổ chức khác rồi thử lại"
#: static/js/jumpserver.js:400
msgid ""
"Please ensure that the following information in the organization has been deleted"
msgstr "Vui lòng đảm bảo rằng các thông tin sau trong tổ chức đã được xóa"
#: static/js/jumpserver.js:401
msgid ""
"User list、User group、Asset list、Domain list、Admin user、System user、Labels、Asset permission"
msgstr "Danh sách người dùng, Nhóm người dùng, Danh sách tài sản, Danh sách miền, Người dùng đặc quyền, Người dùng hệ thống, Quản lý nhãn, Quy tắc cấp quyền tài sản"
#: static/js/jumpserver.js:650
msgid "Unknown error occur"
msgstr "Xuất hiện lỗi không xác định"
#: static/js/jumpserver.js:902
msgid "Password minimum length {N} bits"
msgstr "Mật khẩu phải có tối thiểu {N} ký tự"
#: static/js/jumpserver.js:903
msgid "Must contain capital letters"
msgstr "Phải chứa chữ cái viết hoa"
#: static/js/jumpserver.js:904
msgid "Must contain lowercase letters"
msgstr "Phải chứa chữ cái viết thường"
#: static/js/jumpserver.js:905
msgid "Must contain numeric characters"
msgstr "Phải chứa ký tự số"
#: static/js/jumpserver.js:906
msgid "Must contain special characters"
msgstr "Phải chứa ký tự đặc biệt"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -123,5 +123,108 @@
"Warning": "Warning",
"WebSocketClosed": "WebSocket closed",
"WebSocketConnectionIsClosedHelpText": "WebSocket connection is closed, please refresh the page or reconnect.",
"Writable": "Writable"
"Writable": "Writable",
"No Databases": "",
"No kubernetes": "",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "",
"Enter ID number directly login, multiple search use // + field, such as: //16": "",
"Page up: b\tPage down: n": "",
"No Assets": "",
"ID": "",
"Address": "",
"Platform": "",
"Organization": "",
"Comment": "",
"%s protocol client not installed.": "",
"Terminal does not support protocol %s, please use web terminal to access": "",
"Core API failed": "",
"ACL reject": "",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "",
"Unknown error code: %s, detail: %s": "",
"get connect token err": "",
"%s node has no assets": "",
"Welcome to use JumpServer open source fortress system": "",
"part IP, Hostname, Comment": "",
"to search login if unique": "",
"/ + IP, Hostname, Comment": "",
"to search, such as: /192.168": "",
"display the assets you have permission": "",
"display the node that you have permission": "",
"display the hosts that you have permission": "",
"display the databases that you have permission": "",
"display the kubernetes that you have permission": "",
"refresh your assets and nodes": "",
"language switch": "",
"print help": "",
"exit": "",
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "",
"Announcement: ": "",
"No Account found.": "",
"Username": "",
"Tips: Enter asset[%s] account ID": "",
"Back: B/b": "",
"Hostname": "",
"select one asset to login": "",
"not found matched username %s": "",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "",
"Tips: switch language by ID (Current session only)": "",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "",
"Invalid ID": "",
"Switch language successfully": "",
"Node: [ ID.Name(Asset amount) ]": "",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "",
"Connect idle more than %d minutes, disconnect": "",
"No account found.": "",
"Select account exceed max retry times.": "",
"No protocol found.": "",
"Protocol": "",
"Tips: Enter protocol ID": "",
"Select protocol exceed max retry times.": "",
"Refresh done": "",
"Need ACL review, continue? (y/n): ": "",
"Cancel to login asset or max 3 retry": "",
"Need ticket confirm to login, already send email to the reviewers": "",
"Ticket Reviewers: %s": "",
"Could copy website URL to notify reviewers: %s": "",
"Please waiting for the reviewers to confirm, enter q to exit. ": "",
"Unknown status": "",
"%s approved": "",
"%s rejected": "",
"Cancel confirm": "",
"Search: %s": "",
"Must be unique asset for %s": "",
"Must be unique account for %s": "",
"Must be auto login account for %s": "",
"No found asset": "",
"Create k8s client err: %s": "",
"have no permission to upload file": "",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "",
"The command '%s' requires review. Continue or not [Y/n]?": "",
"Command `%s` is forbidden": "",
"have no permission to download file": "",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "",
"Need ticket confirm to execute command, already send email to the reviewers": "",
"HandleTask does not support protocol %s, please use web terminal to access": "",
"Account <%s> and asset <%s> protocol are inconsistent.": "",
"You don't have permission login %s": "",
"You get auth token failed": "",
"Get auth password failed": "",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "",
"Switched to %s": "",
"Connect with api server failed": "",
"Start domain gateway failed %s": "",
"Manual": "",
"Dynamic": "",
"Connecting to %s@%s": "",
"Connecting to Database %s": "",
"Connecting to Kubernetes %s": "",
"Connecting to Kubernetes %s container %s": "",
"Session max time reached, disconnect": "",
"Permission has expired, disconnect": "",
"Terminated by admin %s": "",
"Authentication failed": "",
"Connection refused": "",
"i/o timeout": "",
"No route to host": "",
"network is unreachable": ""
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) Introduzca {{.GreenBoldColor}}%s{{.ColorEnd}} para %s.%s",
"%s approved": "%s Aprobado en la revisión.",
"%s node has no assets": "El nodo %s no tiene activos",
"%s protocol client not installed.": "El cliente del protocolo %s no está instalado",
"%s rejected": "Revisión rechazada",
"ACL reject": "El acceso se ha denegado en esta ocasión debido a las limitaciones de la política de control de acceso",
"Account <%s> and asset <%s> protocol are inconsistent.": "El usuario del sistema <%s> y el activo <%s> presentan un desacuerdo en el protocolo",
"ActionPerm": "Permisos de acción",
"Address": "La dirección",
"AlreadyExistsPleaseRename": "El archivo ya existe, por favor renombrar",
"Announcement: ": "Anuncio:",
"Authentication failed": "Autenticación fallida (nombre de usuario o contraseña incorrectos)",
"AvailableShortcutKey": "Atajos disponibles",
"Back": "Regresar",
"Back: B/b": "Regresar: B/b",
"Cancel": "Cancelar",
"Cancel confirm": "Cancelar revisión de inicio de sesión",
"Cancel to login asset or max 3 retry": "Cancelar la sesión del activo o alcanzar 3 intentos",
"CancelFileUpload": "Cancelar la subida del archivo",
"CaseSensitive": "Distinguir mayúsculas de minúsculas",
"Clone Connect": "Copiar ventana",
"Close All Tabs": "Cerrar todo",
"Close Current Tab": "Cerrar actual \nColor del tema \nSin dirección \nPegar \nTema \nCerrar todo \nMinuto \nUnirse a compartir \nHas sido removido de la sesión compartida \nIntroduce el nombre de usuario \nPor favor selecciona \nBuscar \nConfirmar \nCrear enlace de compartición \nSubir archivo",
"Command `%s` is forbidden": "El comando `%s` está prohibido ...",
"Comment": "Nota",
"Confirm": "Confirmar",
"ConfirmBtn": "Confirmar",
"ConfirmDelete": "¿Está seguro de que desea eliminar este archivo?",
"Connect": "Conectar",
"Connect idle more than %d minutes, disconnect": "Tiempo de inactividad excedido de %d minutos, desconectando",
"Connect with api server failed": "Fallo en la conexión con el servicio API",
"Connecting to %s@%s": "Comenzando a conectar a %s@%s",
"Connecting to Database %s": "Comenzando a conectar a la base de datos %s",
"Connecting to Kubernetes %s": "Comenzando a conectar con Kubernetes %s",
"Connecting to Kubernetes %s container %s": "Comenzando a conectar con el contenedor de Kubernetes %s en %s",
"Connection refused": "Red inalcanzable (conexión rechazada)",
"CopyLink": "Copiar enlace y código de verificación",
"CopyShareURLSuccess": "Dirección de compartición copiada con éxito",
"Core API failed": "Error en la API principal",
"Could copy website URL to notify reviewers: %s": "Dirección de auditoría copiables, notificar al auditor: %s",
"Create k8s client err: %s": "Error al crear cliente k8s: %s",
"CreateFolder": "Crear carpeta",
"CreateLink": "Crear enlace",
"CreateSuccess": "Creación exitosa",
@@ -27,10 +52,14 @@
"DownloadProgress": "Progreso de descarga",
"DownloadSuccess": "Descarga exitosa",
"Downloading": "Descargando",
"Dynamic": "Cuenta dinámica",
"EndFileTransfer": "Transferencia de archivos finalizada",
"Enter ID number directly login, multiple search use // + field, such as: //16": "Consejo: Ingrese el ID del activo para iniciar sesión directamente; para una búsqueda secundaria, use // + campo, por ejemplo: //192",
"ExceedTransferSize": "Superado el tamaño máximo de transferencia",
"Expand": "Expandir",
"ExpiredTime": "Fecha de validez",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "Este terminal no soporta las reglas de acceso facial, por favor utilice el terminal web para iniciar sesión",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "Esta terminal no soporta la autenticación por reconocimiento facial; por favor inicie sesión a través de la terminal web.",
"FailedCreateConnection": "Fallo al crear conexión",
"FileAlreadyExists": "El archivo ya existe",
"FileListError": "No se pudo obtener la información de la lista de archivos",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "La subida del archivo se ha interrumpido",
"Format": "Formato",
"General": "General",
"Get auth password failed": "Fallo al obtener el token de autenticación",
"GetFileManagerTokenTimeOut": "Tiempo de espera para obtener el token de gestión de archivos",
"GetShareUser": "Introducir nombre de usuario",
"HandleTask does not support protocol %s, please use web terminal to access": "Este terminal no es compatible con el protocolo %s, utiliza la terminal web para iniciar sesión",
"Hostname": "Nombre del host",
"Hotkeys": "Atajos",
"ID": "ID",
"InputVerifyCode": "Por favor, ingrese el código de verificación",
"Invalid ID": "ID inválido",
"JoinShare": "Unirse a la compartición",
"JoinedWithSuccess": "Se ha unido con éxito",
"KubernetesManagement": "Kubernetes gestión",
@@ -53,41 +87,69 @@
"LeftArrow": "Flecha hacia atrás",
"LinkAddr": "Dirección del enlace",
"List": "Lista",
"Manual": "Cuenta manual",
"MatchWholeWords": "Coincidencia exacta",
"Minute": "Minutos",
"Minutes": "Parte",
"Must be auto login account for %s": "Debe ser una cuenta de inicio de sesión automático %s",
"Must be unique account for %s": "Debe ser una cuenta única %s",
"Must be unique asset for %s": "debe ser un activo único %s",
"MustOneFile": "Solo se puede seleccionar un archivo",
"MustSelectOneFile": "Debe seleccionar un archivo",
"Name": "Nombre",
"Need ACL review, continue? (y/n): ": "necesita auditoría, ¿continuar? (s/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "Se necesita un comando de ticket para la revisión de la ejecución, se ha enviado un correo al revisor",
"Need ticket confirm to login, already send email to the reviewers": "Se requiere iniciar sesión mediante ticket para la revisión, correo enviado al auditor",
"NewFolder": "Nueva carpeta",
"No Account found.": "Cuenta no encontrada",
"No Assets": "No hay activos",
"No Databases": "No hay base de datos",
"No found asset": "No se encontró un activo coincidente %s",
"No kubernetes": "No hay Kubernetes",
"No protocol found.": "Sin protocolo",
"No route to host": "Conexión de red no disponible (Enrutador inalcanzable)",
"NoActiveTerminalTabFound": "No se encontró una pestaña de terminal activa",
"NoData": "Sin datos",
"NoLink": "Sin dirección",
"NoRunningTerminalFound": "No se encontró ningún terminal en ejecución",
"Node: [ ID.Name(Asset amount) ]": "Nodos: [ ID. Nombre (Cantidad de activos) ]",
"OnlineUser": "Usuarios en línea",
"OperationSuccessful": "La acción se realizó con éxito",
"Organization": "Organización",
"Owner": "Administrador",
"Page up: b\tPage down: n": "Página anterior: b Página siguiente: n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "Número de página: %d, número de filas por página: %d, número total de páginas: %d, cantidad total: %d",
"Paste": "Pegar",
"PauseSession": "Pausar esta sesión",
"PermissionDenied": "Sin permiso",
"PermissionExpired": "Los permisos han expirado",
"PermissionValid": "Permisos válidos",
"Platform": "Plataforma",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "Por favor, espere la revisión del revisor para el comando `%s`; cancele presionando CTRL+C o CTRL+D.",
"Please waiting for the reviewers to confirm, enter q to exit. ": "Esperando la revisión y confirmación del auditor, presione q y luego Enter para cancelar el inicio de sesión.",
"PleaseInput": "Por favor, ingrese.",
"PleaseInputVerifyCode": "Por favor, ingresa el código de verificación",
"PrimaryUser": "Usuario principal",
"Protocol": "Protocolo",
"ReadOnly": "Solo lectura",
"Reconnect": "Reconectar",
"Refresh": "Refrescar",
"Refresh done": "Actualización completada",
"Remove": "Eliminar",
"RemoveShareUser": "Has sido eliminado de la sesión compartida",
"RemoveUser": "Eliminar usuario",
"Rename": "Renombrar",
"ResumeSession": "Restaurar esta sesión",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "Reutilizando conexión SSH (%s@%s) [Cantidad de conexiones: %d]",
"RightArrow": "Flecha hacia adelante",
"Search": "Buscar",
"Search: %s": "Buscar: %s",
"Select account exceed max retry times.": "Se ha superado el número máximo de intentos de selección de cuenta",
"Select protocol exceed max retry times.": "Se ha superado el número máximo de intentos para seleccionar el protocolo",
"SelectAction": "Por favor selecciona",
"SelectTheme": "Por favor, selecciona un tema",
"Self": "Yo",
"Session max time reached, disconnect": "La sesión ha superado el tiempo máximo de conexión, desconectando",
"SessionDetail": "Detalles de la conversación.",
"SessionShare": "Compartir conversación",
"Settings": "Ajustes",
@@ -96,18 +158,32 @@
"ShareUser": "Compartir usuario",
"ShareUserHelpText": "No se ha seleccionado un usuario, lo que permite la entrada de todos",
"Size": "Tamaño",
"Start domain gateway failed %s": "Fallo al iniciar el gateway de la base de datos %s",
"Switch language successfully": "Cambio de idioma exitoso",
"Switched to %s": "Se ha cambiado a %s",
"Sync": "Sincronizar",
"SyncUserPreferenceFailed": "Falló la sincronización de ajustes",
"SyncUserPreferenceSuccess": "Sincronización de ajustes exitosa",
"Terminal does not support protocol %s, please use web terminal to access": "Este terminal no soporta el protocolo %s, por favor inicie sesión a través del terminal web",
"TerminalInstanceNotFound": "No se encontró una instancia de terminal para la pestaña actual.",
"TerminalInstanceNotFoundForCurrentTab": "La pestaña actual no encontró una instancia de terminal",
"The command '%s' requires review. Continue or not [Y/n]?": "El comando %s necesita ser revisado, ¿continuar? [Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "Su comando ejecutado presenta riesgos, se enviará una notificación de alerta al administrador. ¿Desea continuar? [S/N]",
"TheCurrentTerminalInstanceWasNotFound": "No se encontró la instancia de terminal actual",
"Theme": "Tema",
"ThemeColors": "Color del tema",
"ThemeConfig": "Tema",
"Ticket Reviewers: %s": "Revisor del ticket: %s",
"Tips: Enter asset[%s] account ID": "Sugerencia: Introduzca la ID de cuenta de los activos [%s]",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "Sugerencia: ingrese g+ID del nodo para mostrar los hosts bajo el nodo, por ejemplo: g1",
"Tips: Enter protocol ID": "Sugerencia: Introduzca el ID del protocolo",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "Sugerencia: si deseas configurar el idioma predeterminado, dirígete a la web en \"Configuración personal → Preferencias\"",
"Tips: switch language by ID (Current session only)": "Sugerencia: ingrese el ID para cambiar el idioma",
"Transfer": "Transmisión",
"Type": "Tipo",
"UnableToGenerateWebSocketURL": "No se puede generar la URL de WebSocket, faltan parámetros",
"Unknown error code: %s, detail: %s": "Código de error desconocido: %s, detalles: %s",
"Unknown status": "Estado desconocido",
"UpArrow": "Flecha hacia arriba",
"Upload": "Subir",
"UploadEnd": "La subida ha finalizado, por favor espera el procesamiento posterior",
@@ -117,11 +193,35 @@
"UploadTips": "Arrastra el archivo aquí, o haz clic para subir",
"UploadTitle": "Subir archivo",
"User": "Usuario",
"Username": "Nombre de usuario",
"UsingRegularExpressions": "Usar expresiones regulares",
"VerifyCode": "Código de verificación.",
"WaitFileTransfer": "Esperando que finalice la transferencia de archivos",
"Warning": "Advertencia",
"WebSocketClosed": "WebSocket cerrado",
"WebSocketConnectionIsClosedHelpText": "La conexión WebSocket se ha cerrado, por favor actualiza la página o reconéctate.",
"Writable": "Se puede escribir"
"Welcome to use JumpServer open source fortress system": "Bienvenido al sistema de bastión de código abierto JumpServer",
"Writable": "Se puede escribir",
"You don't have permission login %s": "No tiene autorización para iniciar sesión en %s",
"You get auth token failed": "Ha fallado la obtención del token de autenticación",
"display the assets you have permission": "Mostrar los activos a los que tiene acceso",
"display the databases that you have permission": "Mostrar las bases de datos a las que tiene acceso",
"display the hosts that you have permission": "Mostrar los hosts a los que tiene acceso",
"display the kubernetes that you have permission": "Mostrar los Kubernetes a los que tiene acceso",
"display the node that you have permission": "Mostrar los nodos a los que tiene acceso",
"exit": "Salir",
"get connect token err": "Error al obtener el token de conexión",
"have no permission to download file": "Sin permiso para descargar archivos",
"have no permission to upload file": "Sin permiso para subir archivos",
"i/o timeout": "Conexión de red no disponible (Tiempo de conexión agotado)",
"language switch": "Cambio de idioma",
"network is unreachable": "Conexión de red fallida (red inalcanzable)",
"not found matched username %s": "No se encontró un nombre de usuario coincide %s.",
"part IP, Hostname, Comment": "Parte de IP, nombre de host, nota",
"part IP,, Hostname, Comment": "/ + IP, nombre del host, nota",
"print help": "Mostrar ayuda",
"refresh your assets and nodes": "Actualizando la información más reciente de máquinas y nodos",
"select one asset to login": "Selecciona uno de los activos para iniciar sesión",
"to search login if unique": "Buscar inicio de sesión (si es único)",
"to search, such as: /192.168": "Buscar, por ejemplo: /192.168"
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) {{.GreenBoldColor}}%s{{.ColorEnd}} を入力して%s.%sを実行してください。",
"%s approved": "%s 承認されました",
"%s node has no assets": "%sードに資産がありません",
"%s protocol client not installed.": "%s プロトコルのクライアントがインストールされていません。",
"%s rejected": "審査拒否",
"ACL reject": "今回のログインは拒否されました。理由はアクセス制御ポリシーによる制限です",
"Account <%s> and asset <%s> protocol are inconsistent.": "システムユーザー<%s>と資産<%s>の協定が一致しません",
"ActionPerm": "操作権限",
"Address": "アドレス",
"AlreadyExistsPleaseRename": "ファイルは既に存在します。名前を変更してください",
"Announcement: ": "お知らせ:",
"Authentication failed": "認証に失敗しました(ユーザー名またはパスワードが間違っています)。",
"AvailableShortcutKey": "使用可能なショートカット",
"Back": "戻る",
"Back: B/b": "戻るB/b",
"Cancel": "キャンセル",
"Cancel confirm": "ログインの確認をキャンセル",
"Cancel to login asset or max 3 retry": "資産のログインをキャンセルするか、3回の再試行を行う。",
"CancelFileUpload": "ファイルアップロードをキャンセルする",
"CaseSensitive": "大文字と小文字を区別",
"Clone Connect": "ウィンドウをコピー",
"Close All Tabs": "すべてを閉じる",
"Close Current Tab": "現在を閉じる",
"Command `%s` is forbidden": "コマンド `%s` は禁止されています ...",
"Comment": "備考",
"Confirm": "確認",
"ConfirmBtn": "確定",
"ConfirmDelete": "このファイルを削除してもよろしいですか?",
"Connect": "接続",
"Connect idle more than %d minutes, disconnect": "アイドル時間が%d分を超えたため、接続が切断されました",
"Connect with api server failed": "APIサービスに接続に失敗しました",
"Connecting to %s@%s": "%s@%s への接続を開始中",
"Connecting to Database %s": "データベース %s への接続を開始します。",
"Connecting to Kubernetes %s": "Kubernetes %s への接続を開始します",
"Connecting to Kubernetes %s container %s": "Kubernetes %s コンテナ %s に接続を開始します",
"Connection refused": "ネットワーク接続がありません(接続が拒否されました)",
"CopyLink": "リンクと認証コードのコピー",
"CopyShareURLSuccess": "レプリケーション共有住所成功",
"Core API failed": "Core APIにエラーが発生しました",
"Could copy website URL to notify reviewers: %s": "コピー可能な監査アドレス、監査人に通知:%s",
"Create k8s client err: %s": "k8s クライアントエラーの作成:%s",
"CreateFolder": "フォルダーを作成",
"CreateLink": "リンクを作成する",
"CreateSuccess": "作成に成功しました",
@@ -27,10 +52,14 @@
"DownloadProgress": "ダウンロード進捗",
"DownloadSuccess": "ダウンロードに成功しました",
"Downloading": "ダウンロード中",
"Dynamic": "動的アカウント",
"EndFileTransfer": "ファイル転送終了",
"Enter ID number directly login, multiple search use // + field, such as: //16": "ヒント資産IDを入力して直接ログイン、二次検索には // + フィールドを使用します。例://192",
"ExceedTransferSize": "最大転送サイズを超えています",
"Expand": "展開",
"ExpiredTime": "有効期限",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "この端末は顔認証アクセスルールをサポートしていません。web端末でのログインを使用してください",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "この端末は顔認識認証をサポートしていません。ウェブ端末を使用してログインしてください。",
"FailedCreateConnection": "接続の作成に失敗しました",
"FileAlreadyExists": "ファイルは既に存在します",
"FileListError": "ファイルリスト情報の取得に失敗しました",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "ファイルアップロードが中断されました",
"Format": "フォーマット",
"General": "汎用",
"Get auth password failed": "認証トークンの取得に失敗しました",
"GetFileManagerTokenTimeOut": "ファイル管理トークンの取得がタイムアウトしました",
"GetShareUser": "ユーザー名の入力",
"HandleTask does not support protocol %s, please use web terminal to access": "この端末は %s プロトコルをサポートしていません。Web端末でログインしてください",
"Hostname": "ホスト名",
"Hotkeys": "ショートカットキー",
"ID": "ID",
"InputVerifyCode": "認証コードを入力してください",
"Invalid ID": "無効なID",
"JoinShare": "共有セッションに参加",
"JoinedWithSuccess": "正常に参加しました",
"KubernetesManagement": "Kubernetes 管理",
@@ -53,41 +87,69 @@
"LeftArrow": "戻る矢印",
"LinkAddr": "リンクのアドレス",
"List": "リスト",
"Manual": "手動アカウント",
"MatchWholeWords": "完全一致",
"Minute": "分",
"Minutes": "分",
"Must be auto login account for %s": "自動ログインアカウントである必要があります %s",
"Must be unique account for %s": "唯一のアカウントである必要があります %s",
"Must be unique asset for %s": "は一意の資産でなければなりません %s",
"MustOneFile": "ファイルを1つだけ選択できます",
"MustSelectOneFile": "ファイルを選択する必要があります",
"Name": "名前",
"Need ACL review, continue? (y/n): ": "の审核が必要です。続けますか?(y/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "実行の再確認には作業命令が必要です。審査者にメール通知が送信されました",
"Need ticket confirm to login, already send email to the reviewers": "チケットログインの再確認が必要で、監査人にメール通知が送信されました",
"NewFolder": "新しいフォルダー",
"No Account found.": "アカウントが見つかりません",
"No Assets": "資産がありません",
"No Databases": "データベースがありません",
"No found asset": "一致する資産が見つかりません %s",
"No kubernetes": "kubernetesがありません",
"No protocol found.": "プロトコルがありません。",
"No route to host": "ネットワーク不通(ルーティング不通)",
"NoActiveTerminalTabFound": "アクティブな端末タブが見つかりませんでした",
"NoData": "データがありません",
"NoLink": "住所なし",
"NoRunningTerminalFound": "実行中のターミナルが見つかりませんでした",
"Node: [ ID.Name(Asset amount) ]": "ノード:[ ID.名前(資産数) ]",
"OnlineUser": "オンラインユーザー",
"OperationSuccessful": "操作成功",
"Organization": "組織",
"Owner": "管理者",
"Page up: b\tPage down: n": "前のページb 次のページn",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "ページ番号:%d、1ページの行数%d、総ページ数%d、総数%d",
"Paste": "貼り付け",
"PauseSession": "セッションを一時停止",
"PermissionDenied": "権限がありません",
"PermissionExpired": "許可が期限切れになりました",
"PermissionValid": "権限は有効です",
"Platform": "プラットフォーム",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "レビュアーがコマンド `%s` を確認するまでお待ちください。キャンセルするには CTRL+C または CTRL+D を押してください。",
"Please waiting for the reviewers to confirm, enter q to exit. ": "審査者の確認を待っています。ログインをキャンセルするには q を押してください。",
"PleaseInput": "入力してください",
"PleaseInputVerifyCode": "验证码を入力してください",
"PrimaryUser": "主要ユーザー",
"Protocol": "プロトコル",
"ReadOnly": "読み取り専用",
"Reconnect": "再接続",
"Refresh": "リフレッシュ",
"Refresh done": "更新完了",
"Remove": "削除",
"RemoveShareUser": "あなたはすでに共有セッションから削除されました」という意味です",
"RemoveUser": "ユーザーを削除",
"Rename": "再命名",
"ResumeSession": "セッションを再開",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "SSH接続を再利用中%s@%s[接続数: %d]",
"RightArrow": "進む矢印",
"Search": "検索",
"Search: %s": "検索:%s",
"Select account exceed max retry times.": "アカウントの選択が最大リトライ回数を超えました。",
"Select protocol exceed max retry times.": "選択したプロトコルが最大リトライ回数を超えました",
"SelectAction": "選択してください",
"SelectTheme": "テーマを選択してください",
"Self": "自分",
"Session max time reached, disconnect": "セッションが最大接続時間を超え、接続が切断されました",
"SessionDetail": "会話の詳細",
"SessionShare": "会話を共有",
"Settings": "設定",
@@ -96,18 +158,32 @@
"ShareUser": "共有ユーザー",
"ShareUserHelpText": "ユーザーが選択されていません。つまり、すべての人が参加できます。",
"Size": "サイズ",
"Start domain gateway failed %s": "データベースゲートウェイの起動に失敗しました %s \n最新のマシンとード情報を刷新しています \nコマンド %s の再確認が必要です。続行しますか?[Y/N] \n検索: /192.168 \nネットワークが接続できませんネットワークに到達できません \nデータベースが存在しません \nあなたが権限を持つデータベースを表示します \n%s@%s に接続を開始しています \nあなたが権限を持つKubernetesを表示します \n更新が完了しました \nード[ ID.名称(資産数量) ] \n言語の切り替えに成功しました \nプロトコルの選択が最大再試行回数を超えました \nアイドル時間が%d分を超えたため、接続が切断されました \nヒントg+ードID を入力すると、そのノードの主機を表示します。例: g1",
"Switch language successfully": "言語の切り替えが成功しました",
"Switched to %s": "%sに切り替えました。",
"Sync": "同期",
"SyncUserPreferenceFailed": "ユーザー設定の同期に失敗しました",
"SyncUserPreferenceSuccess": "ユーザー設定の同期に成功しました",
"Terminal does not support protocol %s, please use web terminal to access": "この端末は %s プロトコルをサポートしていません。ウェブ端末を使用してログインしてください。",
"TerminalInstanceNotFound": "現在のタブのターミナルインスタンスが見つかりませんでした",
"TerminalInstanceNotFoundForCurrentTab": "現在のタブに端末インスタンスが見つかりません",
"The command '%s' requires review. Continue or not [Y/n]?": "命令 %s は再確認が必要です。続けますか?[Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "あなたが実行した命令にはリスクがあります。警告通知が管理者に送信されます。続けますか?[Y/N]",
"TheCurrentTerminalInstanceWasNotFound": "現在のターミナルインスタンスが見つかりませんでした",
"Theme": "テーマ",
"ThemeColors": "テーマカラー",
"ThemeConfig": "テーマ",
"Ticket Reviewers: %s": "チケットレビュアー:%s",
"Tips: Enter asset[%s] account ID": "提示:入力された資産[%s]のアカウントID←SEP→ページ番号%d、1ページあたりの行数%d、総ページ数%d、総数量%d←SEP→審査者の確認をお待ちしています。qを押してログインをキャンセルします。←SEP→ネットワーク通信異常接続タイムアウト←SEP→ネットワーク通信異常ルーター接続不可←SEP→APIサービスへの接続に失敗しました←SEP→ヘルプを表示←SEP→プラットフォーム←SEP→ファイルのダウンロード権限がありません←SEP→%s 承認されました",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "ヒントg+ードIDを入力すると、そのードに属するホストが表示されます。例g1",
"Tips: Enter protocol ID": "ヒントプロトコルIDを入力してください",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "ヒントデフォルト言語を設定するには、Web端の「個人設定 → お好み設定」に移動してください",
"Tips: switch language by ID (Current session only)": "ヒントIDを入力して言語を切り替え",
"Transfer": "伝送",
"Type": "タイプ",
"UnableToGenerateWebSocketURL": "WebSocket URLを生成できません。パラメータが不足しています",
"Unknown error code: %s, detail: %s": "不明なエラーコード:%s、詳細%s",
"Unknown status": "不明な状態",
"UpArrow": "上向き矢印",
"Upload": "アップロード",
"UploadEnd": "アップロードが完了しました。後の処理をお待ちください",
@@ -117,11 +193,35 @@
"UploadTips": "ファイルをここにドラッグするか、アップロードをクリックします",
"UploadTitle": "ファイルのアップロード",
"User": "ユーザー",
"Username": "ユーザー名",
"UsingRegularExpressions": "正規表現を使用",
"VerifyCode": "認証コード",
"WaitFileTransfer": "ファイル転送終了待ち",
"Warning": "警告",
"WebSocketClosed": "WebSocket 閉店",
"WebSocketConnectionIsClosedHelpText": "WebSocket接続が閉じられました。ページをリフレッシュするか、再接続してください。",
"Writable": "作成"
"Welcome to use JumpServer open source fortress system": "JumpServerオープンソースバリケードシステムへようこそ",
"Writable": "作成",
"You don't have permission login %s": "あなたは%sにログインする権限がありません",
"You get auth token failed": "認証トークンの取得に失敗しました",
"display the assets you have permission": "あなたが権限を持つ資産を表示",
"display the databases that you have permission": "あなたが権限を持っているデータベースを表示します",
"display the hosts that you have permission": "あなたが権限を持つホストを表示します。",
"display the kubernetes that you have permission": "あなたが権限を持っているKubernetesを表示します",
"display the node that you have permission": "あなたが権限を持つノードを表示",
"exit": "終了",
"get connect token err": "接続トークンの取得に失敗しました",
"have no permission to download file": "ファイルをダウンロードする権限がありません",
"have no permission to upload file": "ファイルのアップロード権限がありません。",
"i/o timeout": "ネットワークが接続できません(タイムアウト)",
"language switch": "言語切替",
"network is unreachable": "ネットワーク不通(ネットワーク到達不可)",
"not found matched username %s": "一致するユーザー名 %s が見つかりませんでした。",
"part IP, Hostname, Comment": "一部のIP、ホスト名、備考",
"part IP,, Hostname, Comment": "/ + IP、ホスト名、備考",
"print help": "ヘルプを表示します",
"refresh your assets and nodes": "最新のマシンとノード情報を更新します",
"select one asset to login": "資産のいずれかを選択してログイン",
"to search login if unique": "ログイン検索(唯一の場合)",
"to search, such as: /192.168": "検索:/192.168"
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) {{.GreenBoldColor}}%s{{.ColorEnd}}를 입력하여 %s.%s 진행",
"%s approved": "%s 검토 통과",
"%s node has no assets": "%s 노드에는 자산이 없습니다",
"%s protocol client not installed.": "%s 프로토콜의 클라이언트가 설치되어 있지 않음",
"%s rejected": "%s 심사 거부",
"ACL reject": "이번 로그인은 접근 제어 정책의 제한으로 거부되었습니다",
"Account <%s> and asset <%s> protocol are inconsistent.": "시스템 사용자<%s>와 자산<%s> 프로토콜 불일치",
"ActionPerm": "작업 권한",
"Address": "주소",
"AlreadyExistsPleaseRename": "파일이 이미 존재합니다, 이름을 변경해 주세요",
"Announcement: ": "공지사항:",
"Authentication failed": "인증 실패(사용자 이름 또는 비밀번호 오류)",
"AvailableShortcutKey": "사용 가능한 단축키",
"Back": "돌아가기",
"Back: B/b": "반환: B/b",
"Cancel": "취소",
"Cancel confirm": "로그인 검토를 취소합니다",
"Cancel to login asset or max 3 retry": "자산 로그인을 취소하거나 3회 재시도에 도달",
"CancelFileUpload": "파일 업로드 취소",
"CaseSensitive": "대소문자 구분",
"Clone Connect": "복사 창",
"Close All Tabs": "모두 닫기",
"Close Current Tab": "현재 닫기",
"Command `%s` is forbidden": "명령 `%s` 는 금지되었습니다 ...",
"Comment": "비고",
"Confirm": "확인",
"ConfirmBtn": "확인",
"ConfirmDelete": "이 파일을 삭제하시겠습니까?",
"Connect": "연결",
"Connect idle more than %d minutes, disconnect": "%d분 넘어 노는 시간, 연결 종료",
"Connect with api server failed": "API 서비스 연결 실패",
"Connecting to %s@%s": "%s@%s에 연결을 시작합니다",
"Connecting to Database %s": "데이터베이스 %s에 연결 중",
"Connecting to Kubernetes %s": "Kubernetes %s에 연결 시작",
"Connecting to Kubernetes %s container %s": "Kubernetes %s 컨테이너 %s에 연결 시작",
"Connection refused": "네트워크 연결 불가 (연결 거부)",
"CopyLink": "링크 및 인증 코드 복사",
"CopyShareURLSuccess": "공유 주소 복사 성공",
"Core API failed": "Core API에서 오류 발생",
"Could copy website URL to notify reviewers: %s": "복사 가능한 감사 주소, 감사인에게 통지: %s",
"Create k8s client err: %s": "k8s 클라이언트 오류 생성: %s",
"CreateFolder": "폴더 생성",
"CreateLink": "링크 생성",
"CreateSuccess": "생성이 성공적으로 완료되었습니다",
@@ -27,10 +52,14 @@
"DownloadProgress": "다운로드 진행 상황",
"DownloadSuccess": "다운로드 성공",
"Downloading": "다운로드 중",
"Dynamic": "동적 계정",
"EndFileTransfer": "파일 전송 종료",
"Enter ID number directly login, multiple search use // + field, such as: //16": "提示:자산 ID를 입력하여 직접 로그인하십시오. 2차 검색은 // + 필드를 사용하십시오. 예: //192",
"ExceedTransferSize": "최대 전송 크기를 초과했습니다",
"Expand": "펼치기",
"ExpiredTime": "유효 기간",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "이 단말기는 얼굴 인식 규칙을 지원하지 않으므로 웹 단말기로 로그인해 주십시오",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "해당 단말기는 얼굴 인식 인증을 지원하지 않습니다, 웹 단말기로 로그인해 주세요",
"FailedCreateConnection": "연결 생성 실패",
"FileAlreadyExists": "파일이 이미 존재합니다",
"FileListError": "파일 목록 정보 가져오기 실패",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "파일 업로드 중단",
"Format": "형식",
"General": "일반",
"Get auth password failed": "인증 토큰을 가져오는 데 실패했습니다",
"GetFileManagerTokenTimeOut": "파일 관리 토큰을 얻는 데 시간 초과",
"GetShareUser": "사용자 이름 입력",
"HandleTask does not support protocol %s, please use web terminal to access": "해당 단말기는 %s 프로토콜을 지원하지 않습니다, 웹 단말기로 로그인해 주십시오",
"Hostname": "호스트 이름",
"Hotkeys": "단축키",
"ID": "아이디",
"InputVerifyCode": "인증 코드를 입력하세요",
"Invalid ID": "유효하지 않은 ID",
"JoinShare": "공유에 가입",
"JoinedWithSuccess": "성공적으로 가입되었습니다",
"KubernetesManagement": "Kubernetes 관리",
@@ -53,41 +87,69 @@
"LeftArrow": "뒤로 화살표",
"LinkAddr": "링크 주소",
"List": "목록",
"Manual": "수동 계정",
"MatchWholeWords": "전체 단어 일치",
"Minute": "분",
"Minutes": "분",
"Must be auto login account for %s": "필수적으로 자동 로그인 계정 %s",
"Must be unique account for %s": "필수적으로 유일한 계정 %s",
"Must be unique asset for %s": "자산 %s는 반드시 고유해야 합니다",
"MustOneFile": "하나의 파일만 선택할 수 있습니다",
"MustSelectOneFile": "파일 하나를 선택해야 합니다",
"Name": "이름",
"Need ACL review, continue? (y/n): ": "검토가 필요합니다, 계속하시겠습니까?(y/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "검토를 수행하기 위해 작업 지시가 필요하며, 검토자에게 이메일 통지를 발송하였습니다",
"Need ticket confirm to login, already send email to the reviewers": "작업 요청 로그인 재검토가 필요합니다, 감사인에게 이메일이 발송되었습니다",
"NewFolder": "새 폴더 만들기",
"No Account found.": "계정이 발견되지 않음",
"No Assets": "자산이 없습니다",
"No Databases": "데이터베이스 없음",
"No found asset": "일치하는 자산을 찾을 수 없습니다 %s",
"No kubernetes": "kubernetes가 없습니다",
"No protocol found.": "프로토콜 없음",
"No route to host": "네트워크가 연결되지 않음 (라우터 연결 실패)",
"NoActiveTerminalTabFound": "활성 터미널 탭을 찾을 수 없음",
"NoData": "데이터 없음",
"NoLink": "주소 없음",
"NoRunningTerminalFound": "실행 중인 터미널을 찾을 수 없습니다",
"Node: [ ID.Name(Asset amount) ]": "노드: [ ID.이름(자산 수량) ]",
"OnlineUser": "온라인 사용자",
"OperationSuccessful": "작업 성공",
"Organization": "조직이 검토가 필요합니다. 계속하시겠습니까? (y/n): 당신이 실행한 명령은 위험이 존재합니다. 경고 알림이 관리자에게 전송됩니다. 계속하시겠습니까? [Y/N] 팁: ID를 입력하여 언어를 전환하세요. 이전 페이지: b 다음 페이지: n 시스템 사용자 <%s>와 자산 <%s>의 프로토콜이 일치하지 않습니다. 세션이 최대 연결 시간을 초과하여 연결이 끊어졌습니다. %s에 로그인할 권한이 없습니다. 계정이 발견되지 않았습니다. 자산이 없습니다. 이번 로그인은 접근 제어 정책의 제한으로 인해 거부되었습니다. 작업 명령 실행 검토가 필요하며, 검토자에게 이메일이 발송되었습니다. 해당 단말기는 얼굴 인식 규칙을 지원하지 않으므로 웹 단말기를 통해 로그인해 주세요. 로그인 검토를 취소하시겠습니까? %s로 전환되었습니다.",
"Owner": "관리자",
"Page up: b\tPage down: n": "이전 페이지: b 다음 페이지: n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "페이지 번호: %d, 매 페이지 행 수: %d, 총 페이지 수: %d, 총 수량: %d",
"Paste": "붙여넣기",
"PauseSession": "이번 대화 일시 중지",
"PermissionDenied": "권한 없음",
"PermissionExpired": "권한이 만료되었습니다",
"PermissionValid": "권한 유효",
"Platform": "플랫폼",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "검토자를 기다려 주십시오, 명령 `%s`의 검토를 위해 CTRL+C 또는 CTRL+D를 눌러 취소하십시오.",
"Please waiting for the reviewers to confirm, enter q to exit. ": "검토자가 확인할 때까지 기다립니다. q를 눌러 로그인을 취소합니다.",
"PleaseInput": "입력해 주세요.",
"PleaseInputVerifyCode": "입력한 인증 코드",
"PrimaryUser": "주 사용자",
"Protocol": "프로토콜",
"ReadOnly": "읽기 전용",
"Reconnect": "재연결",
"Refresh": "새로 고침",
"Refresh done": "새로 고침이 완료되었습니다",
"Remove": "제거",
"RemoveShareUser": "귀하가 공유 세션에서 제거되었습니다",
"RemoveUser": "사용자 제거",
"Rename": "이름 변경",
"ResumeSession": "이 세션을 복원하시겠습니까?",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "SSH 연결 재사용 ( %s@%s ) [연결 수: %d]",
"RightArrow": "앞으로 화살표",
"Search": "검색",
"Search: %s": "검색: %s",
"Select account exceed max retry times.": "계정 선택이 최대 재시도 횟수를 초과했습니다",
"Select protocol exceed max retry times.": "프로토콜 선택이 최대 재시도 횟수를 초과했습니다",
"SelectAction": "선택하십시오",
"SelectTheme": "주제를 선택하세요",
"Self": "나",
"Session max time reached, disconnect": "세션이 최대 연결 시간을 초과하여 연결이 끊겼습니다",
"SessionDetail": "대화 상세 내용",
"SessionShare": "세션 공유",
"Settings": "설정",
@@ -96,18 +158,32 @@
"ShareUser": "공유 사용자",
"ShareUserHelpText": "사용자가 선택되지 않았습니다, 모든 사람이 참여할 수 있습니다",
"Size": "크기",
"Start domain gateway failed %s": "데이터베이스 게이트웨이 시작 실패 %s \n최신 머신 및 노드 정보 새로 고침 \n명령 %s를 재검토해야 합니다. 계속하시겠습니까? [Y/N] \n검색, 예: /192.168 \n네트워크 불통 (네트워크에 도달할 수 없음) \n데이터베이스 없음 \n당신이 권한을 가진 데이터베이스 표시 \n%s@%s에 연결을 시작합니다 \n당신이 권한을 가진 Kubernetes 표시 \n새로 고침 완료 \n노드: [ ID.이름(자산 수) ] \n언어 전환 성공 \n프로토콜 선택이 최대 재시도 횟수를 초과했습니다 \n유휴 시간이 %d분을 초과하여 연결이 끊겼습니다 \n提示: g+노드ID를 입력하여 노드 아래의 호스트를 표시합니다. 예: g1",
"Switch language successfully": "언어 전환이 성공적으로 완료되었습니다",
"Switched to %s": "%s로 전환되었습니다",
"Sync": "동기화",
"SyncUserPreferenceFailed": "동기화 설정 실패",
"SyncUserPreferenceSuccess": "동기화 설정 성공",
"Terminal does not support protocol %s, please use web terminal to access": "해당 단말은 %s 프로토콜을 지원하지 않습니다. 웹 단말로 로그인하십시오",
"TerminalInstanceNotFound": "현재 탭의 터미널 인스턴스를 찾을 수 없습니다.",
"TerminalInstanceNotFoundForCurrentTab": "현재 탭에서 터미널 인스턴스를 찾을 수 없음",
"The command '%s' requires review. Continue or not [Y/n]?": "명령 %s는 재검토가 필요합니다, 계속하시겠습니까?[Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "귀하가 실행한 명령은 위험이 따릅니다, 경고 알림이 관리자에게 전송됩니다. 계속하시겠습니까?[Y/N]",
"TheCurrentTerminalInstanceWasNotFound": "현재 터미널 인스턴스를 찾을 수 없습니다.",
"Theme": "주제",
"ThemeColors": "테마 색상",
"ThemeConfig": "주제",
"Ticket Reviewers: %s": "작업 검토자: %s",
"Tips: Enter asset[%s] account ID": "提示:자산 [%s]의 계정 ID",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "提示: g+노드 ID 입력하여 노드 하위 호스트 표시, 예: g1",
"Tips: Enter protocol ID": "提示: 프로토콜 ID 입력",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "팁: 기본 언어 설정이 필요하시면 웹에서 「개인 설정 → 선호 설정」으로 가십시오",
"Tips: switch language by ID (Current session only)": "提示: ID 입력하여 언어 전환",
"Transfer": "전송",
"Type": "유형",
"UnableToGenerateWebSocketURL": "WebSocket URL을 생성할 수 없습니다, 파라미터가 부족합니다",
"Unknown error code: %s, detail: %s": "알 수 없는 오류 코드: %s, 자세한 내용: %s",
"Unknown status": "알 수 없는 상태",
"UpArrow": "위쪽 화살표",
"Upload": "업로드",
"UploadEnd": "업로드가 완료되었습니다. 후속 처리를 기다려 주십시오.",
@@ -117,11 +193,35 @@
"UploadTips": "파일을 여기로 드래그하거나 업로드를 클릭하세요",
"UploadTitle": "파일 업로드",
"User": "사용자",
"Username": "사용자 이름",
"UsingRegularExpressions": "정규 표현식 사용",
"VerifyCode": "인증 코드",
"WaitFileTransfer": "파일 전송 완료 대기",
"Warning": "경고",
"WebSocketClosed": "WebSocket이 닫혔습니다",
"WebSocketConnectionIsClosedHelpText": "WebSocket 연결이 종료되었습니다, 페이지를 새로 고치거나 다시 연결하세요.",
"Writable": "작성 가능"
"Welcome to use JumpServer open source fortress system": "JumpServer 오픈 소스 방화벽 시스템에 오신 것을 환영합니다",
"Writable": "작성 가능",
"You don't have permission login %s": "%s에 로그인할 권한이 없습니다",
"You get auth token failed": "인증 토큰을 받는 데 실패했습니다",
"display the assets you have permission": "당신이 권한을 가진 자산을 표시",
"display the databases that you have permission": "당신이 권한을 가진 데이터베이스 표시",
"display the hosts that you have permission": "귀하가 권한이 있는 호스트를 표시합니다",
"display the kubernetes that you have permission": "당신이 권한을 가진 Kubernetes 표시",
"display the node that you have permission": "당신이 권한을 가진 노드를 표시",
"exit": "로그아웃",
"get connect token err": "연결 토큰을 가져오는 데 오류가 발생했습니다. <br> %s 노드에 자산이 없습니다. <br> 인증 토큰을 가져오지 못했습니다. <br> 주소는 <br> 고유한 자산이어야 합니다: %s <br> ID: <br> %d) {{.GreenBoldColor}}%s{{.ColorEnd}}를 입력하여 %s.%s을(를) 진행하세요. <br> 자산의 로그인 취소 또는 3회 재시도를 초과했습니다. <br> 티켓 검토자: %s <br> Core API에서 오류가 발생했습니다. <br> 힌트: 프로토콜 ID를 입력하세요. <br> Kubernetes가 없습니다. <br> 검토자가 명령 `%s`를 검토할 때까지 기다리세요. 종료하려면 CTRL+C 또는 CTRL+D를 누르십시오. <br> JumpServer 오픈소스 방화벽 시스템에 오신 것을 환영합니다. <br> 이 터미널은 얼굴 인식 인증을 지원하지 않으므로 웹 터미널을 통해 로그인하시기 바랍니다.",
"have no permission to download file": "파일 다운로드 권한 없음",
"have no permission to upload file": "파일 업로드 권한이 없음",
"i/o timeout": "네트워크가 연결되지 않음 (연결 시간 초과)",
"language switch": "언어 전환",
"network is unreachable": "네트워크 연결 불가(네트워크 도달 불가)",
"not found matched username %s": "일치하는 사용자 이름 %s를 찾을 수 없습니다.",
"part IP, Hostname, Comment": "부분 IP, 호스트 이름, 메모",
"part IP,, Hostname, Comment": "/ + IP, 호스트명, 비고",
"print help": "도움말 표시",
"refresh your assets and nodes": "최신 머신 및 노드 정보 새로 고침",
"select one asset to login": "하나의 자산을 선택하여 로그인합니다",
"to search login if unique": "로그인 검색(유일한 경우)",
"to search, such as: /192.168": "검색, 예: /192.168"
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) Digite {{.GreenBoldColor}}%s{{.ColorEnd}} para %s.%s",
"%s approved": "%s Revisão aprovada.",
"%s node has no assets": "O nó %s não possui ativos",
"%s protocol client not installed.": "O cliente do protocolo %s não está instalado",
"%s rejected": "Rejeição da auditoria",
"ACL reject": "O login foi negado desta vez, devido a uma limitação da política de controle de acesso",
"Account <%s> and asset <%s> protocol are inconsistent.": "O usuário do sistema <%s> e o ativo <%s> têm um acordo inconsistente",
"ActionPerm": "Permissão de Ação",
"Address": "O endereço",
"AlreadyExistsPleaseRename": "o arquivo já existe, por favor renomeie",
"Announcement: ": "Anúncio:",
"Authentication failed": "Falha de autenticação (nome de usuário ou senha incorretos)",
"AvailableShortcutKey": "Atalhos disponíveis",
"Back": "Voltar",
"Back: B/b": "Retorno: B/b",
"Cancel": "Cancelar",
"Cancel confirm": "Cancelar revisão de login",
"Cancel to login asset or max 3 retry": "Cancela o login no ativo ou atinge 3 tentativas",
"CancelFileUpload": "Cancelar upload de arquivo",
"CaseSensitive": "Diferenciar maiúsculas de minúsculas",
"Clone Connect": "Copiar janela",
"Close All Tabs": "Fechar tudo",
"Close Current Tab": "Fechar a atual",
"Command `%s` is forbidden": "O comando `%s` está proibido ...",
"Comment": "Observações",
"Confirm": "Confirmar",
"ConfirmBtn": "Confirmar",
"ConfirmDelete": "Você tem certeza de que deseja excluir este arquivo?",
"Connect": "Conectar",
"Connect idle more than %d minutes, disconnect": "Tempo ocioso superior a %d minutos, conexão encerrada",
"Connect with api server failed": "Falha ao conectar ao serviço API",
"Connecting to %s@%s": "Iniciando conexão com %s@%s",
"Connecting to Database %s": "Iniciando a conexão com o banco de dados %s",
"Connecting to Kubernetes %s": "Iniciando conexão com Kubernetes %s",
"Connecting to Kubernetes %s container %s": "Iniciando conexão com o Kubernetes %s container %s",
"Connection refused": "Rede indisponível (conexão recusada)",
"CopyLink": "Copiar link e código",
"CopyShareURLSuccess": "Cópia de endereço compartilhado bem sucedida",
"Core API failed": "Ocorreu um erro na API Core",
"Could copy website URL to notify reviewers: %s": "Endereço de auditoria copiável, notificar auditor: %s",
"Create k8s client err: %s": "Erro ao criar cliente k8s: %s",
"CreateFolder": "criar pasta",
"CreateLink": "Criar link",
"CreateSuccess": "Criado com sucesso",
@@ -27,10 +52,14 @@
"DownloadProgress": "Progresso do download",
"DownloadSuccess": "Download bem-sucedido",
"Downloading": "Baixando",
"Dynamic": "Conta dinâmica",
"EndFileTransfer": "Transferência de arquivo concluída",
"Enter ID number directly login, multiple search use // + field, such as: //16": "Dica: insira o ID do ativo para login direto, a pesquisa secundária utiliza // + campo, como: //192",
"ExceedTransferSize": "Excede o tamanho máximo de transferência",
"Expand": "Expandir",
"ExpiredTime": "Prazo de validade",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "Este terminal não suporta regras de acesso por reconhecimento facial, por favor use o terminal web para fazer login",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "Este terminal não suporta autenticação por reconhecimento facial, por favor, utilize o terminal web para login.",
"FailedCreateConnection": "Falha ao criar conexão",
"FileAlreadyExists": "arquivo já existe",
"FileListError": "Falha ao obter informações da lista de arquivos",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "Upload de arquivo interrompido",
"Format": "Formato",
"General": "Geral",
"Get auth password failed": "Falha ao obter o token de autenticação",
"GetFileManagerTokenTimeOut": "Tempo limite na obtenção do Token de gerenciamento de arquivo",
"GetShareUser": "Digite o nome de usuário",
"HandleTask does not support protocol %s, please use web terminal to access": "Este terminal não suporta o protocolo %s, por favor utilize o terminal web para logar",
"Hostname": "Nome do host",
"Hotkeys": "Atalhos",
"ID": "ID",
"InputVerifyCode": "Por favor, insira o código de verificação",
"Invalid ID": "ID inválido",
"JoinShare": "Junte-se ao compartilhamento",
"JoinedWithSuccess": "Adicionado com sucesso",
"KubernetesManagement": "Kubernetes gerenciar",
@@ -53,41 +87,69 @@
"LeftArrow": "Seta para trás",
"LinkAddr": "Endereço do link",
"List": "Lista",
"Manual": "Conta manual",
"MatchWholeWords": "Correspondência exata",
"Minute": "minutos",
"Minutes": "minutos",
"Must be auto login account for %s": "Deve ser uma conta de login automático %s",
"Must be unique account for %s": "Deve ser uma conta única %s",
"Must be unique asset for %s": "deve ser um ativo único %s",
"MustOneFile": "Só pode escolher um arquivo",
"MustSelectOneFile": "É necessário selecionar um arquivo",
"Name": "Nome",
"Need ACL review, continue? (y/n): ": "precisa de auditoria, continuar? (s/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "A execução da ordem de revisão requer um comando, um e-mail foi enviado ao revisor",
"Need ticket confirm to login, already send email to the reviewers": "Revisão de login de serviço necessário, auditor notificado por e-mail",
"NewFolder": "Criar nova pasta",
"No Account found.": "Nenhuma conta encontrada",
"No Assets": "Nenhum ativo",
"No Databases": "Sem banco de dados",
"No found asset": "Ativo correspondente não encontrado %s",
"No kubernetes": "Não há kubernetes",
"No protocol found.": "Nenhum protocolo",
"No route to host": "Rede indisponível (roteador inoperante)",
"NoActiveTerminalTabFound": "Não foi encontrada a guia do terminal ativo",
"NoData": "Sem dados",
"NoLink": "Sem endereço",
"NoRunningTerminalFound": "Terminal em execução não encontrado",
"Node: [ ID.Name(Asset amount) ]": "Nós: [ ID.Nome(Quantidade de ativos) ]",
"OnlineUser": "Usuários online",
"OperationSuccessful": "Ação bem-sucedida",
"Organization": "Organização",
"Owner": "Administrador",
"Page up: b\tPage down: n": "Página anterior: b Próxima página: n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "Número da página: %d, linhas por página: %d, total de páginas: %d, quantidade total: %d",
"Paste": "Colar",
"PauseSession": "Pausar esta sessão",
"PermissionDenied": "Sem permissão",
"PermissionExpired": "Permissão expirada",
"PermissionValid": "Permissão válida",
"Platform": "Plataforma",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "Aguarde a revisão do revisor do comando `%s`, cancele pressionando CTRL+C ou CTRL+D.",
"Please waiting for the reviewers to confirm, enter q to exit. ": "Aguardando a confirmação de revisão do avaliador, pressione q e enter para cancelar o login.",
"PleaseInput": "Por favor, insira.",
"PleaseInputVerifyCode": "Por favor, insira o código de verificação",
"PrimaryUser": "Usuário principal",
"Protocol": "Protocolo",
"ReadOnly": "somente leitura",
"Reconnect": "Reconectar",
"Refresh": "Atualizar",
"Refresh done": "Atualização concluída",
"Remove": "Remover",
"RemoveShareUser": "Você foi removido da sessão compartilhada",
"RemoveUser": "Remover usuário",
"Rename": "Renomear",
"ResumeSession": "Restaurar esta sessão",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "Reutilizando conexão SSH (%s@%s) [Número de conexões: %d]",
"RightArrow": "Seta para frente",
"Search": "Pesquisar",
"Search: %s": "Pesquisar: %s",
"Select account exceed max retry times.": "Número de contas selecionadas excede o número máximo de tentativas",
"Select protocol exceed max retry times.": "Número máximo de tentativas de protocolo excedido",
"SelectAction": "Por favor, selecione",
"SelectTheme": "Por favor, selecione um tema",
"Self": "Eu",
"Session max time reached, disconnect": "A sessão excedeu o tempo máximo de conexão, desconectando",
"SessionDetail": "Detalhes da conversa",
"SessionShare": "Compartilhamento de conversa",
"Settings": "Configurações",
@@ -96,18 +158,32 @@
"ShareUser": "usuários de compartilhamento",
"ShareUserHelpText": "Sem usuário selecionado, permitindo que todos se juntem",
"Size": "Tamanho",
"Start domain gateway failed %s": "Falha ao iniciar o gateway do banco de dados %s",
"Switch language successfully": "Mudança de idioma bem-sucedida",
"Switched to %s": "Alterado para %s",
"Sync": "Sincronizar",
"SyncUserPreferenceFailed": "Falha na configuração de sincronização",
"SyncUserPreferenceSuccess": "Configurações sincronizadas com sucesso",
"Terminal does not support protocol %s, please use web terminal to access": "Este terminal não suporta o protocolo %s, por favor, use o terminal web para login",
"TerminalInstanceNotFound": "Não foi encontrada uma instância de terminal para a aba atual",
"TerminalInstanceNotFoundForCurrentTab": "A guia atual não encontrou a instância do terminal",
"The command '%s' requires review. Continue or not [Y/n]?": "O comando %s requer revisão, deseja continuar? [Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "O comando que você executou possui riscos, uma notificação de alerta será enviada ao administrador. Deseja continuar? [S/N]",
"TheCurrentTerminalInstanceWasNotFound": "Instância do terminal atual não encontrada",
"Theme": "Tema",
"ThemeColors": "Cor do tema",
"ThemeConfig": "Tema",
"Ticket Reviewers: %s": "Revisor do ticket: %s",
"Tips: Enter asset[%s] account ID": "Dica: Insira o ID da conta do ativo [%s]",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "Dica: Digite g+ID do nó para exibir os hosts abaixo do nó, por exemplo: g1",
"Tips: Enter protocol ID": "Dica: insira o ID do protocolo",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "Dica: para definir a língua padrão, por favor, vá para a versão web em \"Configurações pessoais → Preferências\"",
"Tips: switch language by ID (Current session only)": "Dica: digite ID para mudar de idioma",
"Transfer": "Transmissão",
"Type": "Tipo",
"UnableToGenerateWebSocketURL": "Não é possível gerar a URL do WebSocket, faltando parâmetros",
"Unknown error code: %s, detail: %s": "Código de erro desconhecido: %s, detalhes: %s",
"Unknown status": "Estado desconhecido",
"UpArrow": "Seta para cima",
"Upload": "Upload",
"UploadEnd": "O upload foi concluído, aguarde o processamento subsequente",
@@ -117,11 +193,35 @@
"UploadTips": "Arraste o arquivo para cá ou clique para fazer o upload",
"UploadTitle": "Enviar arquivo",
"User": "Usuário",
"Username": "Nome de usuário",
"UsingRegularExpressions": "Usar expressão regular",
"VerifyCode": "código de verificação",
"WaitFileTransfer": "Aguarde o fim da transferência do arquivo",
"Warning": "Aviso",
"WebSocketClosed": "WebSocket foi fechado",
"WebSocketConnectionIsClosedHelpText": "Conexão do WebSocket fechada, por favor, atualize a página ou reconecte-se.",
"Writable": "pode escrever"
"Welcome to use JumpServer open source fortress system": "Bem-vindo ao sistema de bastião de código aberto JumpServer",
"Writable": "pode escrever",
"You don't have permission login %s": "Você não tem permissão para acessar %s",
"You get auth token failed": "Falha ao obter o token de autenticação",
"display the assets you have permission": "Mostrar os ativos aos quais você tem permissão",
"display the databases that you have permission": "Mostrar os bancos de dados aos quais você tem acesso",
"display the hosts that you have permission": "Mostrar os hosts aos quais você tem acesso",
"display the kubernetes that you have permission": "Mostrar seus Kubernetes autorizados",
"display the node that you have permission": "Mostrar os nós aos quais você tem permissão",
"exit": "Sair",
"get connect token err": "Erro ao obter o token de conexão",
"have no permission to download file": "Sem permissão para baixar o arquivo",
"have no permission to upload file": "Sem permissão para enviar arquivos",
"i/o timeout": "Rede indisponível (tempo de conexão excedido)",
"language switch": "Trocar idioma",
"network is unreachable": "Rede indisponível (rede inatingível)",
"not found matched username %s": "Não foi encontrado um nome de usuário correspondente %s",
"part IP, Hostname, Comment": "Parte do IP, nome do host, observações",
"part IP,, Hostname, Comment": "/ + IP, nome do host, observações",
"print help": "Mostrar ajuda",
"refresh your assets and nodes": "Atualizando as informações mais recentes sobre máquinas e nós",
"select one asset to login": "Selecione um dos ativos para fazer o login",
"to search login if unique": "Buscar login (se único)",
"to search, such as: /192.168": "Buscar, por exemplo: /192.168"
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) Введите {{.GreenBoldColor}}%s{{.ColorEnd}} для %s.%s",
"%s approved": "%s审核通过",
"%s node has no assets": "У узла %s нет активов",
"%s protocol client not installed.": "Клиент протокола %s не установлен",
"%s rejected": "%s Проверка отклонена",
"ACL reject": "Доступ для данного логина отклонен из-за ограничений политики доступа",
"Account <%s> and asset <%s> protocol are inconsistent.": "Системный пользователь <%s> и актив < %s> не согласованы",
"ActionPerm": "Права доступа",
"Address": "Адрес",
"AlreadyExistsPleaseRename": "Создать папку",
"Announcement: ": "Объявление:",
"Authentication failed": "Ошибка аутентификации (неправильное имя пользователя или пароль)",
"AvailableShortcutKey": "Доступные горячие клавиши",
"Back": "Вернуться",
"Back: B/b": "Возврат: B/b",
"Cancel": "Отмена",
"Cancel confirm": "Отменить проверку входа",
"Cancel to login asset or max 3 retry": "Отмена входа в актив или достижение 3-х попыток",
"CancelFileUpload": "Отменить передачу файла",
"CaseSensitive": "Учитывать регистрар",
"Clone Connect": "Клонировать окно",
"Close All Tabs": "Закрыть все вкладки",
"Close Current Tab": "Закрыть эту вкладку",
"Command `%s` is forbidden": "Команда `%s` запрещена ...",
"Comment": "Примечание",
"Confirm": "Подтвердить",
"ConfirmBtn": "Подтвердить",
"ConfirmDelete": "Вы уверены, что хотите удалить этот файл?",
"Connect": "Подключение",
"Connect idle more than %d minutes, disconnect": "Время простоя превысило %d минут, соединение разорвано",
"Connect with api server failed": "Не удалось подключиться к API сервису",
"Connecting to %s@%s": "Начать подключение к %s@%s",
"Connecting to Database %s": "Начинаю подключение к базе данных %s",
"Connecting to Kubernetes %s": "Начало подключения к Kubernetes %s",
"Connecting to Kubernetes %s container %s": "Начинаю подключение к Kubernetes %s контейнеру %s",
"Connection refused": "Нет соединения (соединение отклонено)",
"CopyLink": "Скопировать ссылку и код подтверждения",
"CopyShareURLSuccess": "URL общего доступа успешно скопирован",
"Core API failed": "Произошла ошибка Core API",
"Could copy website URL to notify reviewers: %s": "Копируемый адрес для аудита, уведомите аудитора: %s",
"Create k8s client err: %s": "Ошибка создания клиента k8s: %s",
"CreateFolder": "Пользователи для分享",
"CreateLink": "Создать ссылку",
"CreateSuccess": "Успешно создано",
@@ -27,10 +52,14 @@
"DownloadProgress": "Прогресс загрузки",
"DownloadSuccess": "Успешное скачивание",
"Downloading": "Ведётся загрузка",
"Dynamic": "Динамический аккаунт",
"EndFileTransfer": "Передача файла завершена",
"Enter ID number directly login, multiple search use // + field, such as: //16": "Подсказка: вводите ID актива для прямого входа, для второго уровня поиска используйте // + поле, например: //192",
"ExceedTransferSize": "Превышен максимальный размер передачи",
"Expand": "Развернуть",
"ExpiredTime": "Срок действия",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "Данный терминал не поддерживает правила доступа по лицу, пожалуйста, войдите через веб-терминал",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "Этот терминал не поддерживает аутентификацию по распознаванию лиц, пожалуйста, выполните вход через веб-терминал.",
"FailedCreateConnection": "Ошибка создания соединения",
"FileAlreadyExists": "Только для чтения",
"FileListError": "Не удалось получить информацию о списке файлов",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "Передача файла прервана",
"Format": "Формат",
"General": "Универсальный",
"Get auth password failed": "Вы не смогли получить токен аутентификации",
"GetFileManagerTokenTimeOut": "Таймаут получения токена для управления файлами",
"GetShareUser": "Введите имя пользователя",
"HandleTask does not support protocol %s, please use web terminal to access": "Этот терминал не поддерживает %s протокол, пожалуйста, войдите через веб-терминал",
"Hostname": "Имя хоста",
"Hotkeys": "Горячие клавиши",
"ID": "ID",
"InputVerifyCode": "Введите код подтверждения",
"Invalid ID": "Недействительный ID",
"JoinShare": "Присоединиться к общей сессии",
"JoinedWithSuccess": "Успешно присоединился",
"KubernetesManagement": "Управление Kubernetes",
@@ -53,41 +87,69 @@
"LeftArrow": "Стрелка влево",
"LinkAddr": "Адрес ссылки",
"List": "Список",
"Manual": "Ручной аккаунт",
"MatchWholeWords": "Полное совпадение",
"Minute": "Минуты",
"Minutes": "Файл уже существует, пожалуйста, переименуйте",
"Must be auto login account for %s": "Должен быть аккаунт для автоматического входа %s",
"Must be unique account for %s": "Должен быть уникальный аккаунт %s",
"Must be unique asset for %s": "должен быть уникальным активом %s",
"MustOneFile": "Можно выбрать только один файл",
"MustSelectOneFile": "Необходимо выбрать файл",
"Name": "Название",
"Need ACL review, continue? (y/n): ": "требует проверки, продолжить? (y/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "Требуется команда рабочего задания для выполнения проверки, уведомление отправлено проверяющему",
"Need ticket confirm to login, already send email to the reviewers": "Требуется вход в систему через заявку, уведомление отправлено аудитору",
"NewFolder": "Создать папку",
"No Account found.": "Учетная запись не найдена",
"No Assets": "Активов нет",
"No Databases": "Нет базы данных",
"No found asset": "Не найдено подходящего актива %s",
"No kubernetes": "Kubernetes отсутствует",
"No protocol found.": "Нет протокола",
"No route to host": "Проблемы с сетью (маршрутизация недоступна)",
"NoActiveTerminalTabFound": "Активная вкладка терминала не найдена",
"NoData": "Нет данных",
"NoLink": "Без адреса",
"NoRunningTerminalFound": "Не найдено работающего терминала",
"Node: [ ID.Name(Asset amount) ]": "Узлы: [ ID.Имя(Количество активов) ]",
"OnlineUser": "Онлайн пользователи",
"OperationSuccessful": "Операция выполнена успешно",
"Organization": "Организация",
"Owner": "Администратор",
"Page up: b\tPage down: n": "Предыдущая страница: b Следующая страница: n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "Номер страницы: %d, количество строк на странице: %d, общее количество страниц: %d, общее количество: %d",
"Paste": "Вставить",
"PauseSession": "Приостановить сессию",
"PermissionDenied": "Нет разрешения",
"PermissionExpired": "Разрешение истекло",
"PermissionValid": "Доступ разрешен",
"Platform": "Платформа",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "Пожалуйста, дождитесь проверки команды проверяющим `%s`, отмените, нажав CTRL+C или CTRL+D.",
"Please waiting for the reviewers to confirm, enter q to exit. ": "Ожидание подтверждения от проверяющего, нажмите q и Enter для отмены входа.",
"PleaseInput": "Пожалуйста, введите",
"PleaseInputVerifyCode": "Введите код безопасности",
"PrimaryUser": "Главный пользователь",
"Protocol": "Протокол",
"ReadOnly": "Минуты",
"Reconnect": "Переподключение",
"Refresh": "Обновить",
"Refresh done": "Обновление завершено",
"Remove": "Удалить",
"RemoveShareUser": "Вас удалили из общей сессии",
"RemoveUser": "Удалить пользователя",
"Rename": "Переименовать",
"ResumeSession": "Возобновить сессию",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "Повторное использование SSH соединения (%s@%s) [Количество соединений: %d]",
"RightArrow": "Стрелка вправо",
"Search": "Поиск",
"Search: %s": "Поиск: %s",
"Select account exceed max retry times.": "Вы выбрали аккаунт, превышающий максимальное количество попыток",
"Select protocol exceed max retry times.": "Превышено максимальное количество попыток выбора протокола",
"SelectAction": "Выберите действие",
"SelectTheme": "Выберите тему",
"Self": "Я",
"Session max time reached, disconnect": "Сессия превысила максимальное время соединения, отключение",
"SessionDetail": "Детали разговора",
"SessionShare": "Поделиться сессией",
"Settings": "Настройки",
@@ -96,18 +158,32 @@
"ShareUser": "Поделиться пользователем",
"ShareUserHelpText": "Пустое поле означает, что присоединиться может каждый желающий.",
"Size": "Размер",
"Start domain gateway failed %s": "Не удалось запустить шлюз базы данных %s",
"Switch language successfully": "Смена языка успешно выполнена",
"Switched to %s": "Переключено на %s",
"Sync": "Синхронизация",
"SyncUserPreferenceFailed": "Ошибка синхронизации настроек",
"SyncUserPreferenceSuccess": "Настройки успешно синхронизированы",
"Terminal does not support protocol %s, please use web terminal to access": "Данный терминал не поддерживает протокол %s, пожалуйста, войдите через веб-терминал",
"TerminalInstanceNotFound": "Не найден экземпляр терминала для текущей вкладки",
"TerminalInstanceNotFoundForCurrentTab": "Текущая вкладка не найдена экземпляр терминала",
"The command '%s' requires review. Continue or not [Y/n]?": "Команда %s требует проверки, продолжить? [Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "Ваша команда содержит риски, уведомление будет отправлено администратору. Продолжить? [Y/N]",
"TheCurrentTerminalInstanceWasNotFound": "Текущий экземпляр терминала не найден.",
"Theme": "Тема",
"ThemeColors": "Цвета темы",
"ThemeConfig": "Настройки темы",
"Ticket Reviewers: %s": "Проверяющий рабочей заявки: %s",
"Tips: Enter asset[%s] account ID": "Подсказка: Введите ID аккаунта актива [%s]",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "Подсказка: введите g+ID узла для отображения хостов в узле, например: g1",
"Tips: Enter protocol ID": "Подсказка: введите ID протокола",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "Подсказка: если хотите установить язык по умолчанию, перейдите на веб-версию в «Личные настройки → Предпочтения»",
"Tips: switch language by ID (Current session only)": "Подсказка: введите ID для смены языка",
"Transfer": "Передача",
"Type": "Тип",
"UnableToGenerateWebSocketURL": "Не удалось сгенерировать WebSocket URL, отсутствуют параметры",
"Unknown error code: %s, detail: %s": "Неизвестный код ошибки: %s, подробности: %s",
"Unknown status": "Неизвестное состояние",
"UpArrow": "Кнопка вверх",
"Upload": "Загрузить",
"UploadEnd": "Загрузка завершена, пожалуйста, подождите дальнейшей обработки",
@@ -117,11 +193,35 @@
"UploadTips": "Перетащите файл сюда или нажмите для загрузки",
"UploadTitle": "Загрузить файл",
"User": "Пользователь",
"Username": "Имя пользователя",
"UsingRegularExpressions": "Использовать регулярные выражения",
"VerifyCode": "Код подтверждения",
"WaitFileTransfer": "Ожидание завершения передачи файла",
"Warning": "Предупреждение",
"WebSocketClosed": "WebSocket закрыт",
"WebSocketConnectionIsClosedHelpText": "WebSocket соединение закрыто, пожалуйста, обновите страницу или переподключитесь.",
"Writable": "Создать ссылку для分享"
"Welcome to use JumpServer open source fortress system": "Добро пожаловать в открытую систему JumpServer Bastion Host",
"Writable": "Создать ссылку для分享",
"You don't have permission login %s": "У вас нет полномочий для входа в %s",
"You get auth token failed": "Вы не смогли получить токен аутентификации",
"display the assets you have permission": "Показать активы, к которым у вас есть доступ",
"display the databases that you have permission": "Показать базы данных, к которым у вас есть доступ",
"display the hosts that you have permission": "Показать хосты, к которым у вас есть доступ",
"display the kubernetes that you have permission": "Показать доступные вам Kubernetes",
"display the node that you have permission": "Показать узлы, к которым у вас есть доступ",
"exit": "Выход",
"get connect token err": "Ошибка получения токена подключения",
"have no permission to download file": "Нет прав для загрузки файла",
"have no permission to upload file": "Нет прав для загрузки файла",
"i/o timeout": "Проблемы с сетью (время соединения истекло)",
"language switch": "Переключение языка",
"network is unreachable": "Сеть недоступна (невозможно достичь сети)",
"not found matched username %s": "Не найдено соответствующее имя пользователя %s",
"part IP, Hostname, Comment": "Частичные IP-адреса, имена хостов, заметки",
"part IP,, Hostname, Comment": "/ + IP, имя хоста, примечание",
"print help": "Показать помощь",
"refresh your assets and nodes": "Обновить актуальную информацию о машинах и узлах",
"select one asset to login": "Выберите один из активов для входа в систему",
"to search login if unique": "Поиск входа (если единственный)",
"to search, such as: /192.168": "Поиск, например: /192.168"
}

227
apps/i18n/koko/vi.json Normal file
View File

@@ -0,0 +1,227 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) Nhập {{.GreenBoldColor}}%s{{.ColorEnd}} để thực hiện %s.%s",
"%s approved": "%s đã được phê duyệt.",
"%s node has no assets": "Tài nguyên trên nút %s không tồn tại",
"%s protocol client not installed.": "%s协议 của khách hàng chưa được cài đặt",
"%s rejected": "Phê duyệt bị từ chối",
"ACL reject": "Đăng nhập lần này đã bị từ chối vì hạn chế của chính sách kiểm soát truy cập",
"Account <%s> and asset <%s> protocol are inconsistent.": "Người dùng hệ thống<%s> và tài sản<%s> không nhất quán",
"ActionPerm": "Quyền hành động",
"Address": "Địa chỉ",
"AlreadyExistsPleaseRename": "Tệp đã tồn tại, vui lòng đổi tên",
"Announcement: ": "Thông báo:",
"Authentication failed": "Xác thực thất bại (tên người dùng hoặc mật khẩu không chính xác)",
"AvailableShortcutKey": "Phím tắt có sẵn",
"Back": "Quay lại",
"Back: B/b": "Quay lại: B/b",
"Cancel": "Hủy bỏ",
"Cancel confirm": "Hủy phê duyệt đăng nhập",
"Cancel to login asset or max 3 retry": "Hủy đăng nhập vào tài nguyên hoặc đã đạt 3 lần thử lại",
"CancelFileUpload": "Hủy tải file lên",
"CaseSensitive": "Phân biệt chữ hoa chữ thường",
"Clone Connect": "Sao chép cửa sổ",
"Close All Tabs": "Đóng tất cả",
"Close Current Tab": "Đóng hiện tại",
"Command `%s` is forbidden": "Lệnh `%s` bị cấm ...",
"Comment": "Ghi chú",
"Confirm": "Xác nhận",
"ConfirmBtn": "Đồng ý",
"ConfirmDelete": "Bạn có chắc chắn muốn xóa tệp này không?",
"Connect": "Kết nối",
"Connect idle more than %d minutes, disconnect": "thời gian rảnh rỗi vượt quá %d phút, ngắt kết nối",
"Connect with api server failed": "Kết nối dịch vụ API thất bại",
"Connecting to %s@%s": "bắt đầu kết nối đến %s@%s",
"Connecting to Database %s": "Bắt đầu kết nối với cơ sở dữ liệu %s",
"Connecting to Kubernetes %s": "Bắt đầu kết nối với Kubernetes %s",
"Connecting to Kubernetes %s container %s": "Bắt đầu kết nối với Kubernetes %s Container %s",
"Connection refused": "Mạng không kết nối (kết nối bị từ chối)",
"CopyLink": "Sao chép liên kết và mã xác thực.",
"CopyShareURLSuccess": "Sao chép địa chỉ chia sẻ thành công",
"Core API failed": "Lỗi xảy ra tại Core API",
"Could copy website URL to notify reviewers: %s": "Địa chỉ kiểm tra có thể sao chép, thông báo cho người kiểm tra: %s",
"Create k8s client err: %s": "Tạo lỗi khách hàng k8s: %s",
"CreateFolder": "Tạo thư mục",
"CreateLink": "Tạo liên kết",
"CreateSuccess": "Tạo thành công",
"CurrentUser": "Người dùng hiện tại",
"Custom Setting": "Cài đặt tùy chỉnh",
"DangerWarning": "Đây là một hành động nguy hiểm",
"Delete": "Xóa",
"DownArrow": "Mũi tên hướng xuống",
"Download": "Tải xuống",
"DownloadProgress": "Tiến độ tải xuống",
"DownloadSuccess": "Tải xuống thành công",
"Downloading": "Đang tải xuống",
"Dynamic": "Tài khoản động",
"EndFileTransfer": "Chuyển file hoàn tất",
"Enter ID number directly login, multiple search use // + field, such as: //16": "Gợi ý: Nhập ID tài sản để đăng nhập trực tiếp, tìm kiếm cấp hai sử dụng // + lĩnh vực, ví dụ: //192",
"ExceedTransferSize": "Vượt quá kích thước truyền tải tối đa",
"Expand": "Mở rộng",
"ExpiredTime": "Thời gian hiệu lực",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "Thiết bị này không hỗ trợ quy tắc truy cập bằng khuôn mặt, vui lòng đăng nhập bằng thiết bị web",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "Thiết bị đầu cuối này không hỗ trợ xác thực nhận diện khuôn mặt, vui lòng đăng nhập bằng thiết bị đầu cuối web.",
"FailedCreateConnection": "Tạo kết nối thất bại",
"FileAlreadyExists": "Tệp đã tồn tại",
"FileListError": "Lấy thông tin danh sách tệp thất bại",
"FileManagement": "Quản lý tập tin",
"FileManagementExpired": "Phiên quản lý tệp hiện tại đã hết hạn.",
"FileManagerTokenTimeout": "Lấy Token quản lý tập tin hết thời gian",
"FileTransferInterrupted": "Chuyển tệp bị gián đoạn",
"FileUploadInterrupted": "Tải tệp bị ngắt quãng",
"Format": "Định dạng",
"General": "Chung",
"Get auth password failed": "Bạn đã không thể lấy mã xác thực",
"GetFileManagerTokenTimeOut": "Lấy Token quản lý tập tin hết thời gian",
"GetShareUser": "Nhập tên người dùng",
"HandleTask does not support protocol %s, please use web terminal to access": "Thiết bị này không hỗ trợ giao thức %s, vui lòng đăng nhập bằng thiết bị web",
"Hostname": "Tên máy chủ",
"Hotkeys": "Phím tắt",
"ID": "ID",
"InputVerifyCode": "Xin vui lòng nhập mã xác minh",
"Invalid ID": "ID không hợp lệ",
"JoinShare": "Tham gia chia sẻ",
"JoinedWithSuccess": "Đã tham gia thành công",
"KubernetesManagement": "Quản lý Kubernetes",
"LastModified": "Thời gian chỉnh sửa cuối cùng",
"LeaveShare": "Rời khỏi chia sẻ",
"LeftArrow": "Mũi tên quay lại",
"LinkAddr": "Địa chỉ liên kết",
"List": "Danh sách",
"Manual": "Tài khoản thủ công",
"MatchWholeWords": "Khớp chính xác",
"Minute": "Phút",
"Minutes": "Phút",
"Must be auto login account for %s": "Tài khoản phải là tài khoản đăng nhập tự động %s",
"Must be unique account for %s": "Tài khoản phải là duy nhất %s",
"Must be unique asset for %s": "Phải là tài nguyên duy nhất %s",
"MustOneFile": "Chỉ có thể chọn một tệp",
"MustSelectOneFile": "Phải chọn một tệp",
"Name": "Tên",
"Need ACL review, continue? (y/n): ": "cần phê duyệt, tiếp tục? (y/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "Cần lệnh công việc để thực hiện phê duyệt, đã gửi email thông báo cho người phê duyệt",
"Need ticket confirm to login, already send email to the reviewers": "Cần đăng nhập công việc để kiểm tra và đã gửi email thông báo cho người kiểm tra",
"NewFolder": "Thư mục mới",
"No Account found.": "Không tìm thấy tài khoản",
"No Assets": "Không có tài sản",
"No Databases": "không có cơ sở dữ liệu",
"No found asset": "Không tìm thấy tài sản phù hợp %s",
"No kubernetes": "Không có Kubernetes",
"No protocol found.": "Không có giao thức",
"No route to host": "Mạng không ổn định (đường truyền không thông)",
"NoActiveTerminalTabFound": "Không tìm thấy tab terminal hoạt động",
"NoData": "Không có dữ liệu",
"NoLink": "Không có địa chỉ",
"NoRunningTerminalFound": "Không tìm thấy terminal đang chạy",
"Node: [ ID.Name(Asset amount) ]": "nút: [ ID.Tên (số lượng tài sản) ]",
"OnlineUser": "Người dùng trực tuyến",
"OperationSuccessful": "Thao tác thành công",
"Organization": "Tổ chức",
"Owner": "Quản lý",
"Page up: b\tPage down: n": "Trang trước: b Trang tiếp theo: n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "Số trang: %d, số dòng mỗi trang: %d, tổng số trang: %d, tổng số lượng: %d",
"Paste": "Dán vào",
"PauseSession": "Tạm dừng phiên này",
"PermissionDenied": "Không có quyền",
"PermissionExpired": "Quyền đã hết hạn",
"PermissionValid": "Quyền vẫn còn hiệu lực",
"Platform": "Nền tảng",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "Vui lòng chờ người xem xét xem xét lệnh `%s`, hủy bằng CTRL+C hoặc CTRL+D.",
"Please waiting for the reviewers to confirm, enter q to exit. ": "Đang chờ người kiểm tra xác nhận, nhấn q và Enter để hủy đăng nhập.",
"PleaseInput": "Vui lòng nhập",
"PleaseInputVerifyCode": "Vui lòng nhập mã xác thực",
"PrimaryUser": "Người dùng chính",
"Protocol": "Giao thức",
"ReadOnly": "Chỉ đọc",
"Reconnect": "Kết nối lại",
"Refresh": "Làm mới",
"Refresh done": "làm mới hoàn tất",
"Remove": "Gỡ bỏ",
"RemoveShareUser": "Bạn đã bị gỡ khỏi phiên chia sẻ.",
"RemoveUser": "Gỡ bỏ người dùng",
"Rename": "Đổi tên",
"ResumeSession": "Khôi phục phiên này",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "Tái sử dụng kết nối SSH (%s@%s) [Số lượng kết nối: %d]",
"RightArrow": "Mũi tên tiến lên",
"Search": "Tìm kiếm",
"Search: %s": "Tìm kiếm: %s",
"Select account exceed max retry times.": "Số tài khoản đã vượt quá số lần thử tối đa",
"Select protocol exceed max retry times.": "chọn giao thức vượt quá số lần thử tối đa.",
"SelectAction": "Vui lòng chọn",
"SelectTheme": "- Chọn chủ đề\n- Định dạng\n- Bạn có chắc chắn muốn xóa tệp này không?\n- Truyền tệp bị gián đoạn\n- Chia sẻ phiên\n- Phải chọn một tệp\n- Tải xuống thành công\n- Chưa chọn người dùng, tức là cho phép tất cả mọi người tham gia\n- Cài đặt đồng bộ thành công\n- Người dùng chia sẻ\n- Tệp đã tồn tại\n- Bạn đã bị gỡ bỏ khỏi phiên chia sẻ\n- Đồng bộ\n- Người dùng chính\n- Mũi tên quay lại",
"Self": "Tôi",
"Session max time reached, disconnect": "Phiên đã vượt quá thời gian kết nối tối đa, ngắt kết nối",
"SessionDetail": "Chi tiết phiên hoạt động.",
"SessionShare": "Chia sẻ phiên",
"Settings": "Cài đặt",
"Share": "Chia sẻ",
"ShareLink": "Chia sẻ liên kết",
"ShareUser": "Chia sẻ người dùng",
"ShareUserHelpText": "Chưa chọn người dùng, tức là cho phép mọi người tham gia",
"Size": "Kích thước",
"Start domain gateway failed %s": "Khởi động cổng cơ sở dữ liệu thất bại %s \nCập nhật thông tin máy móc và nút mới nhất \nLệnh %s cần được xem xét, bạn có muốn tiếp tục không? [Y/N] \nTìm kiếm, ví dụ: /192.168 \nMạng không thông (mạng không thể truy cập) \nKhông có cơ sở dữ liệu \nHiển thị các cơ sở dữ liệu mà bạn có quyền truy cập \nBắt đầu kết nối đến %s@%s \nHiển thị các Kubernetes mà bạn có quyền truy cập \nCập nhật hoàn tất \nNút: [ ID.Tên(Số lượng tài sản) ] \nChuyển đổi ngôn ngữ thành công \nChọn giao thức vượt quá số lần thử tối đa \nThời gian nhàn rỗi vượt quá %d phút, ngắt kết nối \nLời khuyên: Nhập g+nút ID để hiển thị các máy chủ dưới nút, ví dụ: g1",
"Switch language successfully": "chuyển ngôn ngữ thành công",
"Switched to %s": "Đã chuyển sang %s",
"Sync": "Đồng bộ",
"SyncUserPreferenceFailed": "Đồng bộ cài đặt thất bại",
"SyncUserPreferenceSuccess": "Cài đặt đồng bộ thành công",
"Terminal does not support protocol %s, please use web terminal to access": "Thiết bị này không hỗ trợ %sprotocol, vui lòng đăng nhập bằng thiết bị web",
"TerminalInstanceNotFound": "Không tìm thấy phiên bản terminal của tab hiện tại",
"TerminalInstanceNotFoundForCurrentTab": "Không tìm thấy phiên bản terminal trong tab hiện tại",
"The command '%s' requires review. Continue or not [Y/n]?": "lệnh %s cần được xem xét, có tiếp tục không? [Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "Lệnh bạn thực hiện có nguy cơ, thông báo cảnh báo sẽ được gửi đến quản lý. Có muốn tiếp tục không? [Y/N]",
"TheCurrentTerminalInstanceWasNotFound": "Không tìm thấy phiên bản terminal hiện tại",
"Theme": "Chủ đề",
"ThemeColors": "Màu sắc chủ đề",
"ThemeConfig": "Chủ đề",
"Ticket Reviewers: %s": "Người xem xét công việc: %s",
"Tips: Enter asset[%s] account ID": "Gợi ý: Nhập ID tài khoản của tài sản [%s]",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "Ghi chú: Nhập g+ID nút để hiển thị máy chủ dưới nút, ví dụ: g1",
"Tips: Enter protocol ID": "Gợi ý: Nhập ID giao thức",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "Gợi ý: Để thiết lập ngôn ngữ mặc định, vui lòng truy cập vào trang Web \"Cài đặt cá nhân → Tùy chọn\"",
"Tips: switch language by ID (Current session only)": "Gợi ý: Nhập ID để chuyển đổi ngôn ngữ",
"Transfer": "Truyền tải",
"Type": "Loại",
"UnableToGenerateWebSocketURL": "Không thể tạo URL WebSocket, thiếu tham số",
"Unknown error code: %s, detail: %s": "Mã lỗi không xác định: %s, chi tiết: %s",
"Unknown status": "Trạng thái không xác định",
"UpArrow": "Mũi tên lên",
"Upload": "Tải lên",
"UploadEnd": "Tải lên đã hoàn tất, vui lòng chờ xử lý tiếp theo",
"UploadProgress": "Tiến độ tải lên",
"UploadStart": "Bắt đầu tải lên",
"UploadSuccess": "Tải lên thành công",
"UploadTips": "Kéo file đến đây, hoặc nhấp vào tải lên",
"UploadTitle": "Tải lên tệp",
"User": "Người dùng",
"Username": "Tên người dùng",
"UsingRegularExpressions": "Sử dụng biểu thức chính quy",
"VerifyCode": "Mã xác thực",
"WaitFileTransfer": "Chờ đợi kết thúc truyền tệp",
"Warning": "Cảnh báo",
"WebSocketClosed": "WebSocket đã đóng",
"WebSocketConnectionIsClosedHelpText": "Kết nối WebSocket đã bị đóng, vui lòng làm mới trang hoặc kết nối lại.",
"Welcome to use JumpServer open source fortress system": "Chào mừng bạn đến với hệ thống JumpServer mã nguồn mở",
"Writable": "Có thể ghi",
"You don't have permission login %s": "Bạn không có quyền đăng nhập vào %s",
"You get auth token failed": "Bạn đã không lấy được mã thông báo xác thực",
"display the assets you have permission": "Hiển thị tài sản mà bạn có quyền truy cập",
"display the databases that you have permission": "hiển thị cơ sở dữ liệu mà bạn có quyền truy cập",
"display the hosts that you have permission": "Hiển thị các máy chủ mà bạn có quyền",
"display the kubernetes that you have permission": "hiển thị các Kubernetes mà bạn có quyền truy cập",
"display the node that you have permission": "Hiển thị các nút mà bạn có quyền truy cập",
"exit": "Thoát",
"get connect token err": "Lỗi lấy mã kết nối",
"have no permission to download file": "Không có quyền tải xuống tệp",
"have no permission to upload file": "Không có quyền tải lên tệp",
"i/o timeout": "Mạng không ổn định (thời gian kết nối đã hết)",
"language switch": "Chuyển đổi ngôn ngữ",
"network is unreachable": "mạng không thông (mạng không thể tiếp cận)",
"not found matched username %s": "Không tìm thấy tên người dùng khớp %s",
"part IP, Hostname, Comment": "Một phần IP, tên máy chủ, ghi chú",
"part IP,, Hostname, Comment": "/ + IP, tên máy chủ, ghi chú",
"print help": "Hiển thị trợ giúp",
"refresh your assets and nodes": "làm mới thông tin máy và nút mới nhất",
"select one asset to login": "Chọn một tài sản để đăng nhập",
"to search login if unique": "Tìm kiếm đăng nhập (nếu duy nhất)",
"to search, such as: /192.168": "tìm kiếm, ví dụ: /192.168"
}

View File

@@ -123,5 +123,105 @@
"Warning": "警告",
"WebSocketClosed": "WebSocket 已关闭",
"WebSocketConnectionIsClosedHelpText": "WebSocket 连接已关闭,请刷新页面或重新连接。",
"Writable": "可写"
"Writable": "可写",
"No Databases": "无数据库",
"No kubernetes": "没有kubernetes",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "页码:%d每页行数%d总页数%d总数量%d",
"Enter ID number directly login, multiple search use // + field, such as: //16": "提示输入资产ID直接登录二级搜索使用 // + 字段,如://192",
"Page up: b\tPage down: n": "上一页b 下一页n",
"No Assets": "没有资产",
"ID": "ID",
"Address": "地址",
"Platform": "平台",
"Organization": "组织",
"Comment": "备注",
"%s protocol client not installed.": "%s 协议的客户端未安装",
"Terminal does not support protocol %s, please use web terminal to access": "该终端不支持 %s 协议请使用web终端登录",
"Core API failed": "Core API 发生错误",
"ACL reject": "本次登录已拒绝,原因是访问控制策略的限制",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "该终端不支持人脸访问规则请使用web终端登录",
"Unknown error code: %s, detail: %s": "未知错误代码:%s详情%s",
"get connect token err": "获取 connect token 错误",
"%s node has no assets": "%s节点没有资产",
"Welcome to use JumpServer open source fortress system": "欢迎使用JumpServer开源堡垒机系统",
"part IP, Hostname, Comment": "部分IP主机名备注",
"to search login if unique": "搜索登录(如果唯一)",
"part IP,, Hostname, Comment": "/ + IP主机名备注",
"to search, such as: /192.168": "搜索,如:/192.168",
"display the assets you have permission": "显示您有权限的资产",
"display the node that you have permission": "显示您有权限的节点",
"display the hosts that you have permission": "显示您有权限的主机",
"display the databases that you have permission": "显示您有权限的数据库",
"display the kubernetes that you have permission": "显示您有权限的Kubernetes",
"refresh your assets and nodes": "刷新最新的机器和节点信息",
"language switch": "语言切换",
"print help": "显示帮助",
"exit": "退出",
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "\t%d) 输入 {{.GreenBoldColor}}%s{{.ColorEnd}} 进行%s.%s",
"Announcement: ": "公告:",
"No Account found.": "未发现账号",
"Username": "用户名",
"Tips: Enter asset[%s] account ID": "提示:输入资产[%s]的账号ID",
"Back: B/b": "返回B/b",
"Hostname": "主机名",
"select one asset to login": "选择其中一个资产登录",
"not found matched username %s": "未发现匹配的用户名 %s",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "该终端不支持人脸识别认证请使用web终端登录",
"Tips: switch language by ID (Current session only)": "提示输入ID切换语言",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "提示:如需设置默认语言,请前往 Web 端「个人设置 → 偏好设置」",
"Invalid ID": "无效 ID",
"Switch language successfully": "切换语言成功",
"Node: [ ID.Name(Asset amount) ]": "节点:[ ID.名称(资产数量) ]",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "提示:输入 g+节点ID 显示节点下主机,如: g1",
"Connect idle more than %d minutes, disconnect": "空闲时间超过%d分钟断开连接",
"Select account exceed max retry times.": "选择账号超过最大重试次数",
"No protocol found.": "无协议",
"Protocol": "协议",
"Tips: Enter protocol ID": "提示输入协议ID",
"Select protocol exceed max retry times.": "选择协议超过最大重试次数",
"Refresh done": "刷新完成",
"Need ACL review, continue? (y/n): ": "需要审核,继续?(y/n): ",
"Cancel to login asset or max 3 retry": "取消登录资产或达到3次重试",
"Need ticket confirm to login, already send email to the reviewers": "需要工单登录复核,已发邮件通知审核人",
"Ticket Reviewers: %s": "工单审核人:%s ",
"Could copy website URL to notify reviewers: %s": "可复制审核地址,通知审核人:%s",
"Please waiting for the reviewers to confirm, enter q to exit. ": "等待审核人复核确认,按 q 回车取消登录。",
"Unknown status": "未知状态",
"%s approved": "%s 审核通过",
"%s rejected": "%s 审核拒绝",
"Cancel confirm": "取消登录复核",
"Search: %s": "搜索:%s",
"Must be unique asset for %s": "必须是唯一的资产 %s",
"Must be unique account for %s": "必须是唯一的账号 %s",
"Must be auto login account for %s": "必须是自动登录账号 %s",
"No found asset": "未发现匹配的资产 %s",
"Create k8s client err: %s": "创建 k8s 客户端错误:%s",
"have no permission to upload file": "无权限上传文件",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "您执行的命令存在风险,告警通知将发送给管理员。是否继续?[Y/N]",
"The command '%s' requires review. Continue or not [Y/n]?": "命令 %s 需要复核,是否继续?[Y/N]",
"Command `%s` is forbidden": "命令 `%s` 是被禁止的 ...",
"have no permission to download file": "无权限下载文件",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "请等待审核人复核命令 `%s`,取消按 CTRL+C 或 CTRL+D。",
"Need ticket confirm to execute command, already send email to the reviewers": "需要工单命令执行复核,已发邮件通知审核人",
"HandleTask does not support protocol %s, please use web terminal to access": "该终端不支持 %s 协议请使用web终端登录",
"Account <%s> and asset <%s> protocol are inconsistent.": "系统用户<%s>和资产<%s>协议不一致",
"You don't have permission login %s": "你无权限登陆%s",
"You get auth token failed": "你获取认证令牌失败",
"Get auth password failed": "你获取认证令牌失败",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "复用SSH连接%s@%s[连接数量: %d]",
"Switched to %s": "已切换至%s",
"Connect with api server failed": "连接API服务失败",
"Start domain gateway failed %s": "启动数据库网关失败%s",
"Manual": "手动账号",
"Dynamic": "动态账号",
"Connecting to %s@%s": "开始连接到 %s@%s",
"Connecting to Database %s": "开始连接数据库 %s",
"Connecting to Kubernetes %s": "开始连接Kubernetes %s",
"Connecting to Kubernetes %s container %s": "开始连接Kubernetes %s 容器 %s",
"Session max time reached, disconnect": "会话超过最大连接时间,断开连接",
"Authentication failed": "认证失败(用户名或密码错误)",
"Connection refused": "网络不通(连接拒绝)",
"i/o timeout": "网络不通(连接超时)",
"No route to host": "网络不通(路由不通)",
"network is unreachable": "网络不通(网络不可达)"
}

View File

@@ -1,20 +1,45 @@
{
"\t%2d) Enter {{.GreenBoldColor}}%s{{.ColorEnd}} to %s.%s": "%d) 輸入 {{.GreenBoldColor}}%s{{.ColorEnd}} 進行%s.%s",
"%s approved": "%s 審核通過",
"%s node has no assets": "%s節點沒有資產",
"%s protocol client not installed.": "%s 協議的客戶端未安裝",
"%s rejected": "%s 審核拒絕",
"ACL reject": "本次登錄已拒絕,原因是訪問控制策略的限制",
"Account <%s> and asset <%s> protocol are inconsistent.": "系統用戶<%s>和資產<%s>協議不一致",
"ActionPerm": "操作權限",
"Address": "地址",
"AlreadyExistsPleaseRename": "檔案已存在,請重新命名",
"Announcement: ": "公告:",
"Authentication failed": "認證失敗(用戶名或密碼錯誤)",
"AvailableShortcutKey": "可用快捷鍵",
"Back": "返回",
"Back: B/b": "返回B/b",
"Cancel": "取消",
"Cancel confirm": "取消登錄復核",
"Cancel to login asset or max 3 retry": "取消登錄資產或達到3次重試",
"CancelFileUpload": "取消文件上傳",
"CaseSensitive": "區分大小寫",
"Clone Connect": "複製視窗",
"Close All Tabs": "關閉全部",
"Close Current Tab": "關閉當前",
"Command `%s` is forbidden": "命令 `%s` 是被禁止的 ...",
"Comment": "備註",
"Confirm": "確認",
"ConfirmBtn": "確定",
"ConfirmDelete": "您確定要刪除該文件嗎?",
"Connect": "連接",
"Connect idle more than %d minutes, disconnect": "空閒時間超過%d分鐘斷開連接",
"Connect with api server failed": "連接API服務失敗",
"Connecting to %s@%s": "開始連接到 %s@%s",
"Connecting to Database %s": "開始連接數據庫 %s",
"Connecting to Kubernetes %s": "開始連接Kubernetes %s",
"Connecting to Kubernetes %s container %s": "開始連接Kubernetes %s 容器 %s",
"Connection refused": "網絡不通(連接拒絕)",
"CopyLink": "複製連結及驗證碼",
"CopyShareURLSuccess": "複製分享地址成功",
"Core API failed": "Core API 發生錯誤",
"Could copy website URL to notify reviewers: %s": "可複製審核地址,通知審核人:%s",
"Create k8s client err: %s": "創建 k8s 客戶端錯誤:%s",
"CreateFolder": "創建資料夾",
"CreateLink": "創建連結",
"CreateSuccess": "創建成功",
@@ -27,10 +52,14 @@
"DownloadProgress": "下載進度",
"DownloadSuccess": "下載成功",
"Downloading": "正在下載",
"Dynamic": "動態帳號",
"EndFileTransfer": "文件傳輸結束",
"Enter ID number directly login, multiple search use // + field, such as: //16": "提示輸入資產ID直接登錄二級搜索使用 // + 欄位,如://192",
"ExceedTransferSize": "超過最大傳輸大小",
"Expand": "展開",
"ExpiredTime": "有效期限",
"Face ACL is not supported yet. Please use the WebTerminal to connect the asset.": "該終端不支持人臉訪問規則請使用web終端登錄",
"Face verification is not supported yet. Please use the WebTerminal to connect the asset.": "該終端不支持人臉識別認證請使用web終端登錄。",
"FailedCreateConnection": "創建連接失敗",
"FileAlreadyExists": "檔案已存在",
"FileListError": "獲取文件列表資訊失敗",
@@ -41,10 +70,15 @@
"FileUploadInterrupted": "文件上傳中斷",
"Format": "格式",
"General": "通用傳輸",
"Get auth password failed": "你獲取認證令牌失敗",
"GetFileManagerTokenTimeOut": "獲取文件管理 Token 超時",
"GetShareUser": "輸入使用者名稱",
"HandleTask does not support protocol %s, please use web terminal to access": "該終端不支持 %s 協議請使用web終端登錄",
"Hostname": "主機名",
"Hotkeys": "快速鍵",
"ID": "ID",
"InputVerifyCode": "請輸入驗證碼",
"Invalid ID": "無效 ID",
"JoinShare": "加入共享",
"JoinedWithSuccess": "已成功加入",
"KubernetesManagement": "Kubernetes 管理",
@@ -53,41 +87,69 @@
"LeftArrow": "後退箭頭",
"LinkAddr": "連結地址",
"List": "列表",
"Manual": "手動帳號",
"MatchWholeWords": "全字匹配",
"Minute": "分鐘",
"Minutes": "分",
"Must be auto login account for %s": "必須是自動登錄帳號 %s",
"Must be unique account for %s": "必須是唯一的帳號 %s",
"Must be unique asset for %s": "必須是唯一的資產 %s",
"MustOneFile": "只能選擇一個文件",
"MustSelectOneFile": "必須選擇一個文件",
"Name": "名稱",
"Need ACL review, continue? (y/n): ": "需要審核,繼續?(y/n):",
"Need ticket confirm to execute command, already send email to the reviewers": "需要工單命令執行復核,已發郵件通知審核人",
"Need ticket confirm to login, already send email to the reviewers": "需要工單登錄復核,已發郵件通知審核人",
"NewFolder": "新建文件夾",
"No Account found.": "未發現賬號",
"No Assets": "沒有資產",
"No Databases": "無數據庫",
"No found asset": "未發現匹配的資產 %s",
"No kubernetes": "沒有kubernetes",
"No protocol found.": "無協議",
"No route to host": "網絡不通(路由不通)",
"NoActiveTerminalTabFound": "未找到活動終端標籤頁",
"NoData": "無資料",
"NoLink": "無地址",
"NoRunningTerminalFound": "未找到正在運行的終端",
"Node: [ ID.Name(Asset amount) ]": "節點:[ ID.名稱(資產數量) ]",
"OnlineUser": "在線用戶",
"OperationSuccessful": "操作成功",
"Organization": "組織",
"Owner": "管理者",
"Page up: b\tPage down: n": "上一頁b 下一頁n",
"Page: %d, Count: %d, Total Page: %d, Total Count: %d": "頁碼:%d每頁行數%d總頁數%d總數量%d",
"Paste": "貼上",
"PauseSession": "暫停此會話",
"PermissionDenied": "沒有權限",
"PermissionExpired": "權限已過期",
"PermissionValid": "權限有效",
"Platform": "平台",
"Please waiting for the reviewers to confirm command `%s`, cancel by CTRL+C or CTRL+D.": "請等待審核人復核命令 `%s`,取消請按 CTRL+C 或 CTRL+D。",
"Please waiting for the reviewers to confirm, enter q to exit. ": "等待審核人複核確認,按 q 回車取消登錄。",
"PleaseInput": "請輸入",
"PleaseInputVerifyCode": "請輸入驗證碼",
"PrimaryUser": "主用戶",
"Protocol": "協議",
"ReadOnly": "只讀",
"Reconnect": "重新連線",
"Refresh": "刷新",
"Refresh done": "刷新完成",
"Remove": "移除",
"RemoveShareUser": "你已經被移除共享會話",
"RemoveUser": "移除用戶",
"Rename": "重命名",
"ResumeSession": "恢復此會話",
"Reuse SSH connections (%s@%s) [Number of connections: %d]": "複用SSH連接%s@%s[連接數量: %d]",
"RightArrow": "前進箭頭",
"Search": "搜尋",
"Search: %s": "搜索:%s",
"Select account exceed max retry times.": "選擇賬號超過最大重試次數",
"Select protocol exceed max retry times.": "選擇協議超過最大重試次數",
"SelectAction": "請選擇",
"SelectTheme": "請選擇主題",
"Self": "我",
"Session max time reached, disconnect": "會話超過最大連接時間,斷開連接",
"SessionDetail": "會話詳情",
"SessionShare": "會話分享",
"Settings": "設置",
@@ -96,18 +158,32 @@
"ShareUser": "分享用戶",
"ShareUserHelpText": "未選擇用戶,即允許所有人加入",
"Size": "大小",
"Start domain gateway failed %s": "啟動資料庫網關失敗%s \n刷新最新的機器和節點資訊 \n命令 %s 需要複核,是否繼續?[Y/N] \n搜索/192.168 \n網絡不通網絡不可達 \n無資料庫 \n顯示您有權限的資料庫 \n開始連接到 %s@%s \n顯示您有權限的 Kubernetes \n刷新完成 \n節點[ ID.名稱(資產數量) ] \n切換語言成功 \n選擇協議超過最大重試次數 \n空閒時間超過%d分鐘斷開連接 \n提示輸入 g+節點ID 顯示節點下主機,如: g1",
"Switch language successfully": "切換語言成功",
"Switched to %s": "已切換至%s",
"Sync": "同步",
"SyncUserPreferenceFailed": "同步設定失敗",
"SyncUserPreferenceSuccess": "同步設定成功",
"Terminal does not support protocol %s, please use web terminal to access": "該終端不支持 %s 協議請使用web終端登錄",
"TerminalInstanceNotFound": "未找到當前選項卡的終端實例",
"TerminalInstanceNotFoundForCurrentTab": "當前標籤頁未找到終端實例",
"The command '%s' requires review. Continue or not [Y/n]?": "命令 %s 需要復核,是否繼續?[Y/N]",
"The command you executed is risky and an alert notification will be sent to the administrator. Do you want to continue?[Y/N]": "您執行的命令存在風險,告警通知將發送給管理員。是否繼續?[Y/N]",
"TheCurrentTerminalInstanceWasNotFound": "當前終端實例未找到",
"Theme": "主題",
"ThemeColors": "主題顏色",
"ThemeConfig": "主題",
"Ticket Reviewers: %s": "工單審核人:%s",
"Tips: Enter asset[%s] account ID": "提示:輸入資產[%s]的帳號ID",
"Tips: Enter g+NodeID to display the host under the node, such as g1": "提示:輸入 g+節點ID 顯示節點下主機,如: g1",
"Tips: Enter protocol ID": "提示輸入協議ID",
"Tips: To set a default language, go to Personal Settings → Preferences on Web": "提示:如需設置默認語言,請前往 Web 端「個人設置 → 偏好設置」",
"Tips: switch language by ID (Current session only)": "提示輸入ID切換語言",
"Transfer": "傳輸",
"Type": "類型",
"UnableToGenerateWebSocketURL": "無法生成 WebSocket URL缺少參數",
"Unknown error code: %s, detail: %s": "未知錯誤代碼:%s詳情%s",
"Unknown status": "未知狀態",
"UpArrow": "向上箭頭",
"Upload": "上傳",
"UploadEnd": "上傳已完成,請等待後續處理",
@@ -117,11 +193,35 @@
"UploadTips": "將文件拖到此處,或點擊上傳",
"UploadTitle": "上傳文件",
"User": "用戶",
"Username": "用戶名",
"UsingRegularExpressions": "使用正則表達式",
"VerifyCode": "驗證碼",
"WaitFileTransfer": "等待文件傳輸結束",
"Warning": "警告",
"WebSocketClosed": "WebSocket 已關閉",
"WebSocketConnectionIsClosedHelpText": "WebSocket 連接已關閉,請刷新頁面或重新連接。",
"Writable": "可寫"
"Welcome to use JumpServer open source fortress system": "歡迎使用JumpServer開源堡壘機系統",
"Writable": "可寫",
"You don't have permission login %s": "你無權登錄%s",
"You get auth token failed": "您獲取認證令牌失敗",
"display the assets you have permission": "顯示您有權限的資產",
"display the databases that you have permission": "顯示您有權限的數據庫",
"display the hosts that you have permission": "顯示您有權限的主機",
"display the kubernetes that you have permission": "顯示您有權限的Kubernetes",
"display the node that you have permission": "顯示您有權限的節點",
"exit": "退出",
"get connect token err": "獲取連接令牌錯誤",
"have no permission to download file": "無權限下載文件",
"have no permission to upload file": "無權限上傳文件",
"i/o timeout": "網絡不通(連接超時)",
"language switch": "語言切換",
"network is unreachable": "網絡不通(網絡不可達)",
"not found matched username %s": "未發現匹配的用戶名 %s",
"part IP, Hostname, Comment": "部分IP主機名備註",
"part IP,, Hostname, Comment": "/ + IP主機名備註",
"print help": "顯示幫助",
"refresh your assets and nodes": "刷新最新的機器和節點信息",
"select one asset to login": "選擇其中一個資產登錄",
"to search login if unique": "搜索登錄(如果唯一)",
"to search, such as: /192.168": "搜尋,如:/192.168"
}

View File

@@ -1346,6 +1346,7 @@
"Support": "Support",
"SupportedProtocol": "Protocols",
"SupportedProtocolHelpText": "Set supported protocols for the asset, you can modify the custom configurations, such as sftp directory, rdp ad domain, etc., by clicking on the set button",
"SupportedTypes": "Supported types",
"Sync": "Sync",
"SyncAction": "Synchronized action",
"SyncDelete": "Sync delete",
@@ -1524,6 +1525,7 @@
"UserGroupList": "Groups",
"UserGroupUpdate": "Update the user group",
"UserGroups": "Groups",
"UserGroup": "User group",
"UserList": "Users",
"UserLogin": "User login",
"UserLoginACL": "User login ACL",
@@ -1616,5 +1618,9 @@
"removeWarningMsg": "Are you sure you want to remove",
"setVariable": "Set variable",
"userId": "User ID",
"userName": "User name"
"userName": "User name",
"description": "No data yet",
"MsgTemplate": "Msg Template",
"TemplateVariablesHelpText": "You can select a template and use {{ key }} within the template content to read built-in variables.Note: only the {{ }} syntax is supported; other syntaxes such as {% if title %} are not supported.",
"ResetSuccessfully": "Reset successfully"
}

View File

@@ -572,6 +572,7 @@
"EsUrl": "No puede incluir caracteres especiales `#`; ej: http://es_user:es_password@es_host:es_port",
"Every": "Cada",
"Exclude": "No incluir",
"ExcludeAccount": "Excluir cuenta",
"ExcludeAsset": "Activos omitidos",
"ExcludeSymbol": "Caracteres excluidos",
"ExecCloudSyncErrorMsg": "La configuración de la cuenta en la nube está incompleta, por favor actualiza y vuelve a intentarlo",
@@ -1352,6 +1353,7 @@
"Support": "Apoyo",
"SupportedProtocol": "Protocolos soportados",
"SupportedProtocolHelpText": "Establezca los protocolos compatibles con los activos; al hacer clic en el botón de configuración, podrá modificar la configuración personalizada del protocolo, como el directorio SFTP, el dominio RDP AD, entre otros",
"SupportedTypes": "Tipos soportados",
"Sync": "Sincronizar",
"SyncAction": "Sincronizar Acción",
"SyncDelete": "Sincronizar eliminación",
@@ -1525,6 +1527,7 @@
"UserCreate": "crear usuario",
"UserData": "Datos del usuario",
"UserDetail": "Detalles del usuario",
"UserGroup": "Grupo de usuarios",
"UserGroupCreate": "Crear grupo de usuarios",
"UserGroupDetail": "Detalles del grupo de usuarios",
"UserGroupList": "Grupo de usuarios",
@@ -1617,6 +1620,7 @@
"assetId": "ID de activo",
"assetName": "Nombre de activo",
"currentTime": "Hora actual",
"description": "Sin datos disponibles.",
"disallowSelfUpdateFields": "No se permite modificar el campo actual.",
"forceEnableMFAHelpText": "Si se habilita forzosamente, el usuario no podrá desactivarlo por sí mismo",
"isConsoleCanUse": "¿Está disponible la página de gestión?< -SEP->Agregar puerta de enlace al dominio",

View File

@@ -577,6 +577,7 @@
"EsUrl": "特殊文字 `#` は含むことができません;例: http://es_user:es_password@es_host:es_port",
"Every": "毎",
"Exclude": "除外",
"ExcludeAccount": "アカウント除外",
"ExcludeAsset": "スキップされた資産",
"ExcludeSymbol": "文字の除外",
"ExecCloudSyncErrorMsg": "クラウドアカウントの設定が完全でないので、更新して再試行してください",
@@ -1357,6 +1358,7 @@
"Support": "サポート",
"SupportedProtocol": "サポートされているプロトコル",
"SupportedProtocolHelpText": "資産がサポートするプロトコルを設定します。設定ボタンをクリックして、プロトコルのカスタム設定を変更することができます。例えば、SFTPディレクトリやRDP ADドメインなど",
"SupportedTypes": "サポートされているタイプ",
"Sync": "同期する",
"SyncAction": "同期アクション",
"SyncDelete": "同期削除",
@@ -1530,6 +1532,7 @@
"UserCreate": "ユーザーを作成する",
"UserData": "ユーザーデータ",
"UserDetail": "ユーザーの詳細",
"UserGroup": "ユーザーグループ",
"UserGroupCreate": "ユーザーグループの作成",
"UserGroupDetail": "ユーザーグループ詳細",
"UserGroupList": "ユーザーグループ",
@@ -1622,6 +1625,7 @@
"assetId": "資産ID",
"assetName": "資産名",
"currentTime": "現在の時間",
"description": "データはありません。",
"disallowSelfUpdateFields": "現在のフィールドを自分で変更することは許可されていません",
"forceEnableMFAHelpText": "強制的に有効化すると、ユーザーは自分で無効化することができません。",
"isConsoleCanUse": "管理ページの利用可能性",

View File

@@ -572,6 +572,7 @@
"EsUrl": "특수 문자 `#`를 포함할 수 없습니다; 예: http://es_user:es_password@es_host:es_port",
"Every": "매우",
"Exclude": "포함되지 않음",
"ExcludeAccount": "계정 제외",
"ExcludeAsset": "건너뛴 자산",
"ExcludeSymbol": "제외 문자",
"ExecCloudSyncErrorMsg": "클라우드 계정 구성에 문제가 있습니다. 업데이트 후 다시 시도하십시오.",
@@ -1352,6 +1353,7 @@
"Support": "지원",
"SupportedProtocol": "지원하는 프로토콜",
"SupportedProtocolHelpText": "자산 지원 프로토콜을 설정하십시오. 설정 버튼을 클릭하면 SFTP 디렉토리, RDP AD 도메인 등과 같은 프로토콜에 대한 사용자 정의 구성을 수정할 수 있습니다.",
"SupportedTypes": "지원되는 유형",
"Sync": "동기화",
"SyncAction": "동기화 행동",
"SyncDelete": "동기화 삭제",
@@ -1525,6 +1527,7 @@
"UserCreate": "사용자 생성",
"UserData": "사용자 데이터",
"UserDetail": "사용자 세부사항",
"UserGroup": "사용자 그룹",
"UserGroupCreate": "사용자 그룹 생성",
"UserGroupDetail": "사용자 그룹 세부정보",
"UserGroupList": "사용자 그룹",
@@ -1617,6 +1620,7 @@
"assetId": "자산 ID",
"assetName": "자산 이름",
"currentTime": "현재 시간",
"description": "데이터가 없습니다.",
"disallowSelfUpdateFields": "현재 필드를 스스로 수정할 수 없음",
"forceEnableMFAHelpText": "강제로 활성화하면 사용자가 스스로 비활성화할 수 없음",
"isConsoleCanUse": "관리 페이지 사용 가능 여부",

View File

@@ -573,6 +573,7 @@
"EsUrl": "Não pode conter o caractere especial `#`; ex: http://es_user:es_password@es_host:es_port",
"Every": "Cada",
"Exclude": "Não inclui",
"ExcludeAccount": "Excluir conta",
"ExcludeAsset": "Ativos ignorados",
"ExcludeSymbol": " Excluir caracteres",
"ExecCloudSyncErrorMsg": "A configuração da conta em nuvem não está completa, atualize e tente novamente",
@@ -1353,6 +1354,7 @@
"Support": "Suporte",
"SupportedProtocol": "Protocolos suportados",
"SupportedProtocolHelpText": "Configure os protocolos suportados pelos ativos, clicar no botão de configurações permite a personalização, como diretórios SFTP, domínios RDP AD, etc.",
"SupportedTypes": "Tipos suportados",
"Sync": "Sincronizar",
"SyncAction": "Action de sincronização",
"SyncDelete": "Sincronizar e excluir",
@@ -1526,6 +1528,7 @@
"UserCreate": "Criar usuário",
"UserData": "Dados do usuário",
"UserDetail": "Detalhes do usuário",
"UserGroup": "Grupo de usuários",
"UserGroupCreate": "Criar Grupo de Usuários",
"UserGroupDetail": "Detalhes do grupo de usuários",
"UserGroupList": "Grupo de usuários",
@@ -1618,6 +1621,7 @@
"assetId": "ID do ativo",
"assetName": "Nome do ativo",
"currentTime": "Hora atual",
"description": "Nenhum dado disponível.",
"disallowSelfUpdateFields": "Não é permitido alterar o campo atual",
"forceEnableMFAHelpText": "Se for habilitado forçosamente, o usuário não pode desativar por conta própria",
"isConsoleCanUse": "Se a página de gerenciamento está disponível",

View File

@@ -574,6 +574,7 @@
"EsUrl": "Не может содержать специальные символы `#`; например: http://es_user:es_password@es_host:es_port",
"Every": "Каждый",
"Exclude": "Не содержит",
"ExcludeAccount": "Исключенные аккаунты",
"ExcludeAsset": "Пропущенные активы",
"ExcludeSymbol": "Исключить символ",
"ExecCloudSyncErrorMsg": "Выполнить",
@@ -1354,6 +1355,7 @@
"Support": "Поддержка",
"SupportedProtocol": "Протоколы",
"SupportedProtocolHelpText": "Настройте поддерживаемые активом протоколы, нажав кнопку настройки, вы сможете изменить пользовательскую конфигурацию для протоколов, такие как каталог SFTP, домен RDP AD и т.д.",
"SupportedTypes": "Поддерживаемые типы",
"Sync": "Синхронизация",
"SyncAction": "Синхронное действие",
"SyncDelete": "Синхронное удаление",
@@ -1527,6 +1529,7 @@
"UserCreate": "Создать пользователя",
"UserData": "Данные пользователя",
"UserDetail": "Информация о пользователе",
"UserGroup": "Группа пользователей",
"UserGroupCreate": "Создать группу пользователей",
"UserGroupDetail": "Подробности группы пользователей",
"UserGroupList": "Группы",
@@ -1619,6 +1622,7 @@
"assetId": "ID актива",
"assetName": "Название актива",
"currentTime": "Текущее время",
"description": "Нет данных",
"disallowSelfUpdateFields": "Не разрешено самостоятельно изменять текущие поля.",
"forceEnableMFAHelpText": "При принудительном включении пользователь не может отключить самостоятельно",
"isConsoleCanUse": "Доступна ли Консоль",

1632
apps/i18n/lina/vi.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1351,6 +1351,7 @@
"SuperAdmin": "超级管理员",
"SuperOrgAdmin": "超级管理员+组织管理员",
"Support": "支持",
"SupportedTypes": "支持的类型",
"SupportedProtocol": "支持的协议",
"SupportedProtocolHelpText": "设置资产支持的协议,点击设置按钮可以为协议修改自定义配置,如 SFTP 目录RDP AD 域等",
"Sync": "同步",
@@ -1531,6 +1532,7 @@
"UserGroupList": "用户组",
"UserGroupUpdate": "更新用户组",
"UserGroups": "用户组",
"UserGroup": "用户组",
"UserList": "用户列表",
"UserLogin": "用户登录",
"UserLoginACL": "用户登录控制",
@@ -1626,7 +1628,9 @@
"setVariable": "设置参数",
"userId": "用户ID",
"userName": "用户名",
"ExportAsPDF": "导出 PDF",
"EMailReport": "发送邮件报告",
"Print": "打印"
"description": "暂无数据",
"MsgTemplate": "消息模板",
"Example": "示例值",
"TemplateVariablesHelpText": "您可以选择一个模板在模板内容中使用 {{ key }} 读取内置变量,注意:只支持 {{ }} 语法,其他语法不支持。例如 {% if title %}",
"ResetSuccessfully": "重置成功"
}

View File

@@ -577,6 +577,7 @@
"EsUrl": "不能包含特殊字符 `#`eg: http://es_user:es_password@es_host:es_port",
"Every": "每",
"Exclude": "不包含",
"ExcludeAccount": "排除帳號",
"ExcludeAsset": "跳過的資產",
"ExcludeSymbol": "排除字元",
"ExecCloudSyncErrorMsg": "雲帳號配置不完整,請更新後重試",
@@ -1357,6 +1358,7 @@
"Support": "支持",
"SupportedProtocol": "支持的協議",
"SupportedProtocolHelpText": "設置資產支持的協議,點擊設置按鈕可以為協議修改自訂配置,如 SFTP 目錄RDP AD 域等",
"SupportedTypes": "支持的類型",
"Sync": "同步",
"SyncAction": "同步動作",
"SyncDelete": "同步刪除",
@@ -1530,6 +1532,7 @@
"UserCreate": "創建用戶",
"UserData": "使用者資料",
"UserDetail": "用戶詳情",
"UserGroup": "用戶組",
"UserGroupCreate": "創建用戶組",
"UserGroupDetail": "用戶組詳情",
"UserGroupList": "用戶組",
@@ -1622,6 +1625,7 @@
"assetId": "資產 ID",
"assetName": "資產名稱",
"currentTime": "當前時間",
"description": "目前沒有數據。",
"disallowSelfUpdateFields": "不允許自己修改當前欄位",
"forceEnableMFAHelpText": "如果強制啟用,用戶無法自行禁用",
"isConsoleCanUse": "管理頁面是否可用",

110
apps/i18n/lion/vi.json Normal file
View File

@@ -0,0 +1,110 @@
{
"ActionPerm": "Quyền thao tác",
"Admin": "Quản lý",
"AutoFit": "Tự động thích ứng",
"AutoPasteOnClick": "Nhấp vào ô nhập để tự động dán nội dung từ clipboard (cần bật HTTPS và quyền trình duyệt)",
"AvailableShortcutKey": "Các phím tắt có sẵn",
"Back": "Quay lại",
"Cancel": "Hủy bỏ",
"ClearDone": "Làm sạch đã hoàn thành",
"Clipboard": "Bảng chuyển剪贴板",
"Close": "Đóng",
"ConfirmBtn": "Xác nhận",
"Connecting": "Đang kết nối",
"CopyLink": "Sao chép liên kết và mã xác nhận",
"CopyShareURLSuccess": "Sao chép địa chỉ chia sẻ thành công",
"CreateLink": "Tạo liên kết",
"CreateSuccess": "Tạo thành công",
"Display": "Hiển thị",
"Enable": "Kích hoạt",
"ErrTitle": "Kết nối không bình thường",
"ExpiredTime": "Thời gian hiệu lực",
"FileAddUploadingList": "Tệp đã được thêm vào danh sách tải lên",
"FileDownloadDenied": "Không có quyền tải xuống tệp",
"FileManagement": "Quản lý tệp",
"FileUploadStart": "Tải tệp lên bắt đầu",
"FileUploadingWarning": "Tập tin đang được tải lên, không cho phép thao tác.",
"Files": "Quản lý tệp",
"General": "Chung",
"GetShareUser": "Nhập tên người dùng",
"GuaErrClientUnauthorized": "Tên người dùng và mật khẩu xác thực không chính xác, đăng nhập thất bại",
"GuaErrSessionConflict": "Kết nối từ xa đã bị ngắt do xung đột với một kết nối khác. Vui lòng thử lại sau.",
"GuaErrUnSupport": "Yêu cầu hành động này bị cấm",
"GuaErrUpStreamTimeout": "Máy chủ Remote Desktop không phản hồi",
"GuaErrUpstreamNotFound": "Không thể kết nối tới máy chủ máy tính từ xa (mạng không thể truy cập | Lỗi chính sách bảo mật)",
"GuacamoleErrAccessDenied": "Truy cập kết nối từ xa bị từ chối",
"GuacamoleErrActiveSessionTimeLimitExceeded": "Thời gian hoạt động của kết nối từ xa đã vượt quá giới hạn",
"GuacamoleErrAuthenticationFailure": "Xác thực kết nối từ xa thất bại",
"GuacamoleErrConnectionFailed": "Kết nối từ xa thất bại",
"GuacamoleErrCredentialsExpired": "Chứng chỉ kết nối từ xa đã hết hạn",
"GuacamoleErrDNSLookupFailed": "Tra cứu DNS của kết nối từ xa không thành công",
"GuacamoleErrDisconnected": "Kết nối từ xa đã bị ngắt",
"GuacamoleErrDisconnectedByOtherConnection": "Kết nối từ xa bị ngắt bởi kết nối khác",
"GuacamoleErrForciblyDisconnected": "Kết nối từ xa bị ngắt cưỡng bức",
"GuacamoleErrIdleSessionTimeLimitExceeded": "Thời gian rảnh của kết nối từ xa vượt quá giới hạn",
"GuacamoleErrInsufficientPrivileges": "Quyền truy cập của người dùng từ xa không đủ",
"GuacamoleErrLoggedOff": "Người dùng kết nối từ xa đã đăng xuất",
"GuacamoleErrManuallyDisconnected": "Kết nối từ xa đã bị ngắt kết nối thủ công",
"GuacamoleErrManuallyLoggedOff": "Người dùng kết nối từ xa đã bị đăng xuất thủ công",
"GuacamoleErrSSLTLSConnectionFailed": "Kết nối SSL/TLS của kết nối từ xa thất bại",
"GuacamoleErrSecurityNegotiationFailed": "Thương thảo an toàn cho kết nối từ xa thất bại",
"GuacamoleErrServerRefusedConnection": "Máy chủ kết nối từ xa từ chối kết nối.",
"GuacamoleErrServerRefusedConnectionBySecurityType": "Máy chủ kết nối từ xa từ chối kết nối, có thể do loại bảo mật không khớp.",
"GuacamoleErrUnableToConnectToVNCServer": "Không thể kết nối tới máy chủ VNC",
"GuacamoleErrUnsupportedCredentialTypeRequested": "Loại chứng thực cho kết nối từ xa không được hỗ trợ",
"GuacamoleErrUpstreamError": "Đã xảy ra lỗi trên máy chủ kết nối từ xa",
"InputVerifyCode": "Xin vui lòng nhập mã xác thực",
"JMSErrAPIFailed": "Xảy ra lỗi Core API",
"JMSErrAuthUser": "Người dùng chưa được xác thực",
"JMSErrBadParams": "Tham số yêu cầu không hợp lệ",
"JMSErrDisconnected": "Kết nối phiên đã bị ngắt",
"JMSErrGatewayFailed": "Kết nối cổng bị thất bại",
"JMSErrGuacamoleServer": "Không thể kết nối đến máy chủ Guacamole",
"JMSErrIdleTimeOut": "Vượt quá thời gian rảnh tối đa {PLACEHOLDER} phút, ngắt kết nối",
"JMSErrMaxSession": "Đã vượt quá thời gian phiên tối đa {PLACEHOLDER} giờ, ngắt kết nối",
"JMSErrNoSession": "Không thể tìm thấy cuộc trò chuyện",
"JMSErrPermission": "Không có quyền kết nối",
"JMSErrPermissionExpired": "Phân quyền đã hết hạn, ngắt kết nối",
"JMSErrRemoveShareUser": "Bạn đã bị loại khỏi phiên chia sẻ",
"JMSErrTerminatedByAdmin": "Quản trị viên đã chấm dứt phiên",
"JoinShare": "Tham gia chia sẻ",
"KeyboardLayout": "Bố cục",
"LeaveShare": "Rời khỏi chia sẻ",
"LinkAddr": "Địa chỉ liên kết",
"Minute": "Phút",
"Minutes": "Phút",
"Name": "Tên",
"NoData": "Không có dữ liệu",
"OK": "Xác nhận",
"OnlineUser": "Người dùng trực tuyến",
"Other": "Khác",
"Password": "Mật khẩu",
"PauseSession": "Tạm dừng cuộc trò chuyện",
"PleaseInput": "Vui lòng nhập",
"PrimaryUser": "Người dùng chính",
"ReadOnly": "Chỉ đọc",
"Refresh": "Tải lại",
"RemoveShareUserConfirm": "Bạn có chắc chắn muốn gỡ bỏ người dùng này không?",
"RemoveUser": "Xóa người dùng",
"RequireParams": "Tham số bắt buộc",
"ResumeSession": "Khôi phục cuộc trò chuyện",
"SelectAction": "Vui lòng chọn",
"SessionShare": "Chia sẻ phiên làm việc",
"Settings": "Cài đặt",
"Share": "Chia sẻ",
"ShareLink": "Chia sẻ liên kết",
"ShareUser": "Chia sẻ người dùng",
"ShareUserHelpText": "Chưa chọn người dùng, cho phép tất cả mọi người tham gia",
"Shared Drive": "Ổ đĩa chia sẻ",
"Shortcuts": "Phím tắt",
"ShowRemoteClip": "Hiển thị bảng t clipboard từ xa",
"Skip": "Bỏ qua",
"Submit": "Gửi",
"UploadFile": "Tải lên tệp",
"UploadSuccess": "Tải lên thành công",
"Username": "Tên người dùng",
"VerifyCode": "Mã xác thực",
"VirtualKeyboard": "Bàn phím ảo",
"WebSocketError": "Kết nối WebSocket thất bại, vui lòng kiểm tra mạng",
"Writable": "Đọc viết"
}

View File

@@ -285,5 +285,6 @@
"start time": "Start time",
"success": "Success",
"system user": "System user",
"user": "User"
"user": "User",
"Batch actions(select and right click)": "Batch actions(select and right click)"
}

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "atajos disponibles",
"Backspace as Ctrl+H": "Terminal de caracteres Retroceso como Ctrl+H",
"Batch actions": "Operación masiva",
"Batch actions(select and right click)": "Operaciones por lotes (seleccionar y hacer clic derecho)",
"Batch connect": "Conexión por lotes",
"BatchCommands": "Comandos por lotes",
"Belgian French keyboard layout": "Francés belga (Azerty)",

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "利用可能なショートカットキー",
"Backspace as Ctrl+H": "文字端末backspacas Ctrl H",
"Batch actions": "バッチ操作",
"Batch actions(select and right click)": "バッチ操作(選択して右クリック)",
"Batch connect": "バッチ接続",
"BatchCommands": "バッチコマンド",
"Belgian French keyboard layout": "Belgian French (Azerty)",

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "사용 가능한 단축키",
"Backspace as Ctrl+H": "문자 터미널 백스페이스는 Ctrl+H로",
"Batch actions": "대량 작업",
"Batch actions(select and right click)": "배치 작업(선택 후 우클릭)",
"Batch connect": "배치 연결",
"BatchCommands": "배치 명령",
"Belgian French keyboard layout": "벨기에 프랑스어 (Azerty)",

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "Teclas de atalho disponíveis",
"Backspace as Ctrl+H": " Terminal Character Backspace As Ctrl+H ",
"Batch actions": "Operações em Lote",
"Batch actions(select and right click)": "Ação em lote (selecionar e clicar com o botão direito)",
"Batch connect": "Conexão em massa",
"BatchCommands": "Comandos em lote",
"Belgian French keyboard layout": " Francês Belga (Azerty) ",

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "Доступные сочетания клавиш",
"Backspace as Ctrl+H": "Backspace как Ctrl+H",
"Batch actions": "Пакетные операции",
"Batch actions(select and right click)": "Пакетное действие (выбор и щелчок правой кнопкой мыши)",
"Batch connect": "Пакетное подключение",
"BatchCommands": "Пакетные команды",
"Belgian French keyboard layout": "Бельгийская французская раскладка (Azerty)",

290
apps/i18n/luna/vi.json Normal file
View File

@@ -0,0 +1,290 @@
{
"ACL reject login asset": "Đăng nhập lần này đã bị từ chối, lý do là do hạn chế của chính sách kiểm soát truy cập",
"Account info": "Thông tin tài khoản",
"Account not found": "Không tìm thấy tài khoản",
"Account: ": "Tài khoản: {{value}}",
"Action: ": "Hành động:",
"ActionPerm": "Quyền truy cập",
"Advanced option": "Tùy chọn nâng cao",
"All sessions": "Tất cả phiên",
"Applet": "Ứng dụng từ xa",
"Applet connect method": "Cách kết nối ứng dụng từ xa",
"Are you sure to reconnect it?(RDP not support)": "Bạn có chắc chắn muốn kết nối lại không? (RDP tạm thời không hỗ trợ)",
"Asset disabled": "Tài sản này đã bị vô hiệu hóa, xin vui lòng liên hệ quản trị viên",
"Asset not found or You have no permission to access it, please refresh asset tree": "Mật khẩu là mật khẩu đăng nhập vào hệ thống của bạn",
"Asset tree loading method": "Cấu hình phương thức tải tài sản",
"Asset: ": "Tài sản: {{value}}",
"Assignees": "người xử lý",
"Auto": "Tự động",
"Automatic login next": "Đăng nhập tự động lần sau (nhấp chuột phải vào kết nối tài sản để chọn lại)",
"AvailableHotkeys": "Phím tắt khả dụng",
"Backspace as Ctrl+H": "Nhập liệu ký tự Backspace như Ctrl+H",
"Batch actions": "Hành động hàng loạt",
"Batch actions(select and right click)": "Hành động hàng loạt (chọn và nhấp chuột phải)",
"Batch connect": "Kết nối hàng loạt",
"BatchCommands": "Lệnh hàng loạt",
"Belgian French keyboard layout": "Tiếng Pháp Bỉ (Azerty)",
"CLI": "Dòng lệnh",
"CLI font size": "Kích thước phông chữ terminal ký tự",
"Cancel": "Hủy bỏ",
"Charset": "Bộ ký tự",
"Checkbox": "Chọn nhiều",
"Choose a User": "Chọn một người dùng",
"Click to copy": "Nhấp để sao chép",
"Click to download rdp file": "Nhấp để tải xuống tệp RDP",
"Client": "Khách hàng",
"Clone Connect": "Sao chép cửa sổ",
"Close": "Tắt",
"Close All Tabs": "Đóng tất cả",
"Close Current Tab": "Đóng hiện tại",
"Close Left Tabs": "Đóng bên trái",
"Close Other Tabs": "Đóng các mục khác",
"Close Right Tabs": "Đóng bên phải",
"Close split connect": "Đóng chế độ màn hình chia",
"Command": "Lệnh",
"Command Line": "Dòng lệnh",
"CommandBar": "Thanh lệnh",
"Confirm": "Xác nhận",
"ConfirmCreation": "Xác nhận tạo",
"Connect": "Kết nối",
"Connect checked": "Kết nối đã chọn",
"Connect command line": "Kết nối dòng lệnh",
"Connect method": "Phương thức kết nối",
"ConnectSessionCount": "Đã kết nối {{ count }} phiên",
"ConnectionTime": "Thời gian kết nối",
"Copied": "Đã sao chép",
"Copy": "Sao chép",
"Copy link": "Sao chép liên kết",
"CreateLink": "Tạo liên kết",
"Current online": "Đang trực tuyến hiện tại",
"Current session": "phiên hiện tại",
"DarkBlue": "Màu xanh đậm",
"DarkGray": "Ẩn thanh bên trái",
"Database": "Cơ sở dữ liệu",
"Database connect info": "Thông tin kết nối cơ sở dữ liệu",
"Database disabled": "Không hỗ trợ hình thức kết nối này, xin vui lòng liên hệ quản trị viên",
"Database info": "Thông tin cơ sở dữ liệu",
"Database token help text": "Loại cơ sở dữ liệu token sẽ được lưu trong 5 phút, có nghĩa là sau khi sử dụng token, nó sẽ không ngay lập tức hết hiệu lực, mà phải sau 5 phút ngắt kết nối, token này mới hoàn toàn không còn hiệu lực",
"Databases": "Cơ sở dữ liệu",
"Default": "Mặc định",
"Directly": "Tên người dùng chỉ định tài sản và tài khoản kết nối",
"Disable auto completion": "Vô hiệu hóa tự động hoàn thành",
"DisabledAsset": "Tài sản đã bị vô hiệu hóa",
"Disconnect": "Ngắt kết nối",
"Disfavor": "Hủy bỏ đánh dấu yêu thích",
"Do not close this page": "Tùy chọn + Shift + Trái / Phải",
"Document": "Tài liệu",
"Don't prompt again": "Lưu thành công",
"DownArrow": "Màu xám đậm",
"Download": "Tải xuống",
"Download the latest client": "Chuyển sang lệnh nhanh",
"DownloadClient": "Tải xuống ứng dụng",
"DownloadClientMsg": "Khách hàng JumpServer chưa được cài đặt, đi cài đặt và tải xuống ngay bây giờ",
"Driver redirect": "Gắn đĩa",
"Expand": "Mở rộng",
"Expand all": "Mở rộng tất cả",
"Expand all asset": "Mở rộng tất cả tài sản dưới nút",
"Expire time": "Quản lý tệp",
"ExpiredTime": "Thời hạn hiệu lực",
"Face online required": "Đăng nhập lần này cần thực hiện xác minh khuôn mặt và giám sát, có tiếp tục không?",
"Face verify": "Xác thực khuôn mặt",
"Face verify required": "Không hiển thị lại lần sau",
"Face verify success": "Xác thực khuôn mặt thành công",
"FaceOnlineNotSupported": "Không hỗ trợ xác minh trực tuyến bằng khuôn mặt",
"Failed to open address": "Mở địa chỉ không thành công",
"Favorite": "Yêu thích",
"File Manager": "Phiên đang được giám sát",
"FileManagement": "Quản lý tệp",
"FileManagerConnectionFailed": "Kết nối quản lý tệp thất bại",
"Fold": "Gấp lại",
"Fold all": "Gấp gọn tất cả",
"Force refresh": "làm mới cưỡng bức",
"Found": "Khám phá",
"French keyboard layout": "Tiếng Pháp (Azerty)",
"Full Screen": "Chế độ toàn màn hình",
"Full screen": "Toàn màn hình",
"GUI": "Đồ họa",
"General": "Cấu hình cơ bản",
"Go to Settings": "Đi đến cài đặt",
"Help": "Trợ giúp",
"Help or download": "Trợ giúp menu → Tải xuống",
"Help text": "Giới thiệu",
"Hide left manager": "Vui lòng nhập mật khẩu",
"High-speed broadband (2 Mbps 10 Mbps )": "Băng thông cao (2 Mbps - 10 Mbps)",
"HistoryCommands": "Lệnh lịch sử",
"Host": "Máy chủ",
"Hotkeys": "Phím tắt",
"Info": "Gợi ý",
"InstallClientMsg": "Khách hàng JumpServer chưa được cài đặt, bây giờ có muốn đi tải và cài đặt không?",
"Japanese keyboard layout": "Tiếng Nhật (Qwerty)",
"Keyboard keys": "Lần đăng nhập này cần xác thực khuôn mặt, bạn có muốn tiếp tục không?",
"Keyboard layout": "Bố cục bàn phím",
"Keyboard switch session": "Chuyển đổi phiên → Phím tắt",
"Kubernetes": "Kubernetes",
"Language": "Ngôn ngữ",
"Last login": "Lần đăng nhập trước",
"Launch Program": "Khởi động chương trình",
"LeftArrow": "Mũi tên sang trái",
"LeftInfo": "Nhấn vào ghi chép lệnh để nhanh chóng xác định video",
"LinkAddr": "Địa chỉ liên kết",
"Load tree async": "Tải tài sản không đồng bộ",
"Loading": "Đang tải...",
"LoadingFileManager": "Đang tải trình quản lý tệp...",
"Log out": "Đăng xuất",
"Login reminder": "Nhắc nhở đăng nhập",
"Login review approved": "Đăng nhập đã được phê duyệt, đang kết nối tài sản...",
"LoginExpireMsg": "Đăng nhập hiện tại đã hết thời gian, xin đừng đóng cửa sổ. Bạn có thể phục hồi trang hiện tại sau khi đăng nhập lại trong cửa sổ mới, nếu không phục hồi được hãy làm mới trang.",
"Low Speed Broadband (256 Kbps - 2 Mbps)": "Băng thông thấp (256 Kbps - 2 Mbps)",
"Manual accounts": "Tài khoản thủ công",
"Minute": "Phút",
"Minutes": "Phân bổ",
"Module": "Mô-đun",
"Multi Screen": "Hiển thị đa màn hình",
"My applications": "ứng dụng của tôi",
"My assets": "Tài sản của tôi",
"Name": "Tên",
"Native": "Khách hàng",
"Need review for login asset": "Đăng nhập lần này cần có kiểm tra thủ công, có tiếp tục không?",
"Need to use": "Cần sử dụng",
"No": "Không",
"No account available": "Không có tài khoản có sẵn",
"No available connect method": "Không có phương thức kết nối nào khả dụng",
"No facial features": "Chưa có đặc điểm khuôn mặt, vui lòng truy cập trang thông tin cá nhân để liên kết.",
"No matching found": "Không có mục phù hợp",
"No permission": "Không có quyền",
"No protocol available": "Không có giao thức nào có sẵn",
"NoOnlineUser": "Chưa có người dùng trực tuyến",
"NoOnlineUsers": "Hiện tại không có người dùng trực tuyến",
"NoTabs": "Không có cửa sổ",
"Not quick command": "Chưa có lệnh tắt",
"OnlineUser": "Người dùng trực tuyến",
"Open in new window": "Mở cửa sổ mới",
"Operator": "Người dùng hệ thống",
"Password": "mật khẩu",
"Password is token password on the table": "mật khẩu là mật khẩu Token trong bảng",
"Password is your password login to system": "Tiếng Thổ Nhĩ Kỳ-Q (Qwerty)",
"Pause": "Tạm dừng",
"Pause task has been send": "Nhiệm vụ tạm dừng đã được gửi",
"Play List": "Danh sách phát",
"Please choose an account": "Vui lòng chọn một người dùng.",
"Please complete the face verification": "Vui lòng hoàn thành xác thực khuôn mặt này",
"Please input password": "Vui lòng nhập mật khẩu",
"PleaseEnterYourUsername": "Xin vui lòng nhập tên người dùng",
"Port": "Cổng",
"PrimaryUser": "Người dùng chính",
"Protocol": "Giao thức",
"Protocol: ": "Thỏa thuận: {{value}}",
"RDP Client": "RDP Client",
"RDP File": "Vui lòng hoàn thành xác thực khuôn mặt này.",
"RDP client options": "Tùy chọn RDP Client",
"RDP color quality": "Chất lượng màu RDP",
"RDP connection speed": "Tốc độ kết nối RDP",
"RDP file reusable": "Tệp RDP có thể tái sử dụng",
"RDP resolution": "Độ phân giải RDP",
"RDP smart size": "Kích thước thông minh RDP",
"Re-use for a long time after opening": "Khi được bật, thông tin kết nối này có thể được sử dụng nhiều lần trong thời gian dài.",
"ReadOnly": "Chỉ đọc",
"Reconnect": "Kết nối lại",
"Redirecting": "Đang chuyển hướng",
"Refresh": "Làm mới",
"Remember password": "nhớ mật khẩu",
"Remember select": "Nhớ lựa chọn",
"RemoteApp": "Ứng dụng từ xa",
"RemoveShareUserConfirm": "Bạn có chắc chắn muốn xóa người dùng này không?",
"Reselect connection method": "Có thể chọn lại cách kết nối",
"Resume": "Khôi phục",
"Resume task has been send": "Nhiệm vụ phục hồi đã được gửi",
"Right click asset": "Nhấp chuột phải vào tài sản → Kết nối",
"Right click node": "Nhấp chuột phải vào nút → Mở rộng tất cả",
"Right mouse quick paste": "Nhấp chuột phải để dán nhanh",
"RightArrow": "Mũi tên sang phải",
"Run it by client": "Sử dụng khách hàng để thực hiện",
"SQL Client": "Máy khách SQL",
"Save command": "Lệnh lưu",
"Save success": "Tập tin RDP",
"Search": "Tìm kiếm",
"Select account": "Chọn tài khoản",
"SelectCommand": "Vui lòng chọn lệnh cần thực hiện",
"Send": "Gửi",
"Send command": "Gửi lệnh",
"Send text to all ssh terminals": "Gửi đến tất cả các cuộc hội thoại",
"SendCommandPlaceholder": "Nhập lệnh, nhấn Enter để xuống dòng, Ctrl+Enter để thực hiện lệnh",
"Session": "phiên.",
"SessionIsBeingMonitored": "Kết nối màn hình đôi",
"SessionShare": "Chia sẻ phiên",
"Set reusable": "Bật tái sử dụng",
"Setting": "Cài đặt",
"Settings or basic settings": "Cài đặt menu → Cài đặt cơ bản",
"ShareCode": "Mã chia sẻ",
"ShareLink": "Chia sẻ liên kết",
"ShareSession": "Chia sẻ phiên",
"ShareUser": "Chia sẻ người dùng",
"Show left manager": "Hiển thị thanh bên trái",
"Skip": "Bỏ qua",
"Skip manual password": "Bỏ qua cửa sổ mật khẩu thủ công",
"Special accounts": "Tài khoản đặc biệt",
"Speed": "Tốc độ",
"Split connect": "Mũi tên hướng xuống",
"Split connect number": "Một phiên một lúc hỗ trợ tối đa 3 kết nối màn hình phân chia",
"Split vertically": "Chia màn hình dọc",
"SplitVertical": "Chia sẻ theo chiều dọc",
"Start Time: ": "Thời gian bắt đầu: {{value}}",
"Stop": "dừng lại",
"Support": "Hỗ trợ",
"Swiss French keyboard layout": "Người dùng",
"Switch to input command": "Chuyển sang chế độ nhập lệnh",
"Switch to quick command": "Thời gian hết hạn",
"Tab List": "Danh sách cửa sổ",
"Tabs": "Cửa sổ",
"The connection method is invalid, please refresh the page": "Cách kết nối này đã hết hiệu lực, vui lòng làm mới trang",
"Theme": "Chủ đề",
"ThemeSyncFailed": "Đồng bộ chủ đề thất bại",
"ThemeSyncSuccessful": "Chủ đề đồng bộ thành công",
"Ticket review approved for login asset": "Lần đăng nhập này đã được kiểm tra, bạn có muốn kết nối tài sản không?< -SEP->Không tìm thấy tài sản hoặc bạn không có quyền truy cập, vui lòng làm mới cây tài sản",
"Ticket review closed for login asset": "Đợt xem xét đăng nhập này đã đóng, không thể kết nối tài sản",
"Ticket review pending for login asset": "Đơn đăng nhập đã được nộp, đang chờ người tiếp nhận xem xét, bạn cũng có thể sao chép liên kết và gửi cho họ",
"Ticket review rejected for login asset": "lần đăng nhập này đã bị từ chối, không thể kết nối tài sản",
"Tips": "gợi ý",
"Token expired": "Token đã hết hạn, vui lòng kết nối lại",
"TokenVerificationFailedLeaseReconnect": "Xác thực Token thất bại, vui lòng kết nối lại",
"Tool download": "Tải xuống công cụ",
"Turkey keyboard layout": "Tên người dùng@miền AD",
"TurnOffReminders": "Bạn có chắc chắn muốn đóng kết nối hiện tại không?",
"Type tree": "Loại cây",
"UK English keyboard layout": "UK English (Qwerty)",
"US English keyboard layout": "Tiếng Anh Mỹ (Qwerty)",
"UpArrow": "Mũi tên lên",
"User": "Người dùng",
"User: ": "Người dùng: {{value}}",
"Username": "Tải xuống ứng dụng mới nhất",
"Username@Domain": "Xin đừng đóng trang này",
"Users": "Người điều hành",
"Using token": "Sử dụng Token",
"VerificationFailed": "Kiểm tra không thành công",
"View": "Xem",
"Viewer": "Xem người",
"VirtualApp": "Ứng dụng ảo",
"Virtualapp connect method": "Phương thức kết nối ứng dụng ảo",
"Web Terminal": "Giao diện Web",
"Website": "Trang chủ",
"With secret accounts": "Tài khoản quản lý",
"WordSep": "- Không có quyền\n- Kiểm tra thất bại\n- Tài sản đã bị vô hiệu hóa\n- Hủy bỏ\n- Thời gian bắt đầu\n- Mở cửa sổ mới\n- Dòng lệnh\n- Cấu hình phương thức tải cây tài sản\n- Giao thức: {{value}}\n- Chọn nhiều\n- Tạo liên kết\n- Sao chép cửa sổ\n- Phân\n- Phương thức kết nối ứng dụng ảo",
"Writable": "Có thể viết",
"Yes": "là",
"account": "Tài khoản",
"asset": "Tài sản",
"cols": "Số cột",
"confirm": "Xác nhận",
"connect info": "Kết nối thông tin",
"connectDisabledTipsMethodDisabled": "Gợi ý: Không tìm thấy máy phát hành ứng dụng từ xa hiệu quả, tài nguyên hiện tại không thể kết nối, xin vui lòng liên hệ với quản trị viên để xử lý.",
"connectDisabledTipsNoAccount": "Thông báo: Không tìm thấy tài khoản ủy quyền hợp lệ, tài nguyên hiện tại không thể kết nối, xin vui lòng liên hệ với người quản lý để xử lý",
"connectDisabledTipsNoConnectMethod": "Gợi ý: Không tìm thấy phương thức kết nối hợp lệ, tài nguyên hiện tại không thể kết nối, xin vui lòng liên hệ quản trị viên để xử lý",
"download": "Tải xuống",
"recordingIsBeingDownloaded": "Đang tải video, xin vui lòng chờ",
"rows": "số dòng",
"scriptLibrary": "Thư viện kịch bản",
"start time": "Thời gian bắt đầu",
"success": "Thành công",
"system user": "Tên đăng nhập",
"user": "Người dùng"
}

View File

@@ -285,5 +285,6 @@
"start time": "开始时间",
"success": "成功",
"system user": "系统用户",
"user": "用户"
"user": "用户",
"Batch actions(select and right click)": "批量操作(选择并右键单击)"
}

View File

@@ -20,6 +20,7 @@
"AvailableHotkeys": "可用快捷鍵",
"Backspace as Ctrl+H": "字元終端Backspace As Ctrl+H",
"Batch actions": "批次操作",
"Batch actions(select and right click)": "批量操作(選擇並右鍵點擊)",
"Batch connect": "批次連接",
"BatchCommands": "批量命令",
"Belgian French keyboard layout": "Belgian French (Azerty)",

View File

@@ -692,8 +692,9 @@ class Config(dict):
'FTP_FILE_MAX_STORE': 0,
# API 分页
'MAX_LIMIT_PER_PAGE': 10000,
'DEFAULT_PAGE_SIZE': 10,
'MAX_LIMIT_PER_PAGE': 10000, # 给导出用
'MAX_PAGE_SIZE': 1000,
'DEFAULT_PAGE_SIZE': 200, # 给没有请求分页的用
'LIMIT_SUPER_PRIV': False,

View File

@@ -4,7 +4,7 @@ from rest_framework.pagination import LimitOffsetPagination
class MaxLimitOffsetPagination(LimitOffsetPagination):
max_limit = settings.MAX_LIMIT_PER_PAGE
max_limit = settings.MAX_PAGE_SIZE
def get_count(self, queryset):
try:
@@ -15,15 +15,7 @@ class MaxLimitOffsetPagination(LimitOffsetPagination):
def paginate_queryset(self, queryset, request, view=None):
if view and hasattr(view, 'page_max_limit'):
self.max_limit = view.page_max_limit
# 自定义的 api view就默认不约束分页了
if getattr(view, 'action') != 'list' and not getattr(view, 'default_limit'):
self.default_limit = None
if view and hasattr(view, 'page_default_limit'):
self.default_limit = view.page_default_limit
if view and hasattr(view, 'default_limit'):
self.default_limit = view.default_limit
return super().paginate_queryset(queryset, request, view)

View File

@@ -225,7 +225,9 @@ SESSION_RSA_PUBLIC_KEY_NAME = 'jms_public_key'
OPERATE_LOG_ELASTICSEARCH_CONFIG = CONFIG.OPERATE_LOG_ELASTICSEARCH_CONFIG
MAX_LIMIT_PER_PAGE = CONFIG.MAX_LIMIT_PER_PAGE
DEFAULT_PAGE_SIZE = CONFIG.DEAFULT_LIMIT_PER_PAGE
MAX_PAGE_SIZE = CONFIG.MAX_PAGE_SIZE
DEFAULT_PAGE_SIZE = CONFIG.DEFAULT_PAGE_SIZE
PERM_TREE_REGEN_INTERVAL = CONFIG.PERM_TREE_REGEN_INTERVAL
# Magnus DB Port

View File

@@ -47,7 +47,7 @@ REST_FRAMEWORK = {
'DATETIME_FORMAT': '%Y/%m/%d %H:%M:%S %z',
'DATETIME_INPUT_FORMATS': ['%Y/%m/%d %H:%M:%S %z', 'iso-8601', '%Y-%m-%d %H:%M:%S %z'],
'DEFAULT_PAGINATION_CLASS': 'jumpserver.rewriting.pagination.MaxLimitOffsetPagination',
'PAGE_SIZE': CONFIG.DEFAULT_PAGE_SIZE,
'PAGE_SIZE': None,
'EXCEPTION_HANDLER': 'common.drf.exc_handlers.common_exception_handler',
'DEFAULT_SCHEMA_CLASS': 'jumpserver.views.schema.CustomAutoSchema',
}

View File

@@ -103,8 +103,8 @@ class ResourceDownload(TemplateView):
MRD_VERSION=10.6.7
OPENSSH_VERSION=v9.4.0.0
TINKER_VERSION=v0.1.6
VIDEO_PLAYER_VERSION=0.4.0
CLIENT_VERSION=v3.0.6
VIDEO_PLAYER_VERSION=0.6.0
CLIENT_VERSION=v3.0.7
"""
def get_meta_json(self):

View File

@@ -24,7 +24,7 @@ class ContentTypeViewSet(JMSModelViewSet):
rbac_perms = {
'resources': 'rbac.view_contenttype',
}
page_default_limit = None
page_no_limit = True
can_labeled_content_type = []
model = ContentType

View File

@@ -0,0 +1,401 @@
#!/usr/bin/python
# Modified from ansible_collections.community.general.mssql_script
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
module: mssql_script
short_description: Execute SQL scripts on a MSSQL database
version_added: "1.0.0"
description:
- Execute SQL scripts on a MSSQL database.
extends_documentation_fragment:
- community.general.attributes
attributes:
check_mode:
support: partial
details:
- The script is not be executed in check mode.
diff_mode:
support: none
options:
name:
description: Database to run script against.
aliases: [db]
default: ''
type: str
login_user:
description: The username used to authenticate with.
type: str
login_password:
description: The password used to authenticate with.
type: str
login_host:
description: Host running the database.
type: str
required: true
login_port:
description: Port of the MSSQL server. Requires O(login_host) be defined as well.
default: 1433
type: int
script:
description:
- The SQL script to be executed.
- Script can contain multiple SQL statements. Multiple Batches can be separated by V(GO) command.
- Each batch must return at least one result set.
required: true
type: str
transaction:
description:
- If transactional mode is requested, start a transaction and commit the change only if the script succeed. Otherwise,
rollback the transaction.
- If transactional mode is not requested (default), automatically commit the change.
type: bool
default: false
version_added: 8.4.0
output:
description:
- With V(default) each row is returned as a list of values. See RV(query_results).
- Output format V(dict) returns dictionary with the column names as keys. See RV(query_results_dict).
- V(dict) requires named columns to be returned by each query otherwise an error is thrown.
choices: ["dict", "default"]
default: 'default'
type: str
params:
description: |-
Parameters passed to the script as SQL parameters.
(Query V('SELECT %(name\)s"') with V(example: '{"name": "John Doe"}).)'.
type: dict
notes:
- Requires the pymssql Python package on the remote host. For Ubuntu, this is as easy as C(pip install pymssql) (See M(ansible.builtin.pip)).
requirements:
- pymssql
author:
- Kris Budde (@kbudde)
"""
EXAMPLES = r"""
- name: Check DB connection
community.general.mssql_script:
login_user: "{{ mssql_login_user }}"
login_password: "{{ mssql_login_password }}"
login_host: "{{ mssql_host }}"
login_port: "{{ mssql_port }}"
db: master
script: "SELECT 1"
- name: Query with parameter
community.general.mssql_script:
login_user: "{{ mssql_login_user }}"
login_password: "{{ mssql_login_password }}"
login_host: "{{ mssql_host }}"
login_port: "{{ mssql_port }}"
script: |
SELECT name, state_desc FROM sys.databases WHERE name = %(dbname)s
params:
dbname: msdb
register: result_params
- assert:
that:
- result_params.query_results[0][0][0][0] == 'msdb'
- result_params.query_results[0][0][0][1] == 'ONLINE'
- name: Query within a transaction
community.general.mssql_script:
login_user: "{{ mssql_login_user }}"
login_password: "{{ mssql_login_password }}"
login_host: "{{ mssql_host }}"
login_port: "{{ mssql_port }}"
script: |
UPDATE sys.SomeTable SET desc = 'some_table_desc' WHERE name = %(dbname)s
UPDATE sys.AnotherTable SET desc = 'another_table_desc' WHERE name = %(dbname)s
transaction: true
params:
dbname: msdb
- name: two batches with default output
community.general.mssql_script:
login_user: "{{ mssql_login_user }}"
login_password: "{{ mssql_login_password }}"
login_host: "{{ mssql_host }}"
login_port: "{{ mssql_port }}"
script: |
SELECT 'Batch 0 - Select 0'
SELECT 'Batch 0 - Select 1'
GO
SELECT 'Batch 1 - Select 0'
register: result_batches
- assert:
that:
- result_batches.query_results | length == 2 # two batch results
- result_batches.query_results[0] | length == 2 # two selects in first batch
- result_batches.query_results[0][0] | length == 1 # one row in first select
- result_batches.query_results[0][0][0] | length == 1 # one column in first row
- result_batches.query_results[0][0][0][0] == 'Batch 0 - Select 0' # each row contains a list of values.
- name: two batches with dict output
community.general.mssql_script:
login_user: "{{ mssql_login_user }}"
login_password: "{{ mssql_login_password }}"
login_host: "{{ mssql_host }}"
login_port: "{{ mssql_port }}"
output: dict
script: |
SELECT 'Batch 0 - Select 0' as b0s0
SELECT 'Batch 0 - Select 1' as b0s1
GO
SELECT 'Batch 1 - Select 0' as b1s0
register: result_batches_dict
- assert:
that:
- result_batches_dict.query_results_dict | length == 2 # two batch results
- result_batches_dict.query_results_dict[0] | length == 2 # two selects in first batch
- result_batches_dict.query_results_dict[0][0] | length == 1 # one row in first select
- result_batches_dict.query_results_dict[0][0][0]['b0s0'] == 'Batch 0 - Select 0' # column 'b0s0' of first row
"""
RETURN = r"""
query_results:
description: List of batches (queries separated by V(GO) keyword).
type: list
elements: list
returned: success and O(output=default)
sample:
[
[
[
[
"Batch 0 - Select 0"
]
],
[
[
"Batch 0 - Select 1"
]
]
],
[
[
[
"Batch 1 - Select 0"
]
]
]
]
contains:
queries:
description:
- List of result sets of each query.
- If a query returns no results, the results of this and all the following queries are not included in the output.
- Use the V(GO) keyword in O(script) to separate queries.
type: list
elements: list
contains:
rows:
description: List of rows returned by query.
type: list
elements: list
contains:
column_value:
description:
- List of column values.
- Any non-standard JSON type is converted to string.
type: list
example: ["Batch 0 - Select 0"]
returned: success, if output is default
query_results_dict:
description: List of batches (queries separated by V(GO) keyword).
type: list
elements: list
returned: success and O(output=dict)
sample:
[
[
[
[
"Batch 0 - Select 0"
]
],
[
[
"Batch 0 - Select 1"
]
]
],
[
[
[
"Batch 1 - Select 0"
]
]
]
]
contains:
queries:
description:
- List of result sets of each query.
- If a query returns no results, the results of this and all the following queries are not included in the output.
Use V(GO) keyword to separate queries.
type: list
elements: list
contains:
rows:
description: List of rows returned by query.
type: list
elements: list
contains:
column_dict:
description:
- Dictionary of column names and values.
- Any non-standard JSON type is converted to string.
type: dict
example: {"col_name": "Batch 0 - Select 0"}
returned: success, if output is dict
"""
import pymssql
from ansible.module_utils.basic import AnsibleModule
import json
def clean_output(o):
return str(o)
def main():
module_args = dict(
name=dict(aliases=['db'], default=''),
login_user=dict(type='str', required=False, default=None),
login_password=dict(no_log=True),
login_host=dict(required=True),
login_port=dict(type='int', default=1433),
script=dict(required=True),
output=dict(default='default', choices=['dict', 'default']),
params=dict(type='dict'),
transaction=dict(type='bool', default=True),
tds_version=dict(type='str', required=False, default=None),
encryption=dict(type='str', required=False, default=None)
)
result = dict(
changed=False,
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
db = module.params['name']
login_user = module.params['login_user']
login_password = module.params['login_password']
login_host = module.params['login_host']
login_port = module.params['login_port']
script = module.params['script']
output = module.params['output']
sql_params = module.params['params']
transaction = module.params['transaction']
# TODO 待 ansible 官方支持这两个参数
tds_version = module.params['tds_version'] or None
encryption = module.params['encryption'] or None
login_querystring = login_host
if login_port != 1433:
login_querystring = "%s:%s" % (login_host, login_port)
if login_user is not None and login_password is None:
module.fail_json(
msg="when supplying login_user argument, login_password must also be provided")
try:
conn = pymssql.connect(
user=login_user, password=login_password, host=login_querystring,
database=db, encryption=encryption, tds_version=tds_version)
cursor = conn.cursor()
except Exception as e:
if "Unknown database" in str(e):
errno, errstr = e.args
module.fail_json(msg="ERROR: %s %s" % (errno, errstr))
else:
module.fail_json(
msg="unable to connect, check login_user and login_password are correct, or alternatively check your "
"@sysconfdir@/freetds.conf / ${HOME}/.freetds.conf")
# If transactional mode is requested, start a transaction
conn.autocommit(not transaction)
query_results_key = 'query_results'
if output == 'dict':
cursor = conn.cursor(as_dict=True)
query_results_key = 'query_results_dict'
# Process the script into batches
queries = []
current_batch = []
for statement in script.splitlines(True):
# Ignore the Byte Order Mark, if found
if statement.strip() == '\uFEFF':
continue
# Assume each 'GO' is on its own line but may have leading/trailing whitespace
# and be of mixed-case
if statement.strip().upper() != 'GO':
current_batch.append(statement)
else:
queries.append(''.join(current_batch))
current_batch = []
if len(current_batch) > 0:
queries.append(''.join(current_batch))
result['changed'] = True
if module.check_mode:
module.exit_json(**result)
query_results = []
for query in queries:
# Catch and exit on any bad query errors
try:
cursor.execute(query, sql_params)
qry_result = []
rows = cursor.fetchall()
while rows:
qry_result.append(rows)
rows = cursor.fetchall()
query_results.append(qry_result)
except Exception as e:
# We know we executed the statement so this error just means we have no resultset
# which is ok (eg UPDATE/INSERT)
if (
type(e).__name__ == 'OperationalError' and
str(e) == 'Statement not executed or executed statement has no resultset'
):
query_results.append([])
else:
# Rollback transaction before failing the module in case of error
if transaction:
conn.rollback()
error_msg = '%s: %s' % (type(e).__name__, str(e))
module.fail_json(msg="query failed", query=query, error=error_msg, **result)
# Commit transaction before exiting the module in case of no error
if transaction:
conn.commit()
# ensure that the result is json serializable
qry_results = json.loads(json.dumps(query_results, default=clean_output))
result[query_results_key] = qry_results
module.exit_json(**result)
if __name__ == '__main__':
main()

View File

@@ -227,7 +227,7 @@ class SSHClient:
gateway_args = self.module.params['gateway_args'] or ''
pattern = (
r"(?:sshpass -p ([^ ]+))?\s*ssh -o Port=(\d+)\s+-o StrictHostKeyChecking=no\s+"
r"([\w@]+)@([\d.]+)\s+-W %h:%p -q(?: -i (.+))?'"
r"([^@\s]+)@([^\s]+)\s+-W %h:%p -q(?: -i ([^']+))?'"
)
match = re.search(pattern, gateway_args)
if not match:

View File

@@ -1,20 +1,28 @@
import os
from django.template.loader import render_to_string
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, UpdateModelMixin, RetrieveModelMixin
from rest_framework.response import Response
from rest_framework.views import APIView
from common.api import JMSGenericViewSet
from common.permissions import IsValidUser
from common.permissions import OnlySuperUser, IsValidUser
from common.views.template import _get_data_template_path, _get_edit_template_path
from notifications.backends import BACKEND
from notifications.models import SystemMsgSubscription, UserMsgSubscription
from notifications.notifications import CustomMsgTemplateBase
from notifications.notifications import system_msgs
from notifications.serializers import (
SystemMsgSubscriptionSerializer, SystemMsgSubscriptionByCategorySerializer,
UserMsgSubscriptionSerializer,
)
from notifications.serializers import TemplateEditSerializer
__all__ = (
'BackendListView', 'SystemMsgSubscriptionViewSet',
'UserMsgSubscriptionViewSet', 'get_all_test_messages'
'UserMsgSubscriptionViewSet', 'get_all_test_messages', 'TemplateViewSet',
)
@@ -130,3 +138,81 @@ def get_all_test_messages(request):
<hr />
""").format(msg_cls.__name__, msg_text)
return HttpResponse(html_data + text_data)
class TemplateViewSet(JMSGenericViewSet):
permission_classes = [OnlySuperUser]
def list(self, request):
result = []
metas = [cls.as_dict() for cls in CustomMsgTemplateBase._registry]
for meta in metas:
item = {
'template_name': meta['template_name'],
'subject': meta.get('subject', ''),
'contexts': meta.get('contexts', []),
'content': None,
'content_error': None,
'source': None,
}
edit_path = _get_edit_template_path(meta['template_name'])
try:
if os.path.exists(edit_path):
with open(edit_path, 'r', encoding='utf-8') as f:
item['content'] = f.read()
item['source'] = 'data'
else:
ctx = {x.get('name'): x.get('default') for x in item['contexts']}
try:
rendered = render_to_string(meta['template_name'], ctx)
item['content'] = rendered
item['source'] = 'original'
except Exception as e:
item['content_error'] = str(e)
item['source'] = 'original_error'
except Exception as e:
item['content_error'] = str(e)
result.append(item)
return Response(result)
@action(detail=False, methods=['patch'], url_path='edit', name='edit')
def edit(self, request):
"""保存前端编辑的模板内容到 data/template/<template_name> 目录"""
serializer = TemplateEditSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
template_name = serializer.validated_data['template_name']
content = serializer.validated_data['template_content']
render_html = serializer.validated_data['render_html']
data_path = _get_data_template_path(template_name)
edit_path = _get_edit_template_path(template_name)
data_dir = os.path.dirname(data_path)
try:
os.makedirs(data_dir, exist_ok=True)
with open(data_path, 'w', encoding='utf-8') as f:
f.write(render_html)
with open(edit_path, 'w', encoding='utf-8') as f:
f.write(content)
except Exception as e:
return Response({'ok': False, 'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({'ok': True, 'path': data_path})
@action(detail=False, methods=['post'], url_path='reset', name='reset')
def reset(self, request):
template_name = request.data.get('template_name')
if not template_name:
return Response({'ok': False, 'error': 'template_name is required'}, status=status.HTTP_400_BAD_REQUEST)
data_path = _get_data_template_path(template_name)
edit_path = _get_edit_template_path(template_name)
try:
if os.path.exists(data_path) and os.path.isfile(data_path):
os.remove(data_path)
if os.path.exists(edit_path) and os.path.isfile(edit_path):
os.remove(edit_path)
except Exception as e:
return Response({'ok': False, 'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({'ok': True, 'path': data_path})

View File

@@ -54,7 +54,24 @@ def publish_task(receive_user_ids, backends_msg_mapper):
Message.send_msg(receive_user_ids, backends_msg_mapper)
class Message(metaclass=MessageType):
class CustomMsgTemplateBase:
_registry = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls is not CustomMsgTemplateBase and getattr(cls, "template_name", None):
CustomMsgTemplateBase._registry.append(cls)
@classmethod
def as_dict(cls):
return {
"template_name": cls.template_name,
"subject": cls.subject,
"contexts": cls.contexts,
}
class Message(CustomMsgTemplateBase, metaclass=MessageType):
"""
这里封装了什么?
封装不同消息的模板,提供统一的发送消息的接口

View File

@@ -1,3 +1,4 @@
from django.template import Engine, TemplateSyntaxError
from rest_framework import serializers
from common.serializers import BulkModelSerializer
@@ -40,3 +41,17 @@ class UserMsgSubscriptionSerializer(BulkModelSerializer):
class Meta:
model = UserMsgSubscription
fields = ('user_id', 'receive_backends',)
class TemplateEditSerializer(serializers.Serializer):
template_name = serializers.CharField(max_length=256)
template_content = serializers.CharField()
render_html = serializers.CharField()
def validate_template_content(self, value):
safe_engine = Engine(debug=False, libraries={}, builtins=[])
try:
safe_engine.from_string(value)
except TemplateSyntaxError as e:
raise serializers.ValidationError(f'Template syntax error at: {e.token.lineno}')
return value

View File

@@ -10,9 +10,9 @@ router = BulkRouter()
router.register('system-msg-subscription', api.SystemMsgSubscriptionViewSet, 'system-msg-subscription')
router.register('user-msg-subscription', api.UserMsgSubscriptionViewSet, 'user-msg-subscription')
router.register('site-messages', api.SiteMessageViewSet, 'site-message')
router.register('templates', api.TemplateViewSet, 'template')
urlpatterns = [
path('backends/', api.BackendListView.as_view(), name='backends')
path('backends/', api.BackendListView.as_view(), name='backends'),
]
urlpatterns += router.urls

View File

@@ -112,12 +112,21 @@ class JMSInventory:
@staticmethod
def make_protocol_setting_vars(host, protocols):
# 针对 ssh 协议的特殊处理
# 针对 ssh sqlserver 协议的特殊处理
for p in protocols:
if p.name == 'ssh':
if hasattr(p, 'setting'):
setting = getattr(p, 'setting')
host['old_ssh_version'] = setting.get('old_ssh_version', False)
host['jms_asset']['old_ssh_version'] = setting.get('old_ssh_version', False)
if p.name == 'sqlserver':
if hasattr(p, 'setting'):
setting = getattr(p, 'setting')
encryption = setting.get('encrypt', True)
version = setting.get('version', ">=2014")
if version == '<2014':
host['jms_asset']['tds_version'] = '7.0'
if not encryption:
host['jms_asset']['encryption'] = 'off'
def make_account_vars(self, host, asset, account, automation, protocol, platform, gateway, path_dir,
ansible_config):
@@ -226,7 +235,6 @@ class JMSInventory:
})
self.make_protocol_setting_vars(host, protocols)
protocols = host['jms_asset']['protocols']
host['jms_asset'].update({f"{p['name']}_port": p['port'] for p in protocols})
if host['jms_account'] and tp == 'oracle':

View File

@@ -1,11 +1,11 @@
import json
import logging
import os
import sys
import uuid
from collections import defaultdict
from datetime import timedelta, datetime
import sys
from celery import current_task
from django.conf import settings
from django.db import models
@@ -271,7 +271,7 @@ class JobExecution(JMSOrgBaseModel):
db_module_name_map = {
'mysql': 'community.mysql.mysql_query',
'postgresql': 'community.postgresql.postgresql_query',
'sqlserver': 'community.general.mssql_script',
'sqlserver': 'mssql_script',
}
extra_query_token_map = {
'sqlserver': 'script'
@@ -293,6 +293,9 @@ class JobExecution(JMSOrgBaseModel):
"login_password={{login_password}} " \
"login_port={{login_port}} " \
"%s={{login_db}} " % login_db_token
if module == 'mssql_script':
login_args += "encryption={{jms_asset.encryption | default(None) }} " \
"tds_version={{jms_asset.tds_version | default(None) }} "
shell = "{} {}=\"{}\" ".format(login_args, query_token, self.current_job.args)
return module, shell

View File

@@ -3,11 +3,13 @@ from collections import defaultdict
from accounts.const import AliasAccount
from accounts.models import VirtualAccount
from assets.models import Asset, MyAsset
from common.utils import lazyproperty
from common.utils import lazyproperty, get_logger
from orgs.utils import tmp_to_org, tmp_to_root_org
from perms.const import ActionChoices
from .permission import AssetPermissionUtil
logger = get_logger(__name__)
__all__ = ['PermAssetDetailUtil']
@@ -109,7 +111,7 @@ class PermAssetDetailUtil:
alias_action_bit_mapper = {
alias: action_bit
for alias, action_bit in alias_action_bit_mapper.items()
if action_bit
if action_bit and action_bit > 0
}
return alias_action_bit_mapper, alias_date_expired_mapper
@@ -157,7 +159,11 @@ class PermAssetDetailUtil:
virtual_accounts = []
for account, action_bit in cleaned_accounts_action_bit.items():
account.actions = action_bit
account.date_expired = max(cleaned_accounts_expired[account])
all_date_expired = cleaned_accounts_expired[account]
if not all_date_expired:
logger.warning(f"Account {account.username} has no date expired")
continue
account.date_expired = max(all_date_expired)
if account.username.startswith('@'):
virtual_accounts.append(account)

View File

@@ -28,7 +28,7 @@ class RoleViewSet(JMSModelViewSet):
rbac_perms = {
'users': 'rbac.view_rolebinding'
}
default_limit = None
page_no_limit = True
def perform_destroy(self, instance):
from orgs.utils import tmp_to_root_org

View File

@@ -61,7 +61,6 @@ charts_map = {
def export_chart_to_pdf(chart_name, sessionid, request=None):
chart_info = charts_map.get(chart_name)
if not chart_info:
return None, None
@@ -71,7 +70,6 @@ def export_chart_to_pdf(chart_name, sessionid, request=None):
url = urllib.parse.unquote(chart_info['path'])
if settings.DEBUG_DEV:
url = url.replace(":8080", ":9528")
days = request.GET.get('days', 7)
oid = request.COOKIES.get("X-JMS-ORG")
days = request.GET.get('days', 7)
url = url + f"?days={days}&oid={oid}"
@@ -79,7 +77,11 @@ def export_chart_to_pdf(chart_name, sessionid, request=None):
with sync_playwright() as p:
lang = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
browser = p.chromium.launch(headless=True)
context = browser.new_context(viewport={"width": 1040, "height": 800}, locale=lang)
context = browser.new_context(
viewport={"width": 1040, "height": 800},
locale=lang,
ignore_https_errors=True
)
# 设置 sessionid cookie
parsed_url = urlparse(url)
context.add_cookies([
@@ -104,6 +106,7 @@ def export_chart_to_pdf(chart_name, sessionid, request=None):
except Exception as e:
print(f'Playwright error: {e}')
pdf_bytes = None
page_title = chart_info['title']
finally:
browser.close()
return pdf_bytes, page_title

View File

@@ -54,7 +54,7 @@ class LDAPSettingSerializer(LDAPSerializerMixin, serializers.Serializer):
help_text=_('Binding password')
)
AUTH_LDAP_SEARCH_OU = serializers.CharField(
max_length=1024, allow_blank=True, required=False, label=_('Search OU'),
max_length=4096, allow_blank=True, required=False, label=_('Search OU'),
help_text=_(
'User Search Base, if there are multiple OUs, you can separate them with the `|` symbol'
)

View File

@@ -36,7 +36,7 @@ class LDAPHASettingSerializer(LDAPSerializerMixin, serializers.Serializer):
help_text=_('Binding password')
)
AUTH_LDAP_HA_SEARCH_OU = serializers.CharField(
max_length=1024, allow_blank=True, required=False, label=_('Search OU'),
max_length=4096, allow_blank=True, required=False, label=_('Search OU'),
help_text=_(
'User Search Base, if there are multiple OUs, you can separate them with the `|` symbol'
)

View File

@@ -8,7 +8,7 @@ from common.serializers.fields import EncryptedField
__all__ = [
'MailTestSerializer', 'EmailSettingSerializer',
'EmailContentSettingSerializer', 'SMSBackendSerializer',
'EmailContentSettingSerializer', 'SMSBackendSerializer'
]
@@ -35,7 +35,8 @@ class EmailSettingSerializer(serializers.Serializer):
)
EMAIL_HOST_PASSWORD = EncryptedField(
max_length=1024, required=False, label=_("Password"),
help_text=_("Password to use for the email server. It is used in conjunction with `Account` when authenticating to the email server")
help_text=_(
"Password to use for the email server. It is used in conjunction with `Account` when authenticating to the email server")
)
EMAIL_FROM = serializers.CharField(
max_length=128, allow_blank=True, required=False, label=_('Sender'),

View File

@@ -29,6 +29,7 @@ class HostMixin:
('list', 'terminal.view_applethost'),
('retrieve', 'terminal.view_applethost'),
)
page_no_limit = True
def get_permissions(self):
if self.kwargs.get('host') and settings.DEBUG:

View File

@@ -2,6 +2,7 @@
#
import logging
from django.core.cache import cache
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django_filters import rest_framework as filters
@@ -27,11 +28,23 @@ logger = logging.getLogger(__file__)
class TerminalFilterSet(BaseFilterSet):
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
remote_addr = filters.CharFilter(field_name='remote_addr', lookup_expr='icontains')
is_alive = filters.BooleanFilter(method='filter_is_alive')
class Meta:
model = Terminal
fields = ['name', 'remote_addr', 'type']
def filter_is_alive(self, queryset, name, value):
ids = list(queryset.values_list('id', flat=True))
if not ids:
return queryset.none() if value else queryset
alive_ids = [pk for pk in ids if cache.get(Terminal.ALIVE_KEY.format(pk))]
if value:
return queryset.filter(id__in=alive_ids)
else:
return queryset.exclude(id__in=alive_ids)
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
search = self.request.query_params.get('search')

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
#
import uuid
from datetime import datetime
from django.utils import timezone
from rest_framework import generics
from rest_framework.fields import DateTimeField
@@ -217,6 +218,7 @@ class InsecureCommandAlertAPI(generics.CreateAPIView):
cmd_group_mapper = {str(i.id): i for i in cmd_groups}
for command in commands:
command['_time'] = datetime.fromtimestamp(command['timestamp'])
cmd_acl = acl_mapper.get(command['cmd_filter_acl'])
command['_cmd_filter_acl'] = cmd_acl
cmd_group = cmd_group_mapper.get(command['cmd_group'])
@@ -228,6 +230,9 @@ class InsecureCommandAlertAPI(generics.CreateAPIView):
command.update({
'_account': session.account,
'_org_name': session.org.name,
'_protocol': session.protocol,
'_remote_addr': session.remote_addr,
'_login_from': session.get_login_from_display(),
})
if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]:

View File

@@ -36,6 +36,7 @@ class Migration(migrations.Migration):
("RT", "RDP Terminal"),
("WT", "Web Terminal"),
("DT", "DB Terminal"),
("VT", "VNC Terminal"),
],
default="ST",
max_length=2,
@@ -51,6 +52,7 @@ class Migration(migrations.Migration):
("RT", "RDP Terminal"),
("WT", "Web Terminal"),
("DT", "DB Terminal"),
("VT", "VNC Terminal"),
],
default="WT",
max_length=2,

View File

@@ -8,6 +8,7 @@ from common.sdk.im.wecom import wecom_tool
from common.utils import get_logger, reverse
from common.utils import lazyproperty
from common.utils.timezone import local_now_display
from common.views.template import custom_render_to_string
from notifications.backends import BACKEND
from notifications.models import SystemMsgSubscription
from notifications.notifications import SystemMessage, UserMessage
@@ -98,10 +99,15 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage):
cmd_group_name = cmd_group.name if cmd_group else ''
context = {
'recipient': self.user,
'command': command['input'],
'user': command['user'],
'asset': command['asset'],
'account': command.get('_account', ''),
'protocol': command.get('_protocol', ''),
'remote_addr': command.get('_remote_addr', ''),
'login_from': command.get('_login_from', ''),
'time': command.get('_time', ''),
'cmd_filter_acl': cmd_acl_name,
'cmd_group': cmd_group_name,
'risk_level': RiskLevelChoices.get_label(command['risk_level']),
@@ -276,7 +282,17 @@ class StorageConnectivityMessage(SystemMessage):
class SessionSharingMessage(UserMessage):
subject = _('Session sharing')
message_type_label = _('Session sharing')
template_name = 'terminal/_msg_session_sharing.html'
contexts = [
{"name": "asset", "label": _('Asset'), "default": "dev server"},
{"name": "created_by", "label": _('Created by'), "default": "Admin"},
{"name": "account", "label": _('Account'), "default": "root"},
{"name": "url", "label": _('URL'), "default": "http://example.com/session/xxxx"},
{"name": "verify_code", "label": _('Verify code'), "default": "123456"},
{"name": "org", "label": _('Organization'), "default": "Default"},
]
def __init__(self, user, instance):
super().__init__(user)
@@ -285,14 +301,14 @@ class SessionSharingMessage(UserMessage):
def get_html_msg(self) -> dict:
instance = self.instance
context = {
'asset': instance.session.asset,
'asset': str(instance.session.asset),
'created_by': instance.created_by,
'account': instance.session.account,
'account': str(instance.session.account),
'url': instance.url,
'verify_code': instance.verify_code,
'org': instance.org_name,
}
message = render_to_string('terminal/_msg_session_sharing.html', context)
message = custom_render_to_string(self.template_name, context)
return {
'subject': self.message_type_label + ' ' + self.instance.created_by,
'message': message

View File

@@ -46,7 +46,7 @@ class InsecureCommandAlertSerializer(SimpleSessionCommandSerializer):
class Meta(SimpleSessionCommandSerializer.Meta):
fields = SimpleSessionCommandSerializer.Meta.fields + [
'cmd_filter_acl', 'cmd_group',
'cmd_filter_acl', 'cmd_group', 'timestamp'
]
def validate(self, attrs):

View File

@@ -22,6 +22,7 @@ class EndpointSerializer(BulkModelSerializer):
'comment', 'date_created', 'date_updated', 'created_by'
]
extra_kwargs = {
'is_active': {'default': True},
'host': {'help_text': _(
'The host address accessed when connecting to assets, if it is empty, '
'the access address of the current browser will be used '
@@ -71,5 +72,6 @@ class EndpointRuleSerializer(BulkModelSerializer):
'comment', 'date_created', 'date_updated', 'created_by', 'is_active'
]
extra_kwargs = {
'is_active': {'default': True},
'priority': {'default': 50}
}

View File

@@ -1,25 +1,37 @@
{% load i18n %}
<div>
<b>{% trans 'Asset' %}: </b> <span>{{ asset }}</span>
<br/>
<b>{% trans 'User' %}: </b> <span>{{ user }}</span>
<br/>
<b>{% trans 'Account' %}: </b> <span>{{ account }}</span>
<br/>
<b>{% trans 'Risk level' %}: </b><span>{{ risk_level }}</span>
<br/>
<b>{% trans 'Command acl' %}: </b> <span>{{ cmd_filter_acl }}</span>
<br/>
<b>{% trans 'Command group' %}: </b> <span>{{ cmd_group}}</span>
<br/>
{% if session_url %}
<b>{% trans 'Session' %}: </b>
<a href="{{ session_url }}" target="_blank">{% trans 'View' %}</a>
<br/>
<h3>{% trans 'Dear' %}: {{ recipient.name }} [{{ recipient.username }}]</h3>
<hr>
<p>{% trans 'We would like to inform you that a command alert has been triggered with the following details:' %}</p>
<p><strong>{% trans 'Alert details' %}:</strong></p>
<ul>
<li><strong>{% trans 'User' %}:</strong> [{{ user }}]</li>
<li><strong>{% trans 'Asset' %}:</strong> [{{ asset }}]</li>
<li><strong>{% trans 'Account' %}:</strong> [{{ account }}]</li>
{% if remote_addr %}
<li><strong>IP:</strong> [{{ remote_addr }}]</li>
{% endif %}
<b>{% trans 'Organization' %}: </b> <span>{{ org }}</span>
<br/>
<b>{% trans 'Command' %}: </b><span>{{ command }}</span>
<br/>
</div>
{% if login_from %}
<li><strong>{% trans 'Login from' %}:</strong> [{{ login_from }}]</li>
{% endif %}
{% if protocol %}
<li><strong>{% trans 'Protocol' %}:</strong> [{{ protocol }}]</li>
{% endif %}
<li><strong>{% trans 'Risk level' %}:</strong> [{{ risk_level }}]</li>
<li><strong>{% trans 'Command acl' %}:</strong> [{{ cmd_filter_acl }}]</li>
<li><strong>{% trans 'Command group' %}:</strong> [{{ cmd_group }}]</li>
{% if session_url %}
<li><strong>{% trans 'Session' %}:</strong> <a href="{{ session_url }}" target="_blank">{% trans 'View session' %}</a></li>
{% endif %}
<li><strong>{% trans 'Organization' %}:</strong> [{{ org }}]</li>
<li><strong>{% trans 'Command' %}:</strong> [{{ command }}]</li>
{% if time %}
<li><strong>{% trans 'Time' %}:</strong> [{{ time }}]</li>
{% endif %}
</ul>
<hr>
<p>{% trans 'Please review this command execution to ensure it complies with your organizations security policies. If you did not authorize this action or notice anything unusual, please take the necessary actions immediately.' %}</p>
<p>{% trans 'Thank you for your attention to this matter' %}</p>

Some files were not shown because too many files have changed in this diff Show More