From 0c8533257d7904fc5722ad21dce286cdf860a31d Mon Sep 17 00:00:00 2001 From: "s.galanskiy" Date: Wed, 16 Jul 2025 13:48:34 +0500 Subject: [PATCH] =?UTF-8?q?=D0=AD=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D0=BA=D1=80=D0=B5=D1=82=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D1=81=D0=B5=D1=82=D0=B5=D0=B9.=20=D0=9E?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BB=D0=B5=D0=B9=20=D1=83=D1=87=D0=B8=D1=82?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=8F=20=D0=B6=D1=82=D0=B8=20=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- SRV/.gitignore | 3 +- SRV/api/v1/settings.py | 12 ++++--- SRV/locales/en/LC_MESSAGES/messages.mo | Bin 11406 -> 11515 bytes SRV/locales/en/LC_MESSAGES/messages.po | 43 ++++++++++++++----------- SRV/locales/messages.pot | 41 ++++++++++++----------- SRV/locales/ru/LC_MESSAGES/messages.mo | Bin 14115 -> 14247 bytes SRV/locales/ru/LC_MESSAGES/messages.po | 43 ++++++++++++++----------- 8 files changed, 81 insertions(+), 63 deletions(-) diff --git a/.gitignore b/.gitignore index ea15021..5bc94dd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,5 @@ __pycache__ .wheels .vendor .python3-deb -SRV/storage/devices/devices.json +SRV/storage/subnets/* SRV/storage/wifi/wifi.json \ No newline at end of file diff --git a/SRV/.gitignore b/SRV/.gitignore index 9cb3d81..20dffb4 100644 --- a/SRV/.gitignore +++ b/SRV/.gitignore @@ -6,4 +6,5 @@ __pycache__ .wheels .vendor .python3-deb -storage/devices/ \ No newline at end of file +storage/subnets/ +storage/wifi/ \ No newline at end of file diff --git a/SRV/api/v1/settings.py b/SRV/api/v1/settings.py index 94cbdb6..a6d9f23 100644 --- a/SRV/api/v1/settings.py +++ b/SRV/api/v1/settings.py @@ -1,11 +1,12 @@ import os import logging from typing import Optional -from fastapi import APIRouter, HTTPException, Depends, Response, Request +from fastapi import APIRouter, HTTPException, Depends, Response, Request, Body from starlette.responses import FileResponse from services.settings_service import SettingsService from utils.i18n import get_translations from babel.support import Translations +from models.subnet import SubnetScanRequest # Предполагается, что модель определена logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) @@ -96,13 +97,13 @@ def clear_all_data(translations: Translations = Depends(get_translations())): DEVICE_PATH = "storage/devices/devices.json" WIFI_PATH = "storage/wifi/wifi.json" -@router.get("/export_devices", response_class=FileResponse) -async def export_devices(subnet: str, translations: Translations = Depends(get_translations())): +@router.post("/export_devices", response_class=FileResponse) +async def export_devices(request: SubnetScanRequest = Body(...), translations: Translations = Depends(get_translations())): """ Экспортирует файл с данными устройств в формате JSON для указанной подсети. Args: - subnet (str): Подсеть в формате CIDR (например, "10.1.1.0/24"). + request (SubnetScanRequest): Объект с полем subnet в формате CIDR. translations: Объект переводов для текущего языка. Returns: @@ -111,10 +112,11 @@ async def export_devices(subnet: str, translations: Translations = Depends(get_t Raises: HTTPException: Если файл не найден (status_code=404). """ + subnet = request.subnet file_path = f"storage/subnets/{subnet.replace('/', '_')}.json" if not os.path.exists(file_path): logger.warning(f"Export file not found: {file_path}") - raise HTTPException(status_code=404, detail=translations.gettext("Файл не найден")) + raise HTTPException(status_code=404, detail=translations.gettext("Файл для подсети {subnet} не найден").format(subnet=subnet)) logger.info(f"Exporting file: {file_path}") return FileResponse( path=file_path, diff --git a/SRV/locales/en/LC_MESSAGES/messages.mo b/SRV/locales/en/LC_MESSAGES/messages.mo index dcae5aa0bc647cfc08cfe189a17b0cdd1c3078bb..1bdfb80613c97a46b02d3c64f3c327791af0ebd7 100644 GIT binary patch delta 1830 zcmYM!TS!$|9LMp$rlyrso*FG1Pdl?Rok=OR9M3dTcK39%2*WOf9_qydsRf0c3W&SzcrUhBX9YpwH7^~dVi zKp^3$@!8JzC%(1ARQvupon$tGYC9(5IgH0^I2C(QuMGMQ`M$vf+TZzp#F^A>xEVz& zz!bBXl~7nlLpd(TKd}_=VL7HTYXz=BJ=ca|e2PU_$S6y(4lD7DU;p2)FCzNIw6~(3 zdx)!X>PWLH=C@rGLNwgO-!XZVSspII8f?G_x>$yDQoR5hFq?WiE>u6x!t@`!372A+ z`e9s$kNx)I(Ov+}xSaXz4uxenag13BMz9?J!+AJ>1(=oQ^@njH^%hjX$1okA-~xP) zykcbmvu#+3Q?Lh>*$2L3$C7_d5T;O!f1v`nj!M-BRO%Ou^8)z;bEw}yJ^upreD;rC z>Z?&1JBfR77*Q2r3u*!9u^gYH#?8wh|MMwCGrZJxq6Qv9MVvF<8(<0kM!gwl;ziVR zgQyic6U=_agII~Zs4Yy(G|R`3?>4NaegtRXP$v2Rg~DX=DOaK*ZN^pDj+*GR-(SQP zSx21DP}eEW@l5nh z!2~l)^$j3nTL$Vn6(a}ULijT-LWZ&iWKL^EUDr;`!TYG^VxK4|6?v1%0&e7|P#vfT zJ5c@oI1Q7DQvC(KTTq!h?0W@gP=ATv0%RZAO)Ey7g)l0^`;h=+)=7cv+Fj&a*buU< zmdNZJWDBD9un;v+4Jz_RbnrM%$LoH55ZM(Q$#OMrE-Dihn2WWj{=dH&Gdo2gm4+Lr z0QymT^a2^n-eLkyVEKzNh+GVdp!R$>YQUqYm3JbGw@0W6zaT?cE>SAb75q536UQ;X zwNX%nr;)|mEz~K0jk9qQqtsv(YT^#xUepTjqf-4AHBo>l*e#oj>fe9?+=*NaJBSMW z1jaPrWeQrsT`a>_sFmk)hvX{c&&!%n1GS)5*oGB&0hPHgr~uO0F9$=YE!&86SrclZ z$58KI&F7Nn@I0eIhboPYRmXhPgmoCgM%2J(Q5m||^>5Oi^nz~pV&5Uhz2aVWyZiRJ zJ$?J#bIzWIrmgjLjm?gG$?efkhkM@bc6;1QT`5^raq+WDTQ>!#LDzxcuGFkZbcf@; U@%_#EXrmK}Hr3a*zRz#_3W&Mn5&!@I delta 1740 zcmYM!eN4?!9LMo*brlhHqloHC<)Mo_)IzCM){-_4^U!8vY`L?w`6J|M*W=ilNZ4!| zLst2VGJj-Z{)l;;@dvXzY%v_s8#S?z;DNzQ5o3o%8*D&pG|BYpDxI{Jt~B zC&YIW-}Nzy{(sKLn#B{g<8bW6XuOU&*o%7PjWgo>fIhAdI)`u;@i*kpGULofn1wBu z#!@ciV-4=X1vr3Z7{#oWSdQv<6l?JX&c^_wRO4z~h8JA?#l?kWU&Zx9sD6)d1&$kO zwu<>}3yoqf^kFIf#2HvLifZ6ytjD{!2&X1^32w$L;&xo3`#2Y4M|%@4z*^!1xEi0i z>p5e*1RAi0`K_PEQXH9RR)}k`43Fbte2TL%A<4U6f)j}wQ3;>K6nu^q_z8K$^8DVi z7ULA+4pe0yI%ATlza}W5QGk0<3EV)H>NBeJ^Tv9KG+{RJEmZ%vsQ&(OUg@h*6+4Uj z@dwVwMzYfjbYU63Mva@6O8v`eY)JJ=dkG7OBdCnWj`s#A!V=;JoQ2m={oY^*6DOE0 z#9gR8(2H8as5Gj8LFYQGBR-6CF_K38XVOTbp0X5`X#+0DcGN^)-TiEi$Xeo+xBX?R5OV@(x*Mq7+_#KVOG?Mwr#{yKxdQ^vI%*8wI{zqpD zS*v1I&h0pz_%i-W5LrbVLhXSV)>D-&LM0eNiW;_KG}sSz1zAq(LpHFzM6KN*Y9K#Z zDf1Z^z_mCPn_PSmSq-~~3~Uk9M89wvrcnmnuW)X}1m?GWG?YLyYK<--&saD5@EPhK z$V=ov*d)rKHP1&4Sc7`=5c0Bi3N_(PH*7(bx*Ijo17vmVtGk~_R(|3jav-b}m3SR$yhaS`4UW-RgdM0i zfA5Ut4DnCP@=yaUM7?1xR^m2PiHe0y>l*)t))#j zzy(e86N@p9h1P(TsLE{Z>5AQx(pHh~@7b1K7!^IIpsh0_7kZv&>`Z9e8f^UwAH29z diff --git a/SRV/locales/en/LC_MESSAGES/messages.po b/SRV/locales/en/LC_MESSAGES/messages.po index b44ef16..68e1205 100644 --- a/SRV/locales/en/LC_MESSAGES/messages.po +++ b/SRV/locales/en/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-07-16 13:15+0500\n" -"PO-Revision-Date: 2025-07-16 13:15+0500\n" +"POT-Creation-Date: 2025-07-16 13:39+0500\n" +"PO-Revision-Date: 2025-07-16 13:39+0500\n" "Last-Translator: FULL NAME \n" "Language: en\n" "Language-Team: en \n" @@ -96,55 +96,60 @@ msgstr "Failed to update container position: {error}" msgid "Не удалось получить имя хоста" msgstr "Failed to retrieve hostname" -#: api/v1/settings.py:37 +#: api/v1/settings.py:38 #, python-brace-format msgid "Данные узлов подсети {subnet} успешно очищены" msgstr "Subnet node data for {subnet} successfully cleared" -#: api/v1/settings.py:39 +#: api/v1/settings.py:40 msgid "Данные всех подсетей успешно очищены" msgstr "All subnet data successfully cleared" -#: api/v1/settings.py:41 +#: api/v1/settings.py:42 msgid "Не удалось очистить данные узлов подсети" msgstr "Failed to clear subnet node data" -#: api/v1/settings.py:44 api/v1/settings.py:69 api/v1/settings.py:94 +#: api/v1/settings.py:45 api/v1/settings.py:70 api/v1/settings.py:95 #, python-brace-format msgid "Ошибка очистки: {error}" msgstr "Clear error: {error}" -#: api/v1/settings.py:64 +#: api/v1/settings.py:65 msgid "Данные точек доступа Wi-Fi успешно очищены" msgstr "Wi-Fi access point data successfully cleared" -#: api/v1/settings.py:66 +#: api/v1/settings.py:67 msgid "Не удалось очистить данные точек доступа Wi-Fi" msgstr "Failed to clear Wi-Fi access point data" -#: api/v1/settings.py:89 +#: api/v1/settings.py:90 msgid "Все сетевые данные успешно очищены" msgstr "All network data successfully cleared" -#: api/v1/settings.py:91 +#: api/v1/settings.py:92 msgid "Не удалось очистить все сетевые данные" msgstr "Failed to clear all network data" -#: api/v1/settings.py:117 api/v1/settings.py:141 +#: api/v1/settings.py:119 +#, python-brace-format +msgid "Файл для подсети {subnet} не найден" +msgstr "File for subnet {subnet} not found" + +#: api/v1/settings.py:143 msgid "Файл не найден" msgstr "File not found" -#: api/v1/settings.py:166 +#: api/v1/settings.py:168 #, python-brace-format msgid "Язык '{locale}' не поддерживается." msgstr "Language '{locale}' is not supported." -#: api/v1/settings.py:172 +#: api/v1/settings.py:174 #, python-brace-format msgid "Язык '{locale}' не поддерживается (нет файлов переводов)." msgstr "Language '{locale}' is not supported (no translation files)." -#: api/v1/settings.py:175 +#: api/v1/settings.py:177 #, python-brace-format msgid "Язык успешно установлен: {locale}" msgstr "Language successfully set: {locale}" @@ -421,24 +426,24 @@ msgstr "Wi-Fi access point clear error: {error}" msgid "Ошибка очистки всех сетевых данных: {error}" msgstr "All network data clear error: {error}" -#: services/subnet_service.py:75 services/wifi_service.py:115 +#: services/subnet_service.py:151 services/wifi_service.py:115 msgid "Неизвестный" msgstr "Unknown" -#: services/subnet_service.py:185 +#: services/subnet_service.py:327 #, python-brace-format msgid "Ошибка при сохранении устройств: {error}" msgstr "Error saving devices: {error}" -#: services/subnet_service.py:268 +#: services/subnet_service.py:441 msgid "Недопустимая подсеть по умолчанию" msgstr "Invalid default subnet" -#: services/subnet_service.py:288 +#: services/subnet_service.py:461 msgid "В данной подсети не обнаружено устройств" msgstr "No devices found in this subnet" -#: services/subnet_service.py:345 +#: services/subnet_service.py:518 #, python-brace-format msgid "Ошибка сканирования: {error}" msgstr "Scan error: {error}" diff --git a/SRV/locales/messages.pot b/SRV/locales/messages.pot index d24418d..d30c15c 100644 --- a/SRV/locales/messages.pot +++ b/SRV/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-07-16 13:15+0500\n" +"POT-Creation-Date: 2025-07-16 13:39+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -95,55 +95,60 @@ msgstr "" msgid "Не удалось получить имя хоста" msgstr "" -#: api/v1/settings.py:37 +#: api/v1/settings.py:38 #, python-brace-format msgid "Данные узлов подсети {subnet} успешно очищены" msgstr "" -#: api/v1/settings.py:39 +#: api/v1/settings.py:40 msgid "Данные всех подсетей успешно очищены" msgstr "" -#: api/v1/settings.py:41 +#: api/v1/settings.py:42 msgid "Не удалось очистить данные узлов подсети" msgstr "" -#: api/v1/settings.py:44 api/v1/settings.py:69 api/v1/settings.py:94 +#: api/v1/settings.py:45 api/v1/settings.py:70 api/v1/settings.py:95 #, python-brace-format msgid "Ошибка очистки: {error}" msgstr "" -#: api/v1/settings.py:64 +#: api/v1/settings.py:65 msgid "Данные точек доступа Wi-Fi успешно очищены" msgstr "" -#: api/v1/settings.py:66 +#: api/v1/settings.py:67 msgid "Не удалось очистить данные точек доступа Wi-Fi" msgstr "" -#: api/v1/settings.py:89 +#: api/v1/settings.py:90 msgid "Все сетевые данные успешно очищены" msgstr "" -#: api/v1/settings.py:91 +#: api/v1/settings.py:92 msgid "Не удалось очистить все сетевые данные" msgstr "" -#: api/v1/settings.py:117 api/v1/settings.py:141 +#: api/v1/settings.py:119 +#, python-brace-format +msgid "Файл для подсети {subnet} не найден" +msgstr "" + +#: api/v1/settings.py:143 msgid "Файл не найден" msgstr "" -#: api/v1/settings.py:166 +#: api/v1/settings.py:168 #, python-brace-format msgid "Язык '{locale}' не поддерживается." msgstr "" -#: api/v1/settings.py:172 +#: api/v1/settings.py:174 #, python-brace-format msgid "Язык '{locale}' не поддерживается (нет файлов переводов)." msgstr "" -#: api/v1/settings.py:175 +#: api/v1/settings.py:177 #, python-brace-format msgid "Язык успешно установлен: {locale}" msgstr "" @@ -420,24 +425,24 @@ msgstr "" msgid "Ошибка очистки всех сетевых данных: {error}" msgstr "" -#: services/subnet_service.py:75 services/wifi_service.py:115 +#: services/subnet_service.py:151 services/wifi_service.py:115 msgid "Неизвестный" msgstr "" -#: services/subnet_service.py:185 +#: services/subnet_service.py:327 #, python-brace-format msgid "Ошибка при сохранении устройств: {error}" msgstr "" -#: services/subnet_service.py:268 +#: services/subnet_service.py:441 msgid "Недопустимая подсеть по умолчанию" msgstr "" -#: services/subnet_service.py:288 +#: services/subnet_service.py:461 msgid "В данной подсети не обнаружено устройств" msgstr "" -#: services/subnet_service.py:345 +#: services/subnet_service.py:518 #, python-brace-format msgid "Ошибка сканирования: {error}" msgstr "" diff --git a/SRV/locales/ru/LC_MESSAGES/messages.mo b/SRV/locales/ru/LC_MESSAGES/messages.mo index d1ae31a51376e255dbd255d981df783a64c3a4d3..05cd8e759b03ce74a47b06baa69e682ae151ff9c 100644 GIT binary patch delta 1849 zcmb8ueN5F=9LMo5$WZJ_w77{vSG-t(f)70G0@h75dAKYMRM=QP1tT}5MXfD%cd5~% zF4wTN+%j8JHy6wCkdjHO-1;I%3#}`!R~YVhppHbv-_h8utk{;WaG7mAs`MJ1~x4`}l7k zKTGx-=^sFi`wcf^;eBS!%x|yLsG;KmK8>6Eqrd(LA#X?8F#;hEL&TEXBNR_j?mABJM{e zd=zu=3fAJE$Rk!g->eJcxD-cGm7Ve~SU~+XK@*K~Jb+5zM^vf)LY2PuVVB5z7$N={ zHU0)_e8D5G^lhk$9mhVLMOJ0lk6OSO#_&4oy+tAFzm7(C$dz^o_2LvNC$SO#KqdIh5?A_ORO!D%jZ3B#xKkQO?bTt_ z-cO)PxsZKO+=+@$p{~r{o>qdwGx!>H?Y2e)AT6R!Vr+)O-;T58k5Xnh16LIw4he_0aoEHR3as7+#dEKi?`$6U$Bk%E;7_wc{_`; z{oXNDqSLquLrkK1y7b$iV>=xYmantWkGf9dsQxMB-=dYymn(-4XTFhB zIue|nJQxnX55|L$$v1=1$+vf?iYv)%WKNwCH~3nVtWCo_S{G+Rn>6B15T(XAPeg z{-^Tan4swY=R%S($%HW+iLDrq?U;w1s7D5!L(aFDNdJ51C!9z84f!+EM;J58n25=z zQA@`Hti%0Sf{!qWam-qUm8fwia3%KRBFy3~H5kGbc+th5UF;|O<@6sxjeCl#anfjG z8kpZ~rBP1D9jw5gI13k#p&HnXTd*6;uwblBuo<(7V_2=+RrZN9VFLBn1OXa8Jb+5z7OGSqQKc`QXcO6kxx`(l@vl(hQzzNd*PtqP4iDmY zT!g#HP77$mAP%73n~_faD`_;P+tOY_AMp?>+lAa;13L9(F|MiU8r$gsKXhF&$cD5NA3ABR0(@sJe7S=yajcQI#A<& z<7%wtKs4ZaEXPk+frYGU7Pep`Mp3uu8\n" "Language: ru\n" "Language-Team: ru \n" @@ -99,55 +99,60 @@ msgstr "Не удалось обновить положение контейне msgid "Не удалось получить имя хоста" msgstr "Не удалось получить имя хоста" -#: api/v1/settings.py:37 +#: api/v1/settings.py:38 #, python-brace-format msgid "Данные узлов подсети {subnet} успешно очищены" msgstr "Данные узлов подсети {subnet} успешно очищены" -#: api/v1/settings.py:39 +#: api/v1/settings.py:40 msgid "Данные всех подсетей успешно очищены" msgstr "Данные всех подсетей успешно очищены" -#: api/v1/settings.py:41 +#: api/v1/settings.py:42 msgid "Не удалось очистить данные узлов подсети" msgstr "Не удалось очистить данные узлов подсети" -#: api/v1/settings.py:44 api/v1/settings.py:69 api/v1/settings.py:94 +#: api/v1/settings.py:45 api/v1/settings.py:70 api/v1/settings.py:95 #, python-brace-format msgid "Ошибка очистки: {error}" msgstr "Ошибка очистки: {error}" -#: api/v1/settings.py:64 +#: api/v1/settings.py:65 msgid "Данные точек доступа Wi-Fi успешно очищены" msgstr "Данные точек доступа Wi-Fi успешно очищены" -#: api/v1/settings.py:66 +#: api/v1/settings.py:67 msgid "Не удалось очистить данные точек доступа Wi-Fi" msgstr "Не удалось очистить данные точек доступа Wi-Fi" -#: api/v1/settings.py:89 +#: api/v1/settings.py:90 msgid "Все сетевые данные успешно очищены" msgstr "Все сетевые данные успешно очищены" -#: api/v1/settings.py:91 +#: api/v1/settings.py:92 msgid "Не удалось очистить все сетевые данные" msgstr "Не удалось очистить все сетевые данные" -#: api/v1/settings.py:117 api/v1/settings.py:141 +#: api/v1/settings.py:119 +#, python-brace-format +msgid "Файл для подсети {subnet} не найден" +msgstr "Файл для подсети {subnet} не найден" + +#: api/v1/settings.py:143 msgid "Файл не найден" msgstr "Файл не найден" -#: api/v1/settings.py:166 +#: api/v1/settings.py:168 #, python-brace-format msgid "Язык '{locale}' не поддерживается." msgstr "Язык '{locale}' не поддерживается." -#: api/v1/settings.py:172 +#: api/v1/settings.py:174 #, python-brace-format msgid "Язык '{locale}' не поддерживается (нет файлов переводов)." msgstr "Язык '{locale}' не поддерживается (нет файлов переводов)." -#: api/v1/settings.py:175 +#: api/v1/settings.py:177 #, python-brace-format msgid "Язык успешно установлен: {locale}" msgstr "Язык успешно установлен: {locale}" @@ -426,24 +431,24 @@ msgstr "Ошибка очистки точек доступа Wi-Fi: {error}" msgid "Ошибка очистки всех сетевых данных: {error}" msgstr "Ошибка очистки всех сетевых данных: {error}" -#: services/subnet_service.py:75 services/wifi_service.py:115 +#: services/subnet_service.py:151 services/wifi_service.py:115 msgid "Неизвестный" msgstr "Неизвестный" -#: services/subnet_service.py:185 +#: services/subnet_service.py:327 #, python-brace-format msgid "Ошибка при сохранении устройств: {error}" msgstr "Ошибка при сохранении устройств: {error}" -#: services/subnet_service.py:268 +#: services/subnet_service.py:441 msgid "Недопустимая подсеть по умолчанию" msgstr "Недопустимая подсеть по умолчанию" -#: services/subnet_service.py:288 +#: services/subnet_service.py:461 msgid "В данной подсети не обнаружено устройств" msgstr "В данной подсети не обнаружено устройств" -#: services/subnet_service.py:345 +#: services/subnet_service.py:518 #, python-brace-format msgid "Ошибка сканирования: {error}" msgstr "Ошибка сканирования: {error}"