Compare commits
No commits in common. "d3b94aff2cc88a533922e1b5ae452c682c5a0408" and "2e069897db32a845c77319e89b1295edd6d71eee" have entirely different histories.
d3b94aff2c
...
2e069897db
26 changed files with 947 additions and 454 deletions
|
|
@ -1,23 +0,0 @@
|
||||||
[update]
|
|
||||||
tasks = ["code", "normalize"]
|
|
||||||
|
|
||||||
[update.code]
|
|
||||||
codePaths = ["."]
|
|
||||||
localizablePaths = ["dns"]
|
|
||||||
defaultToKeys = true
|
|
||||||
additive = false
|
|
||||||
unstripped = false
|
|
||||||
plistArguments = false
|
|
||||||
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]
|
|
||||||
|
|
||||||
[update.normalize]
|
|
||||||
paths = ["dns"]
|
|
||||||
subpathsToIgnore = ["InfoPlist.strings"]
|
|
||||||
sourceLocale = "en"
|
|
||||||
harmonizeWithSource = true
|
|
||||||
sortByKeys = true
|
|
||||||
|
|
||||||
[lint]
|
|
||||||
paths = ["dns"]
|
|
||||||
duplicateKeys = true
|
|
||||||
emptyValues = true
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// Avoid accidental checkins:
|
|
||||||
// git update-index --skip-worktree Config.xcconfig
|
|
||||||
// git update-index --no-skip-worktree Config.xcconfig
|
|
||||||
|
|
||||||
|
|
||||||
DEVELOPMENT_TEAM[config=Debug] =
|
|
||||||
APP_PRODUCT_BUNDLE_IDENTIFIER[config=Debug] =
|
|
||||||
APP_PROVISIONING_PROFILE_SPECIFIER[config=Debug] =
|
|
||||||
STICKERS_PRODUCT_BUNDLE_IDENTIFIER[config=Debug] =
|
|
||||||
STICKERS_PROVISIONING_PROFILE_SPECIFIER[config=Debug] =
|
|
||||||
|
|
||||||
|
|
||||||
DEVELOPMENT_TEAM[config=Release] =
|
|
||||||
APP_PRODUCT_BUNDLE_IDENTIFIER[config=Release] = uk.sr2.dns
|
|
||||||
APP_PROVISIONING_PROFILE_SPECIFIER[config=Release] =
|
|
||||||
STICKERS_PRODUCT_BUNDLE_IDENTIFIER[config=Release] = uk.sr2.dns.Stickers
|
|
||||||
STICKERS_PROVISIONING_PROFILE_SPECIFIER[config=Release] =
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
A051B5122FC9E0D700EACDC0 /* AsyncDNSResolver in Frameworks */ = {isa = PBXBuildFile; productRef = A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */; };
|
|
||||||
A08264132FC718790077B227 /* Stickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A082640C2FC718790077B227 /* Stickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
A08264132FC718790077B227 /* Stickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A082640C2FC718790077B227 /* Stickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -37,8 +36,6 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
069DCCFA2F8C0DCE00F1EB16 /* dns.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dns.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
069DCCFA2F8C0DCE00F1EB16 /* dns.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dns.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A051B50B2FC9DA9100EACDC0 /* .bartycrouch.toml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .bartycrouch.toml; sourceTree = "<group>"; };
|
|
||||||
A051B5132FC9E7BC00EACDC0 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
|
|
||||||
A06A74772F8E95410093A9E4 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; };
|
A06A74772F8E95410093A9E4 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; };
|
||||||
A06A74782F8E95410093A9E4 /* LICENCE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENCE; sourceTree = "<group>"; };
|
A06A74782F8E95410093A9E4 /* LICENCE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENCE; sourceTree = "<group>"; };
|
||||||
A06A74792F8E95410093A9E4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
A06A74792F8E95410093A9E4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||||
|
|
@ -76,7 +73,6 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A051B5122FC9E0D700EACDC0 /* AsyncDNSResolver in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -89,8 +85,6 @@
|
||||||
A06A74772F8E95410093A9E4 /* .gitignore */,
|
A06A74772F8E95410093A9E4 /* .gitignore */,
|
||||||
A06A74782F8E95410093A9E4 /* LICENCE */,
|
A06A74782F8E95410093A9E4 /* LICENCE */,
|
||||||
A06A74792F8E95410093A9E4 /* README.md */,
|
A06A74792F8E95410093A9E4 /* README.md */,
|
||||||
A051B50B2FC9DA9100EACDC0 /* .bartycrouch.toml */,
|
|
||||||
A051B5132FC9E7BC00EACDC0 /* Config.xcconfig */,
|
|
||||||
069DCCFC2F8C0DCE00F1EB16 /* dns */,
|
069DCCFC2F8C0DCE00F1EB16 /* dns */,
|
||||||
A082640D2FC718790077B227 /* Stickers */,
|
A082640D2FC718790077B227 /* Stickers */,
|
||||||
069DCCFB2F8C0DCE00F1EB16 /* Products */,
|
069DCCFB2F8C0DCE00F1EB16 /* Products */,
|
||||||
|
|
@ -113,7 +107,6 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 069DCD052F8C0DCE00F1EB16 /* Build configuration list for PBXNativeTarget "dns" */;
|
buildConfigurationList = 069DCD052F8C0DCE00F1EB16 /* Build configuration list for PBXNativeTarget "dns" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
A051B50A2FC9DA4300EACDC0 /* BartyCrouch */,
|
|
||||||
069DCCF62F8C0DCE00F1EB16 /* Sources */,
|
069DCCF62F8C0DCE00F1EB16 /* Sources */,
|
||||||
069DCCF72F8C0DCE00F1EB16 /* Frameworks */,
|
069DCCF72F8C0DCE00F1EB16 /* Frameworks */,
|
||||||
069DCCF82F8C0DCE00F1EB16 /* Resources */,
|
069DCCF82F8C0DCE00F1EB16 /* Resources */,
|
||||||
|
|
@ -129,7 +122,6 @@
|
||||||
);
|
);
|
||||||
name = dns;
|
name = dns;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */,
|
|
||||||
);
|
);
|
||||||
productName = dns;
|
productName = dns;
|
||||||
productReference = 069DCCFA2F8C0DCE00F1EB16 /* dns.app */;
|
productReference = 069DCCFA2F8C0DCE00F1EB16 /* dns.app */;
|
||||||
|
|
@ -163,7 +155,7 @@
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = 1;
|
BuildIndependentTargetsInParallel = 1;
|
||||||
LastSwiftUpdateCheck = 2640;
|
LastSwiftUpdateCheck = 2640;
|
||||||
LastUpgradeCheck = 2650;
|
LastUpgradeCheck = 2640;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
069DCCF92F8C0DCE00F1EB16 = {
|
069DCCF92F8C0DCE00F1EB16 = {
|
||||||
CreatedOnToolsVersion = 26.4;
|
CreatedOnToolsVersion = 26.4;
|
||||||
|
|
@ -179,13 +171,9 @@
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
de,
|
|
||||||
);
|
);
|
||||||
mainGroup = 069DCCF12F8C0DCD00F1EB16;
|
mainGroup = 069DCCF12F8C0DCD00F1EB16;
|
||||||
minimizedProjectReferenceProxies = 1;
|
minimizedProjectReferenceProxies = 1;
|
||||||
packageReferences = (
|
|
||||||
A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */,
|
|
||||||
);
|
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = 069DCCFB2F8C0DCE00F1EB16 /* Products */;
|
productRefGroup = 069DCCFB2F8C0DCE00F1EB16 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
|
@ -214,28 +202,6 @@
|
||||||
};
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
A051B50A2FC9DA4300EACDC0 /* BartyCrouch */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = BartyCrouch;
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "if [ -f /opt/homebrew/bin/bartycrouch ]; then\n /opt/homebrew/bin/bartycrouch update -x\n /opt/homebrew/bin/bartycrouch lint -x\nelse\n echo \"warning: BartyCrouch not installed. Download it form https://github.com/Flinesoft/BartyCrouch\"\nfi\n";
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
069DCCF62F8C0DCE00F1EB16 /* Sources */ = {
|
069DCCF62F8C0DCE00F1EB16 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
|
|
@ -257,11 +223,9 @@
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
069DCD032F8C0DCE00F1EB16 /* Debug */ = {
|
069DCD032F8C0DCE00F1EB16 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = A051B5132FC9E7BC00EACDC0 /* Config.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
|
@ -323,11 +287,9 @@
|
||||||
};
|
};
|
||||||
069DCD042F8C0DCE00F1EB16 /* Release */ = {
|
069DCD042F8C0DCE00F1EB16 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = A051B5132FC9E7BC00EACDC0 /* Config.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
|
@ -386,10 +348,11 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "SR2 Cloud DNS";
|
INFOPLIST_KEY_CFBundleDisplayName = "SR2 Cloud DNS";
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
|
@ -405,10 +368,10 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_PRODUCT_BUNDLE_IDENTIFIER)";
|
PRODUCT_BUNDLE_IDENTIFIER = uk.sr2.dns;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "$(APP_PROVISIONING_PROFILE_SPECIFIER)";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -424,10 +387,11 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
CODE_SIGN_ENTITLEMENTS = dns/dns.entitlements;
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "SR2 Cloud DNS";
|
INFOPLIST_KEY_CFBundleDisplayName = "SR2 Cloud DNS";
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
|
|
@ -443,10 +407,10 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_PRODUCT_BUNDLE_IDENTIFIER)";
|
PRODUCT_BUNDLE_IDENTIFIER = uk.sr2.dns;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "$(APP_PROVISIONING_PROFILE_SPECIFIER)";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -460,17 +424,19 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = Stickers/Info.plist;
|
INFOPLIST_FILE = Stickers/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Stickers;
|
INFOPLIST_KEY_CFBundleDisplayName = Stickers;
|
||||||
INFOPLIST_KEY_NSStickerSharingLevel = OS;
|
INFOPLIST_KEY_NSStickerSharingLevel = OS;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.5;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(STICKERS_PRODUCT_BUNDLE_IDENTIFIER)";
|
PRODUCT_BUNDLE_IDENTIFIER = uk.sr2.dns.Stickers;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "$(STICKERS_PROVISIONING_PROFILE_SPECIFIER)";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -482,17 +448,19 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = Stickers/Info.plist;
|
INFOPLIST_FILE = Stickers/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Stickers;
|
INFOPLIST_KEY_CFBundleDisplayName = Stickers;
|
||||||
INFOPLIST_KEY_NSStickerSharingLevel = OS;
|
INFOPLIST_KEY_NSStickerSharingLevel = OS;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.5;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(STICKERS_PRODUCT_BUNDLE_IDENTIFIER)";
|
PRODUCT_BUNDLE_IDENTIFIER = uk.sr2.dns.Stickers;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "$(STICKERS_PROVISIONING_PROFILE_SPECIFIER)";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|
@ -531,25 +499,6 @@
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
|
||||||
A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-async-dns-resolver/";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 0.7.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
|
||||||
A051B5112FC9E0D700EACDC0 /* AsyncDNSResolver */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = A051B5102FC9E0D700EACDC0 /* XCRemoteSwiftPackageReference "swift-async-dns-resolver" */;
|
|
||||||
productName = AsyncDNSResolver;
|
|
||||||
};
|
|
||||||
/* End XCSwiftPackageProductDependency section */
|
|
||||||
};
|
};
|
||||||
rootObject = 069DCCF22F8C0DCD00F1EB16 /* Project object */;
|
rootObject = 069DCCF22F8C0DCD00F1EB16 /* Project object */;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"originHash" : "8d197ac71cfa33d9e3396085f37fbee66795a894a6d74e24ff28bd887e01b9f2",
|
|
||||||
"pins" : [
|
|
||||||
{
|
|
||||||
"identity" : "swift-async-dns-resolver",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-async-dns-resolver/",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "9900d9b4113427a170d5f26075c2128be94984df",
|
|
||||||
"version" : "0.7.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version" : 3
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Foundation
|
import Foundation
|
||||||
import AsyncDNSResolver
|
|
||||||
|
|
||||||
struct BlockedCount: View {
|
struct BlockedCount: View {
|
||||||
|
|
||||||
@Environment(\.scenePhase)
|
|
||||||
private var scenePhase
|
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
private var viewModel: ViewModel
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
|
|
@ -25,39 +21,53 @@ struct BlockedCount: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(txtRecord)
|
Text(txtRecord)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
fetchTxtRecord()
|
fetchTXTRecord()
|
||||||
}
|
}
|
||||||
.onChange(of: viewModel.blocklist) { _ in
|
.onChange(of: viewModel.blocklist) { _ in
|
||||||
fetchTxtRecord()
|
fetchTXTRecord()
|
||||||
}
|
|
||||||
.onChange(of: scenePhase) { newPhase in
|
|
||||||
if newPhase == .active {
|
|
||||||
fetchTxtRecord()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchTxtRecord() {
|
func parseResponse(data: Data) -> String? {
|
||||||
|
// This is a DNS wire format response and we make a lot of assumptions
|
||||||
|
// It is not critical functionality so just let it fail if it fails
|
||||||
|
|
||||||
|
guard data.count > Self.startIndex else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the first space character (ASCII 32).
|
||||||
|
guard let endIndex = data.suffix(from: Self.startIndex).firstIndex(of: 32) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let numberString = String(data: data[Self.startIndex ..< endIndex], encoding: .utf8)
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return Self.formatter.string(for: Int(numberString))
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchTXTRecord() {
|
||||||
|
let dohURL = URL(string: "https://\(viewModel.blocklist.server)/dns-query?dns=DoQBAAABAAAAAAAABXN0YXRzB2ludmFsaWQAABAAAQ")!
|
||||||
|
let request = URLRequest(url: dohURL)
|
||||||
|
|
||||||
|
txtRecord = "…"
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let resolver = try AsyncDNSResolver()
|
let (data, _) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
let records = try await resolver.queryTXT(name: "stats.invalid")
|
if let count = parseResponse(data: data) {
|
||||||
|
txtRecord = count
|
||||||
let text = records.map { $0.txt }.joined()
|
|
||||||
|
|
||||||
if let number = text.split(separator: " ").first,
|
|
||||||
let intValue = Int(number),
|
|
||||||
let formatted = Self.formatter.string(for: intValue)
|
|
||||||
{
|
|
||||||
txtRecord = formatted
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
txtRecord = NSLocalizedString("Error", comment: "")
|
txtRecord = "Error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
txtRecord = NSLocalizedString("Error", comment: "")
|
txtRecord = "Error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,7 @@ enum BlocklistOption: String, CaseIterable, Identifiable {
|
||||||
case secure = "Secure"
|
case secure = "Secure"
|
||||||
case securePlusAdblock = "Secure + Adblock"
|
case securePlusAdblock = "Secure + Adblock"
|
||||||
|
|
||||||
var id: String {
|
var id: String { rawValue }
|
||||||
switch self {
|
|
||||||
case .secure:
|
|
||||||
return NSLocalizedString("Secure", comment: "")
|
|
||||||
|
|
||||||
case .securePlusAdblock:
|
|
||||||
return NSLocalizedString("Secure + Adblock", comment: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var enabled: Bool {
|
var enabled: Bool {
|
||||||
switch self {
|
switch self {
|
||||||
|
|
@ -34,16 +26,12 @@ enum BlocklistOption: String, CaseIterable, Identifiable {
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .secure:
|
case .secure:
|
||||||
return NSLocalizedString("Malware and phishing protection", comment: "")
|
return "Malware and phishing protection"
|
||||||
case .securePlusAdblock:
|
case .securePlusAdblock:
|
||||||
return NSLocalizedString("Security plus ad and tracker blocking", comment: "")
|
return "Security plus ad and tracker blocking"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var title: String {
|
|
||||||
return String(format: "%1$@: %2$@", ViewModel.title, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
var icon: String {
|
var icon: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .secure:
|
case .secure:
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ struct BlocklistRow: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
Text(option.enabled ? option.id : String(format: NSLocalizedString("%@ (Coming Soon)", comment: ""), option.id))
|
Text(option.id + " " + (option.enabled ? "" : "(Coming Soon)"))
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.fontWeight(isSelected ? .semibold : .regular)
|
.fontWeight(isSelected ? .semibold : .regular)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@ import SwiftUI
|
||||||
|
|
||||||
struct HomeView: View {
|
struct HomeView: View {
|
||||||
|
|
||||||
@Environment(\.scenePhase)
|
|
||||||
private var scenePhase
|
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
private var viewModel: ViewModel
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
|
|
@ -23,9 +20,9 @@ struct HomeView: View {
|
||||||
Section {
|
Section {
|
||||||
HStack {
|
HStack {
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
Text(NSLocalizedString("DNS Protection", comment: ""))
|
Text("DNS Protection")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(viewModel.isDnsEnabled ? NSLocalizedString("Active", comment: "") : NSLocalizedString("Inactive", comment: ""))
|
Text(viewModel.isDnsEnabled ? "Active" : "Inactive")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundStyle(viewModel.isDnsEnabled ? .green : .secondary)
|
.foregroundStyle(viewModel.isDnsEnabled ? .green : .secondary)
|
||||||
}
|
}
|
||||||
|
|
@ -34,37 +31,11 @@ struct HomeView: View {
|
||||||
|
|
||||||
Toggle("", isOn: $viewModel.isDnsEnabled)
|
Toggle("", isOn: $viewModel.isDnsEnabled)
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
.disabled(true)
|
|
||||||
.tint(.green)
|
.tint(.green)
|
||||||
}
|
}
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !viewModel.isDnsEnabled {
|
|
||||||
Section {
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
|
||||||
Text(String(format: NSLocalizedString("To enable %@:", comment: ""), ViewModel.title))
|
|
||||||
Text(String(format: NSLocalizedString("%1$@ Tap \"%2$@\"", comment: ""), "–", NSLocalizedString("Open Settings", comment: "")))
|
|
||||||
Text(String(format: NSLocalizedString("%1$@ Go to General", comment: ""), "–"))
|
|
||||||
Text(String(format: NSLocalizedString("%1$@ VPN & Network", comment: ""), "–"))
|
|
||||||
Text(String(format: NSLocalizedString("%1$@ DNS", comment: ""), "–"))
|
|
||||||
Text(String(format: NSLocalizedString("%1$@ Select \"%2$@\"", comment: ""), "–", viewModel.blocklist.title))
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Button {
|
|
||||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
|
||||||
UIApplication.shared.open(url)
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
Text(NSLocalizedString("Open Settings", comment: ""))
|
|
||||||
.frame(maxWidth: .infinity, minHeight: 32)
|
|
||||||
}
|
|
||||||
.buttonStyle(.borderedProminent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blocklist selection
|
// Blocklist selection
|
||||||
Section {
|
Section {
|
||||||
ForEach(BlocklistOption.allCases) { option in
|
ForEach(BlocklistOption.allCases) { option in
|
||||||
|
|
@ -82,24 +53,24 @@ struct HomeView: View {
|
||||||
.opacity(option.enabled ? 1 : 0.6)
|
.opacity(option.enabled ? 1 : 0.6)
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text(NSLocalizedString("Blocklist", comment: ""))
|
Text("Blocklist")
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(NSLocalizedString("Select the level of protection for your DNS queries", comment: ""))
|
Text("Select the level of protection for your DNS queries")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status section
|
// Status section
|
||||||
if viewModel.isDnsEnabled {
|
if viewModel.isDnsEnabled {
|
||||||
Section {
|
Section {
|
||||||
HStack {
|
HStack {
|
||||||
Label(NSLocalizedString("Status", comment: ""), systemImage: "checkmark.circle.fill")
|
Label("Status", systemImage: "checkmark.circle.fill")
|
||||||
.foregroundStyle(.green)
|
.foregroundStyle(.green)
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(NSLocalizedString("Connected", comment: ""))
|
Text("Connected")
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Label(NSLocalizedString("Server", comment: ""), systemImage: "server.rack")
|
Label("Server", systemImage: "server.rack")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(viewModel.blocklist.server)
|
Text(viewModel.blocklist.server)
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
|
|
@ -123,13 +94,13 @@ struct HomeView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Label(NSLocalizedString("Domains in blocklist", comment: ""), systemImage: "xmark.shield.fill")
|
Label("Domains in blocklist", systemImage: "xmark.shield.fill")
|
||||||
Spacer()
|
Spacer()
|
||||||
BlockedCount()
|
BlockedCount()
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text(NSLocalizedString("Connection Details", comment: ""))
|
Text("Connection Details")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +109,7 @@ struct HomeView: View {
|
||||||
Link(destination: falsePositiveURL) {
|
Link(destination: falsePositiveURL) {
|
||||||
HStack {
|
HStack {
|
||||||
Label {
|
Label {
|
||||||
Text(NSLocalizedString("Report False Positive", comment: ""))
|
Text("Report False Positive")
|
||||||
} icon: {
|
} icon: {
|
||||||
Image(systemName: "exclamationmark.bubble")
|
Image(systemName: "exclamationmark.bubble")
|
||||||
.foregroundStyle(.orange)
|
.foregroundStyle(.orange)
|
||||||
|
|
@ -152,7 +123,7 @@ struct HomeView: View {
|
||||||
}
|
}
|
||||||
}.foregroundStyle(.primary)
|
}.foregroundStyle(.primary)
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(NSLocalizedString("Submit incorrectly blocked domains for review", comment: ""))
|
Text("Submit incorrectly blocked domains for review")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service status section
|
// Service status section
|
||||||
|
|
@ -164,7 +135,7 @@ struct HomeView: View {
|
||||||
.frame(width: 12, height: 12)
|
.frame(width: 12, height: 12)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
Text(NSLocalizedString("Service Status", comment: ""))
|
Text("Service Status")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(viewModel.summaryStatus.description)
|
Text(viewModel.summaryStatus.description)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
|
@ -183,7 +154,7 @@ struct HomeView: View {
|
||||||
Link(destination: tosURL) {
|
Link(destination: tosURL) {
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Image(systemName: "doc.text")
|
Image(systemName: "doc.text")
|
||||||
Text(NSLocalizedString("Terms of Service", comment: ""))
|
Text("Terms of Service")
|
||||||
Spacer()
|
Spacer()
|
||||||
Image(systemName: "arrow.up.right.square")
|
Image(systemName: "arrow.up.right.square")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
|
@ -195,7 +166,7 @@ struct HomeView: View {
|
||||||
Link(destination: privacyPolicyURL) {
|
Link(destination: privacyPolicyURL) {
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Image(systemName: "doc.text")
|
Image(systemName: "doc.text")
|
||||||
Text(NSLocalizedString("Privacy Policy", comment: ""))
|
Text("Privacy Policy")
|
||||||
Spacer()
|
Spacer()
|
||||||
Image(systemName: "arrow.up.right.square")
|
Image(systemName: "arrow.up.right.square")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
|
|
@ -205,15 +176,8 @@ struct HomeView: View {
|
||||||
}.foregroundStyle(.primary)
|
}.foregroundStyle(.primary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(ViewModel.title)
|
.navigationTitle("SR2® Cloud DNS")
|
||||||
.animation(.default, value: viewModel.isDnsEnabled)
|
.animation(.default, value: viewModel.isDnsEnabled)
|
||||||
.onChange(of: scenePhase) { newPhase in
|
|
||||||
if newPhase == .active {
|
|
||||||
Task {
|
|
||||||
await viewModel.refreshConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
263
dns/Localizable.xcstrings
Normal file
263
dns/Localizable.xcstrings
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
{
|
||||||
|
"sourceLanguage" : "en",
|
||||||
|
"strings" : {
|
||||||
|
"" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"(Coming Soon)" : {
|
||||||
|
"comment" : "Indicates that this feature is not yet implemented but will be soon",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "(Coming Soon)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Active" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Active"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Blocklist" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Blocklist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Connected" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Connected"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Connection Details" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Connection Details"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DNS Protection" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "DNS Protection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Domains in blocklist" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Domains in blocklist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Inactive" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Inactive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IPv4" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "IPv4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IPv6" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "IPv6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Malware and phishing protection" : {
|
||||||
|
"comment" : "Description of the blocklist contents",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Malware and phishing protection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"No issues detected" : {
|
||||||
|
"comment" : "No current issues detected with the service",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "No issues detected"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Privacy Policy" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Privacy Policy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Report False Positive" : {
|
||||||
|
"comment" : "Link to report that a domain name has been incorrectly blocked",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Report False Positive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Secure" : {
|
||||||
|
"comment" : "Name of the blocklist that only includes malware and security threats",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Secure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Secure + Adblock" : {
|
||||||
|
"comment" : "Name of the blocklist that contains “Secure” plus ad blocking",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Secure + Adblock"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Security plus ad and tracker blocking" : {
|
||||||
|
"comment" : "Description of the blocklist contents",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Security plus ad and tracker blocking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Select the level of protection for your DNS queries" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Select the level of protection for your DNS queries"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Server" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Server"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Service Status" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Service Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SR2® Cloud DNS" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "SR2® Cloud DNS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Status" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Submit incorrectly blocked domains for review" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Submit incorrectly blocked domains for review"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Terms of Service" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Terms of Service"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version" : "1.2"
|
||||||
|
}
|
||||||
7
dns/Localizations/ar.xcloc/Localized Contents/ar.xliff
Normal file
7
dns/Localizations/ar.xcloc/Localized Contents/ar.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
147
dns/Localizations/en.xcloc/Localized Contents/en.xliff
Normal file
147
dns/Localizations/en.xcloc/Localized Contents/en.xliff
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
|
||||||
|
<file original="dns/dns-InfoPlist.xcstrings" source-language="en" target-language="en" datatype="plaintext">
|
||||||
|
<header>
|
||||||
|
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="26.4" build-num="17E192"/>
|
||||||
|
</header>
|
||||||
|
<body>
|
||||||
|
<trans-unit id="CFBundleName" xml:space="preserve">
|
||||||
|
<source>dns</source>
|
||||||
|
<target state="new">dns</target>
|
||||||
|
<note>Bundle name</note>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
<file original="dns/Localizable.xcstrings" source-language="en" target-language="en" datatype="plaintext">
|
||||||
|
<header>
|
||||||
|
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="26.4" build-num="17E192"/>
|
||||||
|
</header>
|
||||||
|
<body>
|
||||||
|
<trans-unit id="" xml:space="preserve">
|
||||||
|
<source/>
|
||||||
|
<target state="new"/>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="(Coming Soon)" xml:space="preserve">
|
||||||
|
<source>(Coming Soon)</source>
|
||||||
|
<target state="translated">(Coming Soon)</target>
|
||||||
|
<note>Indicates that this feature is not yet implemented but will be soon</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Active" xml:space="preserve">
|
||||||
|
<source>Active</source>
|
||||||
|
<target state="translated">Active</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Blocklist" xml:space="preserve">
|
||||||
|
<source>Blocklist</source>
|
||||||
|
<target state="translated">Blocklist</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Connected" xml:space="preserve">
|
||||||
|
<source>Connected</source>
|
||||||
|
<target state="translated">Connected</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Connection Details" xml:space="preserve">
|
||||||
|
<source>Connection Details</source>
|
||||||
|
<target state="translated">Connection Details</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="DNS Protection" xml:space="preserve">
|
||||||
|
<source>DNS Protection</source>
|
||||||
|
<target state="translated">DNS Protection</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Domains in blocklist" xml:space="preserve">
|
||||||
|
<source>Domains in blocklist</source>
|
||||||
|
<target state="translated">Domains in blocklist</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="IPv4" xml:space="preserve">
|
||||||
|
<source>IPv4</source>
|
||||||
|
<target state="translated">IPv4</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="IPv6" xml:space="preserve">
|
||||||
|
<source>IPv6</source>
|
||||||
|
<target state="translated">IPv6</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Inactive" xml:space="preserve">
|
||||||
|
<source>Inactive</source>
|
||||||
|
<target state="translated">Inactive</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Malware and phishing protection" xml:space="preserve">
|
||||||
|
<source>Malware and phishing protection</source>
|
||||||
|
<target state="translated">Malware and phishing protection</target>
|
||||||
|
<note>Description of the blocklist contents</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="No issues detected" xml:space="preserve">
|
||||||
|
<source>No issues detected</source>
|
||||||
|
<target state="translated">No issues detected</target>
|
||||||
|
<note>No current issues detected with the service</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Privacy Policy" xml:space="preserve">
|
||||||
|
<source>Privacy Policy</source>
|
||||||
|
<target state="translated">Privacy Policy</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Report False Positive" xml:space="preserve">
|
||||||
|
<source>Report False Positive</source>
|
||||||
|
<target state="translated">Report False Positive</target>
|
||||||
|
<note>Link to report that a domain name has been incorrectly blocked</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="SR2® Cloud DNS" xml:space="preserve">
|
||||||
|
<source>SR2® Cloud DNS</source>
|
||||||
|
<target state="translated">SR2® Cloud DNS</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Secure" xml:space="preserve">
|
||||||
|
<source>Secure</source>
|
||||||
|
<target state="translated">Secure</target>
|
||||||
|
<note>Name of the blocklist that only includes malware and security threats</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Secure + Adblock" xml:space="preserve">
|
||||||
|
<source>Secure + Adblock</source>
|
||||||
|
<target state="translated">Secure + Adblock</target>
|
||||||
|
<note>Name of the blocklist that contains “Secure” plus ad blocking</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Security plus ad and tracker blocking" xml:space="preserve">
|
||||||
|
<source>Security plus ad and tracker blocking</source>
|
||||||
|
<target state="translated">Security plus ad and tracker blocking</target>
|
||||||
|
<note>Description of the blocklist contents</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Select the level of protection for your DNS queries" xml:space="preserve">
|
||||||
|
<source>Select the level of protection for your DNS queries</source>
|
||||||
|
<target state="translated">Select the level of protection for your DNS queries</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Server" xml:space="preserve">
|
||||||
|
<source>Server</source>
|
||||||
|
<target state="translated">Server</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Service Status" xml:space="preserve">
|
||||||
|
<source>Service Status</source>
|
||||||
|
<target state="translated">Service Status</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Status" xml:space="preserve">
|
||||||
|
<source>Status</source>
|
||||||
|
<target state="translated">Status</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Submit incorrectly blocked domains for review" xml:space="preserve">
|
||||||
|
<source>Submit incorrectly blocked domains for review</source>
|
||||||
|
<target state="translated">Submit incorrectly blocked domains for review</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="Terms of Service" xml:space="preserve">
|
||||||
|
<source>Terms of Service</source>
|
||||||
|
<target state="translated">Terms of Service</target>
|
||||||
|
<note/>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
|
|
@ -0,0 +1,263 @@
|
||||||
|
{
|
||||||
|
"sourceLanguage" : "en",
|
||||||
|
"strings" : {
|
||||||
|
"" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"(Coming Soon)" : {
|
||||||
|
"comment" : "Indicates that this feature is not yet implemented but will be soon",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "(Coming Soon)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Active" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Active"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Blocklist" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Blocklist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Connected" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Connected"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Connection Details" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Connection Details"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DNS Protection" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "DNS Protection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Domains in blocklist" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Domains in blocklist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Inactive" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Inactive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IPv4" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "IPv4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IPv6" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "IPv6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Malware and phishing protection" : {
|
||||||
|
"comment" : "Description of the blocklist contents",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Malware and phishing protection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"No issues detected" : {
|
||||||
|
"comment" : "No current issues detected with the service",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "No issues detected"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Privacy Policy" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Privacy Policy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Report False Positive" : {
|
||||||
|
"comment" : "Link to report that a domain name has been incorrectly blocked",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Report False Positive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Secure" : {
|
||||||
|
"comment" : "Name of the blocklist that only includes malware and security threats",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Secure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Secure + Adblock" : {
|
||||||
|
"comment" : "Name of the blocklist that contains “Secure” plus ad blocking",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Secure + Adblock"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Security plus ad and tracker blocking" : {
|
||||||
|
"comment" : "Description of the blocklist contents",
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Security plus ad and tracker blocking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Select the level of protection for your DNS queries" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Select the level of protection for your DNS queries"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Server" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Server"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Service Status" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Service Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SR2® Cloud DNS" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "SR2® Cloud DNS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Status" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Submit incorrectly blocked domains for review" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Submit incorrectly blocked domains for review"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Terms of Service" : {
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Terms of Service"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version" : "1.2"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"sourceLanguage" : "en",
|
||||||
|
"strings" : {
|
||||||
|
"CFBundleName" : {
|
||||||
|
"comment" : "Bundle name",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "dns"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version" : "1.2"
|
||||||
|
}
|
||||||
12
dns/Localizations/en.xcloc/contents.json
Normal file
12
dns/Localizations/en.xcloc/contents.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"developmentRegion" : "en",
|
||||||
|
"project" : "dns.xcodeproj",
|
||||||
|
"targetLocale" : "en",
|
||||||
|
"toolInfo" : {
|
||||||
|
"toolBuildNumber" : "17E192",
|
||||||
|
"toolID" : "com.apple.dt.xcode",
|
||||||
|
"toolName" : "Xcode",
|
||||||
|
"toolVersion" : "26.4"
|
||||||
|
},
|
||||||
|
"version" : "1.0"
|
||||||
|
}
|
||||||
7
dns/Localizations/fa.xcloc/Localized Contents/fa.xliff
Normal file
7
dns/Localizations/fa.xcloc/Localized Contents/fa.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/fr.xcloc/Localized Contents/fr.xliff
Normal file
7
dns/Localizations/fr.xcloc/Localized Contents/fr.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/prs.xcloc/Localized Contents/prs.xliff
Normal file
7
dns/Localizations/prs.xcloc/Localized Contents/prs.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/ps.xcloc/Localized Contents/ps.xliff
Normal file
7
dns/Localizations/ps.xcloc/Localized Contents/ps.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/ro.xcloc/Localized Contents/ro.xliff
Normal file
7
dns/Localizations/ro.xcloc/Localized Contents/ro.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/ru.xcloc/Localized Contents/ru.xliff
Normal file
7
dns/Localizations/ru.xcloc/Localized Contents/ru.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
7
dns/Localizations/tok.xcloc/Localized Contents/tok.xliff
Normal file
7
dns/Localizations/tok.xcloc/Localized Contents/tok.xliff
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||||
|
<file original="Weblate" source-language="en" datatype="plaintext">
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
24
dns/Settings.swift
Normal file
24
dns/Settings.swift
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// Settings.swift
|
||||||
|
// dns
|
||||||
|
//
|
||||||
|
// Created by Benjamin Erhart on 15.04.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class Settings {
|
||||||
|
|
||||||
|
private static let blocklistKey = "blocklist"
|
||||||
|
|
||||||
|
private static let defaults = UserDefaults.standard
|
||||||
|
|
||||||
|
class var blocklist: BlocklistOption {
|
||||||
|
get {
|
||||||
|
BlocklistOption(rawValue: defaults.string(forKey: blocklistKey) ?? BlocklistOption.secure.rawValue) ?? .secure
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
defaults.set(newValue.rawValue, forKey: blocklistKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,19 +23,19 @@ enum SummaryStatus: String, Codable, CustomStringConvertible {
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .pending:
|
case .pending:
|
||||||
return NSLocalizedString("Fetching service status", comment: "")
|
return "Fetching service status"
|
||||||
|
|
||||||
case .ok:
|
case .ok:
|
||||||
return NSLocalizedString("No issues detected", comment: "")
|
return "No issues detected"
|
||||||
|
|
||||||
case .notice:
|
case .notice:
|
||||||
return NSLocalizedString("In maintenance", comment: "")
|
return "In maintenance"
|
||||||
|
|
||||||
case .disrupted:
|
case .disrupted:
|
||||||
return NSLocalizedString("Service disruption", comment: "")
|
return "Service disruption"
|
||||||
|
|
||||||
case .down:
|
case .down:
|
||||||
return NSLocalizedString("Service down", comment: "")
|
return "Service down"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,31 +12,28 @@ import OSLog
|
||||||
|
|
||||||
class ViewModel: NSObject, ObservableObject {
|
class ViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
static let title = "SR2® Cloud DNS"
|
|
||||||
|
|
||||||
// MARK: Public Properties
|
// MARK: Public Properties
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var blocklist: BlocklistOption = .secure {
|
var blocklist: BlocklistOption = .secure {
|
||||||
didSet {
|
didSet {
|
||||||
Task {
|
Settings.blocklist = blocklist
|
||||||
manager.dnsSettings = blocklist.settings
|
|
||||||
manager.localizedDescription = blocklist.title
|
|
||||||
|
|
||||||
do {
|
if isDnsEnabled {
|
||||||
try await manager.saveToPreferences()
|
toggleDns()
|
||||||
}
|
}
|
||||||
catch {
|
else {
|
||||||
log.error("Error storing preferences: \(error)")
|
isProgrammaticChange = false
|
||||||
}
|
|
||||||
|
|
||||||
isDnsEnabled = manager.isEnabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var isDnsEnabled = false
|
var isDnsEnabled = false {
|
||||||
|
didSet {
|
||||||
|
toggleDns()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var summaryStatus: SummaryStatus = .pending
|
var summaryStatus: SummaryStatus = .pending
|
||||||
|
|
@ -44,6 +41,8 @@ class ViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
// MARK: Private Properties
|
// MARK: Private Properties
|
||||||
|
|
||||||
|
private var isProgrammaticChange = false
|
||||||
|
|
||||||
private let manager = NEDNSSettingsManager.shared()
|
private let manager = NEDNSSettingsManager.shared()
|
||||||
|
|
||||||
private let log = Logger(subsystem: String(describing: ViewModel.self), category: String(describing: ViewModel.self))
|
private let log = Logger(subsystem: String(describing: ViewModel.self), category: String(describing: ViewModel.self))
|
||||||
|
|
@ -52,8 +51,33 @@ class ViewModel: NSObject, ObservableObject {
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
isProgrammaticChange = true
|
||||||
|
blocklist = Settings.blocklist
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
await refreshConfig()
|
do {
|
||||||
|
try await manager.loadFromPreferences()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
log.error("Error loading preferences: \(error)")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if manager.isEnabled, let settings = manager.dnsSettings {
|
||||||
|
for dnsServer in BlocklistOption.allCases {
|
||||||
|
if settings.servers.contains(dnsServer.ipv4) {
|
||||||
|
await MainActor.run {
|
||||||
|
isProgrammaticChange = true
|
||||||
|
blocklist = dnsServer
|
||||||
|
isProgrammaticChange = true
|
||||||
|
isDnsEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
|
|
@ -64,30 +88,42 @@ class ViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
// MARK: Public Methods
|
// MARK: Public Methods
|
||||||
|
|
||||||
func refreshConfig() async {
|
func toggleDns() {
|
||||||
do {
|
guard !isProgrammaticChange else {
|
||||||
try await manager.loadFromPreferences()
|
// Reset, so next one is recognized as coming from the user again.
|
||||||
}
|
isProgrammaticChange = false
|
||||||
catch {
|
|
||||||
log.error("Error loading preferences: \(error)")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isDnsEnabled = manager.isEnabled
|
Task {
|
||||||
|
if isDnsEnabled {
|
||||||
|
manager.dnsSettings = blocklist.settings
|
||||||
|
manager.localizedDescription = blocklist.description
|
||||||
|
|
||||||
if let settings = manager.dnsSettings {
|
do {
|
||||||
for dnsServer in BlocklistOption.allCases {
|
try await manager.saveToPreferences()
|
||||||
if settings.servers.contains(dnsServer.ipv4) {
|
}
|
||||||
await MainActor.run {
|
catch {
|
||||||
blocklist = dnsServer
|
log.error("Error storing preferences: \(error)")
|
||||||
}
|
|
||||||
|
|
||||||
break
|
delayedToggle(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !manager.isEnabled {
|
||||||
|
delayedToggle(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
try await manager.removeFromPreferences()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
log.error("Error removing preferences: \(error)")
|
||||||
|
|
||||||
|
delayedToggle(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Trigger `blocklist.didSet` to store right away, so user has something to select.
|
|
||||||
blocklist = blocklist
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,4 +139,18 @@ class ViewModel: NSObject, ObservableObject {
|
||||||
log.error("Error while checking status: \(error)")
|
log.error("Error while checking status: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Private Methods
|
||||||
|
|
||||||
|
private func delayedToggle(_ enabled: Bool) {
|
||||||
|
Task {
|
||||||
|
try? await Task.sleep(nanoseconds: 500_000_000)
|
||||||
|
|
||||||
|
await MainActor.run {
|
||||||
|
isProgrammaticChange = true
|
||||||
|
isDnsEnabled = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ DNS" = "%1$@ DNS";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Go to General" = "%1$@ Gehe zu Allgemein";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Select \"%2$@\"" = "%1$@ Wähle \"%2$@\"";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Tap \"%2$@\"" = "%1$@ Tippe auf \"%2$@\"";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ VPN & Network" = "%1$@ VPN und Geräteverwaltung";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%@ (Coming Soon)" = "%@ (bald)";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Active" = "Aktiv";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Blocklist" = "Sperrliste";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Connected" = "Verbunden";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Connection Details" = "Verbindungsdetails";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"DNS Protection" = "DNS–Schutz";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Domains in blocklist" = "Domains in Sperrliste";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Error" = "Fehler";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Fetching service status" = "Servicestatus ermitteln";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"In maintenance" = "Wartung";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Inactive" = "Inaktiv";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Malware and phishing protection" = "Malware- und Phishingschutz";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"No issues detected" = "Keine Probleme erkannt";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Open Settings" = "Öffne Einstellungen";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Privacy Policy" = "Datenschutzerklärung";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Report False Positive" = "Berichte über falsch-positive Sperre";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Secure" = "Sicherheit";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Secure + Adblock" = "Sicherheit + Werbeblocker";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Security plus ad and tracker blocking" = "Sicherheit und Werbe- und Trackerschutz";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Select the level of protection for your DNS queries" = "Wähle das Schutzniveau für Deine DNS-Anfragen";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Server" = "Server";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service disruption" = "Serviceunterbrechung";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service down" = "Service unerreichbar";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service Status" = "Servicestatus";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Status" = "Status";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Submit incorrectly blocked domains for review" = "Falsch blockierte Domains zur Überprüfung einreichen";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Terms of Service" = "Geschäftsbedingungen";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"To enable %@:" = "Um %@ zu aktivieren:";
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ DNS" = "%1$@ DNS";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Go to General" = "%1$@ Go to General";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Select \"%2$@\"" = "%1$@ Select \"%2$@\"";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ Tap \"%2$@\"" = "%1$@ Tap \"%2$@\"";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%1$@ VPN & Network" = "%1$@ VPN & Network";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"%@ (Coming Soon)" = "%@ (Coming Soon)";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Active" = "Active";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Blocklist" = "Blocklist";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Connected" = "Connected";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Connection Details" = "Connection Details";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"DNS Protection" = "DNS Protection";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Domains in blocklist" = "Domains in blocklist";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Error" = "Error";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Fetching service status" = "Fetching service status";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"In maintenance" = "In maintenance";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Inactive" = "Inactive";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Malware and phishing protection" = "Malware and phishing protection";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"No issues detected" = "No issues detected";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Open Settings" = "Open Settings";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Privacy Policy" = "Privacy Policy";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Report False Positive" = "Report False Positive";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Secure" = "Secure";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Secure + Adblock" = "Secure + Adblock";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Security plus ad and tracker blocking" = "Security plus ad and tracker blocking";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Select the level of protection for your DNS queries" = "Select the level of protection for your DNS queries";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Server" = "Server";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service disruption" = "Service disruption";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service down" = "Service down";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Service Status" = "Service Status";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Status" = "Status";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Submit incorrectly blocked domains for review" = "Submit incorrectly blocked domains for review";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"Terms of Service" = "Terms of Service";
|
|
||||||
|
|
||||||
/* No comment provided by engineer. */
|
|
||||||
"To enable %@:" = "To enable %@:";
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue