hiddifypanel 10.50.5.dev0__py3-none-any.whl → 10.60.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/hutils/flask.py +5 -3
- hiddifypanel/hutils/network/net.py +22 -11
- hiddifypanel/hutils/proxy/singbox.py +13 -0
- hiddifypanel/hutils/proxy/xray.py +3 -0
- hiddifypanel/models/config_enum.py +114 -114
- hiddifypanel/panel/admin/Actions.py +1 -1
- hiddifypanel/panel/admin/DomainAdmin.py +2 -2
- hiddifypanel/panel/admin/ProxyAdmin.py +1 -1
- hiddifypanel/panel/admin/SettingAdmin.py +2 -2
- hiddifypanel/panel/admin/templates/config.html +129 -1
- hiddifypanel/panel/commercial/restapi/v1/__init__.py +1 -1
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +6 -0
- hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +2 -2
- hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +9 -1
- hiddifypanel/panel/commercial/telegrambot/__init__.py +1 -1
- hiddifypanel/panel/common.py +3 -1
- hiddifypanel/panel/custom_widgets.py +3 -0
- hiddifypanel/panel/hiddify.py +7 -4
- hiddifypanel/panel/init_db.py +4 -0
- hiddifypanel/panel/usage.py +2 -2
- hiddifypanel/panel/user/user.py +38 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +9 -2
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +7 -2
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +7 -2
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +7 -2
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +7 -2
- hiddifypanel/translations.i18n/en.json +2 -1
- hiddifypanel/translations.i18n/fa.json +2 -1
- hiddifypanel/translations.i18n/pt.json +2 -1
- hiddifypanel/translations.i18n/ru.json +2 -1
- hiddifypanel/translations.i18n/zh.json +2 -1
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/METADATA +1 -1
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/RECORD +44 -44
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/WHEEL +1 -1
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-10.50.5.dev0.dist-info → hiddifypanel-10.60.0.dev0.dist-info}/top_level.txt +0 -0
@@ -26,7 +26,8 @@
|
|
26
26
|
|
27
27
|
|
28
28
|
<div class="card">
|
29
|
-
<div class="card-header"><input id="search_settings" type="text" class="form-control" placeholder="{{_(" Search
|
29
|
+
<div class="card-header"><input id="search_settings" type="text" class="form-control" placeholder="{{_(" Search
|
30
|
+
Settings")}}">
|
30
31
|
</div>
|
31
32
|
<div class="card-body">
|
32
33
|
<div class="row">
|
@@ -81,6 +82,133 @@
|
|
81
82
|
|
82
83
|
{% block tail %}
|
83
84
|
{{super()}}
|
85
|
+
<link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/42.0.2/ckeditor5.css">
|
86
|
+
<style>
|
87
|
+
.ck.ck-editor {
|
88
|
+
color: black !important;
|
89
|
+
}
|
90
|
+
</style>
|
91
|
+
<script src="https://cdn.ckeditor.com/ckeditor5/42.0.2/ckeditor5.js"></script>
|
92
|
+
|
93
|
+
<script type="importmap">
|
94
|
+
{
|
95
|
+
"imports": {
|
96
|
+
"ckeditor5": "https://cdn.ckeditor.com/ckeditor5/42.0.2/ckeditor5.js",
|
97
|
+
"ckeditor5/": "https://cdn.ckeditor.com/ckeditor5/42.0.2/"
|
98
|
+
}
|
99
|
+
}
|
100
|
+
</script>
|
101
|
+
<script type="module">
|
102
|
+
import {
|
103
|
+
ClassicEditor,
|
104
|
+
AccessibilityHelp,
|
105
|
+
Autosave,
|
106
|
+
BalloonToolbar,
|
107
|
+
Bold,
|
108
|
+
Code,
|
109
|
+
Essentials,
|
110
|
+
FontBackgroundColor,
|
111
|
+
FontColor,
|
112
|
+
FontFamily,
|
113
|
+
FontSize,
|
114
|
+
FullPage,
|
115
|
+
GeneralHtmlSupport,
|
116
|
+
Highlight,
|
117
|
+
HtmlComment,
|
118
|
+
HtmlEmbed,
|
119
|
+
Italic,
|
120
|
+
Paragraph,
|
121
|
+
SelectAll,
|
122
|
+
ShowBlocks,
|
123
|
+
SourceEditing,
|
124
|
+
SpecialCharacters,
|
125
|
+
Strikethrough,
|
126
|
+
ImageBlock,
|
127
|
+
ImageInsert,
|
128
|
+
ImageInsertViaUrl,
|
129
|
+
ImageToolbar,
|
130
|
+
|
131
|
+
Underline,
|
132
|
+
Undo
|
133
|
+
} from 'ckeditor5';
|
134
|
+
|
135
|
+
const editorConfig = {
|
136
|
+
toolbar: {
|
137
|
+
items: [
|
138
|
+
'undo',
|
139
|
+
'redo',
|
140
|
+
'|',
|
141
|
+
'bold',
|
142
|
+
'italic',
|
143
|
+
'underline',
|
144
|
+
'strikethrough',
|
145
|
+
'code',
|
146
|
+
'insertImage',
|
147
|
+
'|',
|
148
|
+
'fontSize',
|
149
|
+
'fontColor',
|
150
|
+
'fontBackgroundColor',
|
151
|
+
'|',
|
152
|
+
'sourceEditing',
|
153
|
+
|
154
|
+
],
|
155
|
+
shouldNotGroupWhenFull: false
|
156
|
+
},
|
157
|
+
plugins: [
|
158
|
+
AccessibilityHelp,
|
159
|
+
Autosave,
|
160
|
+
BalloonToolbar,
|
161
|
+
Bold,
|
162
|
+
Code,
|
163
|
+
Essentials,
|
164
|
+
FontBackgroundColor,
|
165
|
+
FontColor,
|
166
|
+
FontFamily,
|
167
|
+
FontSize,
|
168
|
+
FullPage,
|
169
|
+
GeneralHtmlSupport,
|
170
|
+
Highlight,
|
171
|
+
HtmlComment,
|
172
|
+
HtmlEmbed,
|
173
|
+
Italic,
|
174
|
+
Paragraph,
|
175
|
+
SelectAll,
|
176
|
+
ShowBlocks,
|
177
|
+
SourceEditing,
|
178
|
+
ImageBlock,
|
179
|
+
ImageInsertViaUrl,
|
180
|
+
|
181
|
+
Strikethrough,
|
182
|
+
Underline,
|
183
|
+
Undo
|
184
|
+
],
|
185
|
+
balloonToolbar: ['bold', 'italic'],
|
186
|
+
fontFamily: {
|
187
|
+
supportAllValues: true
|
188
|
+
},
|
189
|
+
fontSize: {
|
190
|
+
options: [10, 12, 14, 'default', 18, 20, 22],
|
191
|
+
supportAllValues: true
|
192
|
+
},
|
193
|
+
htmlSupport: {
|
194
|
+
allow: [
|
195
|
+
{
|
196
|
+
name: /^.*$/,
|
197
|
+
styles: true,
|
198
|
+
attributes: true,
|
199
|
+
classes: true
|
200
|
+
}
|
201
|
+
]
|
202
|
+
},
|
203
|
+
|
204
|
+
placeholder: 'Type or paste your content here!'
|
205
|
+
};
|
206
|
+
|
207
|
+
ClassicEditor.create(document.querySelector('.ckeditor'), editorConfig);
|
208
|
+
|
209
|
+
|
210
|
+
</script>
|
211
|
+
|
84
212
|
<script>
|
85
213
|
// $("fieldset .form-group").hide()
|
86
214
|
|
@@ -5,7 +5,7 @@ from marshmallow import Schema, fields
|
|
5
5
|
|
6
6
|
from apiflask import APIBlueprint
|
7
7
|
from flask_restful import Api
|
8
|
-
from .tgbot import bot, register_bot, TGBotResource
|
8
|
+
from .tgbot import bot, register_bot, register_bot_cached, TGBotResource
|
9
9
|
from . import tgbot
|
10
10
|
from .tgmsg import SendMsgResource
|
11
11
|
from .resources import *
|
@@ -5,6 +5,7 @@ from flask_restful import Resource
|
|
5
5
|
|
6
6
|
from hiddifypanel.models import *
|
7
7
|
from hiddifypanel import Events
|
8
|
+
from hiddifypanel.cache import cache
|
8
9
|
logger = telebot.logger
|
9
10
|
|
10
11
|
|
@@ -17,6 +18,11 @@ bot = telebot.TeleBot("", parse_mode="HTML", threaded=False, exception_handler=E
|
|
17
18
|
bot.username = ''
|
18
19
|
|
19
20
|
|
21
|
+
@cache.cache(1000)
|
22
|
+
def register_bot_cached(set_hook=False, remove_hook=False):
|
23
|
+
return register_bot(set_hook, remove_hook)
|
24
|
+
|
25
|
+
|
20
26
|
def register_bot(set_hook=False, remove_hook=False):
|
21
27
|
try:
|
22
28
|
global bot
|
@@ -35,8 +35,8 @@ class UserApi(MethodView):
|
|
35
35
|
for field in User.__table__.columns.keys(): # type: ignore
|
36
36
|
if field in ['id', 'expiry_time']:
|
37
37
|
continue
|
38
|
-
if field
|
39
|
-
|
38
|
+
# if field in data:
|
39
|
+
# setattr(user, field, data[field])
|
40
40
|
data['old_uuid'] = uuid
|
41
41
|
user_driver.remove_client(user)
|
42
42
|
dbuser = User.add_or_update(**data) or abort(502, "Unknown issue! User is not patched")
|
@@ -108,7 +108,15 @@ class AllConfigsAPI(MethodView):
|
|
108
108
|
)
|
109
109
|
)
|
110
110
|
|
111
|
-
|
111
|
+
if hconfig(ConfigEnum.wireguard_enable):
|
112
|
+
items.append(
|
113
|
+
create_item(
|
114
|
+
"Wireguard", "Wireguard", "", "", "", "",
|
115
|
+
# f"{base_url}singbox.json?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
|
116
|
+
f"{base_url}wireguard/#{config_name}"
|
117
|
+
)
|
118
|
+
)
|
119
|
+
# Add Singbox: SSh
|
112
120
|
if hconfig(ConfigEnum.sub_singbox_ssh_enable) and hconfig(ConfigEnum.ssh_server_enable):
|
113
121
|
items.append(
|
114
122
|
create_item(
|
hiddifypanel/panel/common.py
CHANGED
@@ -10,6 +10,7 @@ import hiddifypanel.auth as auth
|
|
10
10
|
from hiddifypanel.auth import current_account
|
11
11
|
from apiflask import APIFlask, HTTPError, abort
|
12
12
|
from hiddifypanel import hutils
|
13
|
+
from loguru import logger
|
13
14
|
|
14
15
|
|
15
16
|
def init_app(app: APIFlask):
|
@@ -36,6 +37,7 @@ def init_app(app: APIFlask):
|
|
36
37
|
|
37
38
|
@app.errorhandler(Exception)
|
38
39
|
def internal_server_error(e):
|
40
|
+
logger.exception(e)
|
39
41
|
if isinstance(e, Exception):
|
40
42
|
if hutils.flask.is_api_call(request.path):
|
41
43
|
return {
|
@@ -181,4 +183,4 @@ def init_app(app: APIFlask):
|
|
181
183
|
with app.app_context():
|
182
184
|
import hiddifypanel.panel.commercial.telegrambot as telegrambot
|
183
185
|
if (not telegrambot.bot) or (not telegrambot.bot.username): # type: ignore
|
184
|
-
telegrambot.
|
186
|
+
telegrambot.register_bot_cached(set_hook=True)
|
@@ -47,6 +47,8 @@ class LastResetField(IntegerField):
|
|
47
47
|
|
48
48
|
|
49
49
|
class CKTextAreaWidget(TextArea):
|
50
|
+
extra_js = ['//cdn.ckeditor.com/4.6.0/standard/ckeditor.js']
|
51
|
+
|
50
52
|
def __call__(self, field, **kwargs):
|
51
53
|
if kwargs.get('class'):
|
52
54
|
kwargs['class'] += ' ckeditor'
|
@@ -56,6 +58,7 @@ class CKTextAreaWidget(TextArea):
|
|
56
58
|
|
57
59
|
|
58
60
|
class CKTextAreaField(TextAreaField):
|
61
|
+
extra_js = ['//cdn.ckeditor.com/4.6.0/standard/ckeditor.js']
|
59
62
|
widget = CKTextAreaWidget()
|
60
63
|
|
61
64
|
|
hiddifypanel/panel/hiddify.py
CHANGED
@@ -110,17 +110,20 @@ def reinstall_action(complete_install=False, domain_changed=False, do_update=Fal
|
|
110
110
|
def check_need_reset(old_configs, do=False):
|
111
111
|
restart_mode = ApplyMode.nothing
|
112
112
|
for c in old_configs:
|
113
|
+
if c.apply_mode == ApplyMode.nothing:
|
114
|
+
continue
|
113
115
|
# c=ConfigEnum(c)
|
114
|
-
if
|
115
|
-
|
116
|
-
|
116
|
+
if restart_mode == ApplyMode.reinstall:
|
117
|
+
break
|
118
|
+
if old_configs[c] != hconfig(c):
|
119
|
+
restart_mode = c.apply_mode
|
117
120
|
if old_configs[ConfigEnum.proxy_path_admin] != hconfig(ConfigEnum.proxy_path_admin):
|
118
121
|
g.new_proxy_path = hconfig(ConfigEnum.proxy_path_admin)
|
119
122
|
g.force_proxy_path = g.proxy_path
|
120
123
|
# do_full_install=old_config[ConfigEnum.telegram_lib]!=hconfig(ConfigEnum.telegram_lib)
|
121
124
|
if old_configs[ConfigEnum.package_mode] != hconfig(ConfigEnum.package_mode):
|
122
125
|
return reinstall_action(do_update=True)
|
123
|
-
if not (do and restart_mode == ApplyMode.
|
126
|
+
if not (do and restart_mode == ApplyMode.reinstall):
|
124
127
|
return hutils.flask.flash_config_success(restart_mode=restart_mode, domain_changed=False)
|
125
128
|
|
126
129
|
return reinstall_action(complete_install=True, domain_changed=False)
|
hiddifypanel/panel/init_db.py
CHANGED
hiddifypanel/panel/usage.py
CHANGED
@@ -71,8 +71,8 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
|
|
71
71
|
db.session.add(daily_usage[adm.id])
|
72
72
|
changes = True
|
73
73
|
daily_usage[adm.id].online = User.query.filter(User.added_by == adm.id).filter(func.DATE(User.last_online) == today).count()
|
74
|
-
if changes:
|
75
|
-
|
74
|
+
# if changes:
|
75
|
+
# db.session.commit()
|
76
76
|
_reset_priodic_usage()
|
77
77
|
|
78
78
|
# userDetails = {p.user_id: p for p in UserDetail.query.filter(UserDetail.child_id == child_id).all()}
|
hiddifypanel/panel/user/user.py
CHANGED
@@ -73,6 +73,44 @@ class UserView(FlaskView):
|
|
73
73
|
'''Returns singbox client JSON config (ssh)'''
|
74
74
|
return self.singbox_ssh_imp()
|
75
75
|
|
76
|
+
@route("/wireguard/")
|
77
|
+
@route("/wireguard")
|
78
|
+
@login_required(roles={Role.user})
|
79
|
+
def wireguard(self):
|
80
|
+
'''Returns wireguard client config'''
|
81
|
+
c = get_common_data(g.account.uuid, 'new')
|
82
|
+
wireguards = []
|
83
|
+
servers = set()
|
84
|
+
for pinfo in hutils.proxy.get_valid_proxies(c['domains']):
|
85
|
+
if pinfo['proto'] != ProxyProto.wireguard:
|
86
|
+
continue
|
87
|
+
wireguards.append(pinfo)
|
88
|
+
|
89
|
+
servers.add(pinfo['server'])
|
90
|
+
|
91
|
+
if not len(wireguards):
|
92
|
+
abort(404)
|
93
|
+
wg = wireguards[0]
|
94
|
+
addrs = f"{wg['wg_ipv4']}/32"
|
95
|
+
if wg['wg_ipv6']:
|
96
|
+
addrs += f", {wg['wg_ipv6']}/128"
|
97
|
+
resp = f"""
|
98
|
+
[Interface]
|
99
|
+
PrivateKey = {wg['wg_pk']}
|
100
|
+
Address = {addrs}
|
101
|
+
DNS = 1.1.1.1
|
102
|
+
MTU = 1390
|
103
|
+
|
104
|
+
[Peer]
|
105
|
+
PublicKey = {wg['wg_pub']}
|
106
|
+
PresharedKey = {wg['wg_psk']}
|
107
|
+
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1
|
108
|
+
Endpoint = {next(iter(servers))}:61339 #{servers}
|
109
|
+
"""
|
110
|
+
return add_headers(resp, c)
|
111
|
+
|
112
|
+
# return self.singbox_ssh_imp()
|
113
|
+
|
76
114
|
@route("/clash/")
|
77
115
|
@route("/clash")
|
78
116
|
@login_required(roles={Role.user})
|
Binary file
|
@@ -2,8 +2,12 @@
|
|
2
2
|
msgid ""
|
3
3
|
msgstr ""
|
4
4
|
|
5
|
-
msgid "
|
6
|
-
|
5
|
+
msgid ""
|
6
|
+
" Search\n"
|
7
|
+
" Settings"
|
8
|
+
msgstr ""
|
9
|
+
" Search\n"
|
10
|
+
" Settings"
|
7
11
|
|
8
12
|
msgid "%(count)s records were successfully disabled."
|
9
13
|
msgstr "%(count)s records were successfully disabled."
|
@@ -670,6 +674,9 @@ msgstr "Select this option to restore All Users"
|
|
670
674
|
msgid "Root"
|
671
675
|
msgstr "Root"
|
672
676
|
|
677
|
+
msgid "Russia"
|
678
|
+
msgstr "Russia"
|
679
|
+
|
673
680
|
msgid "Save"
|
674
681
|
msgstr "Save"
|
675
682
|
|
Binary file
|
@@ -2,8 +2,10 @@
|
|
2
2
|
msgid ""
|
3
3
|
msgstr ""
|
4
4
|
|
5
|
-
msgid "
|
6
|
-
|
5
|
+
msgid ""
|
6
|
+
" Search\n"
|
7
|
+
" Settings"
|
8
|
+
msgstr ""
|
7
9
|
|
8
10
|
msgid "%(count)s records were successfully disabled."
|
9
11
|
msgstr "%(count)s رکورد با موفقیت غیرفعال شد."
|
@@ -654,6 +656,9 @@ msgstr "برای بازگرداندن کاربران از این گزینه اس
|
|
654
656
|
msgid "Root"
|
655
657
|
msgstr "ریشه"
|
656
658
|
|
659
|
+
msgid "Russia"
|
660
|
+
msgstr ""
|
661
|
+
|
657
662
|
msgid "Save"
|
658
663
|
msgstr "ذخیره"
|
659
664
|
|
Binary file
|
@@ -2,8 +2,10 @@
|
|
2
2
|
msgid ""
|
3
3
|
msgstr ""
|
4
4
|
|
5
|
-
msgid "
|
6
|
-
|
5
|
+
msgid ""
|
6
|
+
" Search\n"
|
7
|
+
" Settings"
|
8
|
+
msgstr ""
|
7
9
|
|
8
10
|
msgid "%(count)s records were successfully disabled."
|
9
11
|
msgstr "%(count)s registros foram desativados com sucesso."
|
@@ -609,6 +611,9 @@ msgstr "Selecione esta opção para restaurar todos os usuários"
|
|
609
611
|
msgid "Root"
|
610
612
|
msgstr "Raíz"
|
611
613
|
|
614
|
+
msgid "Russia"
|
615
|
+
msgstr ""
|
616
|
+
|
612
617
|
msgid "Save"
|
613
618
|
msgstr "Salvar"
|
614
619
|
|
Binary file
|
@@ -2,8 +2,10 @@
|
|
2
2
|
msgid ""
|
3
3
|
msgstr ""
|
4
4
|
|
5
|
-
msgid "
|
6
|
-
|
5
|
+
msgid ""
|
6
|
+
" Search\n"
|
7
|
+
" Settings"
|
8
|
+
msgstr ""
|
7
9
|
|
8
10
|
msgid "%(count)s records were successfully disabled."
|
9
11
|
msgstr "%(count)s записей были успешно отключены."
|
@@ -668,6 +670,9 @@ msgstr "Выберите этот вариант, чтобы восстанов
|
|
668
670
|
msgid "Root"
|
669
671
|
msgstr "Root"
|
670
672
|
|
673
|
+
msgid "Russia"
|
674
|
+
msgstr ""
|
675
|
+
|
671
676
|
msgid "Save"
|
672
677
|
msgstr "Сохранить"
|
673
678
|
|
Binary file
|
@@ -2,8 +2,10 @@
|
|
2
2
|
msgid ""
|
3
3
|
msgstr ""
|
4
4
|
|
5
|
-
msgid "
|
6
|
-
|
5
|
+
msgid ""
|
6
|
+
" Search\n"
|
7
|
+
" Settings"
|
8
|
+
msgstr ""
|
7
9
|
|
8
10
|
msgid "%(count)s records were successfully disabled."
|
9
11
|
msgstr "%(count)s 条记录已成功禁用。"
|
@@ -647,6 +649,9 @@ msgstr "选择此选项可恢复所有用户"
|
|
647
649
|
msgid "Root"
|
648
650
|
msgstr "根用户"
|
649
651
|
|
652
|
+
msgid "Russia"
|
653
|
+
msgstr ""
|
654
|
+
|
650
655
|
msgid "Save"
|
651
656
|
msgstr "保存"
|
652
657
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
" Search
|
2
|
+
" Search\n Settings": " Search\n Settings",
|
3
3
|
"%(count)s records were successfully disabled.": "%(count)s records were successfully disabled.",
|
4
4
|
"%(count)s records were successfully enabled.": "%(count)s records were successfully enabled.",
|
5
5
|
"%(expire_days)s days": "%(expire_days)s days",
|
@@ -172,6 +172,7 @@
|
|
172
172
|
"Restore Users": "👥 Restore Users",
|
173
173
|
"Restore Users description": "Select this option to restore All Users",
|
174
174
|
"Root": "Root",
|
175
|
+
"Russia": "Russia",
|
175
176
|
"Save": "Save",
|
176
177
|
"Save & Add More": "Save & Add More",
|
177
178
|
"Save Link": "Save Link",
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
" Search
|
2
|
+
" Search\n Settings": "",
|
3
3
|
"%(count)s records were successfully disabled.": "%(count)s رکورد با موفقیت غیرفعال شد.",
|
4
4
|
"%(count)s records were successfully enabled.": "%(count)s رکوردها با موفقیت فعال شد.",
|
5
5
|
"%(expire_days)s days": "%(expire_days)s روز",
|
@@ -172,6 +172,7 @@
|
|
172
172
|
"Restore Users": "👥 بازیابی کاربران",
|
173
173
|
"Restore Users description": "برای بازگرداندن کاربران از این گزینه استفاده کنید.",
|
174
174
|
"Root": "ریشه",
|
175
|
+
"Russia": "",
|
175
176
|
"Save": "ذخیره",
|
176
177
|
"Save & Add More": "ذخیره و افزودن مورد دیگر",
|
177
178
|
"Save Link": "این لینک را در محلی ذخیره نمایید.",
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
" Search
|
2
|
+
" Search\n Settings": "",
|
3
3
|
"%(count)s records were successfully disabled.": "%(count)s registros foram desativados com sucesso.",
|
4
4
|
"%(count)s records were successfully enabled.": "%(count)s registros foram ativados com sucesso.",
|
5
5
|
"%(expire_days)s days": "",
|
@@ -172,6 +172,7 @@
|
|
172
172
|
"Restore Users": "👥 Restaurar usuários",
|
173
173
|
"Restore Users description": "Selecione esta opção para restaurar todos os usuários",
|
174
174
|
"Root": "Raíz",
|
175
|
+
"Russia": "",
|
175
176
|
"Save": "Salvar",
|
176
177
|
"Save & Add More": "Salvar e adicionar mais",
|
177
178
|
"Save Link": "Link salvo",
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
" Search
|
2
|
+
" Search\n Settings": "",
|
3
3
|
"%(count)s records were successfully disabled.": "%(count)s записей были успешно отключены.",
|
4
4
|
"%(count)s records were successfully enabled.": "%(count)s записей были успешно включены.",
|
5
5
|
"%(expire_days)s days": "с дней",
|
@@ -172,6 +172,7 @@
|
|
172
172
|
"Restore Users": "👥 Восстановление пользователей",
|
173
173
|
"Restore Users description": "Выберите этот вариант, чтобы восстановить всех пользователей",
|
174
174
|
"Root": "Root",
|
175
|
+
"Russia": "",
|
175
176
|
"Save": "Сохранить",
|
176
177
|
"Save & Add More": "Сохранить и добавить еще",
|
177
178
|
"Save Link": "Сохранить ссылку",
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
" Search
|
2
|
+
" Search\n Settings": "",
|
3
3
|
"%(count)s records were successfully disabled.": "%(count)s 条记录已成功禁用。",
|
4
4
|
"%(count)s records were successfully enabled.": "%(count)s 条记录已成功启用。",
|
5
5
|
"%(expire_days)s days": "",
|
@@ -172,6 +172,7 @@
|
|
172
172
|
"Restore Users": "👥 恢复用户",
|
173
173
|
"Restore Users description": "选择此选项可恢复所有用户",
|
174
174
|
"Root": "根用户",
|
175
|
+
"Russia": "",
|
175
176
|
"Save": "保存",
|
176
177
|
"Save & Add More": "保存并添加更多",
|
177
178
|
"Save Link": "保存链接",
|