mirror of
https://github.com/amnezia-vpn/DefaultVPN.git
synced 2026-05-17 00:26:23 +03:00
merge with branch update UI
This commit is contained in:
39
.clang-format
Normal file
39
.clang-format
Normal file
@@ -0,0 +1,39 @@
|
||||
BasedOnStyle: WebKit
|
||||
AccessModifierOffset: '-4'
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: 'true'
|
||||
AlignTrailingComments: 'true'
|
||||
AllowAllArgumentsOnNextLine: 'true'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'true'
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AllowShortCaseLabelsOnASingleLine: 'true'
|
||||
AllowShortEnumsOnASingleLine: 'false'
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AlwaysBreakTemplateDeclarations: 'No'
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
ColumnLimit: '120'
|
||||
CommentPragmas: '"^!|^:"'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
ConstructorInitializerIndentWidth: '4'
|
||||
ContinuationIndentWidth: '8'
|
||||
IndentPPDirectives: BeforeHash
|
||||
NamespaceIndentation: All
|
||||
PenaltyExcessCharacter: '10'
|
||||
PointerAlignment: Right
|
||||
SortIncludes: 'true'
|
||||
SpaceAfterTemplateKeyword: 'false'
|
||||
Standard: Auto
|
||||
20
.clang-format-ignore
Normal file
20
.clang-format-ignore
Normal file
@@ -0,0 +1,20 @@
|
||||
/client/3rd
|
||||
/client/3rd-prebuild
|
||||
/client/android
|
||||
/client/cmake
|
||||
/client/core/serialization
|
||||
/client/daemon
|
||||
/client/fonts
|
||||
/client/images
|
||||
/client/ios
|
||||
/client/mozilla
|
||||
/client/platforms/dummy
|
||||
/client/platforms/linux
|
||||
/client/platforms/macos
|
||||
/client/platforms/windows
|
||||
/client/server_scripts
|
||||
/client/translations
|
||||
/deploy
|
||||
/docs
|
||||
/metadata
|
||||
/service/src
|
||||
@@ -1,9 +1,14 @@
|
||||
# Amnezia VPN
|
||||
## _The best client for self-hosted VPN_
|
||||
|
||||
### _The best client for self-hosted VPN_
|
||||
|
||||
|
||||
[](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml?query=branch:dev)
|
||||
[](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
|
||||
|
||||
### [English]([https://github.com/amnezia-vpn/amnezia-client/blob/dev/README_RU.md](https://github.com/amnezia-vpn/amnezia-client/tree/dev?tab=readme-ov-file#)) | [Русский](https://github.com/amnezia-vpn/amnezia-client/blob/dev/README_RU.md)
|
||||
|
||||
|
||||
[Amnezia](https://amnezia.org) is an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server.
|
||||
|
||||
[](https://amnezia.org)
|
||||
|
||||
75
README_RU.md
Normal file
75
README_RU.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Amnezia VPN
|
||||
|
||||
### _Лучший клиент для создания VPN на собственном сервере_
|
||||
|
||||
[](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml?query=branch:dev)
|
||||
[](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
|
||||
|
||||
### [English](https://github.com/amnezia-vpn/amnezia-client/blob/dev/README.md) | Русский
|
||||
[AmneziaVPN](https://amnezia.org) — это open sourse VPN-клиент, ключевая особенность которого заключается в возможности развернуть собственный VPN на вашем сервере.
|
||||
|
||||
[](https://amnezia.org)
|
||||
|
||||
### [Сайт](https://amnezia.org) | [Зеркало на сайт](https://storage.googleapis.com/kldscp/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting)
|
||||
|
||||
> [!TIP]
|
||||
> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/kldscp/amnezia.org).
|
||||
|
||||
<a href="https://storage.googleapis.com/kldscp/amnezia.org/downloads"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/download-website-ru.svg" width="150" style="max-width: 100%; margin-right: 10px"></a>
|
||||
|
||||
|
||||
[Все релизы](https://github.com/amnezia-vpn/amnezia-client/releases)
|
||||
|
||||
<br/>
|
||||
|
||||
<a href="https://www.testiny.io"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/testiny.png" height="28px"></a>
|
||||
|
||||
## Особенности
|
||||
|
||||
- Простой в использовании — введите IP-адрес, SSH-логин и пароль, и Amnezia автоматически установит VPN-контейнеры Docker на ваш сервер и подключится к VPN.
|
||||
- Классические VPN-протоколы: OpenVPN, WireGuard и IKEv2.
|
||||
- Протоколы с маскировкой трафика (обфускацией): OpenVPN с плагином [Cloak](https://github.com/cbeuw/Cloak), Shadowsocks (OpenVPN over Shadowsocks), [AmneziaWG](https://docs.amnezia.org/documentation/amnezia-wg/) and XRay.
|
||||
- Поддержка Split Tunneling — добавляйте любые сайты или приложения в список, чтобы включить VPN только для них.
|
||||
- Поддерживает платформы: Windows, MacOS, Linux, Android, iOS.
|
||||
- Поддержка конфигурации протокола AmneziaWG на [бета-прошивке Keenetic](https://docs.keenetic.com/ua/air/kn-1611/en/6319-latest-development-release.html#UUID-186c4108-5afd-c10b-f38a-cdff6c17fab3_section-idm33192196168192-improved).
|
||||
|
||||
## Ссылки
|
||||
|
||||
- [https://amnezia.org](https://amnezia.org) - Веб-сайт проекта | [Альтернативная ссылка (зеркало)](https://storage.googleapis.com/kldscp/amnezia.org)
|
||||
- [https://docs.amnezia.org](https://docs.amnezia.org) - Документация
|
||||
- [https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
|
||||
- [https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Канал поддржки в Telegram (Английский)
|
||||
- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Канал поддржки в Telegram (Фарси)
|
||||
- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Канал поддржки в Telegram (Мьянма)
|
||||
- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Канал поддржки в Telegram (Русский)
|
||||
- [https://vpnpay.io/en/amnezia-premium/](https://vpnpay.io/en/amnezia-premium/) - Amnezia Premium | [Зеркало](https://storage.googleapis.com/kldscp/vpnpay.io/ru/amnezia-premium\)
|
||||
|
||||
## Технологии
|
||||
|
||||
AmneziaVPN использует несколько проектов с открытым исходным кодом:
|
||||
|
||||
- [OpenSSL](https://www.openssl.org/)
|
||||
- [OpenVPN](https://openvpn.net/)
|
||||
- [Shadowsocks](https://shadowsocks.org/)
|
||||
- [Qt](https://www.qt.io/)
|
||||
- [LibSsh](https://libssh.org)
|
||||
- и другие...
|
||||
|
||||
## Лицензия
|
||||
|
||||
GPL v3.0
|
||||
|
||||
## Донаты
|
||||
|
||||
Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn)
|
||||
|
||||
Bitcoin: bc1q26eevjcg9j0wuyywd2e3uc9cs2w58lpkpjxq6p <br>
|
||||
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4 <br>
|
||||
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d <br>
|
||||
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3 <br>
|
||||
TON: UQDpU1CyKRmg7L8mNScKk9FRc2SlESuI7N-Hby4nX-CcVmns
|
||||
|
||||
## Благодарности
|
||||
|
||||
Этот проект тестируется с помощью BrowserStack.
|
||||
Мы выражаем благодарность [BrowserStack](https://www.browserstack.com) за поддержку нашего проекта.
|
||||
@@ -69,7 +69,7 @@ void AmneziaApplication::init()
|
||||
{
|
||||
m_engine = new QQmlApplicationEngine;
|
||||
|
||||
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
|
||||
const QUrl url(QStringLiteral("qrc:/ui/qml/DefaultVpn/main.qml"));
|
||||
QObject::connect(
|
||||
m_engine, &QQmlApplicationEngine::objectCreated, this,
|
||||
[url](QObject *obj, const QUrl &objUrl) {
|
||||
@@ -154,7 +154,7 @@ void AmneziaApplication::init()
|
||||
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
|
||||
#endif
|
||||
|
||||
m_engine->addImportPath("qrc:/ui/qml/Modules/");
|
||||
m_engine->addImportPath("qrc:/ui/qml/DefaultVpn");
|
||||
m_engine->load(url);
|
||||
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
|
||||
|
||||
@@ -228,7 +228,7 @@ void AmneziaApplication::loadFonts()
|
||||
{
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
|
||||
QFontDatabase::addApplicationFont(":/fonts/VelaSans-GX.ttf");
|
||||
}
|
||||
|
||||
void AmneziaApplication::loadTranslator()
|
||||
|
||||
@@ -3,38 +3,169 @@
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QUuid>
|
||||
#include "logger.h"
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
#include "core/controllers/serverController.h"
|
||||
#include "core/scripts_registry.h"
|
||||
|
||||
namespace {
|
||||
Logger logger("XrayConfigurator");
|
||||
}
|
||||
|
||||
XrayConfigurator::XrayConfigurator(std::shared_ptr<Settings> settings, const QSharedPointer<ServerController> &serverController, QObject *parent)
|
||||
: ConfiguratorBase(settings, serverController, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
|
||||
ErrorCode &errorCode)
|
||||
QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode &errorCode)
|
||||
{
|
||||
QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container),
|
||||
m_serverController->genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
QString xrayPublicKey =
|
||||
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode);
|
||||
xrayPublicKey.replace("\n", "");
|
||||
|
||||
QString xrayUuid = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, errorCode);
|
||||
xrayUuid.replace("\n", "");
|
||||
|
||||
QString xrayShortId =
|
||||
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode);
|
||||
xrayShortId.replace("\n", "");
|
||||
|
||||
// Generate new UUID for client
|
||||
QString clientId = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
|
||||
// Get current server config
|
||||
QString currentConfig = m_serverController->getTextFileFromContainer(
|
||||
container, credentials, amnezia::protocols::xray::serverConfigPath, errorCode);
|
||||
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get server config file";
|
||||
return "";
|
||||
}
|
||||
|
||||
config.replace("$XRAY_CLIENT_ID", xrayUuid);
|
||||
// Parse current config as JSON
|
||||
QJsonDocument doc = QJsonDocument::fromJson(currentConfig.toUtf8());
|
||||
if (doc.isNull() || !doc.isObject()) {
|
||||
logger.error() << "Failed to parse server config JSON";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonObject serverConfig = doc.object();
|
||||
|
||||
// Validate server config structure
|
||||
if (!serverConfig.contains("inbounds")) {
|
||||
logger.error() << "Server config missing 'inbounds' field";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonArray inbounds = serverConfig["inbounds"].toArray();
|
||||
if (inbounds.isEmpty()) {
|
||||
logger.error() << "Server config has empty 'inbounds' array";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonObject inbound = inbounds[0].toObject();
|
||||
if (!inbound.contains("settings")) {
|
||||
logger.error() << "Inbound missing 'settings' field";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonObject settings = inbound["settings"].toObject();
|
||||
if (!settings.contains("clients")) {
|
||||
logger.error() << "Settings missing 'clients' field";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QJsonArray clients = settings["clients"].toArray();
|
||||
|
||||
// Create configuration for new client
|
||||
QJsonObject clientConfig {
|
||||
{"id", clientId},
|
||||
{"flow", "xtls-rprx-vision"}
|
||||
};
|
||||
|
||||
clients.append(clientConfig);
|
||||
|
||||
// Update config
|
||||
settings["clients"] = clients;
|
||||
inbound["settings"] = settings;
|
||||
inbounds[0] = inbound;
|
||||
serverConfig["inbounds"] = inbounds;
|
||||
|
||||
// Save updated config to server
|
||||
QString updatedConfig = QJsonDocument(serverConfig).toJson();
|
||||
errorCode = m_serverController->uploadTextFileToContainer(
|
||||
container,
|
||||
credentials,
|
||||
updatedConfig,
|
||||
amnezia::protocols::xray::serverConfigPath,
|
||||
libssh::ScpOverwriteMode::ScpOverwriteExisting
|
||||
);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload updated config";
|
||||
return "";
|
||||
}
|
||||
|
||||
// Restart container
|
||||
QString restartScript = QString("sudo docker restart $CONTAINER_NAME");
|
||||
errorCode = m_serverController->runScript(
|
||||
credentials,
|
||||
m_serverController->replaceVars(restartScript, m_serverController->genVarsForScript(credentials, container))
|
||||
);
|
||||
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to restart container";
|
||||
return "";
|
||||
}
|
||||
|
||||
return clientId;
|
||||
}
|
||||
|
||||
QString XrayConfigurator::createConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode &errorCode)
|
||||
{
|
||||
// Get client ID from prepareServerConfig
|
||||
QString xrayClientId = prepareServerConfig(credentials, container, containerConfig, errorCode);
|
||||
if (errorCode != ErrorCode::NoError || xrayClientId.isEmpty()) {
|
||||
logger.error() << "Failed to prepare server config";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container),
|
||||
m_serverController->genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
if (config.isEmpty()) {
|
||||
logger.error() << "Failed to get config template";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
QString xrayPublicKey =
|
||||
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode);
|
||||
if (errorCode != ErrorCode::NoError || xrayPublicKey.isEmpty()) {
|
||||
logger.error() << "Failed to get public key";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
xrayPublicKey.replace("\n", "");
|
||||
|
||||
QString xrayShortId =
|
||||
m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode);
|
||||
if (errorCode != ErrorCode::NoError || xrayShortId.isEmpty()) {
|
||||
logger.error() << "Failed to get short ID";
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
xrayShortId.replace("\n", "");
|
||||
|
||||
// Validate all required variables are present
|
||||
if (!config.contains("$XRAY_CLIENT_ID") || !config.contains("$XRAY_PUBLIC_KEY") || !config.contains("$XRAY_SHORT_ID")) {
|
||||
logger.error() << "Config template missing required variables:"
|
||||
<< "XRAY_CLIENT_ID:" << !config.contains("$XRAY_CLIENT_ID")
|
||||
<< "XRAY_PUBLIC_KEY:" << !config.contains("$XRAY_PUBLIC_KEY")
|
||||
<< "XRAY_SHORT_ID:" << !config.contains("$XRAY_SHORT_ID");
|
||||
errorCode = ErrorCode::InternalError;
|
||||
return "";
|
||||
}
|
||||
|
||||
config.replace("$XRAY_CLIENT_ID", xrayClientId);
|
||||
config.replace("$XRAY_PUBLIC_KEY", xrayPublicKey);
|
||||
config.replace("$XRAY_SHORT_ID", xrayShortId);
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ public:
|
||||
|
||||
QString createConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
|
||||
ErrorCode &errorCode);
|
||||
|
||||
private:
|
||||
QString prepareServerConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig,
|
||||
ErrorCode &errorCode);
|
||||
};
|
||||
|
||||
#endif // XRAY_CONFIGURATOR_H
|
||||
|
||||
@@ -379,6 +379,13 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
|
||||
|
||||
auto errorCode = checkErrors(sslErrors, reply);
|
||||
reply->deleteLater();
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
if (!responseBody.contains("services")) {
|
||||
return ErrorCode::ApiServicesMissingError;
|
||||
}
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ namespace amnezia
|
||||
ApiConfigSslError = 1104,
|
||||
ApiMissingAgwPublicKey = 1105,
|
||||
ApiConfigDecryptionError = 1106,
|
||||
ApiServicesMissingError = 1107,
|
||||
|
||||
// QFile errors
|
||||
OpenError = 1200,
|
||||
|
||||
@@ -63,7 +63,8 @@ QString errorString(ErrorCode code) {
|
||||
case (ErrorCode::ApiConfigTimeoutError): errorMessage = QObject::tr("Server response timeout on api request"); break;
|
||||
case (ErrorCode::ApiMissingAgwPublicKey): errorMessage = QObject::tr("Missing AGW public key"); break;
|
||||
case (ErrorCode::ApiConfigDecryptionError): errorMessage = QObject::tr("Failed to decrypt response payload"); break;
|
||||
|
||||
case (ErrorCode::ApiServicesMissingError): errorMessage = QObject::tr("Missing list of available services"); break;
|
||||
|
||||
// QFile errors
|
||||
case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
|
||||
case(ErrorCode::ReadError): errorMessage = QObject::tr("QFile error: An error occurred when reading from the file"); break;
|
||||
|
||||
BIN
client/fonts/VelaSans-GX.ttf
Normal file
BIN
client/fonts/VelaSans-GX.ttf
Normal file
Binary file not shown.
4
client/images/controls/connect-button.svg
Normal file
4
client/images/controls/connect-button.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="82" height="85" viewBox="0 0 82 85" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M61.5 14.4031C70.8668 20.9031 77 31.7353 77 44.0001C77 63.8823 60.8823 80.0001 41 80.0001C21.1177 80.0001 5 63.8823 5 44.0001C5 31.7353 11.1332 20.9031 20.5 14.4031" stroke="white" stroke-width="7" stroke-linecap="round"/>
|
||||
<path d="M41 4V29" stroke="white" stroke-width="7" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 411 B |
@@ -220,6 +220,28 @@
|
||||
<file>ui/qml/Pages2/PageSettingsApiLanguageList.qml</file>
|
||||
<file>images/controls/archive-restore.svg</file>
|
||||
<file>images/controls/help-circle.svg</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/DropDownType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/main.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Pages/PageHome.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/TextTypes/MediumTextType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Config/DeviceInfo.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Config/qmldir</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/TextTypes/XSmallTextType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/ButtonType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/TextTypes/Header1TextType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/TextTypes/Header3TextType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Config/Style.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Components/WhiteButtonWithBorder.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Components/WhiteButtonNoBorder.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Components/BlueButtonNoBorder.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/InputType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/PopupType.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml</file>
|
||||
<file>ui/qml/DefaultVpn/Controls/BusyIndicatorType.qml</file>
|
||||
<file>images/controls/connect-button.svg</file>
|
||||
<file>fonts/VelaSans-GX.ttf</file>
|
||||
</qresource>
|
||||
<qresource prefix="/countriesFlags">
|
||||
<file>images/flagKit/ZW.svg</file>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation>شبكة VPN كلاسيكية للعمل المريح وتنزيل الملفات الكبيرة ومشاهدة مقاطع الفيديو. تعمل مع أي موقع. تصل السرعة إلى %1 ميجابت/ثانية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation>شبكة VPN للولوج للمواقع المحظورة في بلاد ذو مستوي عالي من الرقابة علي الانترنت. </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation>Amenzia Premium - شبكة VPN للعمل المريح, تحميل ملفات كبيرة الحجم, ومشاهدة مقاطع الفيديو ب جودة عالية. تعمل لجميع المواقع, حتي في البلاد ذو مستوي عالي من الرقابة علي الانترنت</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation>Amnezia Free هو VPN مجاني لتخطي الحظر في البلاد ذو مستوي عالي من الرقابة علي الانترنت</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation>%1 ميجابت/ثانية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation>%1 ايام</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation>سيقوم VPN فقط بفتح المواقع المشهورة المحظورة في بلدك, مثل Instagram, Facebook, Twitter و مواقع اخري. المواقع الاخري ستٌفتح من عنوان ال IP الحقيقي الخاص بك, <a href="%1/free" style="color: #FBB26A;">معلومات اخري علي الموقع.</a></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation>مجاني</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation>%1 دولار/الشهر</translation>
|
||||
</message>
|
||||
@@ -482,6 +482,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>لا يمكن تغير الخادم بينما هناك اتصال مفعل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1376,6 +1391,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>سياسات الخصوصية</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1389,64 +1412,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>السعر</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation>مدة العمل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation>السرعة</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation>علامة الدعم</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation>تم النسخ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation>إعادة تحميل تكوين API</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation>إعادة تحميل تكوين API</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation>واصل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation>إلغاء</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation>لا يمكن إعادة تحميل تكوين API اثناء تواجد اتصال نشط</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation>احذف من التطبيق</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation>احذف من التطبيق؟</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation>لا يمكن إزالة الخادم أثناء الاتصال النشط</translation>
|
||||
</message>
|
||||
@@ -2048,30 +2076,50 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>اسم الخادم</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>احفظ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>البروتوكولات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>الخدمات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>الإدارة</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2164,6 +2212,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>الخوادم</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2419,6 +2472,31 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>I have nothing</source>
|
||||
<translation>ليس لدي اي شئ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">مفتاح</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3315,7 +3393,7 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>هذا التكوين بالفعل تمت إضافتة للبرنامج</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
@@ -3420,37 +3498,42 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation>خطأ QFile: لا يمكن فتح الملف</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation>خطأ QFile: ظهر خطأ اثناء القراءه من الملف</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation>خطأ QFile: لا يمكن الوصول للملف</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation>خطأ QFile: ظهر خطأ غير محدد</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation>خطأ QFile: حدث خطأ فادح</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation>خطأ QFile: تم إحباط العملية</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>خطأ داخلي</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation>برای کار راحت، دانلود فایلهای بزرگ و تماشای ویدیوها، از VPN کلاسیک استفاده کنید. این VPN برای هر سایتی کار میکند و سرعت آن تا %1 مگابیت بر ثانیه است.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation>وی پی ان برای دسترسی به سایتهای مسدود شده در مناطق با سانسور شدید اینترنت.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation>امنزیا پریمیوم - یک وی پی ان کلاسیک برای کار راحت، دانلود فایلهای بزرگ و تماشای ویدیو با کیفیت بالا. قابل استفاده برای تمامی سایتها، حتی در کشورهایی با بالاترین سطح سانسور اینترنت.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation>امنزیا رایگان یک وی پی ان رایگان برای دور زدن مسدودیتها در کشورهایی با سطح بالای سانسور اینترنت است.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation>%1 MBit/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation>%1 روز</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation>وی پی ان فقط سایتهای محبوبی را که در منطقه شما مسدود شدهاند، مانند اینستاگرام، فیسبوک، توییتر و غیره باز میکند. سایر سایتها با آدرس آیپی واقعی شما باز خواهند شد. <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation>رایگان</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation>%1 $/ماه</translation>
|
||||
</message>
|
||||
@@ -486,6 +486,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>امکان تغییر سرور در هنگام متصل بودن وجود ندارد</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1459,6 +1474,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1472,64 +1495,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>قیمت</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation>مدت زمان کار</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation>سرعت</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation>کپی شد</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation>بارگذاری مجدد پیکربندی API</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation>آیا میخواهید پیکربندی API را دوباره بارگذاری کنید؟</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation>ادامه دهید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation>لغو</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation>نمیتوان پیکربندی API را در حین اتصال فعال دوباره بارگذاری کرد.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation>حذف از برنامه</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation>آیا میخواهید از برنامه حذف کنید؟</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation>نمیتوان سرور را در حین اتصال فعال حذف کرد.</translation>
|
||||
</message>
|
||||
@@ -2143,30 +2171,50 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>نام سرور</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>ذخیره</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>پروتکلها</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>سرویسها</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>مدیریت</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2259,6 +2307,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>سرورها</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2542,6 +2595,31 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">متن شامل کلید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">کلید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3506,7 +3584,7 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<translation>این پیکربندی قبلاً به برنامه اضافه شده است</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>کد خطا: %1. </translation>
|
||||
</message>
|
||||
@@ -3606,37 +3684,42 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>Internal error</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -482,6 +482,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>सक्रिय कनेक्शन होने पर सर्वर बदलने में असमर्थ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1416,6 +1431,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>गोपनीयता नीति</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1429,64 +1452,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation type="unfinished">कॉपी किया गया</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation type="unfinished">जारी रखना</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">रद्द करना</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation type="unfinished">सक्रिय कनेक्शन के दौरान सर्वर को हटाया नहीं जा सकता</translation>
|
||||
</message>
|
||||
@@ -2096,30 +2124,50 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>सर्वर का नाम</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>सहेजें</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>प्रोटोकॉल</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>सेवाएं</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>प्रबंध</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2212,6 +2260,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>सर्वर</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2487,6 +2540,31 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">पाठ के रूप में कुंजी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">चाबी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3450,7 +3528,12 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>ErrorCode: %1. </translation>
|
||||
</message>
|
||||
@@ -3515,37 +3598,37 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>कॉन्फ़िगरेशन में सर्वर से कनेक्ट करने के लिए कोई कंटेनर और क्रेडेंशियल नहीं है</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation>Qफ़ाइल त्रुटि: फ़ाइल खोली नहीं जा सकी</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation>Qफ़ाइल त्रुटि: फ़ाइल से पढ़ते समय एक त्रुटि उत्पन्न हुई</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation>Qफ़ाइल त्रुटि: फ़ाइल तक नहीं पहुंचा जा सका</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation>Qफ़ाइल त्रुटि: एक अनिर्दिष्ट त्रुटि उत्पन्न हुई</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation>Qफ़ाइल त्रुटि: एक घातक त्रुटि उत्पन्न हुई</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation>Qफ़ाइल त्रुटि: ऑपरेशन निरस्त कर दिया गया था</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>आंतरिक त्रुटि</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation>သက်တောင့်သက်သာအလုပ်လုပ်နိုင်ဖို့အတွက်နှင့် ကြီးမားသောဖိုင်များကိုဒေါင်းလုဒ်လုပ်ခြင်းနှင့် ဗီဒီယိုများကြည့်ရှုခြင်းတို့အတွက် အသုံးပြုနိုင်သော VPN ဖြစ်ပါတယ်။ မည်သည့်ဆိုက်များအတွက်မဆိုအလုပ်လုပ်ပြီး လိုင်းအရှိန် %1 MBit/s အထိအသုံးပြုနိုင်ပါတယ်။</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation>အင်တာနက် ဆင်ဆာဖြတ်တောက်မှု မြင့်မားသော ဒေသများရှိ ပိတ်ဆို့ထားသော ဆိုက်များကို ဝင်ရောက်ရန် VPN။. </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation>Amnezia Premium - သက်တောင့်သက်သာအလုပ်လုပ်နိုင်ဖို့အတွက်နှင့် ကြီးမားသောဖိုင်များကိုဒေါင်းလုဒ်လုပ်ခြင်းနှင့် ဗီဒီယိုများကိုကြည်လင်ပြတ်သားစွာကြည့်ရှုခြင်းတို့အတွက် အသုံးပြုနိုင်သော VPN ဖြစ်ပါတယ်။ အင်တာနက်ဆင်ဆာဖြတ်မှု အဆင့်အမြင့်ဆုံးနိုင်ငံများတွင်ပင် မည်သည့်ဆိုက်များအတွက်မဆို အလုပ်လုပ်ပါသည်။.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation>Amnezia Free သည် အင်တာနက်ဆင်ဆာဖြတ်တောက်မှု မြင့်မားသောနိုင်ငံများတွင် ပိတ်ဆို့ခြင်းကို ကျော်ဖြတ်ရန်အတွက် အခမဲ့ VPN တစ်ခုဖြစ်ပါသည်။</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation>%1 MBit/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation>%1 ရက်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation>ဤ VPN သည် သင့်ဒေသရှိ Instagram၊ Facebook၊ Twitter နှင့် အခြားသော လူကြိုက်များသော ဆိုက်များကိုသာ ဖွင့်ပေးပါမည်။ အခြားဝဘ်ဆိုက်များကိုမူ သင်၏ IP လိပ်စာအစစ်အမှန်ဖြင့်သာ ဖွင့်ပေးပါမည်၊ <a href="%1/free" style="color: #FBB26A;">နောက်ထပ်အသေးစိတ်အချက်အလက်များကို ဝဘ်ဆိုဒ်ပေါ်တွင်ကြည့်ရန်</a></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation>အခမဲ့</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation>%1 $/တစ်လ</translation>
|
||||
</message>
|
||||
@@ -482,6 +482,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>လက်ရှိချိတ်ဆက်မှုတစ်ခုရှိနေချိန်တွင် ဆာဗာကို ပြောင်းလဲ၍မရပါ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1384,6 +1399,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>ကိုယ်ရေးအချက်အလက်မူဝါဒ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1397,64 +1420,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>စျေးနှုန်း</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation>အလုပ်လုပ်မည့်ကာလ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation>မြန်နှုန်း</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation>ကူညီပံ့ပိုးမှု tag</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation>ကူးယူပြီးပါပြီ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation>API config ကို ပြန်လည်စတင်မည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation>API config ကို ပြန်လည်စတင်မည်လား?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation>ဆက်လက်လုပ်ဆောင်မည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation>ပယ်ဖျက်မည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation>ချိတ်ဆက်မှုရှိနေချိန်အတွင်း API config ကို ပြန်လည်စတင်၍မရပါ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation>အပလီကေးရှင်းမှဖယ်ရှားမည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation>အပလီကေးရှင်းမှဖယ်ရှားမည်လား?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation>ချိတ်ဆက်မှုရှိနေချိန်အတွင်း ဆာဗာကို ဖယ်ရှား၍မရပါ</translation>
|
||||
</message>
|
||||
@@ -2057,30 +2085,50 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>ဆာဗာအမည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>သိမ်းဆည်းမည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>ပရိုတိုကောများ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>ဝန်ဆောင်မှုများ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>စီမံခန့်ခွဲမှု</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2173,6 +2221,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>ဆာဗာများ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2428,6 +2481,31 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>I have nothing</source>
|
||||
<translation>ကျွန်ုပ်တွင်ဘာမှမရှိပါ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">Key</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3311,7 +3389,7 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>ဤ config ကို အပလီကေးရှင်းထဲသို့ ထည့်သွင်းပြီးဖြစ်သည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>မှားယွင်းမှုကုတ်: %1. </translation>
|
||||
</message>
|
||||
@@ -3416,37 +3494,42 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation>QFile မှားယွင်းမှု: ဖိုင်ကို ဖွင့်၍မရပါ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation>QFile မှားယွင်းမှု: ဖိုင်ကိုဖတ်နေစဥ်အတွင်း မှားယွင်းမှုဖြစ်သွားသည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation>QFile မှားယွင်းမှု: ဖိုင်ကို ဝင်၍မရပါ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation>QFile မှားယွင်းမှု: သတ်မှတ်မထားသော မှားယွင်းမှုတစ်ခု ဖြစ်ပွားခဲ့သည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation>QFile မှားယွင်းမှု: ကြီးမားသော မှားယွင်းမှုတစ်ခု ဖြစ်ပွားခဲ့သည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation>QFile မှားယွင်းမှု: လုပ်ငန်းစဥ်ကို ဖျက်သိမ်းလိုက်ရသည်</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>စက်တွင်းဖြစ်သော မှားယွင်းမှု</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation>Классический VPN для комфортной работы, загрузки больших файлов и просмотра видео. Работает для любых сайтов. Скорость до %1 Мбит/с</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation>VPN для доступа к заблокированным сайтам в регионах с высоким уровнем интернет-цензуры. </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation>Amnezia Premium — классический VPN для комфортной работы, загрузки больших файлов и просмотра видео в высоком разрешении. Работает на всех сайтах, даже в странах с самым высоким уровнем интернет-цензуры.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation>Amnezia Free - это бесплатный VPN для обхода блокировок в странах с высоким уровнем интернет-цензуры</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation>%1 дней</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation>Через VPN будут открываться только популярные сайты, заблокированные в вашем регионе, такие как Instagram, Facebook, Twitter и другие. Остальные сайты будут открываться с вашего реального IP-адреса, <a href="%1/free" style="color: #FBB26A;">подробности на сайте.</a></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation>Бесплатно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation>%1 $/месяц</translation>
|
||||
</message>
|
||||
@@ -486,6 +486,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>Невозможно изменить сервер во время активного соединения</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1479,6 +1494,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>Политика конфиденциальности</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1492,64 +1515,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>Цена</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation>Период работы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation>Скорость</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation>Скопировано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation>Перезагрузить конфигурацию API</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation>Перезагрузить конфигурацию API?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation>Продолжить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation>Отменить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation>Невозможно перзагрузить API конфигурацию при активном соединении</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation>Удалить из приложения</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation>Удалить из приложения?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation>Невозможно удалить сервер во время активного соединения</translation>
|
||||
</message>
|
||||
@@ -2199,27 +2227,32 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>Имя сервера</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>Сохранить</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>Протоколы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>Сервисы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>Управление</translation>
|
||||
</message>
|
||||
@@ -2227,6 +2260,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Data</source>
|
||||
<translation type="vanished">Данные</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2323,6 +2371,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>Серверы</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2614,6 +2667,31 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">Ключ в виде текста</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">Ключ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3647,7 +3725,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation>Данная конфигурация уже была добавлена в приложение</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>Код ошибки: %1. </translation>
|
||||
</message>
|
||||
@@ -3741,37 +3819,42 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation>Ошибка QFile: не удалось открыть файл</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation>Ошибка QFile: произошла ошибка при чтении из файла</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation>Ошибка QFile: не удалось получить доступ к файлу</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation>Ошибка QFile: произошла неизвестная ошибка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation>Ошибка QFile: произошла фатальная ошибка</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation>Ошибка QFile: операция была прервана</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>Внутренняя ошибка</translation>
|
||||
</message>
|
||||
|
||||
@@ -27,52 +27,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation>Звичайний VPN для комфортної роботи, завантаження великих файлів та перегляду відео. Працює для будь-яких сайтів. Швидкість до %1 MBit/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation>VPN для доступу до заблокованих сайтів у регіонах з високим рівнем інтернет-цензури. </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation>Amnezia Premium - звичайний VPN для комфортної роботи, завантаження великих файлів та перегляду відео у високій роздільній здатності. Працює для всіх вебсайтів, навіть у країнах з найвищим рівнем інтернет-цензури.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation>Amnezia Free — це безкоштовний VPN для обходу блокувань у країнах з високим рівнем інтернет-цензури</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation>%1 MBit/s</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation>%1 днів</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation>Лише популярні сайти, які заблоковані у вашому регіоні, будуть відкриватись за допомогою VPN підключення (Instagram, Facebook, Twitter та ін.). Звичайні сайти будуть відкриватися без використання VPN, <a href="%1/free" style="color: #FBB26A;">більш детально на нашому сайті.</a></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation>Безкоштовно</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation>%1 $/місяць</translation>
|
||||
</message>
|
||||
@@ -512,6 +512,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>Не можна змінити сервер при активному підключенні</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1553,6 +1568,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>Політика конфіденційності</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1566,64 +1589,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>Ціна</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation>Період роботи</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation>Швидкість</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation>Скопійовано</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation>Перезавантажити конфігурацію API</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation>Перезавантажити конфігурацію API?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation>Продовжити</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation>Відмінити</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation>Неможливо перезавантажити конфігурацію API під час активного підключення</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation>Видалити з додатку</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation>Видалити з додатку?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation>Неможливо видалити сервер під час активного підключення</translation>
|
||||
</message>
|
||||
@@ -2285,27 +2313,32 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>Імя сервера</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>Зберегти</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>Протоколи</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>Сервіси</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>Управління</translation>
|
||||
</message>
|
||||
@@ -2313,6 +2346,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Data</source>
|
||||
<translation type="vanished">Дані</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2409,6 +2457,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>Сервери</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2700,6 +2753,31 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">Ключ у вигляді тексту</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">Ключ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3743,7 +3821,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation>Ця конфігурація вже була додана в застосунок</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -3837,37 +3915,42 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>Internal error</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -482,6 +482,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>فعال کنکشن موجود ہونے کی وجہ سے سرور تبدیل کرنے میں ناکام ہیں</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1420,6 +1435,14 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>رازداری کی پالیسی</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1433,64 +1456,69 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation type="unfinished">چالو کنکشن کے دوران سرور کو ہٹایا نہیں جا سکتا</translation>
|
||||
</message>
|
||||
@@ -2100,30 +2128,50 @@ Already installed containers were found on the server. All installed containers
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>سرور کا نام</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>محفوظ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>پروٹوکولات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>خدمات</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>مینجمنٹ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2216,6 +2264,11 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Servers</source>
|
||||
<translation>سرور</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2491,6 +2544,31 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">متن کے طور پر کلید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">کلید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3414,7 +3492,7 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation>یہ تشکیل پہلے ہی ایپلی کیشن میں شامل کی جا چکی ہے</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>ایرر کوڈ: %1. </translation>
|
||||
</message>
|
||||
@@ -3519,37 +3597,42 @@ Already installed containers were found on the server. All installed containers
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation>QFile کی خرابی: فائل کو نہیں کھولا جا سکا</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation>کیو فائل کی خرابی: فائل سے پڑھتے وقت ایک خرابی پیش آگئی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation>QFile کی خرابی: فائل تک رسائی نہیں ہو سکی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation>کیو فائل میں خرابی: ایک غیر متعینہ خرابی پیش آگئی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation>کیو فائل میں خرابی: ایک مہلک خرابی پیش آگئی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation>کیو فائل کی خرابی: آپریشن روک دیا گیا تھا</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation>داخلی خامی</translation>
|
||||
</message>
|
||||
|
||||
@@ -4,52 +4,52 @@
|
||||
<context>
|
||||
<name>ApiServicesModel</name>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="68"/>
|
||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="74"/>
|
||||
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="84"/>
|
||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
||||
<source>%1 MBit/s</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="103"/>
|
||||
<source>%1 days</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="112"/>
|
||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<source>Free</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||
<location filename="../ui/models/apiServicesModel.cpp" line="122"/>
|
||||
<source>%1 $/month</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -500,6 +500,21 @@ Already installed containers were found on the server. All installed containers
|
||||
<source>Unable change server while there is an active connection</source>
|
||||
<translation>已建立连接时无法更改服务器配置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Online</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="35"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageHome.qml" line="43"/>
|
||||
<source>Connection to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageProtocolAwgClientSettings</name>
|
||||
@@ -1484,6 +1499,14 @@ And if you don't like the app, all the more support it - the donation will
|
||||
<translation>隐私政策</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiLanguageList</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiLanguageList.qml" line="61"/>
|
||||
<source>Unable change server location while there is an active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsApiServerInfo</name>
|
||||
<message>
|
||||
@@ -1497,64 +1520,69 @@ And if you don't like the app, all the more support it - the donation will
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Work period</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="65"/>
|
||||
<source>Valid until</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="77"/>
|
||||
<source>Speed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="109"/>
|
||||
<source>Support tag</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="122"/>
|
||||
<source>Copied</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="142"/>
|
||||
<source>Reload API config</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="147"/>
|
||||
<source>Reload API config?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="148"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="188"/>
|
||||
<source>Continue</source>
|
||||
<translation type="unfinished">继续</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="149"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="189"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="153"/>
|
||||
<source>Cannot reload API config during active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="182"/>
|
||||
<source>Remove from application</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="187"/>
|
||||
<source>Remove from application?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="193"/>
|
||||
<source>Cannot remove server during active connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -2212,27 +2240,32 @@ And if you don't like the app, all the more support it - the donation will
|
||||
<context>
|
||||
<name>PageSettingsServerInfo</name>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="104"/>
|
||||
<source>Subscription is valid until </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="167"/>
|
||||
<source>Server name</source>
|
||||
<translation>服务器名</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="174"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="180"/>
|
||||
<source>Save</source>
|
||||
<translation>保存</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="220"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="224"/>
|
||||
<source>Protocols</source>
|
||||
<translation>协议</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="232"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="236"/>
|
||||
<source>Services</source>
|
||||
<translation>服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="242"/>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="246"/>
|
||||
<source>Management</source>
|
||||
<translation>管理</translation>
|
||||
</message>
|
||||
@@ -2240,6 +2273,21 @@ And if you don't like the app, all the more support it - the donation will
|
||||
<source>Data</source>
|
||||
<translation type="vanished">数据</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="61"/>
|
||||
<source>Server settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="73"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml" line="90"/>
|
||||
<source>Remove server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsServerProtocol</name>
|
||||
@@ -2340,6 +2388,11 @@ And if you don't like the app, all the more support it - the donation will
|
||||
<source>Servers</source>
|
||||
<translation>服务器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml" line="53"/>
|
||||
<source>Connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSettingsSplitTunneling</name>
|
||||
@@ -2646,6 +2699,31 @@ It's okay as long as it's from someone you trust.</source>
|
||||
<source>Key as text</source>
|
||||
<translation type="vanished">授权码文本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="65"/>
|
||||
<source>Adding a server to connect to</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="77"/>
|
||||
<source>Key</source>
|
||||
<translation type="unfinished">授权码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="88"/>
|
||||
<source>VPN://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="97"/>
|
||||
<source>Add</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml" line="103"/>
|
||||
<source>Unsupported config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PageSetupWizardCredentials</name>
|
||||
@@ -3748,37 +3826,42 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="68"/>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||
<source>Missing list of available services</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="69"/>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<source>QFile error: The file could not be opened</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="70"/>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<source>QFile error: An error occurred when reading from the file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="71"/>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<source>QFile error: The file could not be accessed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="72"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<source>QFile error: An unspecified error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="73"/>
|
||||
<source>QFile error: A fatal error occurred</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="74"/>
|
||||
<source>QFile error: The operation was aborted</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="80"/>
|
||||
<location filename="../core/errorstrings.cpp" line="81"/>
|
||||
<source>ErrorCode: %1. </source>
|
||||
<translation>错误代码: %1. </translation>
|
||||
</message>
|
||||
@@ -3846,7 +3929,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
||||
<translation type="vanished">该配置不包含任何用于连接到服务器的容器和凭据。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core/errorstrings.cpp" line="77"/>
|
||||
<location filename="../core/errorstrings.cpp" line="78"/>
|
||||
<source>Internal error</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
|
||||
@@ -55,7 +55,7 @@ void ConnectionController::openConnection()
|
||||
&& !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
|
||||
emit updateApiConfigFromGateway();
|
||||
} else if (configVersion && m_serversModel->isApiKeyExpired(serverIndex)) {
|
||||
qDebug() << "attempt to update api config by end_date event";
|
||||
qDebug() << "attempt to update api config by expires_at event";
|
||||
if (configVersion == ApiConfigSources::Telegram) {
|
||||
emit updateApiConfigFromTelegram();
|
||||
} else {
|
||||
|
||||
@@ -121,9 +121,8 @@ ErrorCode ExportController::generateNativeConfig(const DockerContainer container
|
||||
|
||||
jsonNativeConfig = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||
|
||||
if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg) {
|
||||
auto clientId = jsonNativeConfig.value(config_key::clientId).toString();
|
||||
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials, serverController);
|
||||
if (protocol == Proto::OpenVpn || protocol == Proto::WireGuard || protocol == Proto::Awg || protocol == Proto::Xray) {
|
||||
errorCode = m_clientManagementModel->appendClient(jsonNativeConfig, clientName, container, credentials, serverController);
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
@@ -248,10 +247,10 @@ void ExportController::generateCloakConfig()
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
void ExportController::generateXrayConfig()
|
||||
void ExportController::generateXrayConfig(const QString &clientName)
|
||||
{
|
||||
QJsonObject nativeConfig;
|
||||
ErrorCode errorCode = generateNativeConfig(DockerContainer::Xray, "", Proto::Xray, nativeConfig);
|
||||
ErrorCode errorCode = generateNativeConfig(DockerContainer::Xray, clientName, Proto::Xray, nativeConfig);
|
||||
if (errorCode) {
|
||||
emit exportErrorOccurred(errorCode);
|
||||
return;
|
||||
|
||||
@@ -28,7 +28,7 @@ public slots:
|
||||
void generateAwgConfig(const QString &clientName);
|
||||
void generateShadowSocksConfig();
|
||||
void generateCloakConfig();
|
||||
void generateXrayConfig();
|
||||
void generateXrayConfig(const QString &clientName);
|
||||
|
||||
QString getConfig();
|
||||
QString getNativeConfigString();
|
||||
|
||||
@@ -51,7 +51,7 @@ QString PageController::getPagePath(PageLoader::PageEnum page)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<PageLoader::PageEnum>();
|
||||
QString pageName = metaEnum.valueToKey(static_cast<int>(page));
|
||||
return "qrc:/ui/qml/Pages2/" + pageName + ".qml";
|
||||
return "qrc:/ui/qml/DefaultVpn/Pages/" + pageName + ".qml";
|
||||
}
|
||||
|
||||
void PageController::closeWindow()
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace
|
||||
constexpr char storeEndpoint[] = "store_endpoint";
|
||||
|
||||
constexpr char isAvailable[] = "is_available";
|
||||
|
||||
constexpr char subscription[] = "subscription";
|
||||
constexpr char endDate[] = "end_date";
|
||||
}
|
||||
|
||||
namespace serviceType
|
||||
@@ -51,23 +54,23 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(rowCount()))
|
||||
return QVariant();
|
||||
|
||||
QJsonObject service = m_services.at(index.row()).toObject();
|
||||
QJsonObject serviceInfo = service.value(configKey::serviceInfo).toObject();
|
||||
auto serviceType = service.value(configKey::serviceType).toString();
|
||||
auto apiServiceData = m_services.at(index.row());
|
||||
auto serviceType = apiServiceData.type;
|
||||
auto isServiceAvailable = apiServiceData.isServiceAvailable;
|
||||
|
||||
switch (role) {
|
||||
case NameRole: {
|
||||
return serviceInfo.value(configKey::name).toString();
|
||||
return apiServiceData.serviceInfo.name;
|
||||
}
|
||||
case CardDescriptionRole: {
|
||||
auto speed = serviceInfo.value(configKey::speed).toString();
|
||||
auto speed = apiServiceData.serviceInfo.speed;
|
||||
if (serviceType == serviceType::amneziaPremium) {
|
||||
return tr("Classic VPN for comfortable work, downloading large files and watching videos. "
|
||||
"Works for any sites. Speed up to %1 MBit/s")
|
||||
.arg(speed);
|
||||
} else if (serviceType == serviceType::amneziaFree){
|
||||
QString description = tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
|
||||
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
||||
if (isServiceAvailable) {
|
||||
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a>");
|
||||
}
|
||||
return description;
|
||||
@@ -83,25 +86,24 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
case IsServiceAvailableRole: {
|
||||
if (serviceType == serviceType::amneziaFree) {
|
||||
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
||||
if (isServiceAvailable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SpeedRole: {
|
||||
auto speed = serviceInfo.value(configKey::speed).toString();
|
||||
return tr("%1 MBit/s").arg(speed);
|
||||
return tr("%1 MBit/s").arg(apiServiceData.serviceInfo.speed);
|
||||
}
|
||||
case WorkPeriodRole: {
|
||||
auto timelimit = serviceInfo.value(configKey::timelimit).toString();
|
||||
if (timelimit == "0") {
|
||||
case TimeLimitRole: {
|
||||
auto timeLimit = apiServiceData.serviceInfo.timeLimit;
|
||||
if (timeLimit == "0") {
|
||||
return "";
|
||||
}
|
||||
return tr("%1 days").arg(timelimit);
|
||||
return tr("%1 days").arg(timeLimit);
|
||||
}
|
||||
case RegionRole: {
|
||||
return serviceInfo.value(configKey::region).toString();
|
||||
return apiServiceData.serviceInfo.region;
|
||||
}
|
||||
case FeaturesRole: {
|
||||
if (serviceType == serviceType::amneziaPremium) {
|
||||
@@ -113,12 +115,15 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
}
|
||||
case PriceRole: {
|
||||
auto price = serviceInfo.value(configKey::price).toString();
|
||||
auto price = apiServiceData.serviceInfo.price;
|
||||
if (price == "free") {
|
||||
return tr("Free");
|
||||
}
|
||||
return tr("%1 $/month").arg(price);
|
||||
}
|
||||
case EndDateRole: {
|
||||
return QDateTime::fromString(apiServiceData.subscription.endDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -128,15 +133,18 @@ void ApiServicesModel::updateModel(const QJsonObject &data)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_countryCode = data.value(configKey::userCountryCode).toString();
|
||||
m_services = data.value(configKey::services).toArray();
|
||||
if (m_services.isEmpty()) {
|
||||
QJsonObject service;
|
||||
service.insert(configKey::serviceInfo, data.value(configKey::serviceInfo));
|
||||
service.insert(configKey::serviceType, data.value(configKey::serviceType));
|
||||
m_services.clear();
|
||||
|
||||
m_services.push_back(service);
|
||||
m_countryCode = data.value(configKey::userCountryCode).toString();
|
||||
auto services = data.value(configKey::services).toArray();
|
||||
|
||||
if (services.isEmpty()) {
|
||||
m_services.push_back(getApiServicesData(data));
|
||||
m_selectedServiceIndex = 0;
|
||||
} else {
|
||||
for (const auto &service : services) {
|
||||
m_services.push_back(getApiServicesData(service.toObject()));
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
@@ -149,32 +157,32 @@ void ApiServicesModel::setServiceIndex(const int index)
|
||||
|
||||
QJsonObject ApiServicesModel::getSelectedServiceInfo()
|
||||
{
|
||||
QJsonObject service = m_services.at(m_selectedServiceIndex).toObject();
|
||||
return service.value(configKey::serviceInfo).toObject();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.serviceInfo.object;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceType()
|
||||
{
|
||||
QJsonObject service = m_services.at(m_selectedServiceIndex).toObject();
|
||||
return service.value(configKey::serviceType).toString();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.type;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceProtocol()
|
||||
{
|
||||
QJsonObject service = m_services.at(m_selectedServiceIndex).toObject();
|
||||
return service.value(configKey::serviceProtocol).toString();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.protocol;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceName()
|
||||
{
|
||||
auto modelIndex = index(m_selectedServiceIndex, 0);
|
||||
return data(modelIndex, ApiServicesModel::Roles::NameRole).toString();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.serviceInfo.name;
|
||||
}
|
||||
|
||||
QJsonArray ApiServicesModel::getSelectedServiceCountries()
|
||||
{
|
||||
QJsonObject service = m_services.at(m_selectedServiceIndex).toObject();
|
||||
return service.value(configKey::availableCountries).toArray();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.availableCountries;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getCountryCode()
|
||||
@@ -184,8 +192,8 @@ QString ApiServicesModel::getCountryCode()
|
||||
|
||||
QString ApiServicesModel::getStoreEndpoint()
|
||||
{
|
||||
QJsonObject service = m_services.at(m_selectedServiceIndex).toObject();
|
||||
return service.value(configKey::storeEndpoint).toString();
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.storeEndpoint;
|
||||
}
|
||||
|
||||
QVariant ApiServicesModel::getSelectedServiceData(const QString roleString)
|
||||
@@ -209,10 +217,46 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
|
||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||
roles[IsServiceAvailableRole] = "isServiceAvailable";
|
||||
roles[SpeedRole] = "speed";
|
||||
roles[WorkPeriodRole] = "workPeriod";
|
||||
roles[TimeLimitRole] = "timeLimit";
|
||||
roles[RegionRole] = "region";
|
||||
roles[FeaturesRole] = "features";
|
||||
roles[PriceRole] = "price";
|
||||
roles[EndDateRole] = "endDate";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJsonObject &data)
|
||||
{
|
||||
auto serviceInfo = data.value(configKey::serviceInfo).toObject();
|
||||
auto serviceType = data.value(configKey::serviceType).toString();
|
||||
auto serviceProtocol = data.value(configKey::serviceProtocol).toString();
|
||||
auto availableCountries = data.value(configKey::availableCountries).toArray();
|
||||
|
||||
auto subscriptionObject = data.value(configKey::subscription).toObject();
|
||||
|
||||
ApiServicesData serviceData;
|
||||
serviceData.serviceInfo.name = serviceInfo.value(configKey::name).toString();
|
||||
serviceData.serviceInfo.price = serviceInfo.value(configKey::price).toString();
|
||||
serviceData.serviceInfo.region = serviceInfo.value(configKey::region).toString();
|
||||
serviceData.serviceInfo.speed = serviceInfo.value(configKey::speed).toString();
|
||||
serviceData.serviceInfo.timeLimit = serviceInfo.value(configKey::timelimit).toString();
|
||||
|
||||
serviceData.type = serviceType;
|
||||
serviceData.protocol = serviceProtocol;
|
||||
|
||||
serviceData.storeEndpoint = serviceInfo.value(configKey::storeEndpoint).toString();
|
||||
|
||||
if (serviceInfo.value(configKey::isAvailable).isBool()) {
|
||||
serviceData.isServiceAvailable = data.value(configKey::isAvailable).toBool();
|
||||
} else {
|
||||
serviceData.isServiceAvailable = true;
|
||||
}
|
||||
|
||||
serviceData.serviceInfo.object = serviceInfo;
|
||||
serviceData.availableCountries = availableCountries;
|
||||
|
||||
serviceData.subscription.endDate = subscriptionObject.value(configKey::endDate).toString();
|
||||
|
||||
return serviceData;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
class ApiServicesModel : public QAbstractListModel
|
||||
{
|
||||
@@ -15,10 +16,11 @@ public:
|
||||
ServiceDescriptionRole,
|
||||
IsServiceAvailableRole,
|
||||
SpeedRole,
|
||||
WorkPeriodRole,
|
||||
TimeLimitRole,
|
||||
RegionRole,
|
||||
FeaturesRole,
|
||||
PriceRole
|
||||
PriceRole,
|
||||
EndDateRole
|
||||
};
|
||||
|
||||
explicit ApiServicesModel(QObject *parent = nullptr);
|
||||
@@ -48,8 +50,40 @@ protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct ServiceInfo
|
||||
{
|
||||
QString name;
|
||||
QString speed;
|
||||
QString timeLimit;
|
||||
QString region;
|
||||
QString price;
|
||||
|
||||
QJsonObject object;
|
||||
};
|
||||
|
||||
struct Subscription
|
||||
{
|
||||
QString endDate;
|
||||
};
|
||||
|
||||
struct ApiServicesData
|
||||
{
|
||||
bool isServiceAvailable;
|
||||
|
||||
QString type;
|
||||
QString protocol;
|
||||
QString storeEndpoint;
|
||||
|
||||
ServiceInfo serviceInfo;
|
||||
Subscription subscription;
|
||||
|
||||
QJsonArray availableCountries;
|
||||
};
|
||||
|
||||
ApiServicesData getApiServicesData(const QJsonObject &data);
|
||||
|
||||
QString m_countryCode;
|
||||
QJsonArray m_services;
|
||||
QVector<ApiServicesData> m_services;
|
||||
|
||||
int m_selectedServiceIndex;
|
||||
};
|
||||
|
||||
@@ -106,6 +106,8 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
||||
error = getOpenVpnClients(container, credentials, serverController, count);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
error = getWireGuardClients(container, credentials, serverController, count);
|
||||
} else if (container == DockerContainer::Xray) {
|
||||
error = getXrayClients(container, credentials, serverController, count);
|
||||
}
|
||||
if (error != ErrorCode::NoError) {
|
||||
endResetModel();
|
||||
@@ -239,6 +241,68 @@ ErrorCode ClientManagementModel::getWireGuardClients(const DockerContainer conta
|
||||
}
|
||||
return error;
|
||||
}
|
||||
ErrorCode ClientManagementModel::getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
const QString serverConfigPath = amnezia::protocols::xray::serverConfigPath;
|
||||
const QString configString = serverController->getTextFileFromContainer(container, credentials, serverConfigPath, error);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get the xray server config file from the server";
|
||||
return error;
|
||||
}
|
||||
|
||||
QJsonDocument serverConfig = QJsonDocument::fromJson(configString.toUtf8());
|
||||
if (serverConfig.isNull()) {
|
||||
logger.error() << "Failed to parse xray server config JSON";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
if (!serverConfig.object().contains("inbounds") || serverConfig.object()["inbounds"].toArray().isEmpty()) {
|
||||
logger.error() << "Invalid xray server config structure";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonObject inbound = serverConfig.object()["inbounds"].toArray()[0].toObject();
|
||||
if (!inbound.contains("settings")) {
|
||||
logger.error() << "Missing settings in xray inbound config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonObject settings = inbound["settings"].toObject();
|
||||
if (!settings.contains("clients")) {
|
||||
logger.error() << "Missing clients in xray settings config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonArray clients = settings["clients"].toArray();
|
||||
for (const auto &clientValue : clients) {
|
||||
const QJsonObject clientObj = clientValue.toObject();
|
||||
if (!clientObj.contains("id")) {
|
||||
logger.error() << "Missing id in xray client config";
|
||||
continue;
|
||||
}
|
||||
QString clientId = clientObj["id"].toString();
|
||||
|
||||
QString xrayDefaultUuid = serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, error);
|
||||
xrayDefaultUuid.replace("\n", "");
|
||||
|
||||
if (!isClientExists(clientId) && clientId != xrayDefaultUuid) {
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = clientId;
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = QString("Client %1").arg(count);
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
m_clientsTable.push_back(client);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data)
|
||||
@@ -326,17 +390,67 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
Proto protocol;
|
||||
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
protocol = Proto::OpenVpn;
|
||||
} else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
} else {
|
||||
return ErrorCode::NoError;
|
||||
switch (container) {
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak:
|
||||
protocol = Proto::OpenVpn;
|
||||
break;
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg:
|
||||
case DockerContainer::Xray:
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
break;
|
||||
default:
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
|
||||
return appendClient(protocolConfig, clientName, container, credentials, serverController);
|
||||
}
|
||||
|
||||
return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials, serverController);
|
||||
ErrorCode ClientManagementModel::appendClient(QJsonObject &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject outbound = outbounds[0].toObject();
|
||||
if (!outbound.contains("settings")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject settings = outbound["settings"].toObject();
|
||||
if (!settings.contains("vnext")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray vnext = settings["vnext"].toArray();
|
||||
if (vnext.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject vnextObj = vnext[0].toObject();
|
||||
if (!vnextObj.contains("users")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray users = vnextObj["users"].toArray();
|
||||
if (users.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject user = users[0].toObject();
|
||||
if (!user.contains("id")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
}
|
||||
|
||||
return appendClient(clientId, clientName, container, credentials, serverController);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
@@ -422,10 +536,27 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain
|
||||
auto client = m_clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
switch(container)
|
||||
{
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg: {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::Xray: {
|
||||
errorCode = revokeXray(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
@@ -463,19 +594,69 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
|
||||
}
|
||||
|
||||
Proto protocol;
|
||||
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
protocol = Proto::OpenVpn;
|
||||
} else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
} else {
|
||||
return ErrorCode::NoError;
|
||||
|
||||
switch(container)
|
||||
{
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
protocol = Proto::OpenVpn;
|
||||
break;
|
||||
}
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg:
|
||||
case DockerContainer::Xray: {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
}
|
||||
|
||||
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
|
||||
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject outbound = outbounds[0].toObject();
|
||||
if (!outbound.contains("settings")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject settings = outbound["settings"].toObject();
|
||||
if (!settings.contains("vnext")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray vnext = settings["vnext"].toArray();
|
||||
if (vnext.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject vnextObj = vnext[0].toObject();
|
||||
if (!vnextObj.contains("users")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray users = vnextObj["users"].toArray();
|
||||
if (users.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject user = users[0].toObject();
|
||||
if (!user.contains("id")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
}
|
||||
|
||||
int row;
|
||||
bool clientExists = false;
|
||||
QString clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
for (row = 0; row < rowCount(); row++) {
|
||||
auto client = m_clientsTable.at(row).toObject();
|
||||
if (clientId == client.value(configKey::clientId).toString()) {
|
||||
@@ -487,11 +668,28 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
switch (container)
|
||||
{
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg: {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::Xray: {
|
||||
errorCode = revokeXray(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
@@ -594,6 +792,117 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::revokeXray(const int row,
|
||||
const DockerContainer container,
|
||||
const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
// Get server config
|
||||
const QString serverConfigPath = amnezia::protocols::xray::serverConfigPath;
|
||||
const QString configString = serverController->getTextFileFromContainer(container, credentials, serverConfigPath, error);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get the xray server config file";
|
||||
return error;
|
||||
}
|
||||
|
||||
QJsonDocument serverConfig = QJsonDocument::fromJson(configString.toUtf8());
|
||||
if (serverConfig.isNull()) {
|
||||
logger.error() << "Failed to parse xray server config JSON";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
// Get client ID to remove
|
||||
auto client = m_clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
|
||||
// Remove client from server config
|
||||
QJsonObject configObj = serverConfig.object();
|
||||
if (!configObj.contains("inbounds")) {
|
||||
logger.error() << "Missing inbounds in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonArray inbounds = configObj["inbounds"].toArray();
|
||||
if (inbounds.isEmpty()) {
|
||||
logger.error() << "Empty inbounds array in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonObject inbound = inbounds[0].toObject();
|
||||
if (!inbound.contains("settings")) {
|
||||
logger.error() << "Missing settings in xray inbound config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonObject settings = inbound["settings"].toObject();
|
||||
if (!settings.contains("clients")) {
|
||||
logger.error() << "Missing clients in xray settings";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonArray clients = settings["clients"].toArray();
|
||||
if (clients.isEmpty()) {
|
||||
logger.error() << "Empty clients array in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
for (int i = 0; i < clients.size(); ++i) {
|
||||
QJsonObject clientObj = clients[i].toObject();
|
||||
if (clientObj.contains("id") && clientObj["id"].toString() == clientId) {
|
||||
clients.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update server config
|
||||
settings["clients"] = clients;
|
||||
inbound["settings"] = settings;
|
||||
inbounds[0] = inbound;
|
||||
configObj["inbounds"] = inbounds;
|
||||
|
||||
// Upload updated config
|
||||
error = serverController->uploadTextFileToContainer(
|
||||
container,
|
||||
credentials,
|
||||
QJsonDocument(configObj).toJson(),
|
||||
serverConfigPath
|
||||
);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload updated xray config";
|
||||
return error;
|
||||
}
|
||||
|
||||
// Remove from local table
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_clientsTable.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
// Update clients table file on server
|
||||
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable")
|
||||
.arg(ContainerProps::containerTypeToString(container));
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload the clientsTable file";
|
||||
}
|
||||
|
||||
// Restart container
|
||||
QString restartScript = QString("sudo docker restart $CONTAINER_NAME");
|
||||
error = serverController->runScript(
|
||||
credentials,
|
||||
serverController->replaceVars(restartScript, serverController->genVarsForScript(credentials, container))
|
||||
);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to restart xray container";
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
@@ -604,4 +913,4 @@ QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
||||
roles[DataSentRole] = "dataSent";
|
||||
roles[AllowedIpsRole] = "allowedIps";
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,8 @@ public slots:
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig,
|
||||
const QString &clientName, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(QJsonObject &protocolConfig, const QString &clientName,const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, const ServerCredentials &credentials,
|
||||
@@ -64,11 +66,15 @@ private:
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode revokeXray(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
ErrorCode getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
ErrorCode getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
ErrorCode getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
|
||||
ErrorCode wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace
|
||||
constexpr char serviceProtocol[] = "service_protocol";
|
||||
|
||||
constexpr char publicKeyInfo[] = "public_key";
|
||||
constexpr char endDate[] = "end_date";
|
||||
constexpr char expiresAt[] = "expires_at";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
emit ServersModel::defaultServerNameChanged();
|
||||
updateDefaultServerContainersModel();
|
||||
});
|
||||
|
||||
connect(this, &ServersModel::processedServerIndexChanged, this, &ServersModel::processedServerChanged);
|
||||
connect(this, &ServersModel::dataChanged, this, &ServersModel::processedServerChanged);
|
||||
}
|
||||
|
||||
int ServersModel::rowCount(const QModelIndex &parent) const
|
||||
@@ -79,6 +82,12 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServersModel::setData(const int index, const QVariant &value, int role)
|
||||
{
|
||||
QModelIndex modelIndex = this->index(index);
|
||||
return setData(modelIndex, value, role);
|
||||
}
|
||||
|
||||
QVariant ServersModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_servers.size())) {
|
||||
@@ -679,6 +688,18 @@ QVariant ServersModel::getProcessedServerData(const QString roleString)
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ServersModel::setProcessedServerData(const QString &roleString, const QVariant &value)
|
||||
{
|
||||
const auto roles = roleNames();
|
||||
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||
if (QString(it.value()) == roleString) {
|
||||
return setData(m_processedServerIndex, value, it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||
{
|
||||
auto server = m_servers.at(m_defaultServerIndex).toObject();
|
||||
@@ -718,9 +739,9 @@ bool ServersModel::isApiKeyExpired(const int serverIndex)
|
||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||
|
||||
auto publicKeyInfo = apiConfig.value(configKey::publicKeyInfo).toObject();
|
||||
const QString endDate = publicKeyInfo.value(configKey::endDate).toString();
|
||||
if (endDate.isEmpty()) {
|
||||
publicKeyInfo.insert(configKey::endDate, QDateTime::currentDateTimeUtc().addDays(1).toString(Qt::ISODate));
|
||||
const QString expiresAt = publicKeyInfo.value(configKey::expiresAt).toString();
|
||||
if (expiresAt.isEmpty()) {
|
||||
publicKeyInfo.insert(configKey::expiresAt, QDateTime::currentDateTimeUtc().addDays(1).toString(Qt::ISODate));
|
||||
apiConfig.insert(configKey::publicKeyInfo, publicKeyInfo);
|
||||
serverConfig.insert(configKey::apiConfig, apiConfig);
|
||||
editServer(serverConfig, serverIndex);
|
||||
@@ -728,8 +749,8 @@ bool ServersModel::isApiKeyExpired(const int serverIndex)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto endDateDateTime = QDateTime::fromString(endDate, Qt::ISODate).toUTC();
|
||||
if (endDateDateTime < QDateTime::currentDateTimeUtc()) {
|
||||
auto expiresAtDateTime = QDateTime::fromString(expiresAt, Qt::ISODate).toUTC();
|
||||
if (expiresAtDateTime < QDateTime::currentDateTimeUtc()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
bool setData(const int index, const QVariant &value, int role = Qt::EditRole);
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const int index, int role = Qt::DisplayRole) const;
|
||||
|
||||
@@ -115,6 +116,7 @@ public slots:
|
||||
QVariant getDefaultServerData(const QString roleString);
|
||||
|
||||
QVariant getProcessedServerData(const QString roleString);
|
||||
bool setProcessedServerData(const QString &roleString, const QVariant &value);
|
||||
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling();
|
||||
|
||||
@@ -127,6 +129,9 @@ protected:
|
||||
|
||||
signals:
|
||||
void processedServerIndexChanged(const int index);
|
||||
// emitted when the processed server index or processed server data is changed
|
||||
void processedServerChanged();
|
||||
|
||||
void defaultServerIndexChanged(const int index);
|
||||
void defaultServerNameChanged();
|
||||
void defaultServerDescriptionChanged();
|
||||
|
||||
36
client/ui/qml/DefaultVpn/Components/BlueButtonNoBorder.qml
Normal file
36
client/ui/qml/DefaultVpn/Components/BlueButtonNoBorder.qml
Normal file
@@ -0,0 +1,36 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "../Controls/TextTypes"
|
||||
import "../Controls"
|
||||
|
||||
ButtonType {
|
||||
defaultBackgroundColor: Style.color.accent1
|
||||
defaultBorderColor: Style.color.gray3
|
||||
defaultTextColor: Style.color.white
|
||||
defaultImageColor: Style.color.white
|
||||
|
||||
hoveredBackgroundColor: Style.color.accent2
|
||||
hoveredBorderColor: Style.color.gray3
|
||||
hoveredTextColor: Style.color.white
|
||||
hoveredImageColor: Style.color.white
|
||||
|
||||
pressedBackgroundColor: Style.color.accent3
|
||||
pressedBorderColor: Style.color.gray3
|
||||
pressedTextColor: Style.color.white
|
||||
pressedImageColor: Style.color.white
|
||||
|
||||
disabledBackgroundColor: Style.color.gray6
|
||||
disabledBorderColor: Style.color.gray3
|
||||
disabledTextColor: Style.color.gray2
|
||||
disabledImageColor: Style.color.gray2
|
||||
|
||||
defaultBorderWidth: 0
|
||||
disabledBorderWidth: 0
|
||||
}
|
||||
36
client/ui/qml/DefaultVpn/Components/WhiteButtonNoBorder.qml
Normal file
36
client/ui/qml/DefaultVpn/Components/WhiteButtonNoBorder.qml
Normal file
@@ -0,0 +1,36 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "../Controls/TextTypes"
|
||||
import "../Controls"
|
||||
|
||||
ButtonType {
|
||||
defaultBackgroundColor: Style.color.white
|
||||
defaultBorderColor: Style.color.gray3
|
||||
defaultTextColor: Style.color.accent1
|
||||
defaultImageColor: Style.color.accent1
|
||||
|
||||
hoveredBackgroundColor: Style.color.gray1
|
||||
hoveredBorderColor: Style.color.gray3
|
||||
hoveredTextColor: Style.color.accent2
|
||||
hoveredImageColor: Style.color.accent2
|
||||
|
||||
pressedBackgroundColor: Style.color.gray2
|
||||
pressedBorderColor: Style.color.gray3
|
||||
pressedTextColor: Style.color.accent3
|
||||
pressedImageColor: Style.color.accent3
|
||||
|
||||
disabledBackgroundColor: Style.color.white
|
||||
disabledBorderColor: Style.color.gray3
|
||||
disabledTextColor: Style.color.gray8
|
||||
disabledImageColor: Style.color.gray8
|
||||
|
||||
defaultBorderWidth: 0
|
||||
disabledBorderWidth: 0
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "../Controls/TextTypes"
|
||||
import "../Controls"
|
||||
|
||||
ButtonType {
|
||||
defaultBackgroundColor: Style.color.white
|
||||
defaultBorderColor: Style.color.gray3
|
||||
defaultTextColor: Style.color.black
|
||||
defaultImageColor: Style.color.black
|
||||
|
||||
hoveredBackgroundColor: Style.color.white
|
||||
hoveredBorderColor: Style.color.gray6
|
||||
hoveredTextColor: Style.color.black
|
||||
hoveredImageColor: Style.color.black
|
||||
|
||||
pressedBackgroundColor: Style.color.gray1
|
||||
pressedBorderColor: Style.color.gray6
|
||||
pressedTextColor: Style.color.black
|
||||
pressedImageColor: Style.color.black
|
||||
|
||||
disabledBackgroundColor: Style.color.gray3
|
||||
disabledBorderColor: Style.color.gray2
|
||||
disabledTextColor: Style.color.gray9
|
||||
disabledImageColor: Style.color.gray9
|
||||
|
||||
defaultBorderWidth: 1
|
||||
disabledBorderWidth: 1
|
||||
hoveredBorderWidth: 1
|
||||
}
|
||||
37
client/ui/qml/DefaultVpn/Config/DeviceInfo.qml
Normal file
37
client/ui/qml/DefaultVpn/Config/DeviceInfo.qml
Normal file
@@ -0,0 +1,37 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
readonly property int screenWidth: 380
|
||||
readonly property int screenHeight: 680
|
||||
|
||||
function isMobile() {
|
||||
if (Qt.platform.os === "android" ||
|
||||
Qt.platform.os === "ios") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isDesktop() {
|
||||
if (Qt.platform.os === "windows" ||
|
||||
Qt.platform.os === "linux" ||
|
||||
Qt.platform.os === "osx") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: clipboard
|
||||
visible: false
|
||||
}
|
||||
|
||||
function copyToClipBoard(text) {
|
||||
clipboard.text = text
|
||||
clipboard.selectAll()
|
||||
clipboard.copy()
|
||||
clipboard.select(0, 0)
|
||||
}
|
||||
}
|
||||
30
client/ui/qml/DefaultVpn/Config/Style.qml
Normal file
30
client/ui/qml/DefaultVpn/Config/Style.qml
Normal file
@@ -0,0 +1,30 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
property QtObject color: QtObject {
|
||||
readonly property color transparent: 'transparent'
|
||||
readonly property color gray1: '#F2F2F7'
|
||||
readonly property color gray2: '#E5E5EA'
|
||||
readonly property color gray3: '#D1D1D6'
|
||||
readonly property color gray4: '#C7C7CC'
|
||||
readonly property color gray5: '#AEAEB2'
|
||||
readonly property color gray6: '#8E8E93'
|
||||
readonly property color gray7: '#7C7C83'
|
||||
readonly property color gray8: '#707075'
|
||||
readonly property color gray9: '#57575B'
|
||||
readonly property color accent1: '#007AFF'
|
||||
readonly property color accent2: '#0B6EDA'
|
||||
readonly property color accent3: '#1256A1'
|
||||
readonly property color error: '#FF3B30'
|
||||
readonly property color warning: '#FF9500'
|
||||
readonly property color success: '#34C759'
|
||||
readonly property color black: '#000000'
|
||||
readonly property color white: '#FFFFFF'
|
||||
|
||||
readonly property color transparentBlack: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
readonly property string font: "Vela Sans GX"
|
||||
}
|
||||
4
client/ui/qml/DefaultVpn/Config/qmldir
Normal file
4
client/ui/qml/DefaultVpn/Config/qmldir
Normal file
@@ -0,0 +1,4 @@
|
||||
module Config
|
||||
|
||||
singleton DeviceInfo 1.0 DeviceInfo.qml
|
||||
singleton Style 1.0 Style.qml
|
||||
70
client/ui/qml/DefaultVpn/Controls/BusyIndicatorType.qml
Normal file
70
client/ui/qml/DefaultVpn/Controls/BusyIndicatorType.qml
Normal file
@@ -0,0 +1,70 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Shapes
|
||||
|
||||
import Config 1.0
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
anchors.centerIn: parent
|
||||
|
||||
modal: true
|
||||
closePolicy: Popup.NoAutoClose
|
||||
|
||||
visible: false
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: Style.color.transparentBlack
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: Style.color.transparent
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: busyIndicator
|
||||
|
||||
visible: true
|
||||
running: true
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: 46
|
||||
implicitHeight: 46
|
||||
transformOrigin: Item.Center
|
||||
|
||||
Shape {
|
||||
id: shape
|
||||
width: parent.implicitWidth
|
||||
height: parent.implicitHeight
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
layer.enabled: true
|
||||
layer.samples: 4
|
||||
|
||||
ShapePath {
|
||||
fillColor: Style.color.transparent
|
||||
strokeColor: Style.color.gray3
|
||||
strokeWidth: 3
|
||||
capStyle: ShapePath.RoundCap
|
||||
|
||||
PathAngleArc {
|
||||
centerX: shape.width / 2
|
||||
centerY: shape.height / 2
|
||||
radiusX: 18
|
||||
radiusY: 18
|
||||
startAngle: 225
|
||||
sweepAngle: -90
|
||||
}
|
||||
}
|
||||
RotationAnimator {
|
||||
target: shape
|
||||
running: busyIndicator.visible && busyIndicator.running
|
||||
from: 0
|
||||
to: 360
|
||||
loops: Animation.Infinite
|
||||
duration: 1250
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
154
client/ui/qml/DefaultVpn/Controls/ButtonType.qml
Normal file
154
client/ui/qml/DefaultVpn/Controls/ButtonType.qml
Normal file
@@ -0,0 +1,154 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Button {
|
||||
id: root
|
||||
|
||||
property string defaultBackgroundColor: Style.color.white
|
||||
property string defaultBorderColor: Style.color.gray3
|
||||
property string defaultTextColor: Style.color.accent1
|
||||
property string defaultImageColor: Style.color.accent1
|
||||
|
||||
property string hoveredBackgroundColor: Style.color.gray1
|
||||
property string hoveredBorderColor: Style.color.gray3
|
||||
property string hoveredTextColor: Style.color.accent2
|
||||
property string hoveredImageColor: Style.color.accent2
|
||||
|
||||
property string pressedBackgroundColor: Style.color.gray2
|
||||
property string pressedBorderColor: Style.color.gray3
|
||||
property string pressedTextColor: Style.color.accent3
|
||||
property string pressedImageColor: Style.color.accent3
|
||||
|
||||
property string disabledBackgroundColor: Style.color.white
|
||||
property string disabledBorderColor: Style.color.gray3
|
||||
property string disabledTextColor: Style.color.gray8
|
||||
property string disabledImageColor: Style.color.gray8
|
||||
|
||||
property int defaultBorderWidth: 0
|
||||
property int disabledBorderWidth: 0
|
||||
property int hoveredBorderWidth: 0
|
||||
|
||||
property string imageSource: ""
|
||||
|
||||
readonly property bool isImageOnly: root.text !== ""
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 6
|
||||
|
||||
color: root.enabled ? root.defaultBackgroundColor : root.disabledBackgroundColor
|
||||
border.color: root.enabled ? root.defaultBorderColor : root.disabledBorderColor
|
||||
border.width: root.enabled ? root.defaultBorderWidth : root.disabledBorderWidth
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: background
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
hoverEnabled: true
|
||||
enabled: root.enabled
|
||||
|
||||
onEntered: {
|
||||
background.color = root.hoveredBackgroundColor
|
||||
background.border.color = root.hoveredBorderColor
|
||||
background.border.width = root.hoveredBorderWidth
|
||||
image.imageColor = root.hoveredImageColor
|
||||
buttonText.color = root.hoveredTextColor
|
||||
}
|
||||
|
||||
onExited: {
|
||||
background.color = root.defaultBackgroundColor
|
||||
background.border.color = root.defaultBorderColor
|
||||
background.border.width = root.defaultBorderWidth
|
||||
image.imageColor = root.defaultImageColor
|
||||
buttonText.color = root.defaultTextColor
|
||||
}
|
||||
|
||||
onPressedChanged: {
|
||||
if (pressed) {
|
||||
background.color = root.pressedBackgroundColor
|
||||
background.border.color = root.pressedBorderColor
|
||||
image.imageColor = root.pressedImageColor
|
||||
buttonText.color = root.pressedTextColor
|
||||
} else if (entered) {
|
||||
background.color = root.hoveredBackgroundColor
|
||||
background.border.color = root.hoveredBorderColor
|
||||
image.imageColor = root.hoveredImageColor
|
||||
buttonText.color = root.hoveredTextColor
|
||||
} else {
|
||||
background.color = root.defaultBackgroundColor
|
||||
background.border.color = root.defaultBorderColor
|
||||
image.imageColor = root.defaultImageColor
|
||||
buttonText.color = root.defaultTextColor
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
|
||||
MediumTextType {
|
||||
id: buttonText
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 12
|
||||
Layout.bottomMargin: 12
|
||||
Layout.leftMargin: 12
|
||||
Layout.rightMargin: 12
|
||||
visible: root.isImageOnly
|
||||
|
||||
color: root.defaultTextColor
|
||||
text: root.text
|
||||
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image
|
||||
|
||||
property color imageColor: root.enabled ? root.defaultImageColor : root.disabledImageColor
|
||||
|
||||
Layout.preferredHeight: 22
|
||||
Layout.preferredWidth: 22
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 12
|
||||
Layout.bottomMargin: 12
|
||||
Layout.leftMargin: 12
|
||||
Layout.rightMargin: 12
|
||||
|
||||
source: root.imageSource
|
||||
visible: root.imageSource === "" ? false : true
|
||||
|
||||
layer {
|
||||
enabled: true
|
||||
effect: ColorOverlay {
|
||||
color: image.imageColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
client/ui/qml/DefaultVpn/Controls/DropDownType.qml
Normal file
99
client/ui/qml/DefaultVpn/Controls/DropDownType.qml
Normal file
@@ -0,0 +1,99 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Button {
|
||||
id: root
|
||||
|
||||
property string defaultBackgroundColor: "#FFFFFF"
|
||||
property string defaultBorderColor: "#D1D1D6"
|
||||
property string defaultTextColor: "#000000"
|
||||
property string defaultImageColor: "#000000"
|
||||
|
||||
property string hoveredBackgroundColor: "#FFFFFF"
|
||||
property string hoveredBorderColor: "#D1D1D6"
|
||||
property string hoveredTextColor: "#D1D1D6"
|
||||
property string hoveredImageColor: "#D1D1D6"
|
||||
|
||||
property string pressedBackgroundColor: "#FFFFFF"
|
||||
property string pressedBorderColor: "#D1D1D6"
|
||||
property string pressedTextColor: "#D1D1D6"
|
||||
property string pressedImageColor: "#D1D1D6"
|
||||
|
||||
property string disabledBackgroundColor: "#FFFFFF"
|
||||
property string disabledBorderColor: "#D1D1D6"
|
||||
property string disabledTextColor: "#D1D1D6"
|
||||
property string disabledImageColor: "#D1D1D6"
|
||||
|
||||
property string imageSource: "qrc:/images/controls/chevron-down.svg"
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
background: Rectangle {
|
||||
id: focusBorder
|
||||
|
||||
color: root.defaultBackgroundColor
|
||||
border.color: root.defaultBorderColor
|
||||
border.width: 1
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 6
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: focusBorder
|
||||
enabled: false
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.fill: focusBorder
|
||||
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
MediumTextType {
|
||||
id: buttonText
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 12
|
||||
Layout.bottomMargin: 12
|
||||
|
||||
color: root.defaultTextColor
|
||||
text: root.text
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.preferredHeight: 22
|
||||
Layout.preferredWidth: 22
|
||||
|
||||
source: root.imageSource
|
||||
visible: root.imageSource === "" ? false : true
|
||||
|
||||
layer {
|
||||
enabled: true
|
||||
effect: ColorOverlay {
|
||||
color: root.defaultImageColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
client/ui/qml/DefaultVpn/Controls/InputType.qml
Normal file
56
client/ui/qml/DefaultVpn/Controls/InputType.qml
Normal file
@@ -0,0 +1,56 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
TextField {
|
||||
id: root
|
||||
|
||||
property string defaultBackgroundColor: Style.color.white
|
||||
property string defaultBorderColor: Style.color.gray3
|
||||
property string defaultTextColor: Style.color.gray6
|
||||
|
||||
property string hoveredBackgroundColor: Style.color.white
|
||||
property string hoveredBorderColor: Style.color.gray6
|
||||
property string hoveredTextColor: Style.color.black
|
||||
|
||||
property string disabledBackgroundColor: Style.color.gray2
|
||||
property string disabledBorderColor: Style.color.gray3
|
||||
property string disabledTextColor: Style.color.gray9
|
||||
|
||||
|
||||
color: root.enabled ? root.defaultTextColor : (root.hovered || root.pressed) ? root.hoveredTextColor : root.disabledTextColor
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
color: root.enabled ? root.defaultBackgroundColor : (root.hovered || root.pressed) ? root.hoveredBackgroundColor : root.disabledBackgroundColor
|
||||
border.color: root.enabled ? root.defaultBorderColor : (root.hovered || root.pressed) ? root.hoveredBorderColor : root.disabledBorderColor
|
||||
border.width: 1
|
||||
radius: 6
|
||||
}
|
||||
|
||||
topPadding: 12
|
||||
bottomPadding: 12
|
||||
leftPadding: 16
|
||||
rightPadding: 16
|
||||
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
|
||||
|
||||
selectionColor: Style.color.accent1
|
||||
selectedTextColor: Style.color.white
|
||||
|
||||
font.pixelSize: 17
|
||||
font.weight: 400
|
||||
font.family: Style.font
|
||||
|
||||
wrapMode: TextEdit.Wrap
|
||||
|
||||
verticalAlignment: Text.AlignTop
|
||||
|
||||
}
|
||||
96
client/ui/qml/DefaultVpn/Controls/PopupType.qml
Normal file
96
client/ui/qml/DefaultVpn/Controls/PopupType.qml
Normal file
@@ -0,0 +1,96 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Config 1.0
|
||||
|
||||
import "TextTypes"
|
||||
import "../Components"
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
|
||||
property string text
|
||||
property bool closeButtonVisible: true
|
||||
|
||||
leftMargin: 25
|
||||
rightMargin: 25
|
||||
bottomMargin: 70
|
||||
|
||||
width: parent.width - leftMargin - rightMargin
|
||||
|
||||
anchors.centerIn: parent
|
||||
modal: root.closeButtonVisible
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
visible: root.closeButtonVisible
|
||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.color.white
|
||||
radius: 8
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
color: Style.color.gray3
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 1
|
||||
radius: 10
|
||||
samples: 25
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
XSmallTextType {
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
|
||||
onLinkActivated: function(link) {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
|
||||
text: root.text
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: closeButton
|
||||
}
|
||||
|
||||
WhiteButtonNoBorder {
|
||||
id: closeButton
|
||||
visible: closeButtonVisible
|
||||
|
||||
imageSource: "qrc:/images/controls/x-circle.svg"
|
||||
|
||||
onClicked: function() {
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import QtQuick
|
||||
|
||||
import Config 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 34
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: Style.color.black
|
||||
font.pixelSize: 28
|
||||
font.weight: 700
|
||||
font.family: Style.font
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import QtQuick
|
||||
|
||||
import Config 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 24
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: Style.color.black
|
||||
font.pixelSize: 20
|
||||
font.weight: 700
|
||||
font.family: Style.font
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import QtQuick
|
||||
|
||||
import Config 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 22
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: Style.color.black
|
||||
font.pixelSize: 17
|
||||
font.weight: 400
|
||||
font.family: Style.font
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import QtQuick
|
||||
|
||||
import Config 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: Style.color.black
|
||||
font.pixelSize: 13
|
||||
font.weight: 400
|
||||
font.family: Style.font
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
122
client/ui/qml/DefaultVpn/Pages/PageHome.qml
Normal file
122
client/ui/qml/DefaultVpn/Pages/PageHome.qml
Normal file
@@ -0,0 +1,122 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
import Config 1.0
|
||||
|
||||
import "../Components"
|
||||
import "../Controls"
|
||||
import "../Controls/TextTypes"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 8
|
||||
anchors.bottomMargin: 36
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 0
|
||||
|
||||
Text {
|
||||
lineHeight: 68
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: Style.color.gray2
|
||||
font.pixelSize: 56
|
||||
font.weight: 700
|
||||
font.family: Style.font
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
|
||||
text: ConnectionController.isConnected ? qsTr("Online") : qsTr("Offline")
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
XSmallTextType {
|
||||
text: qsTr("Connection to")
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
DropDownType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: ServersModel.defaultServerName
|
||||
|
||||
onClicked: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsServersList)
|
||||
}
|
||||
}
|
||||
|
||||
WhiteButtonWithBorder {
|
||||
imageSource: "qrc:/images/controls/plus.svg"
|
||||
|
||||
onClicked: function() {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: connectButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 358
|
||||
|
||||
Layout.topMargin: 16
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 16
|
||||
|
||||
color: {
|
||||
if (ConnectionController.isConnectionInProgress) {
|
||||
return Style.color.accent3
|
||||
} else if (ConnectionController.isConnected) {
|
||||
return Style.color.accent1
|
||||
} else {
|
||||
return Style.color.black
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
|
||||
Image {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
|
||||
source: "qrc:/images/controls/connect-button.svg"
|
||||
}
|
||||
|
||||
Header3TextType {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 24
|
||||
|
||||
text: ConnectionController.connectionStateText
|
||||
|
||||
color: Style.color.white
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: function() {
|
||||
ServersModel.setProcessedServerIndex(ServersModel.defaultIndex)
|
||||
ConnectionController.connectButtonClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
client/ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml
Normal file
103
client/ui/qml/DefaultVpn/Pages/PageSettingsServerInfo.qml
Normal file
@@ -0,0 +1,103 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
import Config 1.0
|
||||
|
||||
import "../Components"
|
||||
import "../Controls"
|
||||
import "../Controls/TextTypes"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
function onRemoveProcessedServerFinished(finishedMessage) {
|
||||
if (!ServersModel.getServersCount()) {
|
||||
PageController.goToStartPage()
|
||||
} else {
|
||||
PageController.closePage()
|
||||
}
|
||||
PageController.showNotificationMessage(finishedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.topMargin: 8
|
||||
|
||||
WhiteButtonNoBorder {
|
||||
id: backButton
|
||||
imageSource: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
onClicked: PageController.closePage()
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Header1TextType {
|
||||
id: header
|
||||
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 24
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Server settings")
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
XSmallTextType {
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 8
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Name")
|
||||
}
|
||||
|
||||
InputType {
|
||||
id: textKey
|
||||
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
WhiteButtonWithBorder {
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.topMargin: 24
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Remove server")
|
||||
|
||||
onClicked: function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
InstallController.removeProcessedServer()
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
165
client/ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml
Normal file
165
client/ui/qml/DefaultVpn/Pages/PageSettingsServersList.qml
Normal file
@@ -0,0 +1,165 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
import Config 1.0
|
||||
|
||||
import "../Components"
|
||||
import "../Controls"
|
||||
import "../Controls/TextTypes"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.topMargin: 8
|
||||
|
||||
WhiteButtonNoBorder {
|
||||
id: backButton
|
||||
imageSource: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
onClicked: PageController.closePage()
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
WhiteButtonNoBorder {
|
||||
imageSource: "qrc:/images/controls/plus.svg"
|
||||
|
||||
onClicked: function() {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Header1TextType {
|
||||
id: header
|
||||
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Connect to")
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: serversRadioButtonGroup
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: serversListView
|
||||
|
||||
Layout.topMargin: 16
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
model: ServersModel
|
||||
currentIndex: ServersModel.defaultIndex
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
function onDefaultServerIndexChanged(serverIndex) {
|
||||
serversListView.currentIndex = serverIndex
|
||||
serversListView.positionViewAtIndex(serversListView.currentIndex, ListView.Contain)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: positionViewAtIndex(currentIndex, ListView.Center)
|
||||
|
||||
delegate: Item {
|
||||
id: menuContentDelegate
|
||||
required property string name
|
||||
required property int index
|
||||
|
||||
implicitWidth: serversListView.width
|
||||
implicitHeight: serverItem.implicitHeight
|
||||
|
||||
RadioButton {
|
||||
id: serverItem
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
ButtonGroup.group: serversRadioButtonGroup
|
||||
|
||||
checked: index === serversListView.currentIndex
|
||||
|
||||
indicator: Item { }
|
||||
|
||||
contentItem: Item {
|
||||
id: contentContainer
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 8
|
||||
|
||||
color: serverItem.checked ? Style.color.gray1 : Style.color.transparent
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
|
||||
Header3TextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 8
|
||||
Layout.topMargin: 19
|
||||
Layout.bottomMargin: 19
|
||||
|
||||
text: name
|
||||
|
||||
color: serverItem.hovered ? Style.color.gray9 : Style.color.black
|
||||
}
|
||||
|
||||
ButtonType {
|
||||
Layout.rightMargin: 8
|
||||
imageSource: "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
hoveredBorderColor: Style.color.gray2
|
||||
hoveredBorderWidth: 1
|
||||
|
||||
onClicked: function() {
|
||||
ServersModel.processedIndex = index
|
||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: function() {
|
||||
ServersModel.defaultIndex = index
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: serverItem
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
client/ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml
Normal file
112
client/ui/qml/DefaultVpn/Pages/PageSetupWizardConfigSource.qml
Normal file
@@ -0,0 +1,112 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
import Config 1.0
|
||||
|
||||
import "../Components"
|
||||
import "../Controls"
|
||||
import "../Controls/TextTypes"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: ImportController
|
||||
|
||||
function onImportErrorOccurred(error, goToPageHome) {
|
||||
PageController.showErrorMessage(error)
|
||||
}
|
||||
|
||||
function onImportFinished() {
|
||||
if (!ConnectionController.isConnected) {
|
||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||
}
|
||||
|
||||
PageController.goToStartPage()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.topMargin: 8
|
||||
|
||||
WhiteButtonNoBorder {
|
||||
id: backButton
|
||||
imageSource: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
onClicked: PageController.closePage()
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Header1TextType {
|
||||
id: header
|
||||
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 24
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Adding a server to connect to")
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
XSmallTextType {
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 8
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Key")
|
||||
}
|
||||
|
||||
InputType {
|
||||
id: textKey
|
||||
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 308
|
||||
|
||||
placeholderText: qsTr("VPN://")
|
||||
}
|
||||
|
||||
BlueButtonNoBorder {
|
||||
Layout.topMargin: 24
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Add")
|
||||
|
||||
onClicked: function() {
|
||||
if (ImportController.extractConfigFromData(textKey.text)) {
|
||||
ImportController.importConfig()
|
||||
} else {
|
||||
PageController.showErrorMessage(qsTr("Unsupported config file"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
195
client/ui/qml/DefaultVpn/main.qml
Normal file
195
client/ui/qml/DefaultVpn/main.qml
Normal file
@@ -0,0 +1,195 @@
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import Config 1.0
|
||||
import PageEnum 1.0
|
||||
|
||||
import "Controls"
|
||||
import "Pages"
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
objectName: "mainWindow"
|
||||
visible: true
|
||||
width: DeviceInfo.screenWidth
|
||||
height: DeviceInfo.screenHeight
|
||||
minimumWidth: DeviceInfo.isDesktop() ? 360 : 0
|
||||
minimumHeight: DeviceInfo.isDesktop() ? 640 : 0
|
||||
maximumWidth: 600
|
||||
maximumHeight: 800
|
||||
|
||||
color: Style.color.white
|
||||
|
||||
onClosing: function() {
|
||||
console.debug("QML onClosing signal")
|
||||
PageController.closeWindow()
|
||||
}
|
||||
|
||||
title: "DefaultVPN"
|
||||
|
||||
Connections {
|
||||
target: PageController
|
||||
|
||||
function onRaiseMainWindow() {
|
||||
root.show()
|
||||
root.raise()
|
||||
root.requestActivate()
|
||||
}
|
||||
|
||||
function onHideMainWindow() {
|
||||
root.hide()
|
||||
}
|
||||
|
||||
function onShowErrorMessage(errorMessage) {
|
||||
popupErrorMessage.text = errorMessage
|
||||
popupErrorMessage.open()
|
||||
}
|
||||
|
||||
function onShowNotificationMessage(message) {
|
||||
popupNotificationMessage.text = message
|
||||
popupNotificationMessage.closeButtonVisible = false
|
||||
popupNotificationMessage.open()
|
||||
popupNotificationTimer.start()
|
||||
}
|
||||
|
||||
function onShowBusyIndicator(visible) {
|
||||
busyIndicator.visible = visible
|
||||
PageController.disableControls(visible)
|
||||
}
|
||||
|
||||
function onClosePage() {
|
||||
if (stackview.depth <= 1) {
|
||||
PageController.hideWindow()
|
||||
return
|
||||
}
|
||||
stackview.pop()
|
||||
}
|
||||
|
||||
function onGoToPage(page, slide) {
|
||||
var pagePath = PageController.getPagePath(page)
|
||||
|
||||
if (slide) {
|
||||
stackview.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
||||
} else {
|
||||
stackview.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||
}
|
||||
}
|
||||
|
||||
function onGoToStartPage() {
|
||||
while (stackview.depth > 1) {
|
||||
stackview.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsController
|
||||
|
||||
function onChangeSettingsFinished(finishedMessage) {
|
||||
PageController.showNotificationMessage(finishedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: stackview
|
||||
anchors.fill: parent
|
||||
|
||||
Component.onCompleted: {
|
||||
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
||||
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||
|
||||
stackview.push(pagePath, { "objectName" : pagePath })
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
implicitHeight: popupNotificationMessage.height
|
||||
|
||||
PopupType {
|
||||
id: popupNotificationMessage
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: popupNotificationTimer
|
||||
|
||||
interval: 3000
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
popupNotificationMessage.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
implicitHeight: popupErrorMessage.height
|
||||
|
||||
PopupType {
|
||||
id: popupErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
// Item {
|
||||
// anchors.fill: parent
|
||||
|
||||
// QuestionDrawer {
|
||||
// id: questionDrawer
|
||||
|
||||
// anchors.fill: parent
|
||||
// }
|
||||
// }
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
BusyIndicatorType {
|
||||
id: busyIndicator
|
||||
anchors.centerIn: parent
|
||||
z: 1
|
||||
}
|
||||
}
|
||||
|
||||
// function showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) {
|
||||
// questionDrawer.headerText = headerText
|
||||
// questionDrawer.descriptionText = descriptionText
|
||||
// questionDrawer.yesButtonText = yesButtonText
|
||||
// questionDrawer.noButtonText = noButtonText
|
||||
|
||||
// questionDrawer.yesButtonFunction = function() {
|
||||
// questionDrawer.close()
|
||||
// if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||
// yesButtonFunction()
|
||||
// }
|
||||
// }
|
||||
// questionDrawer.noButtonFunction = function() {
|
||||
// questionDrawer.close()
|
||||
// if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||
// noButtonFunction()
|
||||
// }
|
||||
// }
|
||||
// questionDrawer.open()
|
||||
// }
|
||||
|
||||
FileDialog {
|
||||
id: mainFileDialog
|
||||
|
||||
property bool isSaveMode: false
|
||||
|
||||
objectName: "mainFileDialog"
|
||||
fileMode: isSaveMode ? FileDialog.SaveFile : FileDialog.OpenFile
|
||||
|
||||
onAccepted: SystemController.fileDialogClosed(true)
|
||||
onRejected: SystemController.fileDialogClosed(false)
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,14 @@ PageType {
|
||||
imageSource: "qrc:/images/controls/download.svg"
|
||||
|
||||
checked: index === ApiCountryModel.currentIndex
|
||||
checkable: !ConnectionController.isConnected
|
||||
|
||||
onClicked: {
|
||||
if (ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Unable change server location while there is an active connection"))
|
||||
return
|
||||
}
|
||||
|
||||
if (index !== ApiCountryModel.currentIndex) {
|
||||
PageController.showBusyIndicator(true)
|
||||
var prevIndex = ApiCountryModel.currentIndex
|
||||
|
||||
@@ -56,12 +56,15 @@ PageType {
|
||||
}
|
||||
|
||||
LabelWithImageType {
|
||||
property bool showSubscriptionEndDate: ServersModel.getProcessedServerData("isCountrySelectionAvailable")
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 16
|
||||
|
||||
imageSource: "qrc:/images/controls/history.svg"
|
||||
leftText: qsTr("Work period")
|
||||
rightText: ApiServicesModel.getSelectedServiceData("workPeriod")
|
||||
leftText: showSubscriptionEndDate ? qsTr("Valid until") : qsTr("Work period")
|
||||
rightText: showSubscriptionEndDate ? ApiServicesModel.getSelectedServiceData("endDate")
|
||||
: ApiServicesModel.getSelectedServiceData("workPeriod")
|
||||
|
||||
visible: rightText !== ""
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ PageType {
|
||||
property int pageSettingsApiServerInfo: 3
|
||||
property int pageSettingsApiLanguageList: 4
|
||||
|
||||
property var processedServer
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Connections {
|
||||
@@ -35,8 +37,18 @@ PageType {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onProcessedServerChanged() {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyServersModel
|
||||
objectName: "proxyServersModel"
|
||||
|
||||
sourceModel: ServersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
@@ -44,147 +56,139 @@ PageType {
|
||||
value: true
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem
|
||||
KeyNavigation.tab: header
|
||||
//KeyNavigation.tab: header
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 16
|
||||
spacing: 4
|
||||
|
||||
Repeater {
|
||||
id: header
|
||||
model: proxyServersModel
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
activeFocusOnTab: true
|
||||
onFocusChanged: {
|
||||
header.itemAt(0).focusItem.forceActiveFocus()
|
||||
Layout.topMargin: 20
|
||||
KeyNavigation.tab: headerContent.actionButton
|
||||
|
||||
backButtonFunction: function() {
|
||||
if (nestedStackView.currentIndex === root.pageSettingsApiServerInfo &&
|
||||
root.processedServer.isCountrySelectionAvailable) {
|
||||
nestedStackView.currentIndex = root.pageSettingsApiLanguageList
|
||||
} else {
|
||||
PageController.closePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: headerContent
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
actionButtonImage: nestedStackView.currentIndex === root.pageSettingsApiLanguageList ? "qrc:/images/controls/settings.svg"
|
||||
: "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
headerText: root.processedServer.name
|
||||
descriptionText: {
|
||||
if (root.processedServer.isServerFromGatewayApi) {
|
||||
if (nestedStackView.currentIndex === root.pageSettingsApiLanguageList) {
|
||||
return qsTr("Subscription is valid until ") + ApiServicesModel.getSelectedServiceData("endDate")
|
||||
} else {
|
||||
return ApiServicesModel.getSelectedServiceData("serviceDescription")
|
||||
}
|
||||
} else if (root.processedServer.isServerFromTelegramApi) {
|
||||
return root.processedServer.serverDescription
|
||||
} else if (root.processedServer.hasWriteAccess) {
|
||||
return root.processedServer.credentialsLogin + " · " + root.processedServer.hostName
|
||||
} else {
|
||||
return root.processedServer.hostName
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ColumnLayout {
|
||||
KeyNavigation.tab: tabBar
|
||||
|
||||
property alias focusItem: backButton
|
||||
actionButtonFunction: function() {
|
||||
if (nestedStackView.currentIndex === root.pageSettingsApiLanguageList) {
|
||||
nestedStackView.currentIndex = root.pageSettingsApiServerInfo
|
||||
} else {
|
||||
serverNameEditDrawer.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
id: content
|
||||
DrawerType2 {
|
||||
id: serverNameEditDrawer
|
||||
|
||||
Layout.topMargin: 20
|
||||
parent: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
KeyNavigation.tab: headerContent.actionButton
|
||||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.35
|
||||
|
||||
backButtonFunction: function() {
|
||||
if (nestedStackView.currentIndex === root.pageSettingsApiServerInfo &&
|
||||
ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
|
||||
nestedStackView.currentIndex = root.pageSettingsApiLanguageList
|
||||
} else {
|
||||
PageController.closePage()
|
||||
}
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
headerContent.actionButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 32
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
Connections {
|
||||
target: serverNameEditDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
serverName.textField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: headerContent
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: serverName.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: serverName
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
headerText: qsTr("Server name")
|
||||
textFieldText: root.processedServer.name
|
||||
textField.maximumLength: 30
|
||||
checkEmptyText: true
|
||||
|
||||
actionButtonImage: nestedStackView.currentIndex === root.pageSettingsApiLanguageList ? "qrc:/images/controls/settings.svg" : "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
headerText: name
|
||||
descriptionText: {
|
||||
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
|
||||
return ApiServicesModel.getSelectedServiceData("serviceDescription")
|
||||
} else if (ServersModel.getProcessedServerData("isServerFromTelegramApi")) {
|
||||
return serverDescription
|
||||
} else if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||
return credentialsLogin + " · " + hostName
|
||||
} else {
|
||||
return hostName
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.tab: tabBar
|
||||
|
||||
actionButtonFunction: function() {
|
||||
if (nestedStackView.currentIndex === root.pageSettingsApiLanguageList) {
|
||||
nestedStackView.currentIndex = root.pageSettingsApiServerInfo
|
||||
} else {
|
||||
serverNameEditDrawer.open()
|
||||
}
|
||||
}
|
||||
KeyNavigation.tab: saveButton
|
||||
}
|
||||
|
||||
DrawerType2 {
|
||||
id: serverNameEditDrawer
|
||||
BasicButtonType {
|
||||
id: saveButton
|
||||
|
||||
parent: root
|
||||
Layout.fillWidth: true
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.35
|
||||
text: qsTr("Save")
|
||||
KeyNavigation.tab: focusItem1
|
||||
|
||||
onClosed: {
|
||||
if (!GC.isMobile()) {
|
||||
headerContent.actionButton.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 32
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
Connections {
|
||||
target: serverNameEditDrawer
|
||||
enabled: !GC.isMobile()
|
||||
function onOpened() {
|
||||
serverName.textField.forceActiveFocus()
|
||||
}
|
||||
clickedFunc: function() {
|
||||
if (serverName.textFieldText === "") {
|
||||
return
|
||||
}
|
||||
|
||||
Item {
|
||||
id: focusItem1
|
||||
KeyNavigation.tab: serverName.textField
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: serverName
|
||||
|
||||
Layout.fillWidth: true
|
||||
headerText: qsTr("Server name")
|
||||
textFieldText: name
|
||||
textField.maximumLength: 30
|
||||
checkEmptyText: true
|
||||
|
||||
KeyNavigation.tab: saveButton
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: saveButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save")
|
||||
KeyNavigation.tab: focusItem1
|
||||
|
||||
clickedFunc: function() {
|
||||
if (serverName.textFieldText === "") {
|
||||
return
|
||||
}
|
||||
|
||||
if (serverName.textFieldText !== name) {
|
||||
name = serverName.textFieldText
|
||||
}
|
||||
serverNameEditDrawer.close()
|
||||
}
|
||||
if (serverName.textFieldText !== root.processedServer.name) {
|
||||
ServersModel.setProcessedServerData("name", serverName.textFieldText);
|
||||
}
|
||||
serverNameEditDrawer.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,8 +261,7 @@ PageType {
|
||||
|
||||
StackLayout {
|
||||
id: nestedStackView
|
||||
Layout.preferredWidth: root.width
|
||||
Layout.preferredHeight: root.height - tabBar.implicitHeight - header.implicitHeight
|
||||
Layout.fillWidth: true
|
||||
|
||||
currentIndex: ServersModel.getProcessedServerData("isServerFromGatewayApi") ?
|
||||
(ServersModel.getProcessedServerData("isCountrySelectionAvailable") ?
|
||||
|
||||
@@ -92,7 +92,7 @@ PageType {
|
||||
break
|
||||
}
|
||||
case PageShare.ConfigType.Xray: {
|
||||
ExportController.generateXrayConfig()
|
||||
ExportController.generateXrayConfig(clientNameTextField.textFieldText)
|
||||
shareConnectionDrawer.configCaption = qsTr("Save XRay config")
|
||||
shareConnectionDrawer.configExtension = ".json"
|
||||
shareConnectionDrawer.configFileName = "amnezia_for_xray"
|
||||
|
||||
8
metadata/img-readme/download-website-ru.svg
Normal file
8
metadata/img-readme/download-website-ru.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="208" height="56" viewBox="0 0 208 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="208" height="56" rx="16" fill="#FBB36A"/>
|
||||
<path d="M76.012 27.24C75.0654 27.24 74.212 27.0933 73.452 26.8C72.692 26.4933 72.0454 26.0467 71.512 25.46C70.9787 24.86 70.5654 24.12 70.272 23.24C69.9787 22.3467 69.832 21.3067 69.832 20.12C69.832 18.9467 69.9787 17.9067 70.272 17C70.5654 16.08 70.9787 15.3133 71.512 14.7C72.0454 14.0733 72.692 13.6 73.452 13.28C74.212 12.96 75.0654 12.8 76.012 12.8C77.3054 12.8 78.372 13.0667 79.212 13.6C80.052 14.12 80.7254 14.9467 81.232 16.08L78.612 17.44C78.4254 16.8533 78.132 16.3867 77.732 16.04C77.3454 15.68 76.772 15.5 76.012 15.5C75.1187 15.5 74.3987 15.7933 73.852 16.38C73.3187 16.9533 73.052 17.7933 73.052 18.9V21.14C73.052 22.2467 73.3187 23.0933 73.852 23.68C74.3987 24.2533 75.1187 24.54 76.012 24.54C76.7587 24.54 77.352 24.34 77.792 23.94C78.2454 23.5267 78.5787 23.0333 78.792 22.46L81.272 23.9C80.752 24.9667 80.0654 25.7933 79.212 26.38C78.372 26.9533 77.3054 27.24 76.012 27.24ZM83.2394 16.5H86.1994V20.52H87.7194L89.0994 17.96C89.3794 17.44 89.6927 17.0667 90.0394 16.84C90.3994 16.6133 90.8594 16.5 91.4194 16.5H92.6394V18.8H91.5794L90.6794 20.48C90.4927 20.8267 90.306 21.0733 90.1194 21.22C89.946 21.3667 89.7394 21.4733 89.4994 21.54V21.64C89.726 21.6933 89.9327 21.7867 90.1194 21.92C90.3194 22.0533 90.4994 22.2667 90.6594 22.56L91.8394 24.7H92.9194V27H91.5394C90.9794 27 90.526 26.8867 90.1794 26.66C89.8327 26.4333 89.506 26.0467 89.1994 25.5L87.7194 22.82H86.1994V27H83.2394V16.5ZM102.62 27C102.087 27 101.64 26.8333 101.28 26.5C100.934 26.1667 100.714 25.72 100.62 25.16H100.5C100.34 25.84 99.9871 26.36 99.4405 26.72C98.8938 27.0667 98.2205 27.24 97.4205 27.24C96.3671 27.24 95.5605 26.96 95.0005 26.4C94.4405 25.84 94.1605 25.1 94.1605 24.18C94.1605 23.0733 94.5605 22.2533 95.3605 21.72C96.1738 21.1733 97.2738 20.9 98.6605 20.9H100.32V20.24C100.32 19.7333 100.187 19.3333 99.9205 19.04C99.6538 18.7333 99.2071 18.58 98.5805 18.58C97.9938 18.58 97.5271 18.7067 97.1805 18.96C96.8338 19.2133 96.5471 19.5 96.3205 19.82L94.5605 18.26C94.9871 17.6333 95.5205 17.1467 96.1605 16.8C96.8138 16.44 97.6938 16.26 98.8005 16.26C100.294 16.26 101.414 16.5867 102.16 17.24C102.907 17.8933 103.28 18.8467 103.28 20.1V24.7H104.26V27H102.62ZM98.5205 25.18C99.0138 25.18 99.4338 25.0733 99.7805 24.86C100.14 24.6467 100.32 24.3 100.32 23.82V22.58H98.8805C97.7205 22.58 97.1405 22.9733 97.1405 23.76V24.06C97.1405 24.4467 97.2605 24.7333 97.5005 24.92C97.7405 25.0933 98.0805 25.18 98.5205 25.18ZM111.736 22.54H111.636C111.396 22.9667 111.049 23.3067 110.596 23.56C110.156 23.8 109.596 23.92 108.916 23.92C107.729 23.92 106.862 23.6133 106.316 23C105.782 22.3867 105.516 21.4467 105.516 20.18V16.5H108.476V20.04C108.476 20.56 108.596 20.94 108.836 21.18C109.089 21.4067 109.496 21.52 110.056 21.52C110.616 21.52 111.036 21.42 111.316 21.22C111.596 21.02 111.736 20.7667 111.736 20.46V16.5H114.696V27H111.736V22.54ZM125.218 27C124.685 27 124.238 26.8333 123.878 26.5C123.531 26.1667 123.311 25.72 123.218 25.16H123.098C122.938 25.84 122.585 26.36 122.038 26.72C121.491 27.0667 120.818 27.24 120.018 27.24C118.965 27.24 118.158 26.96 117.598 26.4C117.038 25.84 116.758 25.1 116.758 24.18C116.758 23.0733 117.158 22.2533 117.958 21.72C118.771 21.1733 119.871 20.9 121.258 20.9H122.918V20.24C122.918 19.7333 122.785 19.3333 122.518 19.04C122.251 18.7333 121.805 18.58 121.178 18.58C120.591 18.58 120.125 18.7067 119.778 18.96C119.431 19.2133 119.145 19.5 118.918 19.82L117.158 18.26C117.585 17.6333 118.118 17.1467 118.758 16.8C119.411 16.44 120.291 16.26 121.398 16.26C122.891 16.26 124.011 16.5867 124.758 17.24C125.505 17.8933 125.878 18.8467 125.878 20.1V24.7H126.858V27H125.218ZM121.118 25.18C121.611 25.18 122.031 25.0733 122.378 24.86C122.738 24.6467 122.918 24.3 122.918 23.82V22.58H121.478C120.318 22.58 119.738 22.9733 119.738 23.76V24.06C119.738 24.4467 119.858 24.7333 120.098 24.92C120.338 25.0933 120.678 25.18 121.118 25.18ZM130.553 18.8H127.513V16.5H136.553V18.8H133.513V27H130.553V18.8ZM138.337 16.5H141.297V19.62H144.057C144.564 19.62 145.037 19.7 145.477 19.86C145.917 20.02 146.297 20.26 146.617 20.58C146.95 20.8867 147.21 21.2667 147.397 21.72C147.584 22.1733 147.677 22.7 147.677 23.3C147.677 23.9 147.584 24.4333 147.397 24.9C147.21 25.3533 146.95 25.74 146.617 26.06C146.297 26.3667 145.917 26.6 145.477 26.76C145.037 26.92 144.564 27 144.057 27H138.337V16.5ZM143.417 24.9C143.804 24.9 144.11 24.8 144.337 24.6C144.577 24.3867 144.697 24.0867 144.697 23.7V22.92C144.697 22.5333 144.577 22.24 144.337 22.04C144.11 21.8267 143.804 21.72 143.417 21.72H141.297V24.9H143.417Z" fill="#472402"/>
|
||||
<path opacity="0.8" d="M74.308 45.144C73.74 45.144 73.228 45.056 72.772 44.88C72.316 44.696 71.928 44.428 71.608 44.076C71.288 43.716 71.04 43.272 70.864 42.744C70.688 42.208 70.6 41.584 70.6 40.872C70.6 40.168 70.688 39.544 70.864 39C71.04 38.448 71.288 37.988 71.608 37.62C71.928 37.244 72.316 36.96 72.772 36.768C73.228 36.576 73.74 36.48 74.308 36.48C75.084 36.48 75.724 36.64 76.228 36.96C76.732 37.272 77.136 37.768 77.44 38.448L75.868 39.264C75.756 38.912 75.58 38.632 75.34 38.424C75.108 38.208 74.764 38.1 74.308 38.1C73.772 38.1 73.34 38.276 73.012 38.628C72.692 38.972 72.532 39.476 72.532 40.14V41.484C72.532 42.148 72.692 42.656 73.012 43.008C73.34 43.352 73.772 43.524 74.308 43.524C74.756 43.524 75.112 43.404 75.376 43.164C75.648 42.916 75.848 42.62 75.976 42.276L77.464 43.14C77.152 43.78 76.74 44.276 76.228 44.628C75.724 44.972 75.084 45.144 74.308 45.144ZM84.0243 45.144C83.5523 45.144 83.1323 45.068 82.7643 44.916C82.3963 44.756 82.0883 44.536 81.8403 44.256C81.5923 43.968 81.4043 43.62 81.2763 43.212C81.1483 42.804 81.0843 42.348 81.0843 41.844C81.0843 41.34 81.1483 40.888 81.2763 40.488C81.4043 40.08 81.5923 39.732 81.8403 39.444C82.0883 39.156 82.3963 38.936 82.7643 38.784C83.1323 38.632 83.5523 38.556 84.0243 38.556C84.6643 38.556 85.1963 38.7 85.6203 38.988C86.0523 39.276 86.3603 39.68 86.5443 40.2L85.1043 40.824C85.0483 40.584 84.9323 40.38 84.7563 40.212C84.5803 40.044 84.3363 39.96 84.0243 39.96C83.6643 39.96 83.3923 40.08 83.2083 40.32C83.0243 40.552 82.9323 40.868 82.9323 41.268V42.444C82.9323 42.844 83.0243 43.16 83.2083 43.392C83.3923 43.624 83.6643 43.74 84.0243 43.74C84.3443 43.74 84.5963 43.656 84.7803 43.488C84.9723 43.312 85.1123 43.084 85.2003 42.804L86.5803 43.404C86.3723 44.004 86.0483 44.444 85.6083 44.724C85.1763 45.004 84.6483 45.144 84.0243 45.144ZM92.3356 45C92.0156 45 91.7476 44.9 91.5316 44.7C91.3236 44.5 91.1916 44.232 91.1356 43.896H91.0636C90.9676 44.304 90.7556 44.616 90.4276 44.832C90.0996 45.04 89.6956 45.144 89.2156 45.144C88.5836 45.144 88.0996 44.976 87.7636 44.64C87.4276 44.304 87.2596 43.86 87.2596 43.308C87.2596 42.644 87.4996 42.152 87.9796 41.832C88.4676 41.504 89.1276 41.34 89.9596 41.34H90.9556V40.944C90.9556 40.64 90.8756 40.4 90.7156 40.224C90.5556 40.04 90.2876 39.948 89.9116 39.948C89.5596 39.948 89.2796 40.024 89.0716 40.176C88.8636 40.328 88.6916 40.5 88.5556 40.692L87.4996 39.756C87.7556 39.38 88.0756 39.088 88.4596 38.88C88.8516 38.664 89.3796 38.556 90.0436 38.556C90.9396 38.556 91.6116 38.752 92.0596 39.144C92.5076 39.536 92.7316 40.108 92.7316 40.86V43.62H93.3196V45H92.3356ZM89.8756 43.908C90.1716 43.908 90.4236 43.844 90.6316 43.716C90.8476 43.588 90.9556 43.38 90.9556 43.092V42.348H90.0916C89.3956 42.348 89.0476 42.584 89.0476 43.056V43.236C89.0476 43.468 89.1196 43.64 89.2636 43.752C89.4076 43.856 89.6116 43.908 89.8756 43.908ZM94.5116 38.7H96.2516V41.232L96.0956 42.696H96.1316L96.8636 41.352L98.6156 38.7H100.2V45H98.4596V42.468L98.6156 41.004H98.5796L97.8476 42.348L96.0956 45H94.5116V38.7ZM97.3676 38.052C96.8396 38.052 96.4116 37.936 96.0836 37.704C95.7556 37.472 95.4996 37.14 95.3156 36.708L95.0636 36.096L96.4436 35.58L96.8276 36.792C96.8756 36.816 96.9516 36.836 97.0556 36.852C97.1596 36.868 97.2636 36.876 97.3676 36.876C97.4716 36.876 97.5756 36.868 97.6796 36.852C97.7836 36.836 97.8596 36.816 97.9076 36.792L98.2916 35.58L99.6716 36.096L99.4196 36.708C99.2356 37.14 98.9796 37.472 98.6516 37.704C98.3236 37.936 97.8956 38.052 97.3676 38.052ZM103.095 40.08H101.271V38.7H106.695V40.08H104.871V45H103.095V40.08ZM112.363 45C112.043 45 111.775 44.9 111.559 44.7C111.351 44.5 111.219 44.232 111.163 43.896H111.091C110.995 44.304 110.783 44.616 110.455 44.832C110.127 45.04 109.723 45.144 109.243 45.144C108.611 45.144 108.127 44.976 107.791 44.64C107.455 44.304 107.287 43.86 107.287 43.308C107.287 42.644 107.527 42.152 108.007 41.832C108.495 41.504 109.155 41.34 109.987 41.34H110.983V40.944C110.983 40.64 110.903 40.4 110.743 40.224C110.583 40.04 110.315 39.948 109.939 39.948C109.587 39.948 109.307 40.024 109.099 40.176C108.891 40.328 108.719 40.5 108.583 40.692L107.527 39.756C107.783 39.38 108.103 39.088 108.487 38.88C108.879 38.664 109.407 38.556 110.071 38.556C110.967 38.556 111.639 38.752 112.087 39.144C112.535 39.536 112.759 40.108 112.759 40.86V43.62H113.347V45H112.363ZM109.903 43.908C110.199 43.908 110.451 43.844 110.659 43.716C110.875 43.588 110.983 43.38 110.983 43.092V42.348H110.119C109.423 42.348 109.075 42.584 109.075 43.056V43.236C109.075 43.468 109.147 43.64 109.291 43.752C109.435 43.856 109.639 43.908 109.903 43.908Z" fill="#472402"/>
|
||||
<path d="M37.4987 29.5415V37.8748L33.332 33.7082" stroke="#472402" stroke-width="3.33" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M37.5 37.8752L41.6667 33.7085" stroke="#472402" stroke-width="3.33" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M29.5766 31.9052C28.7259 31.161 28.0598 30.2292 27.631 29.1833C27.2022 28.1374 27.0224 27.0062 27.1058 25.8789C27.1893 24.7516 27.5336 23.6592 28.1118 22.6879C28.6899 21.7165 29.4859 20.8929 30.437 20.282C31.388 19.6712 32.4681 19.2898 33.5919 19.1679C34.7157 19.0461 35.8524 19.1873 36.9122 19.5802C37.9721 19.9731 38.9261 20.6071 39.6989 21.432C40.4717 22.2569 41.0422 23.2502 41.3652 24.3334H43.2298C44.2423 24.3332 45.2277 24.661 46.0385 25.2676C46.8492 25.8742 47.4418 26.727 47.7274 27.6985C48.0131 28.6699 47.9765 29.7077 47.6232 30.6566C47.2698 31.6055 46.6187 32.4145 45.7673 32.9625" stroke="#472402" stroke-width="3.33" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user