Move app-related strings in

Move Core strings to app target.

SwiftGen uses same bundle by default. No problem because Core
does not (and should not) any string internally.
This commit is contained in:
Davide De Rosa 2019-06-21 23:15:43 +02:00
parent 4d81661cce
commit 282728ae1e
39 changed files with 1932 additions and 353 deletions

View File

@ -44,17 +44,17 @@ extension OpenVPN.ConfigurationParser.Result {
} catch let e as ConfigurationError { } catch let e as ConfigurationError {
switch e { switch e {
case .encryptionPassphrase, .unableToDecrypt(_): case .encryptionPassphrase, .unableToDecrypt(_):
let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.EncryptionPassphrase.message) let alert = Macros.alert(url.normalizedFilename, L10n.Core.ParsedFile.Alerts.EncryptionPassphrase.message)
alert.addTextField { (field) in alert.addTextField { (field) in
field.isSecureTextEntry = true field.isSecureTextEntry = true
} }
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
guard let passphrase = alert.textFields?.first?.text else { guard let passphrase = alert.textFields?.first?.text else {
return return
} }
passphraseBlock(passphrase) passphraseBlock(passphrase)
} }
alert.addCancelAction(L10n.Global.cancel) { alert.addCancelAction(L10n.Core.Global.cancel) {
passphraseCancelBlock?() passphraseCancelBlock?()
} }
viewController.present(alert, animated: true, completion: nil) viewController.present(alert, animated: true, completion: nil)
@ -76,22 +76,22 @@ extension OpenVPN.ConfigurationParser.Result {
private static func alertImportError(url: URL, in vc: UIViewController, withMessage message: String) { private static func alertImportError(url: URL, in vc: UIViewController, withMessage message: String) {
let alert = Macros.alert(url.normalizedFilename, message) let alert = Macros.alert(url.normalizedFilename, message)
// alert.addDefaultAction(L10n.ParsedFile.Alerts.Buttons.report) { // alert.addDefaultAction(L10n.Core.ParsedFile.Alerts.Buttons.report) {
// var attach = IssueReporter.Attachments(debugLog: false, configurationURL: url) // var attach = IssueReporter.Attachments(debugLog: false, configurationURL: url)
// attach.description = message // attach.description = message
// IssueReporter.shared.present(in: vc, withAttachments: attach) // IssueReporter.shared.present(in: vc, withAttachments: attach)
// } // }
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
vc.present(alert, animated: true, completion: nil) vc.present(alert, animated: true, completion: nil)
} }
static func alertImportWarning(url: URL, in vc: UIViewController, withWarning warning: ConfigurationError, completionHandler: @escaping (Bool) -> Void) { static func alertImportWarning(url: URL, in vc: UIViewController, withWarning warning: ConfigurationError, completionHandler: @escaping (Bool) -> Void) {
let message = details(forWarning: warning) let message = details(forWarning: warning)
let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.PotentiallyUnsupported.message(message)) let alert = Macros.alert(url.normalizedFilename, L10n.Core.ParsedFile.Alerts.PotentiallyUnsupported.message(message))
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
completionHandler(true) completionHandler(true)
} }
alert.addCancelAction(L10n.Global.cancel) { alert.addCancelAction(L10n.Core.Global.cancel) {
completionHandler(false) completionHandler(false)
} }
vc.present(alert, animated: true, completion: nil) vc.present(alert, animated: true, completion: nil)
@ -102,22 +102,22 @@ extension OpenVPN.ConfigurationParser.Result {
switch appError { switch appError {
case .malformed(let option): case .malformed(let option):
log.error("Could not parse configuration URL: malformed option, \(option)") log.error("Could not parse configuration URL: malformed option, \(option)")
return L10n.ParsedFile.Alerts.Malformed.message(option) return L10n.Core.ParsedFile.Alerts.Malformed.message(option)
case .missingConfiguration(let option): case .missingConfiguration(let option):
log.error("Could not parse configuration URL: missing configuration, \(option)") log.error("Could not parse configuration URL: missing configuration, \(option)")
return L10n.ParsedFile.Alerts.Missing.message(option) return L10n.Core.ParsedFile.Alerts.Missing.message(option)
case .unsupportedConfiguration(let option): case .unsupportedConfiguration(let option):
log.error("Could not parse configuration URL: unsupported configuration, \(option)") log.error("Could not parse configuration URL: unsupported configuration, \(option)")
return L10n.ParsedFile.Alerts.Unsupported.message(option) return L10n.Core.ParsedFile.Alerts.Unsupported.message(option)
default: default:
break break
} }
} }
log.error("Could not parse configuration URL: \(error)") log.error("Could not parse configuration URL: \(error)")
return L10n.ParsedFile.Alerts.Parsing.message(error.localizedDescription) return L10n.Core.ParsedFile.Alerts.Parsing.message(error.localizedDescription)
} }
private static func details(forWarning warning: ConfigurationError) -> String { private static func details(forWarning warning: ConfigurationError) -> String {

View File

@ -57,8 +57,8 @@ class IssueReporter: NSObject {
func present(in viewController: UIViewController, withAttachments attachments: Attachments) { func present(in viewController: UIViewController, withAttachments attachments: Attachments) {
guard MFMailComposeViewController.canSendMail() else { guard MFMailComposeViewController.canSendMail() else {
let alert = Macros.alert(L10n.IssueReporter.title, L10n.Global.emailNotConfigured) let alert = Macros.alert(L10n.Core.IssueReporter.title, L10n.Core.Global.emailNotConfigured)
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
viewController.present(alert, animated: true, completion: nil) viewController.present(alert, animated: true, completion: nil)
return return
} }
@ -66,13 +66,13 @@ class IssueReporter: NSObject {
self.viewController = viewController self.viewController = viewController
if attachments.debugLog { if attachments.debugLog {
let alert = Macros.alert(L10n.IssueReporter.title, L10n.IssueReporter.message) let alert = Macros.alert(L10n.Core.IssueReporter.title, L10n.Core.IssueReporter.message)
alert.addDefaultAction(L10n.IssueReporter.Buttons.accept) { alert.addDefaultAction(L10n.Core.IssueReporter.Buttons.accept) {
VPN.shared.requestDebugLog(fallback: AppConstants.Log.debugSnapshot) { VPN.shared.requestDebugLog(fallback: AppConstants.Log.debugSnapshot) {
self.composeEmail(withDebugLog: $0, configurationURL: attachments.configurationURL, description: attachments.description) self.composeEmail(withDebugLog: $0, configurationURL: attachments.configurationURL, description: attachments.description)
} }
} }
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
viewController.present(alert, animated: true, completion: nil) viewController.present(alert, animated: true, completion: nil)
} else { } else {
composeEmail(withDebugLog: nil, configurationURL: attachments.configurationURL, description: attachments.description) composeEmail(withDebugLog: nil, configurationURL: attachments.configurationURL, description: attachments.description)

View File

@ -0,0 +1,992 @@
// swiftlint:disable all
// Generated using SwiftGen https://github.com/SwiftGen/SwiftGen
import Foundation
// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length
// MARK: - Strings
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name
internal enum L10n {
internal enum App {
internal enum Account {
internal enum Sections {
internal enum Credentials {
/// Credentials
internal static let header = L10n.tr("App", "account.sections.credentials.header")
}
}
}
internal enum Endpoint {
internal enum Sections {
internal enum LocationAddresses {
/// Addresses
internal static let header = L10n.tr("App", "endpoint.sections.location_addresses.header")
}
internal enum LocationProtocols {
/// Protocols
internal static let header = L10n.tr("App", "endpoint.sections.location_protocols.header")
}
}
}
internal enum ImportedHosts {
/// Imported hosts
internal static let title = L10n.tr("App", "imported_hosts.title")
}
internal enum NetworkSettings {
internal enum Cells {
internal enum AddDnsServer {
/// Add address
internal static let caption = L10n.tr("App", "network_settings.cells.add_dns_server.caption")
}
internal enum AddProxyBypass {
/// Add bypass domain
internal static let caption = L10n.tr("App", "network_settings.cells.add_proxy_bypass.caption")
}
internal enum ProxyBypass {
/// Bypass domain
internal static let caption = L10n.tr("App", "network_settings.cells.proxy_bypass.caption")
}
}
}
internal enum Organizer {
internal enum Cells {
internal enum AddHost {
/// Add new host
internal static let caption = L10n.tr("App", "organizer.cells.add_host.caption")
}
internal enum AddProvider {
/// Add new provider
internal static let caption = L10n.tr("App", "organizer.cells.add_provider.caption")
}
internal enum Profile {
internal enum Value {
/// In use
internal static let current = L10n.tr("App", "organizer.cells.profile.value.current")
}
}
}
}
internal enum Provider {
internal enum Preset {
internal enum Cells {
internal enum TechDetails {
/// Technical details
internal static let caption = L10n.tr("App", "provider.preset.cells.tech_details.caption")
}
}
}
}
internal enum Service {
internal enum Cells {
internal enum Host {
internal enum Parameters {
/// Parameters
internal static let caption = L10n.tr("App", "service.cells.host.parameters.caption")
}
}
internal enum Provider {
internal enum Refresh {
/// Refresh infrastructure
internal static let caption = L10n.tr("App", "service.cells.provider.refresh.caption")
}
}
internal enum Reconnect {
/// Reconnect
internal static let caption = L10n.tr("App", "service.cells.reconnect.caption")
}
internal enum TrustedAddWifi {
/// Add current Wi-Fi
internal static let caption = L10n.tr("App", "service.cells.trusted_add_wifi.caption")
}
internal enum UseProfile {
/// Use this profile
internal static let caption = L10n.tr("App", "service.cells.use_profile.caption")
}
internal enum VpnService {
/// Enabled
internal static let caption = L10n.tr("App", "service.cells.vpn_service.caption")
}
}
internal enum Sections {
internal enum Configuration {
/// Configuration
internal static let header = L10n.tr("App", "service.sections.configuration.header")
}
internal enum Status {
/// Connection
internal static let header = L10n.tr("App", "service.sections.status.header")
}
internal enum Vpn {
/// VPN
internal static let header = L10n.tr("App", "service.sections.vpn.header")
}
}
internal enum Welcome {
/// Welcome to Passepartout!\n\nUse the organizer to add a new profile.
internal static let message = L10n.tr("App", "service.welcome.message")
}
}
internal enum Shortcuts {
internal enum Add {
/// Add shortcut
internal static let title = L10n.tr("App", "shortcuts.add.title")
}
internal enum Edit {
/// Manage shortcuts
internal static let title = L10n.tr("App", "shortcuts.edit.title")
internal enum Cells {
internal enum AddShortcut {
/// Add shortcut
internal static let caption = L10n.tr("App", "shortcuts.edit.cells.add_shortcut.caption")
}
}
}
}
internal enum Wizards {
internal enum Host {
internal enum Cells {
internal enum TitleInput {
/// Title
internal static let caption = L10n.tr("App", "wizards.host.cells.title_input.caption")
}
}
internal enum Sections {
internal enum Existing {
/// Existing profiles
internal static let header = L10n.tr("App", "wizards.host.sections.existing.header")
}
}
}
}
}
internal enum Core {
internal enum About {
/// About
internal static let title = L10n.tr("Core", "about.title")
internal enum Cells {
internal enum Credits {
/// Credits
internal static let caption = L10n.tr("Core", "about.cells.credits.caption")
}
internal enum Disclaimer {
/// Disclaimer
internal static let caption = L10n.tr("Core", "about.cells.disclaimer.caption")
}
internal enum Faq {
/// FAQ
internal static let caption = L10n.tr("Core", "about.cells.faq.caption")
}
internal enum PrivacyPolicy {
/// Privacy policy
internal static let caption = L10n.tr("Core", "about.cells.privacy_policy.caption")
}
internal enum ShareGeneric {
/// Invite a friend
internal static let caption = L10n.tr("Core", "about.cells.share_generic.caption")
}
internal enum ShareTwitter {
/// Tweet about it!
internal static let caption = L10n.tr("Core", "about.cells.share_twitter.caption")
}
internal enum Website {
/// Home page
internal static let caption = L10n.tr("Core", "about.cells.website.caption")
}
}
internal enum Sections {
internal enum Share {
/// Share
internal static let header = L10n.tr("Core", "about.sections.share.header")
}
internal enum Web {
/// Web
internal static let header = L10n.tr("Core", "about.sections.web.header")
}
}
}
internal enum Account {
/// Account
internal static let title = L10n.tr("Core", "account.title")
internal enum Cells {
internal enum OpenGuide {
/// See your credentials
internal static let caption = L10n.tr("Core", "account.cells.open_guide.caption")
}
internal enum Password {
/// Password
internal static let caption = L10n.tr("Core", "account.cells.password.caption")
/// secret
internal static let placeholder = L10n.tr("Core", "account.cells.password.placeholder")
}
internal enum Signup {
/// Register with %@
internal static func caption(_ p1: String) -> String {
return L10n.tr("Core", "account.cells.signup.caption", p1)
}
}
internal enum Username {
/// Username
internal static let caption = L10n.tr("Core", "account.cells.username.caption")
/// username
internal static let placeholder = L10n.tr("Core", "account.cells.username.placeholder")
}
}
internal enum Sections {
internal enum Guidance {
internal enum Footer {
internal enum Infrastructure {
/// Use your %@ website credentials. Your username is usually numeric.
internal static func mullvad(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.mullvad", p1)
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func nordvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.nordvpn", p1)
}
/// Use your %@ website credentials. Your username is usually numeric with a "p" prefix.
internal static func pia(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.pia", p1)
}
/// Find your %@ credentials in the "Account > OpenVPN / IKEv2 Username" section of the website.
internal static func protonvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.protonvpn", p1)
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func tunnelbear(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.tunnelbear", p1)
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func vyprvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.vyprvpn", p1)
}
/// Find your %@ credentials in the OpenVPN Config Generator on the website.
internal static func windscribe(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.windscribe", p1)
}
}
}
}
internal enum Registration {
/// Go get an account on the %@ website.
internal static func footer(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.registration.footer", p1)
}
}
}
}
internal enum Configuration {
internal enum Cells {
internal enum Cipher {
/// Cipher
internal static let caption = L10n.tr("Core", "configuration.cells.cipher.caption")
}
internal enum Client {
/// Client certificate
internal static let caption = L10n.tr("Core", "configuration.cells.client.caption")
internal enum Value {
/// Not verified
internal static let disabled = L10n.tr("Core", "configuration.cells.client.value.disabled")
/// Verified
internal static let enabled = L10n.tr("Core", "configuration.cells.client.value.enabled")
}
}
internal enum CompressionAlgorithm {
/// Algorithm
internal static let caption = L10n.tr("Core", "configuration.cells.compression_algorithm.caption")
internal enum Value {
/// LZO
internal static let lzo = L10n.tr("Core", "configuration.cells.compression_algorithm.value.lzo")
/// Unsupported
internal static let other = L10n.tr("Core", "configuration.cells.compression_algorithm.value.other")
}
}
internal enum CompressionFraming {
/// Framing
internal static let caption = L10n.tr("Core", "configuration.cells.compression_framing.caption")
internal enum Value {
/// --compress
internal static let compress = L10n.tr("Core", "configuration.cells.compression_framing.value.compress")
/// --comp-lzo
internal static let lzo = L10n.tr("Core", "configuration.cells.compression_framing.value.lzo")
}
}
internal enum Digest {
/// Authentication
internal static let caption = L10n.tr("Core", "configuration.cells.digest.caption")
internal enum Value {
/// Embedded
internal static let embedded = L10n.tr("Core", "configuration.cells.digest.value.embedded")
}
}
internal enum Eku {
/// Extended verification
internal static let caption = L10n.tr("Core", "configuration.cells.eku.caption")
}
internal enum KeepAlive {
/// Keep-alive
internal static let caption = L10n.tr("Core", "configuration.cells.keep_alive.caption")
internal enum Value {
/// %d seconds
internal static func seconds(_ p1: Int) -> String {
return L10n.tr("Core", "configuration.cells.keep_alive.value.seconds", p1)
}
}
}
internal enum RandomEndpoint {
/// Randomize endpoint
internal static let caption = L10n.tr("Core", "configuration.cells.random_endpoint.caption")
}
internal enum RenegotiationSeconds {
/// Renegotiation
internal static let caption = L10n.tr("Core", "configuration.cells.renegotiation_seconds.caption")
internal enum Value {
/// after %@
internal static func after(_ p1: String) -> String {
return L10n.tr("Core", "configuration.cells.renegotiation_seconds.value.after", p1)
}
}
}
internal enum ResetOriginal {
/// Reset configuration
internal static let caption = L10n.tr("Core", "configuration.cells.reset_original.caption")
}
internal enum TlsWrapping {
/// Wrapping
internal static let caption = L10n.tr("Core", "configuration.cells.tls_wrapping.caption")
internal enum Value {
/// Authentication
internal static let auth = L10n.tr("Core", "configuration.cells.tls_wrapping.value.auth")
/// Encryption
internal static let crypt = L10n.tr("Core", "configuration.cells.tls_wrapping.value.crypt")
}
}
}
internal enum Sections {
internal enum Communication {
/// Communication
internal static let header = L10n.tr("Core", "configuration.sections.communication.header")
}
internal enum Compression {
/// Compression
internal static let header = L10n.tr("Core", "configuration.sections.compression.header")
}
internal enum Network {
/// Network
internal static let header = L10n.tr("Core", "configuration.sections.network.header")
}
internal enum Other {
/// Other
internal static let header = L10n.tr("Core", "configuration.sections.other.header")
}
internal enum Reset {
/// If you ended up with broken connectivity after changing the communication parameters, tap to revert to the original configuration.
internal static let footer = L10n.tr("Core", "configuration.sections.reset.footer")
}
internal enum Tls {
/// TLS
internal static let header = L10n.tr("Core", "configuration.sections.tls.header")
}
}
}
internal enum Credits {
/// Credits
internal static let title = L10n.tr("Core", "credits.title")
internal enum Sections {
internal enum Licenses {
/// Licenses
internal static let header = L10n.tr("Core", "credits.sections.licenses.header")
}
internal enum Notices {
/// Notices
internal static let header = L10n.tr("Core", "credits.sections.notices.header")
}
internal enum Translations {
/// Translations
internal static let header = L10n.tr("Core", "credits.sections.translations.header")
}
}
}
internal enum DebugLog {
internal enum Alerts {
internal enum EmptyLog {
/// The debug log is empty.
internal static let message = L10n.tr("Core", "debug_log.alerts.empty_log.message")
}
}
internal enum Buttons {
/// Next
internal static let next = L10n.tr("Core", "debug_log.buttons.next")
/// Previous
internal static let previous = L10n.tr("Core", "debug_log.buttons.previous")
}
}
internal enum Donation {
/// Donate
internal static let title = L10n.tr("Core", "donation.title")
internal enum Alerts {
internal enum Purchase {
internal enum Failure {
/// Unable to perform the donation. %@
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "donation.alerts.purchase.failure.message", p1)
}
}
internal enum Success {
/// This means a lot to me and I really hope you keep using and promoting this app.
internal static let message = L10n.tr("Core", "donation.alerts.purchase.success.message")
/// Thank you
internal static let title = L10n.tr("Core", "donation.alerts.purchase.success.title")
}
}
}
internal enum Cells {
internal enum Loading {
/// Loading donations
internal static let caption = L10n.tr("Core", "donation.cells.loading.caption")
}
internal enum Purchasing {
/// Performing donation
internal static let caption = L10n.tr("Core", "donation.cells.purchasing.caption")
}
}
internal enum Sections {
internal enum OneTime {
/// If you want to display gratitude for my free work, here are a couple amounts you can donate instantly.\n\nYou will only be charged once per donation, and you can donate multiple times.
internal static let footer = L10n.tr("Core", "donation.sections.one_time.footer")
/// One time
internal static let header = L10n.tr("Core", "donation.sections.one_time.header")
}
}
}
internal enum Endpoint {
/// Endpoint
internal static let title = L10n.tr("Core", "endpoint.title")
internal enum Cells {
internal enum AnyAddress {
/// Automatic
internal static let caption = L10n.tr("Core", "endpoint.cells.any_address.caption")
}
internal enum AnyProtocol {
/// Automatic
internal static let caption = L10n.tr("Core", "endpoint.cells.any_protocol.caption")
}
}
}
internal enum Global {
/// Cancel
internal static let cancel = L10n.tr("Core", "global.cancel")
/// Close
internal static let close = L10n.tr("Core", "global.close")
/// No e-mail account is configured.
internal static let emailNotConfigured = L10n.tr("Core", "global.email_not_configured")
/// Next
internal static let next = L10n.tr("Core", "global.next")
/// OK
internal static let ok = L10n.tr("Core", "global.ok")
internal enum Captions {
/// Address
internal static let address = L10n.tr("Core", "global.captions.address")
/// Port
internal static let port = L10n.tr("Core", "global.captions.port")
}
internal enum Host {
internal enum TitleInput {
/// Acceptable characters are alphanumerics plus dash "-", underscore "_" and dot ".".
internal static let message = L10n.tr("Core", "global.host.title_input.message")
/// My profile
internal static let placeholder = L10n.tr("Core", "global.host.title_input.placeholder")
}
}
internal enum Values {
/// Automatic
internal static let automatic = L10n.tr("Core", "global.values.automatic")
/// Disabled
internal static let disabled = L10n.tr("Core", "global.values.disabled")
/// Enabled
internal static let enabled = L10n.tr("Core", "global.values.enabled")
/// Manual
internal static let manual = L10n.tr("Core", "global.values.manual")
/// None
internal static let `none` = L10n.tr("Core", "global.values.none")
}
}
internal enum IssueReporter {
/// The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.\n\nThe .ovpn configuration file, if any, is attached stripped of any sensitive data.\n\nPlease double check the e-mail attachments if unsure.
internal static let message = L10n.tr("Core", "issue_reporter.message")
/// Report issue
internal static let title = L10n.tr("Core", "issue_reporter.title")
internal enum Buttons {
/// I understand
internal static let accept = L10n.tr("Core", "issue_reporter.buttons.accept")
}
}
internal enum Label {
internal enum License {
/// Unable to download full license content.
internal static let error = L10n.tr("Core", "label.license.error")
}
}
internal enum NetworkChoice {
/// Read .ovpn
internal static let client = L10n.tr("Core", "network_choice.client")
/// Pull from server
internal static let server = L10n.tr("Core", "network_choice.server")
}
internal enum NetworkSettings {
/// Network settings
internal static let title = L10n.tr("Core", "network_settings.title")
internal enum Dns {
/// DNS
internal static let title = L10n.tr("Core", "network_settings.dns.title")
internal enum Cells {
internal enum Domain {
/// Domain
internal static let caption = L10n.tr("Core", "network_settings.dns.cells.domain.caption")
}
}
}
internal enum Gateway {
/// Default gateway
internal static let title = L10n.tr("Core", "network_settings.gateway.title")
}
internal enum Proxy {
/// Proxy
internal static let title = L10n.tr("Core", "network_settings.proxy.title")
}
}
internal enum Organizer {
internal enum Alerts {
internal enum AddHost {
/// Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.\n\nYou can also import an .ovpn with iTunes File Sharing.
internal static let message = L10n.tr("Core", "organizer.alerts.add_host.message")
}
internal enum CannotDonate {
/// There is no payment method configured on this device.
internal static let message = L10n.tr("Core", "organizer.alerts.cannot_donate.message")
}
internal enum DeleteVpnProfile {
/// Do you really want to erase the VPN configuration from your device settings? This may fix some broken VPN states and will not affect your provider and host profiles.
internal static let message = L10n.tr("Core", "organizer.alerts.delete_vpn_profile.message")
}
internal enum ExhaustedProviders {
/// You have created profiles for any available provider.
internal static let message = L10n.tr("Core", "organizer.alerts.exhausted_providers.message")
}
}
internal enum Cells {
internal enum About {
/// About %@
internal static func caption(_ p1: String) -> String {
return L10n.tr("Core", "organizer.cells.about.caption", p1)
}
}
internal enum Donate {
/// Make a donation
internal static let caption = L10n.tr("Core", "organizer.cells.donate.caption")
}
internal enum JoinCommunity {
/// Join community
internal static let caption = L10n.tr("Core", "organizer.cells.join_community.caption")
}
internal enum Patreon {
/// Support me on Patreon
internal static let caption = L10n.tr("Core", "organizer.cells.patreon.caption")
}
internal enum SiriShortcuts {
/// Manage shortcuts
internal static let caption = L10n.tr("Core", "organizer.cells.siri_shortcuts.caption")
}
internal enum Translate {
/// Offer to translate
internal static let caption = L10n.tr("Core", "organizer.cells.translate.caption")
}
internal enum Uninstall {
/// Remove VPN configuration
internal static let caption = L10n.tr("Core", "organizer.cells.uninstall.caption")
}
internal enum WriteReview {
/// Write a review
internal static let caption = L10n.tr("Core", "organizer.cells.write_review.caption")
}
}
internal enum Sections {
internal enum Feedback {
/// Feedback
internal static let header = L10n.tr("Core", "organizer.sections.feedback.header")
}
internal enum Hosts {
/// Import hosts from raw .ovpn configuration files.
internal static let footer = L10n.tr("Core", "organizer.sections.hosts.footer")
/// Hosts
internal static let header = L10n.tr("Core", "organizer.sections.hosts.header")
}
internal enum Providers {
/// Here you find a few providers with preset configuration profiles.
internal static let footer = L10n.tr("Core", "organizer.sections.providers.footer")
/// Providers
internal static let header = L10n.tr("Core", "organizer.sections.providers.header")
}
internal enum Siri {
/// Get help from Siri to speed up your most common interactions with the app.
internal static let footer = L10n.tr("Core", "organizer.sections.siri.footer")
/// Siri
internal static let header = L10n.tr("Core", "organizer.sections.siri.header")
}
internal enum Support {
/// Support
internal static let header = L10n.tr("Core", "organizer.sections.support.header")
}
}
}
internal enum ParsedFile {
internal enum Alerts {
internal enum Buttons {
/// Report an issue
internal static let report = L10n.tr("Core", "parsed_file.alerts.buttons.report")
}
internal enum Decryption {
/// The configuration contains an encrypted private key and it could not be decrypted. Double check your entered passphrase.
internal static let message = L10n.tr("Core", "parsed_file.alerts.decryption.message")
}
internal enum EncryptionPassphrase {
/// Please enter the encryption passphrase.
internal static let message = L10n.tr("Core", "parsed_file.alerts.encryption_passphrase.message")
}
internal enum Malformed {
/// The configuration file contains a malformed option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.malformed.message", p1)
}
}
internal enum Missing {
/// The configuration file lacks a required option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.missing.message", p1)
}
}
internal enum Parsing {
/// Unable to parse the provided configuration file (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.parsing.message", p1)
}
}
internal enum PotentiallyUnsupported {
/// The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings.
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.potentially_unsupported.message", p1)
}
}
internal enum Unsupported {
/// The configuration file contains an unsupported option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.unsupported.message", p1)
}
}
}
}
internal enum Reddit {
/// Did you know that Passepartout has a subreddit? Subscribe for updates or to discuss issues, features, new platforms or whatever you like.\n\nIt's also a great way to show you care about this project.
internal static let message = L10n.tr("Core", "reddit.message")
/// Reddit
internal static let title = L10n.tr("Core", "reddit.title")
internal enum Buttons {
/// Don't ask again
internal static let never = L10n.tr("Core", "reddit.buttons.never")
/// Remind me later
internal static let remind = L10n.tr("Core", "reddit.buttons.remind")
/// Subscribe now!
internal static let subscribe = L10n.tr("Core", "reddit.buttons.subscribe")
}
}
internal enum Service {
internal enum Alerts {
internal enum Buttons {
/// Reconnect
internal static let reconnect = L10n.tr("Core", "service.alerts.buttons.reconnect")
}
internal enum CredentialsNeeded {
/// You need to enter account credentials first.
internal static let message = L10n.tr("Core", "service.alerts.credentials_needed.message")
}
internal enum Download {
/// Failed to download configuration files. %@
internal static func failed(_ p1: String) -> String {
return L10n.tr("Core", "service.alerts.download.failed", p1)
}
/// %@ requires the download of additional configuration files.\n\nConfirm to start the download.
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "service.alerts.download.message", p1)
}
/// Download required
internal static let title = L10n.tr("Core", "service.alerts.download.title")
internal enum Hud {
/// Extracting files, please be patient...
internal static let extracting = L10n.tr("Core", "service.alerts.download.hud.extracting")
}
}
internal enum MasksPrivateData {
internal enum Messages {
/// In order to safely reset the current debug log and apply the new masking preference, you must reconnect to the VPN now.
internal static let mustReconnect = L10n.tr("Core", "service.alerts.masks_private_data.messages.must_reconnect")
}
}
internal enum ReconnectVpn {
/// Do you want to reconnect to the VPN?
internal static let message = L10n.tr("Core", "service.alerts.reconnect_vpn.message")
}
internal enum Rename {
/// Rename profile
internal static let title = L10n.tr("Core", "service.alerts.rename.title")
}
internal enum TestConnectivity {
/// Connectivity
internal static let title = L10n.tr("Core", "service.alerts.test_connectivity.title")
internal enum Messages {
/// Your device has no Internet connectivity, please review your profile parameters.
internal static let failure = L10n.tr("Core", "service.alerts.test_connectivity.messages.failure")
/// Your device is connected to the Internet!
internal static let success = L10n.tr("Core", "service.alerts.test_connectivity.messages.success")
}
}
internal enum Trusted {
internal enum NoNetwork {
/// You are not connected to any Wi-Fi network.
internal static let message = L10n.tr("Core", "service.alerts.trusted.no_network.message")
}
internal enum WillDisconnectPolicy {
/// By changing the trust policy, the VPN may be disconnected. Continue?
internal static let message = L10n.tr("Core", "service.alerts.trusted.will_disconnect_policy.message")
}
internal enum WillDisconnectTrusted {
/// By trusting this network, the VPN may be disconnected. Continue?
internal static let message = L10n.tr("Core", "service.alerts.trusted.will_disconnect_trusted.message")
}
}
}
internal enum Cells {
internal enum ConnectionStatus {
/// Status
internal static let caption = L10n.tr("Core", "service.cells.connection_status.caption")
}
internal enum DataCount {
/// Exchanged data
internal static let caption = L10n.tr("Core", "service.cells.data_count.caption")
/// Unavailable
internal static let `none` = L10n.tr("Core", "service.cells.data_count.none")
}
internal enum DebugLog {
/// Debug log
internal static let caption = L10n.tr("Core", "service.cells.debug_log.caption")
}
internal enum MasksPrivateData {
/// Mask network data
internal static let caption = L10n.tr("Core", "service.cells.masks_private_data.caption")
}
internal enum Provider {
internal enum Pool {
/// Location
internal static let caption = L10n.tr("Core", "service.cells.provider.pool.caption")
}
internal enum Preset {
/// Preset
internal static let caption = L10n.tr("Core", "service.cells.provider.preset.caption")
}
}
internal enum ReportIssue {
/// Report connectivity issue
internal static let caption = L10n.tr("Core", "service.cells.report_issue.caption")
}
internal enum TestConnectivity {
/// Test connectivity
internal static let caption = L10n.tr("Core", "service.cells.test_connectivity.caption")
}
internal enum TrustedMobile {
/// Cellular network
internal static let caption = L10n.tr("Core", "service.cells.trusted_mobile.caption")
}
internal enum TrustedPolicy {
/// Trust disables VPN
internal static let caption = L10n.tr("Core", "service.cells.trusted_policy.caption")
}
internal enum VpnResolvesHostname {
/// Resolve server hostname
internal static let caption = L10n.tr("Core", "service.cells.vpn_resolves_hostname.caption")
}
internal enum VpnSurvivesSleep {
/// Keep alive on sleep
internal static let caption = L10n.tr("Core", "service.cells.vpn_survives_sleep.caption")
}
}
internal enum Sections {
internal enum Diagnostics {
/// Masking status will be effective after reconnecting. Network data are hostnames, IP addresses, routing, SSID. Credentials and private keys are not logged regardless.
internal static let footer = L10n.tr("Core", "service.sections.diagnostics.footer")
/// Diagnostics
internal static let header = L10n.tr("Core", "service.sections.diagnostics.header")
}
internal enum ProviderInfrastructure {
/// Last updated on %@.
internal static func footer(_ p1: String) -> String {
return L10n.tr("Core", "service.sections.provider_infrastructure.footer", p1)
}
}
internal enum Trusted {
/// When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior.
internal static let footer = L10n.tr("Core", "service.sections.trusted.footer")
/// Trusted networks
internal static let header = L10n.tr("Core", "service.sections.trusted.header")
}
internal enum Vpn {
/// The connection will be established whenever necessary.
internal static let footer = L10n.tr("Core", "service.sections.vpn.footer")
}
internal enum VpnResolvesHostname {
/// Preferred in most networks and required in some IPv6 networks. Disable where DNS is blocked, or to speed up negotiation when DNS is slow to respond.
internal static let footer = L10n.tr("Core", "service.sections.vpn_resolves_hostname.footer")
}
internal enum VpnSurvivesSleep {
/// Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections.
internal static let footer = L10n.tr("Core", "service.sections.vpn_survives_sleep.footer")
}
}
}
internal enum Share {
/// Passepartout is an user-friendly, open source OpenVPN client for iOS and macOS
internal static let message = L10n.tr("Core", "share.message")
}
internal enum Shortcuts {
internal enum Add {
internal enum Alerts {
internal enum NoProfiles {
/// There is no profile to connect to.
internal static let message = L10n.tr("Core", "shortcuts.add.alerts.no_profiles.message")
}
}
internal enum Cells {
internal enum Connect {
/// Connect to
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.connect.caption")
}
internal enum DisableVpn {
/// Disable VPN
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.disable_vpn.caption")
}
internal enum EnableVpn {
/// Enable VPN
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.enable_vpn.caption")
}
internal enum TrustCellular {
/// Trust cellular network
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.trust_cellular.caption")
}
internal enum TrustCurrentWifi {
/// Trust current Wi-Fi
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.trust_current_wifi.caption")
}
internal enum UntrustCellular {
/// Untrust cellular network
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.untrust_cellular.caption")
}
internal enum UntrustCurrentWifi {
/// Untrust current Wi-Fi
internal static let caption = L10n.tr("Core", "shortcuts.add.cells.untrust_current_wifi.caption")
}
}
internal enum Sections {
internal enum Cellular {
/// Cellular
internal static let header = L10n.tr("Core", "shortcuts.add.sections.cellular.header")
}
internal enum Vpn {
/// VPN
internal static let header = L10n.tr("Core", "shortcuts.add.sections.vpn.header")
}
internal enum Wifi {
/// Wi-Fi
internal static let header = L10n.tr("Core", "shortcuts.add.sections.wifi.header")
}
}
}
internal enum Edit {
internal enum Sections {
internal enum All {
/// Existing shortcuts
internal static let header = L10n.tr("Core", "shortcuts.edit.sections.all.header")
}
}
}
}
internal enum Translations {
/// Translations
internal static let title = L10n.tr("Core", "translations.title")
}
internal enum Version {
/// Version
internal static let title = L10n.tr("Core", "version.title")
internal enum Labels {
/// Passepartout and TunnelKit are written and maintained by Davide De Rosa (keeshux).\n\nSource code for Passepartout and TunnelKit is publicly available on GitHub under the GPLv3, you can find links in the home page.\n\nPassepartout is a non-official client and is in no way affiliated with OpenVPN Inc.
internal static let intro = L10n.tr("Core", "version.labels.intro")
}
}
internal enum Vpn {
/// Active
internal static let active = L10n.tr("Core", "vpn.active")
/// Connecting
internal static let connecting = L10n.tr("Core", "vpn.connecting")
/// Disabled
internal static let disabled = L10n.tr("Core", "vpn.disabled")
/// Disconnecting
internal static let disconnecting = L10n.tr("Core", "vpn.disconnecting")
/// Inactive
internal static let inactive = L10n.tr("Core", "vpn.inactive")
internal enum Errors {
/// Auth failed
internal static let auth = L10n.tr("Core", "vpn.errors.auth")
/// Compression unsupported
internal static let compression = L10n.tr("Core", "vpn.errors.compression")
/// DNS failed
internal static let dns = L10n.tr("Core", "vpn.errors.dns")
/// Encryption failed
internal static let encryption = L10n.tr("Core", "vpn.errors.encryption")
/// No gateway
internal static let gateway = L10n.tr("Core", "vpn.errors.gateway")
/// Network changed
internal static let network = L10n.tr("Core", "vpn.errors.network")
/// Missing routing
internal static let routing = L10n.tr("Core", "vpn.errors.routing")
/// Timeout
internal static let timeout = L10n.tr("Core", "vpn.errors.timeout")
/// TLS failed
internal static let tls = L10n.tr("Core", "vpn.errors.tls")
}
}
internal enum Wizards {
internal enum Host {
internal enum Alerts {
internal enum Existing {
/// A host profile with the same title already exists. Replace it?
internal static let message = L10n.tr("Core", "wizards.host.alerts.existing.message")
}
}
}
}
}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name
// MARK: - Implementation Details
extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// swiftlint:disable:next nslocalizedstring_key
let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
return String(format: format, locale: Locale.current, arguments: args)
}
}
private final class BundleToken {}

View File

@ -78,18 +78,18 @@ extension SettingTableViewCell {
func applyVPN(_ theme: Theme, with vpnStatus: VPNStatus?, error: OpenVPNTunnelProvider.ProviderError?) { func applyVPN(_ theme: Theme, with vpnStatus: VPNStatus?, error: OpenVPNTunnelProvider.ProviderError?) {
leftTextColor = theme.palette.primaryText leftTextColor = theme.palette.primaryText
guard let vpnStatus = vpnStatus else { guard let vpnStatus = vpnStatus else {
rightText = L10n.Vpn.disabled rightText = L10n.Core.Vpn.disabled
rightTextColor = theme.palette.secondaryText rightTextColor = theme.palette.secondaryText
return return
} }
switch vpnStatus { switch vpnStatus {
case .connecting: case .connecting:
rightText = L10n.Vpn.connecting rightText = L10n.Core.Vpn.connecting
rightTextColor = theme.palette.indeterminate rightTextColor = theme.palette.indeterminate
case .connected: case .connected:
rightText = L10n.Vpn.active rightText = L10n.Core.Vpn.active
rightTextColor = theme.palette.on rightTextColor = theme.palette.on
case .disconnecting, .disconnected: case .disconnecting, .disconnected:
@ -97,31 +97,31 @@ extension SettingTableViewCell {
if let error = error { if let error = error {
switch error { switch error {
case .socketActivity, .timeout: case .socketActivity, .timeout:
disconnectionReason = L10n.Vpn.Errors.timeout disconnectionReason = L10n.Core.Vpn.Errors.timeout
case .dnsFailure: case .dnsFailure:
disconnectionReason = L10n.Vpn.Errors.dns disconnectionReason = L10n.Core.Vpn.Errors.dns
case .tlsInitialization, .tlsServerVerification, .tlsHandshake: case .tlsInitialization, .tlsServerVerification, .tlsHandshake:
disconnectionReason = L10n.Vpn.Errors.tls disconnectionReason = L10n.Core.Vpn.Errors.tls
case .authentication: case .authentication:
disconnectionReason = L10n.Vpn.Errors.auth disconnectionReason = L10n.Core.Vpn.Errors.auth
case .encryptionInitialization, .encryptionData: case .encryptionInitialization, .encryptionData:
disconnectionReason = L10n.Vpn.Errors.encryption disconnectionReason = L10n.Core.Vpn.Errors.encryption
case .serverCompression: case .serverCompression:
disconnectionReason = L10n.Vpn.Errors.compression disconnectionReason = L10n.Core.Vpn.Errors.compression
case .networkChanged: case .networkChanged:
disconnectionReason = L10n.Vpn.Errors.network disconnectionReason = L10n.Core.Vpn.Errors.network
case .routing: case .routing:
disconnectionReason = L10n.Vpn.Errors.routing disconnectionReason = L10n.Core.Vpn.Errors.routing
case .gatewayUnattainable: case .gatewayUnattainable:
disconnectionReason = L10n.Vpn.Errors.gateway disconnectionReason = L10n.Core.Vpn.Errors.gateway
default: default:
break break
@ -129,11 +129,11 @@ extension SettingTableViewCell {
} }
switch vpnStatus { switch vpnStatus {
case .disconnecting: case .disconnecting:
rightText = disconnectionReason ?? L10n.Vpn.disconnecting rightText = disconnectionReason ?? L10n.Core.Vpn.disconnecting
rightTextColor = theme.palette.indeterminate rightTextColor = theme.palette.indeterminate
case .disconnected: case .disconnected:
rightText = disconnectionReason ?? L10n.Vpn.inactive rightText = disconnectionReason ?? L10n.Core.Vpn.inactive
rightTextColor = theme.palette.off rightTextColor = theme.palette.off
default: default:

View File

@ -135,7 +135,7 @@ extension UIButton {
extension UITextField { extension UITextField {
func applyProfileId(_ theme: Theme) { func applyProfileId(_ theme: Theme) {
placeholder = L10n.Global.Host.TitleInput.placeholder placeholder = L10n.Core.Global.Host.TitleInput.placeholder
clearButtonMode = .always clearButtonMode = .always
keyboardType = .asciiCapable keyboardType = .asciiCapable
returnKeyType = .done returnKeyType = .done

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 4/23/19.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "In Benutzung";
"organizer.cells.add_provider.caption" = "Neuen Anbieter hinzufügen";
"organizer.cells.add_host.caption" = "Neuen Host hinzufügen";
"wizards.host.cells.title_input.caption" = "Titel";
"wizards.host.sections.existing.header" = "Bestehende Profile";
"imported_hosts.title" = "Importierte Hosts";
"service.welcome.message" = "Willkommen bei Passepartout!\n\nBenutze den Organizer um ein neues Profil hinzuzufügen.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Verbindung";
"service.sections.configuration.header" = "Konfiguration";
"service.cells.use_profile.caption" = "Dieses Profil verwenden";
"service.cells.vpn_service.caption" = "Aktiviert";
"service.cells.reconnect.caption" = "Erneut verbinden";
"service.cells.provider.refresh.caption" = "Infrastruktur neu laden";
"service.cells.host.parameters.caption" = "Parameter";
"service.cells.trusted_add_wifi.caption" = "Aktuelles WLAN hinzufügen";
"account.sections.credentials.header" = "Zugangsdaten";
"endpoint.sections.location_addresses.header" = "Adressen";
"endpoint.sections.location_protocols.header" = "Protokolle";
"provider.preset.cells.tech_details.caption" = "Technische Details";
"network_settings.cells.add_dns_server.caption" = "Adresse hinzufügen";
"network_settings.cells.proxy_bypass.caption" = "Domäne umgehen";
"network_settings.cells.add_proxy_bypass.caption" = "Zu umgehende Domäne hinzufügen";
"shortcuts.add.title" = "Füge Kurzbefehl hinzu";
"shortcuts.edit.title" = "Kurzbefehle bearbeiten";
"shortcuts.edit.cells.add_shortcut.caption" = "Kurzbefehl hinzufügen";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "Σε χρήση";
"organizer.cells.add_provider.caption" = "Προσθήκη νέου παρόχου";
"organizer.cells.add_host.caption" = "Προσθήκη νέου διακομιστή";
"wizards.host.cells.title_input.caption" = "Τίτλος";
"wizards.host.sections.existing.header" = "Υπάρχον Προφίλ";
"imported_hosts.title" = "Εισαγόμενοι διακομιστές";
"service.welcome.message" = "Καλώς Ήλθατε στο Passepartout!\n\nΧρησιμοποιήστε τον διοργανωτή για να προσθέσετε ένα νέο προφίλ.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Σύνδεση";
"service.sections.configuration.header" = "Ρύθμιση";
"service.cells.use_profile.caption" = "Χρησιμοποιήστε αυτό το προφίλ";
"service.cells.vpn_service.caption" = "Ενεργοποιήθηκε";
"service.cells.reconnect.caption" = "Επανασύνδεση";
"service.cells.provider.refresh.caption" = "Ανανέωση της υποδομής";
"service.cells.host.parameters.caption" = "Παράμετροι";
"service.cells.trusted_add_wifi.caption" = "Προσθέστε το τρέχον Wi-Fi";
"account.sections.credentials.header" = "Διαπιστευτήρια";
"endpoint.sections.location_addresses.header" = "Διεθύνσεις";
"endpoint.sections.location_protocols.header" = "Πρωτόκολλα";
"provider.preset.cells.tech_details.caption" = "Τεχνικές Λεπτομέρειες";
"network_settings.cells.add_dns_server.caption" = "Προσθήκη Διεύθυνσης";
"network_settings.cells.proxy_bypass.caption" = "Παράκαμψη Τομέα";
"network_settings.cells.add_proxy_bypass.caption" = "Προσθήκη τομέα παράκαμψης";
"shortcuts.add.title" = "Προσθήκη Συντόμευσης";
"shortcuts.edit.title" = "Διαχείριση συντομεύσεων";
"shortcuts.edit.cells.add_shortcut.caption" = "Προσθήκη Συντόμευσης";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/21/19.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "In use";
"organizer.cells.add_provider.caption" = "Add new provider";
"organizer.cells.add_host.caption" = "Add new host";
"wizards.host.cells.title_input.caption" = "Title";
"wizards.host.sections.existing.header" = "Existing profiles";
"imported_hosts.title" = "Imported hosts";
"service.welcome.message" = "Welcome to Passepartout!\n\nUse the organizer to add a new profile.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Connection";
"service.sections.configuration.header" = "Configuration";
"service.cells.use_profile.caption" = "Use this profile";
"service.cells.vpn_service.caption" = "Enabled";
"service.cells.reconnect.caption" = "Reconnect";
"service.cells.provider.refresh.caption" = "Refresh infrastructure";
"service.cells.host.parameters.caption" = "Parameters";
"service.cells.trusted_add_wifi.caption" = "Add current Wi-Fi";
"account.sections.credentials.header" = "Credentials";
"endpoint.sections.location_addresses.header" = "Addresses";
"endpoint.sections.location_protocols.header" = "Protocols";
"provider.preset.cells.tech_details.caption" = "Technical details";
"network_settings.cells.add_dns_server.caption" = "Add address";
"network_settings.cells.proxy_bypass.caption" = "Bypass domain";
"network_settings.cells.add_proxy_bypass.caption" = "Add bypass domain";
"shortcuts.add.title" = "Add shortcut";
"shortcuts.edit.title" = "Manage shortcuts";
"shortcuts.edit.cells.add_shortcut.caption" = "Add shortcut";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "En uso";
"organizer.cells.add_provider.caption" = "Añadir proveedor";
"organizer.cells.add_host.caption" = "Añadir host";
"wizards.host.cells.title_input.caption" = "Título";
"wizards.host.sections.existing.header" = "Perfiles existentes";
"imported_hosts.title" = "Hosts importados";
"service.welcome.message" = "Bienvenid@ a Passepartout!\n\nUsa el organizador para añadir un nuevo perfil.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Conexión";
"service.sections.configuration.header" = "Configuración";
"service.cells.use_profile.caption" = "Usar este perfil";
"service.cells.vpn_service.caption" = "Habilitado";
"service.cells.reconnect.caption" = "Reconectar";
"service.cells.provider.refresh.caption" = "Refrescar infraestructura";
"service.cells.host.parameters.caption" = "Parámetros";
"service.cells.trusted_add_wifi.caption" = "Añadir Wi-Fi en uso";
"account.sections.credentials.header" = "Credenciales";
"endpoint.sections.location_addresses.header" = "Direcciones";
"endpoint.sections.location_protocols.header" = "Protocolos";
"provider.preset.cells.tech_details.caption" = "Detalles técnicos";
"network_settings.cells.add_dns_server.caption" = "Añadir dirección";
"network_settings.cells.proxy_bypass.caption" = "Dominio ignorado";
"network_settings.cells.add_proxy_bypass.caption" = "Añadir dominio ignorado";
"shortcuts.add.title" = "Añadir atajo";
"shortcuts.edit.title" = "Gestionar atajos";
"shortcuts.edit.cells.add_shortcut.caption" = "Añadir atajo";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "En utilisation";
"organizer.cells.add_provider.caption" = "Ajouter un nouveau fournisseur";
"organizer.cells.add_host.caption" = "Ajouter un nouvel hôte";
"wizards.host.cells.title_input.caption" = "Titre";
"wizards.host.sections.existing.header" = "Profiles existants";
"imported_hosts.title" = "Hôtes importés";
"service.welcome.message" = "Bienvenue à Passepartout!\n\nUtilisez l'organiseur pour ajouter un nouveau profile.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Connection";
"service.sections.configuration.header" = "Configuration";
"service.cells.use_profile.caption" = "Utiliser ce profile";
"service.cells.vpn_service.caption" = "Activer";
"service.cells.reconnect.caption" = "Reconnecter";
"service.cells.provider.refresh.caption" = "Rafraîchir l'infrastructure";
"service.cells.host.parameters.caption" = "Paramètres";
"service.cells.trusted_add_wifi.caption" = "Ajouter le présent Wi-Fi";
"account.sections.credentials.header" = "Indetifiants";
"endpoint.sections.location_addresses.header" = "Adresses";
"endpoint.sections.location_protocols.header" = "Protocols";
"provider.preset.cells.tech_details.caption" = "Détails techniques";
"network_settings.cells.add_dns_server.caption" = "Ajouter une adresse";
"network_settings.cells.proxy_bypass.caption" = "Outrepasser le domaine";
"network_settings.cells.add_proxy_bypass.caption" = "Ajouter outrepasser le domaine";
"shortcuts.add.title" = "Ajouter un raccourcis";
"shortcuts.edit.title" = "Gérer les raccourcis";
"shortcuts.edit.cells.add_shortcut.caption" = "Ajouter un raccourcis";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "In uso";
"organizer.cells.add_provider.caption" = "Aggiungi provider";
"organizer.cells.add_host.caption" = "Aggiungi host";
"wizards.host.cells.title_input.caption" = "Titolo";
"wizards.host.sections.existing.header" = "Profili esistenti";
"imported_hosts.title" = "Host importati";
"service.welcome.message" = "Benvenuto in Passepartout!\n\nUsa il menu per aggiungere un nuovo profilo.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Connessione";
"service.sections.configuration.header" = "Configurazione";
"service.cells.use_profile.caption" = "Usa questo profilo";
"service.cells.vpn_service.caption" = "Abilitato";
"service.cells.reconnect.caption" = "Riconnetti";
"service.cells.provider.refresh.caption" = "Aggiorna infrastruttura";
"service.cells.host.parameters.caption" = "Parametri";
"service.cells.trusted_add_wifi.caption" = "Aggiungi Wi-Fi corrente";
"account.sections.credentials.header" = "Credenziali";
"endpoint.sections.location_addresses.header" = "Indirizzi";
"endpoint.sections.location_protocols.header" = "Protocolli";
"provider.preset.cells.tech_details.caption" = "Dettagli tecnici";
"network_settings.cells.add_dns_server.caption" = "Aggiungi indirizzo";
"network_settings.cells.proxy_bypass.caption" = "Dominio ignorato";
"network_settings.cells.add_proxy_bypass.caption" = "Aggiungi dominio ignorato";
"shortcuts.add.title" = "Aggiungi comando rapido";
"shortcuts.edit.title" = "Gestisci comandi rapidi";
"shortcuts.edit.cells.add_shortcut.caption" = "Aggiungi comando rapido";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "In gebruik";
"organizer.cells.add_provider.caption" = "Voeg nieuwe aanbieder toe";
"organizer.cells.add_host.caption" = "Voeg nieuwe host toe";
"wizards.host.cells.title_input.caption" = "Titel";
"wizards.host.sections.existing.header" = "Bestaande profielen";
"imported_hosts.title" = "Geïmporteerde hosts";
"service.welcome.message" = "Welkom bij Passepartout!\n\nGebruik de organizer om een nieuw profiel toe te voegen.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Verbinding";
"service.sections.configuration.header" = "Configuratie";
"service.cells.use_profile.caption" = "Gebruik dit profiel";
"service.cells.vpn_service.caption" = "Ingeschakeld";
"service.cells.reconnect.caption" = "Opnieuw verbinden";
"service.cells.provider.refresh.caption" = "Vernieuw de infrastructuur";
"service.cells.host.parameters.caption" = "Parameters";
"service.cells.trusted_add_wifi.caption" = "Voeg huidige WiFi toe";
"account.sections.credentials.header" = "Inloggegevens";
"endpoint.sections.location_addresses.header" = "Adressen";
"endpoint.sections.location_protocols.header" = "Protocollen";
"provider.preset.cells.tech_details.caption" = "Technische details";
"network_settings.cells.add_dns_server.caption" = "Voeg adress toe";
"network_settings.cells.proxy_bypass.caption" = "Omzeil domein";
"network_settings.cells.add_proxy_bypass.caption" = "Voeg omzeil optie voor domein toe";
"shortcuts.add.title" = "Voeg snelkoppeling toe";
"shortcuts.edit.title" = "Beheer snelkoppelingen";
"shortcuts.edit.cells.add_shortcut.caption" = "Voeg snelkoppeling toe";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "Ativo";
"organizer.cells.add_provider.caption" = "Adicionar novo perfil";
"organizer.cells.add_host.caption" = "Adicionar novo host";
"wizards.host.cells.title_input.caption" = "Título";
"wizards.host.sections.existing.header" = "Perfis existentes";
"imported_hosts.title" = "Hosts importados";
"service.welcome.message" = "Bem-vindo ao Passepartout!\n\nUse o organizador para adicionar um novo perfil.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Conexão";
"service.sections.configuration.header" = "Configuração";
"service.cells.use_profile.caption" = "Usar esse perfil";
"service.cells.vpn_service.caption" = "Ativado";
"service.cells.reconnect.caption" = "Reconectar";
"service.cells.provider.refresh.caption" = "Atualizar infraestrutura";
"service.cells.host.parameters.caption" = "Parâmetros";
"service.cells.trusted_add_wifi.caption" = "Adicionar Wi-Fi atual";
"account.sections.credentials.header" = "Credenciais";
"endpoint.sections.location_addresses.header" = "Endereços";
"endpoint.sections.location_protocols.header" = "Protocolos";
"provider.preset.cells.tech_details.caption" = "Detalhes técnicos";
"network_settings.cells.add_dns_server.caption" = "Adicionar endereço";
"network_settings.cells.proxy_bypass.caption" = "Domínio ignorado";
"network_settings.cells.add_proxy_bypass.caption" = "Adicionar domínio ignorado";
"shortcuts.add.title" = "Adicionar atalho";
"shortcuts.edit.title" = "Configuração de atalhos";
"shortcuts.edit.cells.add_shortcut.caption" = "Adicionar atalho";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 4/23/19.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "Используется";
"organizer.cells.add_provider.caption" = "Добавить нового провайдера";
"organizer.cells.add_host.caption" = "Добавить новый хост";
"wizards.host.cells.title_input.caption" = "Название";
"wizards.host.sections.existing.header" = "Существующие профили";
"imported_hosts.title" = "Импортированные хост профили";
"service.welcome.message" = "Добро пожаловать в Passepartout!\n\nИспользуйте организатор для добавления нового профиля.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Соединение";
"service.sections.configuration.header" = "Конфигурация";
"service.cells.use_profile.caption" = "Использовать это профиль.";
"service.cells.vpn_service.caption" = "Включен";
"service.cells.reconnect.caption" = "Переподключиться";
"service.cells.provider.refresh.caption" = "Обновить инфраструктуру";
"service.cells.host.parameters.caption" = "Параметры";
"service.cells.trusted_add_wifi.caption" = "Добавить текущий Wi-Fi";
"account.sections.credentials.header" = "Данные для входа";
"endpoint.sections.location_addresses.header" = "Адреса";
"endpoint.sections.location_protocols.header" = "Протоколы";
"provider.preset.cells.tech_details.caption" = "Техническая информация";
"network_settings.cells.add_dns_server.caption" = "Добавить адрес";
"network_settings.cells.proxy_bypass.caption" = "Обход домена";
"network_settings.cells.add_proxy_bypass.caption" = "Добавить обходной домен";
"shortcuts.add.title" = "Создать команду";
"shortcuts.edit.title" = "Управлять командами";
"shortcuts.edit.cells.add_shortcut.caption" = "Создать команду";

View File

@ -0,0 +1,61 @@
//
// App.strings
// Passepartout-iOS
//
// Created by Davide De Rosa on 6/13/18.
// Copyright (c) 2019 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
"organizer.cells.profile.value.current" = "Under användning";
"organizer.cells.add_provider.caption" = "Lägg till ny leverantör";
"organizer.cells.add_host.caption" = "Lägg till ny värd";
"wizards.host.cells.title_input.caption" = "Namn";
"wizards.host.sections.existing.header" = "Befintliga profiler";
"imported_hosts.title" = "Importerade värdar";
"service.welcome.message" = "Välkommen till Passepartout! \n\nAnvänd arrangören för att lägga till en ny profil.";
"service.sections.vpn.header" = "VPN";
"service.sections.status.header" = "Koppling";
"service.sections.configuration.header" = "Konfiguration";
"service.cells.use_profile.caption" = "Använd den här profilen";
"service.cells.vpn_service.caption" = "Aktiverad";
"service.cells.reconnect.caption" = "Återanslut";
"service.cells.provider.refresh.caption" = "Uppdatera infrastruktur";
"service.cells.host.parameters.caption" = "Parametrar";
"service.cells.trusted_add_wifi.caption" = "Lägg till nuvarande Wi-Fi";
"account.sections.credentials.header" = "Referenser";
"endpoint.sections.location_addresses.header" = "Adresser";
"endpoint.sections.location_protocols.header" = "Protokoll";
"provider.preset.cells.tech_details.caption" = "Tekniska detaljer";
"network_settings.cells.add_dns_server.caption" = "Lägg till adress";
"network_settings.cells.proxy_bypass.caption" = "Bypass-domän";
"network_settings.cells.add_proxy_bypass.caption" = "Add bypass domain";
"shortcuts.add.title" = "Lägg till genväg";
"shortcuts.edit.title" = "Hantera genvägar";
"shortcuts.edit.cells.add_shortcut.caption" = "Lägg till genväg";

View File

@ -38,8 +38,8 @@ class AboutViewController: UITableViewController, TableModelHost {
model.add(.share) model.add(.share)
model.setHeader("", for: .info) model.setHeader("", for: .info)
model.setHeader("GitHub", for: .github) model.setHeader("GitHub", for: .github)
model.setHeader(L10n.About.Sections.Web.header, for: .web) model.setHeader(L10n.Core.About.Sections.Web.header, for: .web)
model.setHeader(L10n.About.Sections.Share.header, for: .share) model.setHeader(L10n.Core.About.Sections.Share.header, for: .share)
model.set([.version, .credits], in: .info) model.set([.version, .credits], in: .info)
model.set([.readme, .changelog], in: .github) model.set([.readme, .changelog], in: .github)
model.set([.website, .faq, .disclaimer, .privacyPolicy], in: .web) model.set([.website, .faq, .disclaimer, .privacyPolicy], in: .web)
@ -61,7 +61,7 @@ class AboutViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.About.title title = L10n.Core.About.title
} }
// MARK: Actions // MARK: Actions
@ -79,7 +79,7 @@ class AboutViewController: UITableViewController, TableModelHost {
} }
private func inviteFriend(sender: UITableViewCell?) { private func inviteFriend(sender: UITableViewCell?) {
let message = "\(L10n.Share.message) \(AppConstants.URLs.website)" let message = "\(L10n.Core.Share.message) \(AppConstants.URLs.website)"
let vc = UIActivityViewController(activityItems: [message], applicationActivities: nil) let vc = UIActivityViewController(activityItems: [message], applicationActivities: nil)
vc.popoverPresentationController?.sourceView = sender vc.popoverPresentationController?.sourceView = sender
present(vc, animated: true, completion: nil) present(vc, animated: true, completion: nil)
@ -153,11 +153,11 @@ extension AboutViewController {
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
switch model.row(at: indexPath) { switch model.row(at: indexPath) {
case .version: case .version:
cell.leftText = L10n.Version.title cell.leftText = L10n.Core.Version.title
cell.rightText = Utils.versionString() cell.rightText = Utils.versionString()
case .credits: case .credits:
cell.leftText = L10n.About.Cells.Credits.caption cell.leftText = L10n.Core.About.Cells.Credits.caption
case .readme: case .readme:
cell.leftText = "README" cell.leftText = "README"
@ -166,22 +166,22 @@ extension AboutViewController {
cell.leftText = "CHANGELOG" cell.leftText = "CHANGELOG"
case .website: case .website:
cell.leftText = L10n.About.Cells.Website.caption cell.leftText = L10n.Core.About.Cells.Website.caption
case .faq: case .faq:
cell.leftText = L10n.About.Cells.Faq.caption cell.leftText = L10n.Core.About.Cells.Faq.caption
case .disclaimer: case .disclaimer:
cell.leftText = L10n.About.Cells.Disclaimer.caption cell.leftText = L10n.Core.About.Cells.Disclaimer.caption
case .privacyPolicy: case .privacyPolicy:
cell.leftText = L10n.About.Cells.PrivacyPolicy.caption cell.leftText = L10n.Core.About.Cells.PrivacyPolicy.caption
case .shareTwitter: case .shareTwitter:
cell.leftText = L10n.About.Cells.ShareTwitter.caption cell.leftText = L10n.Core.About.Cells.ShareTwitter.caption
case .shareGeneric: case .shareGeneric:
cell.leftText = L10n.About.Cells.ShareGeneric.caption cell.leftText = L10n.Core.About.Cells.ShareGeneric.caption
} }
return cell return cell
} }
@ -213,7 +213,7 @@ extension AboutViewController {
visit(AppConstants.URLs.privacyPolicy) visit(AppConstants.URLs.privacyPolicy)
case .shareTwitter: case .shareTwitter:
visit(AppConstants.URLs.twitterIntent) visit(AppConstants.URLs.twitterIntent(withMessage: L10n.Core.Share.message))
case .shareGeneric: case .shareGeneric:
inviteFriend(sender: tableView.cellForRow(at: indexPath)) inviteFriend(sender: tableView.cellForRow(at: indexPath))

View File

@ -44,9 +44,9 @@ class CreditsViewController: UITableViewController, TableModelHost {
model.add(.notices) model.add(.notices)
model.add(.translations) model.add(.translations)
model.setHeader(L10n.Credits.Sections.Licenses.header, for: .licenses) model.setHeader(L10n.Core.Credits.Sections.Licenses.header, for: .licenses)
model.setHeader(L10n.Credits.Sections.Notices.header, for: .notices) model.setHeader(L10n.Core.Credits.Sections.Notices.header, for: .notices)
model.setHeader(L10n.Credits.Sections.Translations.header, for: .translations) model.setHeader(L10n.Core.Credits.Sections.Translations.header, for: .translations)
model.set(.license, count: licenses.count, in: .licenses) model.set(.license, count: licenses.count, in: .licenses)
model.set(.notice, count: notices.count, in: .notices) model.set(.notice, count: notices.count, in: .notices)
@ -58,7 +58,7 @@ class CreditsViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Credits.title title = L10n.Core.Credits.title
reloadModel() reloadModel()
} }

View File

@ -69,7 +69,7 @@ class LabelViewController: UIViewController {
content = try String(contentsOf: license.url) content = try String(contentsOf: license.url)
couldFetch = true couldFetch = true
} catch { } catch {
content = L10n.Label.License.error content = L10n.Core.Label.License.error
couldFetch = false couldFetch = false
} }
DispatchQueue.main.async { DispatchQueue.main.async {

View File

@ -44,10 +44,10 @@ class VersionViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Version.title title = L10n.Core.Version.title
labelTitle?.text = GroupConstants.App.name labelTitle?.text = GroupConstants.App.name
labelVersion?.text = Utils.versionString() labelVersion?.text = Utils.versionString()
labelIntro?.text = L10n.Version.Labels.intro labelIntro?.text = L10n.Core.Version.Labels.intro
scrollView?.applyPrimaryBackground(Theme.current) scrollView?.applyPrimaryBackground(Theme.current)
for label in [labelTitle, labelVersion, labelIntro] { for label in [labelTitle, labelVersion, labelIntro] {

View File

@ -60,7 +60,7 @@ class AccountViewController: UIViewController, TableModelHost {
guard let name = infrastructureName else { guard let name = infrastructureName else {
return nil return nil
} }
let V = L10n.Account.Sections.Guidance.Footer.Infrastructure.self let V = L10n.Core.Account.Sections.Guidance.Footer.Infrastructure.self
switch name { switch name {
case .mullvad: case .mullvad:
return V.mullvad(name.rawValue) return V.mullvad(name.rawValue)
@ -109,7 +109,7 @@ class AccountViewController: UIViewController, TableModelHost {
model.clear() model.clear()
model.add(.credentials) model.add(.credentials)
model.setHeader(L10n.Account.Sections.Credentials.header, for: .credentials) model.setHeader(L10n.App.Account.Sections.Credentials.header, for: .credentials)
model.set([.username, .password], in: .credentials) model.set([.username, .password], in: .credentials)
if let name = infrastructureName { if let name = infrastructureName {
@ -125,7 +125,7 @@ class AccountViewController: UIViewController, TableModelHost {
} }
if let _ = referralURL { if let _ = referralURL {
model.add(.registration) model.add(.registration)
model.setFooter(L10n.Account.Sections.Registration.footer(name.rawValue), for: .registration) model.setFooter(L10n.Core.Account.Sections.Registration.footer(name.rawValue), for: .registration)
model.set([.signUp], in: .registration) model.set([.signUp], in: .registration)
} }
} }
@ -142,7 +142,7 @@ class AccountViewController: UIViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Service.Cells.Account.caption title = L10n.Core.Account.title
cellUsername?.field.text = currentCredentials?.username cellUsername?.field.text = currentCredentials?.username
cellPassword?.field.text = currentCredentials?.password cellPassword?.field.text = currentCredentials?.password
@ -234,8 +234,8 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate, Fie
case .username: case .username:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cellUsername = cell cellUsername = cell
cell.caption = L10n.Account.Cells.Username.caption cell.caption = L10n.Core.Account.Cells.Username.caption
cell.field.placeholder = usernamePlaceholder ?? L10n.Account.Cells.Username.placeholder cell.field.placeholder = usernamePlaceholder ?? L10n.Core.Account.Cells.Username.placeholder
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.isSecureTextEntry = false cell.field.isSecureTextEntry = false
cell.field.text = currentCredentials?.username cell.field.text = currentCredentials?.username
@ -249,8 +249,8 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate, Fie
case .password: case .password:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cellPassword = cell cellPassword = cell
cell.caption = L10n.Account.Cells.Password.caption cell.caption = L10n.Core.Account.Cells.Password.caption
cell.field.placeholder = L10n.Account.Cells.Password.placeholder cell.field.placeholder = L10n.Core.Account.Cells.Password.placeholder
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.isSecureTextEntry = true cell.field.isSecureTextEntry = true
cell.field.text = currentCredentials?.password cell.field.text = currentCredentials?.password
@ -262,7 +262,7 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate, Fie
case .openGuide: case .openGuide:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Account.Cells.OpenGuide.caption cell.leftText = L10n.Core.Account.Cells.OpenGuide.caption
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
return cell return cell
@ -271,7 +271,7 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate, Fie
fatalError("Sign-up shown when not a provider profile") fatalError("Sign-up shown when not a provider profile")
} }
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Account.Cells.Signup.caption(name.rawValue) cell.leftText = L10n.Core.Account.Cells.Signup.caption(name.rawValue)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
return cell return cell
} }

View File

@ -59,19 +59,17 @@ class ConfigurationViewController: UIViewController, TableModelHost {
model.add(.reset) model.add(.reset)
} }
model.add(.tls) model.add(.tls)
// model.add(.network)
model.add(.other) model.add(.other)
// headers // headers
model.setHeader(L10n.Configuration.Sections.Communication.header, for: .communication) model.setHeader(L10n.Core.Configuration.Sections.Communication.header, for: .communication)
model.setHeader(L10n.Configuration.Sections.Tls.header, for: .tls) model.setHeader(L10n.Core.Configuration.Sections.Tls.header, for: .tls)
model.setHeader(L10n.Configuration.Sections.Compression.header, for: .compression) model.setHeader(L10n.Core.Configuration.Sections.Compression.header, for: .compression)
model.setHeader(L10n.Configuration.Sections.Network.header, for: .network) model.setHeader(L10n.Core.Configuration.Sections.Other.header, for: .other)
model.setHeader(L10n.Configuration.Sections.Other.header, for: .other)
// footers // footers
if isEditable { if isEditable {
model.setFooter(L10n.Configuration.Sections.Reset.footer, for: .reset) model.setFooter(L10n.Core.Configuration.Sections.Reset.footer, for: .reset)
} }
// rows // rows
@ -81,17 +79,6 @@ class ConfigurationViewController: UIViewController, TableModelHost {
} }
model.set([.client, .tlsWrapping, .eku], in: .tls) model.set([.client, .tlsWrapping, .eku], in: .tls)
model.set([.compressionFraming, .compressionAlgorithm], in: .compression) model.set([.compressionFraming, .compressionAlgorithm], in: .compression)
var networkRows: [RowType]
if let dnsServers = configuration.dnsServers {
networkRows = [RowType](repeating: .dnsServer, count: dnsServers.count)
} else {
networkRows = []
}
networkRows.insert(.defaultGateway, at: 0)
networkRows.append(.dnsDomain)
networkRows.append(.httpProxy)
networkRows.append(.httpsProxy)
model.set(networkRows, in: .network)
model.set([.keepAlive, .renegSeconds, .randomEndpoint], in: .other) model.set([.keepAlive, .renegSeconds, .randomEndpoint], in: .other)
return model return model
@ -198,16 +185,6 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
case compressionAlgorithm case compressionAlgorithm
case defaultGateway
case dnsServer
case dnsDomain
case httpProxy
case httpsProxy
case keepAlive case keepAlive
case renegSeconds case renegSeconds
@ -237,7 +214,7 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let row = model.row(at: indexPath) let row = model.row(at: indexPath)
let V = L10n.Configuration.Cells.self let V = L10n.Core.Configuration.Cells.self
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
if !isEditable { if !isEditable {
@ -262,7 +239,7 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
if let compressionAlgorithm = configuration.compressionAlgorithm { if let compressionAlgorithm = configuration.compressionAlgorithm {
cell.rightText = compressionAlgorithm.cellDescription cell.rightText = compressionAlgorithm.cellDescription
} else { } else {
cell.rightText = L10n.Global.Cells.disabled cell.rightText = L10n.Core.Global.Values.disabled
} }
cell.isTappable = (configuration.compressionFraming != .disabled) cell.isTappable = (configuration.compressionFraming != .disabled)
@ -287,51 +264,14 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
cell.rightText = V.TlsWrapping.Value.crypt cell.rightText = V.TlsWrapping.Value.crypt
} }
} else { } else {
cell.rightText = L10n.Global.Cells.disabled cell.rightText = L10n.Core.Global.Values.disabled
} }
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
case .eku: case .eku:
cell.leftText = V.Eku.caption cell.leftText = V.Eku.caption
cell.rightText = (configuration.checksEKU ?? false) ? L10n.Global.Cells.enabled : L10n.Global.Cells.disabled cell.rightText = (configuration.checksEKU ?? false) ? L10n.Core.Global.Values.enabled : L10n.Core.Global.Values.disabled
cell.accessoryType = .none
cell.isTappable = false
case .defaultGateway:
cell.leftText = V.DefaultGateway.caption
if let policies = configuration.routingPolicies {
cell.rightText = policies.map { $0.rawValue }.joined(separator: " / ")
} else {
cell.rightText = L10n.Global.Cells.none
}
cell.accessoryType = .none
cell.isTappable = false
case .dnsServer:
guard let dnsServers = configuration.dnsServers else {
fatalError("Showing DNS section without any custom server")
}
cell.leftText = V.DnsServer.caption
cell.rightText = dnsServers[indexPath.row - 1]
cell.accessoryType = .none
cell.isTappable = false
case .dnsDomain:
cell.leftText = V.DnsDomain.caption
cell.rightText = configuration.searchDomain ?? L10n.Global.Cells.none
cell.accessoryType = .none
cell.isTappable = false
case .httpProxy:
cell.leftText = V.ProxyHttp.caption
cell.rightText = configuration.httpProxy?.description ?? L10n.Global.Cells.none
cell.accessoryType = .none
cell.isTappable = false
case .httpsProxy:
cell.leftText = V.ProxyHttps.caption
cell.rightText = configuration.httpsProxy?.description ?? L10n.Global.Cells.none
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
@ -340,7 +280,7 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
if let keepAlive = configuration.keepAliveInterval, keepAlive > 0 { if let keepAlive = configuration.keepAliveInterval, keepAlive > 0 {
cell.rightText = V.KeepAlive.Value.seconds(Int(keepAlive)) cell.rightText = V.KeepAlive.Value.seconds(Int(keepAlive))
} else { } else {
cell.rightText = L10n.Global.Cells.disabled cell.rightText = L10n.Core.Global.Values.disabled
} }
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
@ -350,14 +290,14 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
if let reneg = configuration.renegotiatesAfter, reneg > 0 { if let reneg = configuration.renegotiatesAfter, reneg > 0 {
cell.rightText = V.RenegotiationSeconds.Value.after(TimeInterval(reneg).localized) cell.rightText = V.RenegotiationSeconds.Value.after(TimeInterval(reneg).localized)
} else { } else {
cell.rightText = L10n.Global.Cells.disabled cell.rightText = L10n.Core.Global.Values.disabled
} }
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
case .randomEndpoint: case .randomEndpoint:
cell.leftText = V.RandomEndpoint.caption cell.leftText = V.RandomEndpoint.caption
cell.rightText = (configuration.randomizeEndpoint ?? false) ? L10n.Global.Cells.enabled : L10n.Global.Cells.disabled cell.rightText = (configuration.randomizeEndpoint ?? false) ? L10n.Core.Global.Values.enabled : L10n.Core.Global.Values.disabled
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
} }
@ -451,10 +391,10 @@ extension ConfigurationViewController: UITableViewDataSource, UITableViewDelegat
private extension OpenVPN.CompressionFraming { private extension OpenVPN.CompressionFraming {
var cellDescription: String { var cellDescription: String {
let V = L10n.Configuration.Cells.self let V = L10n.Core.Configuration.Cells.self
switch self { switch self {
case .disabled: case .disabled:
return L10n.Global.Cells.disabled return L10n.Core.Global.Values.disabled
case .compLZO: case .compLZO:
return V.CompressionFraming.Value.lzo return V.CompressionFraming.Value.lzo
@ -467,10 +407,10 @@ private extension OpenVPN.CompressionFraming {
private extension OpenVPN.CompressionAlgorithm { private extension OpenVPN.CompressionAlgorithm {
var cellDescription: String { var cellDescription: String {
let V = L10n.Configuration.Cells.self let V = L10n.Core.Configuration.Cells.self
switch self { switch self {
case .disabled: case .disabled:
return L10n.Global.Cells.disabled return L10n.Core.Global.Values.disabled
case .LZO: case .LZO:
return V.CompressionAlgorithm.Value.lzo return V.CompressionAlgorithm.Value.lzo

View File

@ -49,7 +49,7 @@ class DebugLogViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Service.Cells.DebugLog.caption title = L10n.Core.Service.Cells.DebugLog.caption
textLog?.contentInsetAdjustmentBehavior = .never textLog?.contentInsetAdjustmentBehavior = .never
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(toggleBars)) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(toggleBars))
@ -84,8 +84,8 @@ class DebugLogViewController: UIViewController {
@IBAction private func share(_ sender: Any?) { @IBAction private func share(_ sender: Any?) {
guard let raw = textLog?.text, !raw.isEmpty else { guard let raw = textLog?.text, !raw.isEmpty else {
let alert = Macros.alert(title, L10n.DebugLog.Alerts.EmptyLog.message) let alert = Macros.alert(title, L10n.Core.DebugLog.Alerts.EmptyLog.message)
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }

View File

@ -66,8 +66,8 @@ class EndpointViewController: UIViewController, TableModelHost {
model.add(.locationAddresses) model.add(.locationAddresses)
model.add(.locationProtocols) model.add(.locationProtocols)
model.setHeader(L10n.Endpoint.Sections.LocationAddresses.header, for: .locationAddresses) model.setHeader(L10n.App.Endpoint.Sections.LocationAddresses.header, for: .locationAddresses)
model.setHeader(L10n.Endpoint.Sections.LocationProtocols.header, for: .locationProtocols) model.setHeader(L10n.App.Endpoint.Sections.LocationProtocols.header, for: .locationProtocols)
if dataSource.canCustomizeEndpoint { if dataSource.canCustomizeEndpoint {
var addressRows: [RowType] = Array(repeating: .availableAddress, count: dataSource.addresses.count) var addressRows: [RowType] = Array(repeating: .availableAddress, count: dataSource.addresses.count)
@ -99,7 +99,7 @@ class EndpointViewController: UIViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Service.Cells.Endpoint.caption title = L10n.Core.Endpoint.title
guard let _ = dataSource else { guard let _ = dataSource else {
fatalError("Data source not set") fatalError("Data source not set")
} }
@ -208,7 +208,7 @@ extension EndpointViewController: UITableViewDataSource, UITableViewDelegate {
switch row { switch row {
case .anyAddress: case .anyAddress:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Endpoint.Cells.AnyAddress.caption cell.leftText = L10n.Core.Endpoint.Cells.AnyAddress.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = true cell.isTappable = true
if let _ = currentAddress { if let _ = currentAddress {
@ -235,7 +235,7 @@ extension EndpointViewController: UITableViewDataSource, UITableViewDelegate {
case .anyProtocol: case .anyProtocol:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Endpoint.Cells.AnyProtocol.caption cell.leftText = L10n.Core.Endpoint.Cells.AnyProtocol.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = true cell.isTappable = true
if let _ = currentProtocol { if let _ = currentProtocol {

View File

@ -101,12 +101,12 @@ class NetworkSettingsViewController: UITableViewController {
// headers // headers
model.setHeader("", for: .choices) model.setHeader("", for: .choices)
model.setHeader(L10n.Configuration.Cells.DefaultGateway.caption, for: .manualGateway) model.setHeader(L10n.Core.NetworkSettings.Gateway.title, for: .manualGateway)
model.setHeader(L10n.Configuration.Cells.DnsServer.caption, for: .manualDNS) model.setHeader(L10n.Core.NetworkSettings.Dns.title, for: .manualDNS)
model.setHeader(L10n.Configuration.Cells.ProxyHttp.caption, for: .manualProxy) model.setHeader(L10n.Core.NetworkSettings.Proxy.title, for: .manualProxy)
// footers // footers
// model.setFooter(L10n.Configuration.Sections.Reset.footer, for: .reset) // model.setFooter(L10n.Core.Configuration.Sections.Reset.footer, for: .reset)
// rows // rows
model.set([.gateway, .dns, .proxy], in: .choices) model.set([.gateway, .dns, .proxy], in: .choices)
@ -342,9 +342,9 @@ extension NetworkSettingsViewController {
case .dnsDomain: case .dnsDomain:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.Configuration.Cells.DnsDomain.caption cell.caption = L10n.Core.NetworkSettings.Dns.Cells.Domain.caption
cell.field.tag = FieldTag.dnsDomain.rawValue cell.field.tag = FieldTag.dnsDomain.rawValue
cell.field.placeholder = L10n.Global.Cells.none cell.field.placeholder = L10n.Core.Global.Values.none
cell.field.text = networkSettings.dnsDomainName cell.field.text = networkSettings.dnsDomainName
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.keyboardType = .asciiCapable cell.field.keyboardType = .asciiCapable
@ -357,9 +357,9 @@ extension NetworkSettingsViewController {
let i = indexPath.row - Offsets.dnsAddress let i = indexPath.row - Offsets.dnsAddress
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.NetworkSettings.Cells.Address.caption cell.caption = L10n.Core.Global.Captions.address
cell.field.tag = FieldTag.dnsAddress.rawValue + i cell.field.tag = FieldTag.dnsAddress.rawValue + i
cell.field.placeholder = L10n.Global.Cells.none cell.field.placeholder = L10n.Core.Global.Values.none
cell.field.text = networkSettings.dnsServers?[i] cell.field.text = networkSettings.dnsServers?[i]
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.keyboardType = .decimalPad cell.field.keyboardType = .decimalPad
@ -371,14 +371,14 @@ extension NetworkSettingsViewController {
case .dnsAddAddress: case .dnsAddAddress:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.NetworkSettings.Cells.AddDnsServer.caption cell.leftText = L10n.App.NetworkSettings.Cells.AddDnsServer.caption
return cell return cell
case .proxyAddress: case .proxyAddress:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.NetworkSettings.Cells.Address.caption cell.caption = L10n.Core.Global.Captions.address
cell.field.tag = FieldTag.proxyAddress.rawValue cell.field.tag = FieldTag.proxyAddress.rawValue
cell.field.placeholder = L10n.Global.Cells.none cell.field.placeholder = L10n.Core.Global.Values.none
cell.field.text = networkSettings.proxyAddress cell.field.text = networkSettings.proxyAddress
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.keyboardType = .decimalPad cell.field.keyboardType = .decimalPad
@ -389,9 +389,9 @@ extension NetworkSettingsViewController {
case .proxyPort: case .proxyPort:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.NetworkSettings.Cells.Port.caption cell.caption = L10n.Core.Global.Captions.port
cell.field.tag = FieldTag.proxyPort.rawValue cell.field.tag = FieldTag.proxyPort.rawValue
cell.field.placeholder = L10n.Global.Cells.none cell.field.placeholder = L10n.Core.Global.Values.none
cell.field.text = networkSettings.proxyPort?.description cell.field.text = networkSettings.proxyPort?.description
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.keyboardType = .numberPad cell.field.keyboardType = .numberPad
@ -404,9 +404,9 @@ extension NetworkSettingsViewController {
let i = indexPath.row - Offsets.proxyBypass let i = indexPath.row - Offsets.proxyBypass
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.NetworkSettings.Cells.ProxyBypass.caption cell.caption = L10n.App.NetworkSettings.Cells.ProxyBypass.caption
cell.field.tag = FieldTag.proxyBypass.rawValue + i cell.field.tag = FieldTag.proxyBypass.rawValue + i
cell.field.placeholder = L10n.Global.Cells.none cell.field.placeholder = L10n.Core.Global.Values.none
cell.field.text = networkSettings.proxyBypassDomains?[i] cell.field.text = networkSettings.proxyBypassDomains?[i]
cell.field.clearButtonMode = .always cell.field.clearButtonMode = .always
cell.field.keyboardType = .asciiCapable cell.field.keyboardType = .asciiCapable
@ -418,7 +418,7 @@ extension NetworkSettingsViewController {
case .proxyAddBypass: case .proxyAddBypass:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.NetworkSettings.Cells.AddProxyBypass.caption cell.leftText = L10n.App.NetworkSettings.Cells.AddProxyBypass.caption
return cell return cell
} }
} }
@ -573,13 +573,13 @@ extension NetworkChoice: CustomStringConvertible {
public var description: String { public var description: String {
switch self { switch self {
case .client: case .client:
return L10n.NetworkSettings.Cells.Choice.client return L10n.Core.NetworkChoice.client
case .server: case .server:
return L10n.NetworkSettings.Cells.Choice.server return L10n.Core.NetworkChoice.server
case .manual: case .manual:
return L10n.Global.Cells.manual return L10n.Core.Global.Values.manual
} }
} }
} }

View File

@ -53,8 +53,8 @@ class DonationViewController: UITableViewController, TableModelHost {
model.clear() model.clear()
model.add(.oneTime) model.add(.oneTime)
model.setHeader(L10n.Donation.Sections.OneTime.header, for: .oneTime) model.setHeader(L10n.Core.Donation.Sections.OneTime.header, for: .oneTime)
model.setFooter(L10n.Donation.Sections.OneTime.footer, for: .oneTime) model.setFooter(L10n.Core.Donation.Sections.OneTime.footer, for: .oneTime)
guard !isLoading else { guard !isLoading else {
model.set([.loading], in: .oneTime) model.set([.loading], in: .oneTime)
@ -81,7 +81,7 @@ class DonationViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Donation.title title = L10n.Core.Donation.title
reloadModel() reloadModel()
let inApp = InAppHelper.shared let inApp = InAppHelper.shared
@ -122,12 +122,12 @@ class DonationViewController: UITableViewController, TableModelHost {
switch model.row(at: indexPath) { switch model.row(at: indexPath) {
case .loading: case .loading:
let cell = Cells.activity.dequeue(from: tableView, for: indexPath) let cell = Cells.activity.dequeue(from: tableView, for: indexPath)
cell.textLabel?.text = L10n.Donation.Cells.Loading.caption cell.textLabel?.text = L10n.Core.Donation.Cells.Loading.caption
return cell return cell
case .purchasing: case .purchasing:
let cell = Cells.activity.dequeue(from: tableView, for: indexPath) let cell = Cells.activity.dequeue(from: tableView, for: indexPath)
cell.textLabel?.text = L10n.Donation.Cells.Purchasing.caption cell.textLabel?.text = L10n.Core.Donation.Cells.Purchasing.caption
return cell return cell
case .donation: case .donation:
@ -178,12 +178,12 @@ class DonationViewController: UITableViewController, TableModelHost {
return return
case .success: case .success:
alert = Macros.alert(L10n.Donation.Alerts.Purchase.Success.title, L10n.Donation.Alerts.Purchase.Success.message) alert = Macros.alert(L10n.Core.Donation.Alerts.Purchase.Success.title, L10n.Core.Donation.Alerts.Purchase.Success.message)
case .failure: case .failure:
alert = Macros.alert(title, L10n.Donation.Alerts.Purchase.Failure.message(error?.localizedDescription ?? "")) alert = Macros.alert(title, L10n.Core.Donation.Alerts.Purchase.Failure.message(error?.localizedDescription ?? ""))
} }
alert.addCancelAction(L10n.Global.ok) { alert.addCancelAction(L10n.Core.Global.ok) {
self.isPurchasing = false self.isPurchasing = false
self.reloadModel() self.reloadModel()
self.tableView.reloadData() self.tableView.reloadData()

View File

@ -38,7 +38,7 @@ class ImportedHostsViewController: UITableViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.ImportedHosts.title title = L10n.App.ImportedHosts.title
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@ -53,9 +53,9 @@ class ImportedHostsViewController: UITableViewController {
guard !pendingConfigurationURLs.isEmpty else { guard !pendingConfigurationURLs.isEmpty else {
let alert = Macros.alert( let alert = Macros.alert(
title, title,
L10n.Organizer.Alerts.AddHost.message L10n.Core.Organizer.Alerts.AddHost.message
) )
alert.addCancelAction(L10n.Global.ok) { alert.addCancelAction(L10n.Core.Global.ok) {
self.close() self.close()
} }
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)

View File

@ -55,18 +55,18 @@ class OrganizerViewController: UITableViewController, TableModelHost {
model.add(.feedback) model.add(.feedback)
model.add(.about) model.add(.about)
model.add(.destruction) model.add(.destruction)
model.setHeader(L10n.Service.Sections.Vpn.header, for: .vpn) model.setHeader(L10n.App.Service.Sections.Vpn.header, for: .vpn)
model.setHeader(L10n.Organizer.Sections.Providers.header, for: .providers) model.setHeader(L10n.Core.Organizer.Sections.Providers.header, for: .providers)
model.setHeader(L10n.Organizer.Sections.Hosts.header, for: .hosts) model.setHeader(L10n.Core.Organizer.Sections.Hosts.header, for: .hosts)
model.setFooter(L10n.Organizer.Sections.Providers.footer, for: .providers) model.setFooter(L10n.Core.Organizer.Sections.Providers.footer, for: .providers)
model.setFooter(L10n.Organizer.Sections.Hosts.footer, for: .hosts) model.setFooter(L10n.Core.Organizer.Sections.Hosts.footer, for: .hosts)
if #available(iOS 12, *) { if #available(iOS 12, *) {
model.setHeader(L10n.Organizer.Sections.Siri.header, for: .siri) model.setHeader(L10n.Core.Organizer.Sections.Siri.header, for: .siri)
model.setFooter(L10n.Organizer.Sections.Siri.footer, for: .siri) model.setFooter(L10n.Core.Organizer.Sections.Siri.footer, for: .siri)
model.set([.siriShortcuts], in: .siri) model.set([.siriShortcuts], in: .siri)
} }
model.setHeader(L10n.Organizer.Sections.Support.header, for: .support) model.setHeader(L10n.Core.Organizer.Sections.Support.header, for: .support)
model.setHeader(L10n.Organizer.Sections.Feedback.header, for: .feedback) model.setHeader(L10n.Core.Organizer.Sections.Feedback.header, for: .feedback)
model.set([.connectionStatus], in: .vpn) model.set([.connectionStatus], in: .vpn)
model.set([.donate, .patreon, .translate], in: .support) model.set([.donate, .patreon, .translate], in: .support)
model.set([.joinCommunity, .writeReview], in: .feedback) model.set([.joinCommunity, .writeReview], in: .feedback)
@ -125,15 +125,15 @@ class OrganizerViewController: UITableViewController, TableModelHost {
if !didShowSubreddit && !TransientStore.didHandleSubreddit { if !didShowSubreddit && !TransientStore.didHandleSubreddit {
didShowSubreddit = true didShowSubreddit = true
let alert = Macros.alert(L10n.Reddit.title, L10n.Reddit.message) let alert = Macros.alert(L10n.Core.Reddit.title, L10n.Core.Reddit.message)
alert.addDefaultAction(L10n.Reddit.Buttons.subscribe) { alert.addDefaultAction(L10n.Core.Reddit.Buttons.subscribe) {
TransientStore.didHandleSubreddit = true TransientStore.didHandleSubreddit = true
self.subscribeSubreddit() self.subscribeSubreddit()
} }
alert.addAction(L10n.Reddit.Buttons.never) { alert.addAction(L10n.Core.Reddit.Buttons.never) {
TransientStore.didHandleSubreddit = true TransientStore.didHandleSubreddit = true
} }
alert.addCancelAction(L10n.Reddit.Buttons.remind) alert.addCancelAction(L10n.Core.Reddit.Buttons.remind)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
} }
} }
@ -195,10 +195,10 @@ class OrganizerViewController: UITableViewController, TableModelHost {
guard !names.isEmpty else { guard !names.isEmpty else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Organizer.Sections.Providers.header, L10n.Core.Organizer.Sections.Providers.header,
L10n.Organizer.Alerts.ExhaustedProviders.message L10n.Core.Organizer.Alerts.ExhaustedProviders.message
) )
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
@ -218,10 +218,10 @@ class OrganizerViewController: UITableViewController, TableModelHost {
private func donateToDeveloper() { private func donateToDeveloper() {
guard SKPaymentQueue.canMakePayments() else { guard SKPaymentQueue.canMakePayments() else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Organizer.Cells.Donate.caption, L10n.Core.Organizer.Cells.Donate.caption,
L10n.Organizer.Alerts.CannotDonate.message L10n.Core.Organizer.Alerts.CannotDonate.message
) )
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
@ -234,8 +234,8 @@ class OrganizerViewController: UITableViewController, TableModelHost {
private func offerTranslation() { private func offerTranslation() {
guard MFMailComposeViewController.canSendMail() else { guard MFMailComposeViewController.canSendMail() else {
let alert = Macros.alert(L10n.IssueReporter.title, L10n.Global.emailNotConfigured) let alert = Macros.alert(L10n.Core.IssueReporter.title, L10n.Core.Global.emailNotConfigured)
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
@ -304,13 +304,13 @@ class OrganizerViewController: UITableViewController, TableModelHost {
private func confirmVpnProfileDeletion() { private func confirmVpnProfileDeletion() {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Organizer.Cells.Uninstall.caption, L10n.Core.Organizer.Cells.Uninstall.caption,
L10n.Organizer.Alerts.DeleteVpnProfile.message L10n.Core.Organizer.Alerts.DeleteVpnProfile.message
) )
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
VPN.shared.uninstall(completionHandler: nil) VPN.shared.uninstall(completionHandler: nil)
} }
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
} }
@ -330,7 +330,7 @@ class OrganizerViewController: UITableViewController, TableModelHost {
return return
} }
let alert = Macros.alert("Debug log", log) let alert = Macros.alert("Debug log", log)
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
} }
@ -419,7 +419,7 @@ extension OrganizerViewController {
case .connectionStatus: case .connectionStatus:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyVPN(Theme.current, with: VPN.shared.isEnabled ? VPN.shared.status : nil, error: nil) cell.applyVPN(Theme.current, with: VPN.shared.isEnabled ? VPN.shared.status : nil, error: nil)
cell.leftText = L10n.Service.Cells.ConnectionStatus.caption cell.leftText = L10n.Core.Service.Cells.ConnectionStatus.caption
return cell return cell
case .profile: case .profile:
@ -431,61 +431,61 @@ extension OrganizerViewController {
cell.imageView?.image = nil cell.imageView?.image = nil
} }
cell.leftText = rowProfile.id cell.leftText = rowProfile.id
cell.rightText = service.isActiveProfile(rowProfile) ? L10n.Organizer.Cells.Profile.Value.current : nil cell.rightText = service.isActiveProfile(rowProfile) ? L10n.App.Organizer.Cells.Profile.Value.current : nil
return cell return cell
case .addProvider: case .addProvider:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Organizer.Cells.AddProvider.caption cell.leftText = L10n.App.Organizer.Cells.AddProvider.caption
return cell return cell
case .addHost: case .addHost:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Organizer.Cells.AddHost.caption cell.leftText = L10n.App.Organizer.Cells.AddHost.caption
return cell return cell
case .siriShortcuts: case .siriShortcuts:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Organizer.Cells.SiriShortcuts.caption cell.leftText = L10n.Core.Organizer.Cells.SiriShortcuts.caption
return cell return cell
case .donate: case .donate:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.Donate.caption cell.leftText = L10n.Core.Organizer.Cells.Donate.caption
return cell return cell
case .patreon: case .patreon:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.Patreon.caption cell.leftText = L10n.Core.Organizer.Cells.Patreon.caption
return cell return cell
case .translate: case .translate:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.Translate.caption cell.leftText = L10n.Core.Organizer.Cells.Translate.caption
return cell return cell
case .joinCommunity: case .joinCommunity:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.JoinCommunity.caption cell.leftText = L10n.Core.Organizer.Cells.JoinCommunity.caption
return cell return cell
case .writeReview: case .writeReview:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.WriteReview.caption cell.leftText = L10n.Core.Organizer.Cells.WriteReview.caption
return cell return cell
case .openAbout: case .openAbout:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Organizer.Cells.About.caption(GroupConstants.App.name) cell.leftText = L10n.Core.Organizer.Cells.About.caption(GroupConstants.App.name)
cell.rightText = Utils.versionString() cell.rightText = Utils.versionString()
return cell return cell
case .uninstall: case .uninstall:
let cell = Cells.destructive.dequeue(from: tableView, for: indexPath) let cell = Cells.destructive.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.Organizer.Cells.Uninstall.caption cell.caption = L10n.Core.Organizer.Cells.Uninstall.caption
return cell return cell
case .testDisplayLog: case .testDisplayLog:

View File

@ -52,10 +52,10 @@ class WizardHostViewController: UITableViewController, TableModelHost {
lazy var model: TableModel<SectionType, RowType> = { lazy var model: TableModel<SectionType, RowType> = {
let model: TableModel<SectionType, RowType> = TableModel() let model: TableModel<SectionType, RowType> = TableModel()
model.add(.meta) model.add(.meta)
model.setFooter(L10n.Global.Host.TitleInput.message, for: .meta) model.setFooter(L10n.Core.Global.Host.TitleInput.message, for: .meta)
if !existingHosts.isEmpty { if !existingHosts.isEmpty {
model.add(.existing) model.add(.existing)
model.setHeader(L10n.Wizards.Host.Sections.Existing.header, for: .existing) model.setHeader(L10n.App.Wizards.Host.Sections.Existing.header, for: .existing)
} }
model.set([.titleInput], in: .meta) model.set([.titleInput], in: .meta)
model.set(.existingHost, count: existingHosts.count, in: .existing) model.set(.existingHost, count: existingHosts.count, in: .existing)
@ -70,8 +70,8 @@ class WizardHostViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Organizer.Sections.Hosts.header title = L10n.Core.Organizer.Sections.Hosts.header
itemNext.title = L10n.Global.next itemNext.title = L10n.Core.Global.next
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@ -110,11 +110,11 @@ class WizardHostViewController: UITableViewController, TableModelHost {
let service = TransientStore.shared.service let service = TransientStore.shared.service
guard !service.containsProfile(profile) else { guard !service.containsProfile(profile) else {
let replacedProfile = service.profile(withContext: profile.context, id: profile.id) let replacedProfile = service.profile(withContext: profile.context, id: profile.id)
let alert = Macros.alert(title, L10n.Wizards.Host.Alerts.Existing.message) let alert = Macros.alert(title, L10n.Core.Wizards.Host.Alerts.Existing.message)
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
self.next(withProfile: profile, replacedProfile: replacedProfile) self.next(withProfile: profile, replacedProfile: replacedProfile)
} }
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
@ -203,7 +203,7 @@ extension WizardHostViewController {
switch model.row(at: indexPath) { switch model.row(at: indexPath) {
case .titleInput: case .titleInput:
let cell = Cells.field.dequeue(from: tableView, for: indexPath) let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.Wizards.Host.Cells.TitleInput.caption cell.caption = L10n.App.Wizards.Host.Cells.TitleInput.caption
cell.captionWidth = 100.0 cell.captionWidth = 100.0
cell.allowedCharset = .filename cell.allowedCharset = .filename
cell.field.applyProfileId(Theme.current) cell.field.applyProfileId(Theme.current)

View File

@ -34,7 +34,7 @@ class WizardProviderViewController: UITableViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Organizer.Sections.Providers.header title = L10n.Core.Organizer.Sections.Providers.header
} }
private func next(withName name: Infrastructure.Name) { private func next(withName name: Infrastructure.Name) {

View File

@ -72,7 +72,7 @@ class ProviderPoolViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Service.Cells.Provider.Pool.caption title = L10n.Core.Service.Cells.Provider.Pool.caption
tableView.reloadData() tableView.reloadData()
if let ip = selectedIndexPath { if let ip = selectedIndexPath {
tableView.selectRowAsync(at: ip) tableView.selectRowAsync(at: ip)

View File

@ -54,7 +54,7 @@ class ProviderPresetViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Service.Cells.Provider.Preset.caption title = L10n.Core.Service.Cells.Provider.Preset.caption
tableView.reloadData() tableView.reloadData()
if let ip = selectedIndexPath { if let ip = selectedIndexPath {
tableView.scrollToRowAsync(at: ip) tableView.scrollToRowAsync(at: ip)
@ -94,7 +94,7 @@ extension ProviderPresetViewController: UITableViewDataSource, UITableViewDelega
} }
// func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { // func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
// return L10n.Provider.Preset.Sections.Main.footer // return L10n.Core.Provider.Preset.Sections.Main.footer
// } // }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
@ -113,7 +113,7 @@ extension ProviderPresetViewController: UITableViewDataSource, UITableViewDelega
case .techDetails: case .techDetails:
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Provider.Preset.Cells.TechDetails.caption cell.leftText = L10n.App.Provider.Preset.Cells.TechDetails.caption
cell.accessoryType = .none cell.accessoryType = .none
} }
return cell return cell

View File

@ -25,7 +25,6 @@
import UIKit import UIKit
import NetworkExtension import NetworkExtension
import CoreTelephony
import MBProgressHUD import MBProgressHUD
import TunnelKit import TunnelKit
import PassepartoutCore import PassepartoutCore
@ -98,7 +97,7 @@ class ServiceViewController: UIViewController, TableModelHost {
navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
navigationItem.leftItemsSupplementBackButton = true navigationItem.leftItemsSupplementBackButton = true
labelWelcome.text = L10n.Service.Welcome.message labelWelcome.text = L10n.App.Service.Welcome.message
labelWelcome.apply(Theme.current) labelWelcome.apply(Theme.current)
let nc = NotificationCenter.default let nc = NotificationCenter.default
@ -174,14 +173,14 @@ class ServiceViewController: UIViewController, TableModelHost {
case .hostParametersSegueIdentifier: case .hostParametersSegueIdentifier:
let vc = destination as? ConfigurationViewController let vc = destination as? ConfigurationViewController
vc?.title = L10n.Service.Cells.Host.Parameters.caption vc?.title = L10n.App.Service.Cells.Host.Parameters.caption
vc?.initialConfiguration = uncheckedHostProfile.parameters.sessionConfiguration vc?.initialConfiguration = uncheckedHostProfile.parameters.sessionConfiguration
vc?.originalConfigurationURL = service.configurationURL(for: uncheckedHostProfile) vc?.originalConfigurationURL = service.configurationURL(for: uncheckedHostProfile)
vc?.delegate = self vc?.delegate = self
case .networkSettingsSegueIdentifier: case .networkSettingsSegueIdentifier:
let vc = destination as? NetworkSettingsViewController let vc = destination as? NetworkSettingsViewController
vc?.title = L10n.Service.Cells.NetworkSettings.caption vc?.title = L10n.Core.NetworkSettings.title
vc?.profile = profile vc?.profile = profile
case .debugLogSegueIdentifier: case .debugLogSegueIdentifier:
@ -218,19 +217,19 @@ class ServiceViewController: UIViewController, TableModelHost {
} }
@IBAction private func renameProfile() { @IBAction private func renameProfile() {
let alert = Macros.alert(L10n.Service.Alerts.Rename.title, L10n.Global.Host.TitleInput.message) let alert = Macros.alert(L10n.Core.Service.Alerts.Rename.title, L10n.Core.Global.Host.TitleInput.message)
alert.addTextField { (field) in alert.addTextField { (field) in
field.text = self.profile?.id field.text = self.profile?.id
field.applyProfileId(Theme.current) field.applyProfileId(Theme.current)
field.delegate = self field.delegate = self
} }
pendingRenameAction = alert.addDefaultAction(L10n.Global.ok) { pendingRenameAction = alert.addDefaultAction(L10n.Core.Global.ok) {
guard let newId = alert.textFields?.first?.text else { guard let newId = alert.textFields?.first?.text else {
return return
} }
self.doRenameCurrentProfile(to: newId) self.doRenameCurrentProfile(to: newId)
} }
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
pendingRenameAction?.isEnabled = false pendingRenameAction?.isEnabled = false
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
} }
@ -247,10 +246,10 @@ class ServiceViewController: UIViewController, TableModelHost {
} }
guard !service.needsCredentials(for: uncheckedProfile) else { guard !service.needsCredentials(for: uncheckedProfile) else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Sections.Vpn.header, L10n.App.Service.Sections.Vpn.header,
L10n.Service.Alerts.CredentialsNeeded.message L10n.Core.Service.Alerts.CredentialsNeeded.message
) )
alert.addCancelAction(L10n.Global.ok) { alert.addCancelAction(L10n.Core.Global.ok) {
cell.setOn(false, animated: true) cell.setOn(false, animated: true)
} }
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
@ -285,13 +284,13 @@ class ServiceViewController: UIViewController, TableModelHost {
private func confirmVpnReconnection() { private func confirmVpnReconnection() {
guard vpn.status == .disconnected else { guard vpn.status == .disconnected else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Cells.ConnectionStatus.caption, L10n.Core.Service.Cells.ConnectionStatus.caption,
L10n.Service.Alerts.ReconnectVpn.message L10n.Core.Service.Alerts.ReconnectVpn.message
) )
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
self.vpn.reconnect(completionHandler: nil) self.vpn.reconnect(completionHandler: nil)
} }
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
@ -349,13 +348,13 @@ class ServiceViewController: UIViewController, TableModelHost {
return return
} }
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Sections.Trusted.header, L10n.Core.Service.Sections.Trusted.header,
L10n.Service.Alerts.Trusted.WillDisconnectPolicy.message L10n.Core.Service.Alerts.Trusted.WillDisconnectPolicy.message
) )
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
completionHandler() completionHandler()
} }
alert.addCancelAction(L10n.Global.cancel) { alert.addCancelAction(L10n.Core.Global.cancel) {
sender.setOn(false, animated: true) sender.setOn(false, animated: true)
} }
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
@ -363,13 +362,13 @@ class ServiceViewController: UIViewController, TableModelHost {
private func confirmPotentialTrustedDisconnection(at rowIndex: Int?, completionHandler: @escaping () -> Void) { private func confirmPotentialTrustedDisconnection(at rowIndex: Int?, completionHandler: @escaping () -> Void) {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Sections.Trusted.header, L10n.Core.Service.Sections.Trusted.header,
L10n.Service.Alerts.Trusted.WillDisconnectTrusted.message L10n.Core.Service.Alerts.Trusted.WillDisconnectTrusted.message
) )
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
completionHandler() completionHandler()
} }
alert.addCancelAction(L10n.Global.cancel) { alert.addCancelAction(L10n.Core.Global.cancel) {
guard let rowIndex = rowIndex else { guard let rowIndex = rowIndex else {
return return
} }
@ -385,12 +384,12 @@ class ServiceViewController: UIViewController, TableModelHost {
Utils.checkConnectivityURL(AppConstants.Web.connectivityURL, timeout: AppConstants.Web.connectivityTimeout) { Utils.checkConnectivityURL(AppConstants.Web.connectivityURL, timeout: AppConstants.Web.connectivityTimeout) {
hud.hide() hud.hide()
let V = L10n.Service.Alerts.TestConnectivity.Messages.self let V = L10n.Core.Service.Alerts.TestConnectivity.Messages.self
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Alerts.TestConnectivity.title, L10n.Core.Service.Alerts.TestConnectivity.title,
$0 ? V.success : V.failure $0 ? V.success : V.failure
) )
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
self.present(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
} }
@ -398,10 +397,10 @@ class ServiceViewController: UIViewController, TableModelHost {
// private func displayDataCount() { // private func displayDataCount() {
// guard vpn.isEnabled else { // guard vpn.isEnabled else {
// let alert = Macros.alert( // let alert = Macros.alert(
// L10n.Service.Cells.DataCount.caption, // L10n.Core.Service.Cells.DataCount.caption,
// L10n.Service.Alerts.DataCount.Messages.notAvailable // L10n.Core.Service.Alerts.DataCount.Messages.notAvailable
// ) // )
// alert.addCancelAction(L10n.Global.ok) // alert.addCancelAction(L10n.Core.Global.ok)
// present(alert, animated: true, completion: nil) // present(alert, animated: true, completion: nil)
// return // return
// } // }
@ -409,15 +408,15 @@ class ServiceViewController: UIViewController, TableModelHost {
// vpn.requestBytesCount { // vpn.requestBytesCount {
// let message: String // let message: String
// if let count = $0 { // if let count = $0 {
// message = L10n.Service.Alerts.DataCount.Messages.current(Int(count.0), Int(count.1)) // message = L10n.Core.Service.Alerts.DataCount.Messages.current(Int(count.0), Int(count.1))
// } else { // } else {
// message = L10n.Service.Alerts.DataCount.Messages.notAvailable // message = L10n.Core.Service.Alerts.DataCount.Messages.notAvailable
// } // }
// let alert = Macros.alert( // let alert = Macros.alert(
// L10n.Service.Cells.DataCount.caption, // L10n.Core.Service.Cells.DataCount.caption,
// message // message
// ) // )
// alert.addCancelAction(L10n.Global.ok) // alert.addCancelAction(L10n.Core.Global.ok)
// self.present(alert, animated: true, completion: nil) // self.present(alert, animated: true, completion: nil)
// } // }
// } // }
@ -430,15 +429,15 @@ class ServiceViewController: UIViewController, TableModelHost {
guard vpn.status == .disconnected else { guard vpn.status == .disconnected else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Cells.MasksPrivateData.caption, L10n.Core.Service.Cells.MasksPrivateData.caption,
L10n.Service.Alerts.MasksPrivateData.Messages.mustReconnect L10n.Core.Service.Alerts.MasksPrivateData.Messages.mustReconnect
) )
alert.addDestructiveAction(L10n.Service.Alerts.Buttons.reconnect) { alert.addDestructiveAction(L10n.Core.Service.Alerts.Buttons.reconnect) {
handler() handler()
self.shouldDeleteLogOnDisconnection = true self.shouldDeleteLogOnDisconnection = true
self.vpn.reconnect(completionHandler: nil) self.vpn.reconnect(completionHandler: nil)
} }
alert.addCancelAction(L10n.Global.cancel) { alert.addCancelAction(L10n.Core.Global.cancel) {
cell.setOn(!cell.isOn, animated: true) cell.setOn(!cell.isOn, animated: true)
} }
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
@ -464,11 +463,11 @@ class ServiceViewController: UIViewController, TableModelHost {
} }
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Alerts.Download.title, L10n.Core.Service.Alerts.Download.title,
L10n.Service.Alerts.Download.message(providerProfile.name.rawValue) L10n.Core.Service.Alerts.Download.message(providerProfile.name.rawValue)
) )
alert.addCancelAction(L10n.Global.cancel) alert.addCancelAction(L10n.Core.Global.cancel)
alert.addDefaultAction(L10n.Global.ok) { alert.addDefaultAction(L10n.Core.Global.ok) {
self.confirmDownload(URL(string: downloadURL)!) self.confirmDownload(URL(string: downloadURL)!)
} }
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
@ -483,15 +482,15 @@ class ServiceViewController: UIViewController, TableModelHost {
private func handleDownloadedProviderResources(url: URL?, error: Error?) { private func handleDownloadedProviderResources(url: URL?, error: Error?) {
guard let url = url else { guard let url = url else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Alerts.Download.title, L10n.Core.Service.Alerts.Download.title,
L10n.Service.Alerts.Download.failed(error?.localizedDescription ?? "") L10n.Core.Service.Alerts.Download.failed(error?.localizedDescription ?? "")
) )
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return return
} }
let hud = HUD(label: L10n.Service.Alerts.Download.Hud.extracting) let hud = HUD(label: L10n.Core.Service.Alerts.Download.Hud.extracting)
hud.show() hud.show()
uncheckedProviderProfile.name.importExternalResources(from: url) { uncheckedProviderProfile.name.importExternalResources(from: url) {
hud.hide() hud.hide()
@ -661,7 +660,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
let rows = model.rows(for: section) let rows = model.rows(for: section)
if rows.contains(.providerRefresh), let date = lastInfrastructureUpdate { if rows.contains(.providerRefresh), let date = lastInfrastructureUpdate {
return L10n.Service.Sections.ProviderInfrastructure.footer(date.timestamp) return L10n.Core.Service.Sections.ProviderInfrastructure.footer(date.timestamp)
} }
return model.footer(for: section) return model.footer(for: section)
} }
@ -680,7 +679,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .useProfile: case .useProfile:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Service.Cells.UseProfile.caption cell.leftText = L10n.App.Service.Cells.UseProfile.caption
return cell return cell
case .vpnService: case .vpnService:
@ -689,7 +688,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
} }
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.VpnService.caption cell.caption = L10n.App.Service.Cells.VpnService.caption
cell.isOn = vpn.isEnabled cell.isOn = vpn.isEnabled
return cell return cell
@ -700,7 +699,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyVPN(Theme.current, with: vpn.isEnabled ? vpn.status : nil, error: service.vpnLastError) cell.applyVPN(Theme.current, with: vpn.isEnabled ? vpn.status : nil, error: service.vpnLastError)
cell.leftText = L10n.Service.Cells.ConnectionStatus.caption cell.leftText = L10n.Core.Service.Cells.ConnectionStatus.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
return cell return cell
@ -708,7 +707,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .reconnect: case .reconnect:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Service.Cells.Reconnect.caption cell.leftText = L10n.App.Service.Cells.Reconnect.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = !service.needsCredentials(for: uncheckedProfile) && vpn.isEnabled cell.isTappable = !service.needsCredentials(for: uncheckedProfile) && vpn.isEnabled
return cell return cell
@ -717,15 +716,15 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .account: case .account:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.Account.caption cell.leftText = L10n.Core.Account.title
cell.rightText = profile?.username cell.rightText = profile?.username
return cell return cell
case .endpoint: case .endpoint:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.Endpoint.caption cell.leftText = L10n.Core.Endpoint.title
let V = L10n.Global.Cells.self let V = L10n.Core.Global.Values.self
if let provider = profile as? ProviderConnectionProfile { if let provider = profile as? ProviderConnectionProfile {
cell.rightText = provider.usesProviderEndpoint ? V.manual : V.automatic cell.rightText = provider.usesProviderEndpoint ? V.manual : V.automatic
} else { } else {
@ -735,27 +734,27 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .networkSettings: case .networkSettings:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.NetworkSettings.caption cell.leftText = L10n.Core.NetworkSettings.title
return cell return cell
// provider cells // provider cells
case .providerPool: case .providerPool:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.Provider.Pool.caption cell.leftText = L10n.Core.Service.Cells.Provider.Pool.caption
cell.rightText = uncheckedProviderProfile.pool?.localizedId cell.rightText = uncheckedProviderProfile.pool?.localizedId
return cell return cell
case .providerPreset: case .providerPreset:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.Provider.Preset.caption cell.leftText = L10n.Core.Service.Cells.Provider.Preset.caption
cell.rightText = uncheckedProviderProfile.preset?.name // XXX: localize? cell.rightText = uncheckedProviderProfile.preset?.name // XXX: localize?
return cell return cell
case .providerRefresh: case .providerRefresh:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Service.Cells.Provider.Refresh.caption cell.leftText = L10n.App.Service.Cells.Provider.Refresh.caption
return cell return cell
// host cells // host cells
@ -763,7 +762,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .hostParameters: case .hostParameters:
let parameters = uncheckedHostProfile.parameters let parameters = uncheckedHostProfile.parameters
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.Host.Parameters.caption cell.leftText = L10n.App.Service.Cells.Host.Parameters.caption
if !parameters.sessionConfiguration.fallbackCipher.embedsDigest { if !parameters.sessionConfiguration.fallbackCipher.embedsDigest {
cell.rightText = "\(parameters.sessionConfiguration.fallbackCipher.genericName) / \(parameters.sessionConfiguration.fallbackDigest.genericName)" cell.rightText = "\(parameters.sessionConfiguration.fallbackCipher.genericName) / \(parameters.sessionConfiguration.fallbackDigest.genericName)"
} else { } else {
@ -775,19 +774,19 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .vpnResolvesHostname: case .vpnResolvesHostname:
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.VpnResolvesHostname.caption cell.caption = L10n.Core.Service.Cells.VpnResolvesHostname.caption
cell.isOn = service.preferences.resolvesHostname cell.isOn = service.preferences.resolvesHostname
return cell return cell
case .vpnSurvivesSleep: case .vpnSurvivesSleep:
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.VpnSurvivesSleep.caption cell.caption = L10n.Core.Service.Cells.VpnSurvivesSleep.caption
cell.isOn = !service.preferences.disconnectsOnSleep cell.isOn = !service.preferences.disconnectsOnSleep
return cell return cell
case .trustedMobile: case .trustedMobile:
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.TrustedMobile.caption cell.caption = L10n.Core.Service.Cells.TrustedMobile.caption
cell.isOn = service.preferences.trustsMobileNetwork cell.isOn = service.preferences.trustsMobileNetwork
return cell return cell
@ -801,12 +800,12 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .trustedAddCurrentWiFi: case .trustedAddCurrentWiFi:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Service.Cells.TrustedAddWifi.caption cell.leftText = L10n.App.Service.Cells.TrustedAddWifi.caption
return cell return cell
case .trustedPolicy: case .trustedPolicy:
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.TrustedPolicy.caption cell.caption = L10n.Core.Service.Cells.TrustedPolicy.caption
cell.isOn = (service.preferences.trustPolicy == .disconnect) cell.isOn = (service.preferences.trustPolicy == .disconnect)
return cell return cell
@ -814,18 +813,18 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .testConnectivity: case .testConnectivity:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.TestConnectivity.caption cell.leftText = L10n.Core.Service.Cells.TestConnectivity.caption
return cell return cell
case .dataCount: case .dataCount:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.DataCount.caption cell.leftText = L10n.Core.Service.Cells.DataCount.caption
if let count = currentDataCount, vpn.status == .connected { if let count = currentDataCount, vpn.status == .connected {
let down = count.0.dataUnitDescription let down = count.0.dataUnitDescription
let up = count.1.dataUnitDescription let up = count.1.dataUnitDescription
cell.rightText = "\(down) / ↑\(up)" cell.rightText = "\(down) / ↑\(up)"
} else { } else {
cell.rightText = L10n.Service.Cells.DataCount.none cell.rightText = L10n.Core.Service.Cells.DataCount.none
} }
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = false cell.isTappable = false
@ -833,12 +832,12 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .debugLog: case .debugLog:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.DebugLog.caption cell.leftText = L10n.Core.Service.Cells.DebugLog.caption
return cell return cell
case .masksPrivateData: case .masksPrivateData:
let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self) let cell = Cells.toggle.dequeue(from: tableView, for: indexPath, tag: row.rawValue, delegate: self)
cell.caption = L10n.Service.Cells.MasksPrivateData.caption cell.caption = L10n.Core.Service.Cells.MasksPrivateData.caption
cell.isOn = TransientStore.masksPrivateData cell.isOn = TransientStore.masksPrivateData
return cell return cell
@ -846,7 +845,7 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
case .reportIssue: case .reportIssue:
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = L10n.Service.Cells.ReportIssue.caption cell.leftText = L10n.Core.Service.Cells.ReportIssue.caption
return cell return cell
} }
} }
@ -933,10 +932,10 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
guard trustedNetworks.addCurrentWifi() else { guard trustedNetworks.addCurrentWifi() else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Service.Sections.Trusted.header, L10n.Core.Service.Sections.Trusted.header,
L10n.Service.Alerts.Trusted.NoNetwork.message L10n.Core.Service.Alerts.Trusted.NoNetwork.message
) )
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Core.Global.ok)
present(alert, animated: true, completion: nil) present(alert, animated: true, completion: nil)
return false return false
} }
@ -1034,31 +1033,31 @@ extension ServiceViewController: UITableViewDataSource, UITableViewDelegate, Tog
} }
// headers // headers
model.setHeader(L10n.Service.Sections.Vpn.header, for: .vpn) model.setHeader(L10n.App.Service.Sections.Vpn.header, for: .vpn)
if isProvider { if isProvider {
model.setHeader(L10n.Service.Sections.Configuration.header, for: .authentication) model.setHeader(L10n.App.Service.Sections.Configuration.header, for: .authentication)
} else { } else {
model.setHeader(L10n.Service.Sections.Configuration.header, for: .configuration) model.setHeader(L10n.App.Service.Sections.Configuration.header, for: .configuration)
} }
if isActiveProfile { if isActiveProfile {
if isProvider { if isProvider {
model.setHeader("", for: .vpnResolvesHostname) model.setHeader("", for: .vpnResolvesHostname)
model.setHeader("", for: .vpnSurvivesSleep) model.setHeader("", for: .vpnSurvivesSleep)
} }
model.setHeader(L10n.Service.Sections.Trusted.header, for: .trusted) model.setHeader(L10n.Core.Service.Sections.Trusted.header, for: .trusted)
model.setHeader(L10n.Service.Sections.Diagnostics.header, for: .diagnostics) model.setHeader(L10n.Core.Service.Sections.Diagnostics.header, for: .diagnostics)
model.setHeader(L10n.Organizer.Sections.Feedback.header, for: .feedback) model.setHeader(L10n.Core.Organizer.Sections.Feedback.header, for: .feedback)
} }
// footers // footers
if isActiveProfile { if isActiveProfile {
model.setFooter(L10n.Service.Sections.Vpn.footer, for: .vpn) model.setFooter(L10n.Core.Service.Sections.Vpn.footer, for: .vpn)
if isProvider { if isProvider {
model.setFooter(L10n.Service.Sections.VpnResolvesHostname.footer, for: .vpnResolvesHostname) model.setFooter(L10n.Core.Service.Sections.VpnResolvesHostname.footer, for: .vpnResolvesHostname)
} }
model.setFooter(L10n.Service.Sections.VpnSurvivesSleep.footer, for: .vpnSurvivesSleep) model.setFooter(L10n.Core.Service.Sections.VpnSurvivesSleep.footer, for: .vpnSurvivesSleep)
model.setFooter(L10n.Service.Sections.Trusted.footer, for: .trustedPolicy) model.setFooter(L10n.Core.Service.Sections.Trusted.footer, for: .trustedPolicy)
model.setFooter(L10n.Service.Sections.Diagnostics.footer, for: .diagnostics) model.setFooter(L10n.Core.Service.Sections.Diagnostics.footer, for: .diagnostics)
} }
// rows // rows

View File

@ -41,9 +41,9 @@ class ShortcutsAddViewController: UITableViewController, TableModelHost {
model.set([.connect, .enableVPN, .disableVPN], in: .vpn) model.set([.connect, .enableVPN, .disableVPN], in: .vpn)
model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi) model.set([.trustCurrentWiFi, .untrustCurrentWiFi], in: .wifi)
model.set([.trustCellular, .untrustCellular], in: .cellular) model.set([.trustCellular, .untrustCellular], in: .cellular)
model.setHeader(L10n.Shortcuts.Add.Sections.Vpn.header, for: .vpn) model.setHeader(L10n.Core.Shortcuts.Add.Sections.Vpn.header, for: .vpn)
model.setHeader(L10n.Shortcuts.Add.Sections.Wifi.header, for: .wifi) model.setHeader(L10n.Core.Shortcuts.Add.Sections.Wifi.header, for: .wifi)
model.setHeader(L10n.Shortcuts.Add.Sections.Cellular.header, for: .cellular) model.setHeader(L10n.Core.Shortcuts.Add.Sections.Cellular.header, for: .cellular)
return model return model
}() }()
@ -55,7 +55,7 @@ class ShortcutsAddViewController: UITableViewController, TableModelHost {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Shortcuts.Add.title title = L10n.App.Shortcuts.Add.title
} }
// MARK: UITableViewController // MARK: UITableViewController
@ -100,25 +100,25 @@ class ShortcutsAddViewController: UITableViewController, TableModelHost {
let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
switch model.row(at: indexPath) { switch model.row(at: indexPath) {
case .connect: case .connect:
cell.leftText = L10n.Shortcuts.Add.Cells.Connect.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.Connect.caption
case .enableVPN: case .enableVPN:
cell.leftText = L10n.Shortcuts.Add.Cells.EnableVpn.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.EnableVpn.caption
case .disableVPN: case .disableVPN:
cell.leftText = L10n.Shortcuts.Add.Cells.DisableVpn.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.DisableVpn.caption
case .trustCurrentWiFi: case .trustCurrentWiFi:
cell.leftText = L10n.Shortcuts.Add.Cells.TrustCurrentWifi.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.TrustCurrentWifi.caption
case .untrustCurrentWiFi: case .untrustCurrentWiFi:
cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCurrentWifi.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.UntrustCurrentWifi.caption
case .trustCellular: case .trustCellular:
cell.leftText = L10n.Shortcuts.Add.Cells.TrustCellular.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.TrustCellular.caption
case .untrustCellular: case .untrustCellular:
cell.leftText = L10n.Shortcuts.Add.Cells.UntrustCellular.caption cell.leftText = L10n.Core.Shortcuts.Add.Cells.UntrustCellular.caption
} }
return cell return cell
} }
@ -159,10 +159,10 @@ class ShortcutsAddViewController: UITableViewController, TableModelHost {
private func addConnect() { private func addConnect() {
guard TransientStore.shared.service.hasProfiles() else { guard TransientStore.shared.service.hasProfiles() else {
let alert = Macros.alert( let alert = Macros.alert(
L10n.Shortcuts.Add.Cells.Connect.caption, L10n.Core.Shortcuts.Add.Cells.Connect.caption,
L10n.Shortcuts.Add.Alerts.NoProfiles.message L10n.Core.Shortcuts.Add.Alerts.NoProfiles.message
) )
alert.addAction(L10n.Global.ok) { alert.addAction(L10n.Core.Global.ok) {
if let ip = self.tableView.indexPathForSelectedRow { if let ip = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: ip, animated: true) self.tableView.deselectRow(at: ip, animated: true)
} }

View File

@ -44,8 +44,8 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
let model: TableModel<SectionType, RowType> = { let model: TableModel<SectionType, RowType> = {
let model: TableModel<SectionType, RowType> = TableModel() let model: TableModel<SectionType, RowType> = TableModel()
model.setHeader(L10n.Organizer.Sections.Providers.header, for: .providers) model.setHeader(L10n.Core.Organizer.Sections.Providers.header, for: .providers)
model.setHeader(L10n.Organizer.Sections.Hosts.header, for: .hosts) model.setHeader(L10n.Core.Organizer.Sections.Hosts.header, for: .hosts)
return model return model
}() }()
@ -68,7 +68,7 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Shortcuts.Add.Cells.Connect.caption title = L10n.Core.Shortcuts.Add.Cells.Connect.caption
reloadModel() reloadModel()
} }

View File

@ -75,7 +75,7 @@ class ShortcutsViewController: UITableViewController, INUIAddVoiceShortcutViewCo
let model: TableModel<SectionType, RowType> = { let model: TableModel<SectionType, RowType> = {
let model: TableModel<SectionType, RowType> = TableModel() let model: TableModel<SectionType, RowType> = TableModel()
model.add(.all) model.add(.all)
model.setHeader(L10n.Shortcuts.Edit.Sections.All.header, for: .all) model.setHeader(L10n.Core.Shortcuts.Edit.Sections.All.header, for: .all)
model.set([], in: .all) model.set([], in: .all)
return model return model
}() }()
@ -91,7 +91,7 @@ class ShortcutsViewController: UITableViewController, INUIAddVoiceShortcutViewCo
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
title = L10n.Organizer.Cells.SiriShortcuts.caption title = L10n.Core.Organizer.Cells.SiriShortcuts.caption
INVoiceShortcutCenter.shared.getAllVoiceShortcuts { [weak self] (shortcuts, error) in INVoiceShortcutCenter.shared.getAllVoiceShortcuts { [weak self] (shortcuts, error) in
DispatchQueue.main.async { DispatchQueue.main.async {
@ -121,9 +121,9 @@ class ShortcutsViewController: UITableViewController, INUIAddVoiceShortcutViewCo
// TODO: really show it? // TODO: really show it?
// let alert = Macros.alert( // let alert = Macros.alert(
// title, // title,
// L10n.Shortcuts.Edit.message(error?.localizedDescription ?? "") // L10n.Core.Shortcuts.Edit.message(error?.localizedDescription ?? "")
// ) // )
// alert.addCancelAction(L10n.Global.ok) { // alert.addCancelAction(L10n.Core.Global.ok) {
// self.close() // self.close()
// } // }
// present(alert, animated: true, completion: nil) // present(alert, animated: true, completion: nil)
@ -191,7 +191,7 @@ class ShortcutsViewController: UITableViewController, INUIAddVoiceShortcutViewCo
case .addShortcut: case .addShortcut:
cell.applyAction(Theme.current) cell.applyAction(Theme.current)
cell.leftText = L10n.Shortcuts.Edit.Cells.AddShortcut.caption cell.leftText = L10n.App.Shortcuts.Edit.Cells.AddShortcut.caption
cell.accessoryType = .none cell.accessoryType = .none
cell.isTappable = true cell.isTappable = true
} }

View File

@ -27,7 +27,6 @@
0E3152BC223FA03D00F61841 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; }; 0E3152BC223FA03D00F61841 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; };
0E3152BD223FA03D00F61841 /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; 0E3152BD223FA03D00F61841 /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; };
0E3152BE223FA03D00F61841 /* Reviewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E78179E21BE852200950C58 /* Reviewer.swift */; }; 0E3152BE223FA03D00F61841 /* Reviewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E78179E21BE852200950C58 /* Reviewer.swift */; };
0E3152BF223FA03D00F61841 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05C5E320D1993C006EE732 /* SwiftGen+Strings.swift */; };
0E3152C0223FA03D00F61841 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7ED20D539A0002221FF /* Utils.swift */; }; 0E3152C0223FA03D00F61841 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7ED20D539A0002221FF /* Utils.swift */; };
0E3152C1223FA04800F61841 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */; }; 0E3152C1223FA04800F61841 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */; };
0E3152C2223FA04800F61841 /* MockVPNProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7E020D3E4C5002221FF /* MockVPNProvider.swift */; }; 0E3152C2223FA04800F61841 /* MockVPNProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7E020D3E4C5002221FF /* MockVPNProvider.swift */; };
@ -61,10 +60,12 @@
0E36D24D2240234B006AF062 /* ShortcutsAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */; }; 0E36D24D2240234B006AF062 /* ShortcutsAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D24C2240234B006AF062 /* ShortcutsAddViewController.swift */; };
0E36D25822403469006AF062 /* Shortcuts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E36D25A22403469006AF062 /* Shortcuts.storyboard */; }; 0E36D25822403469006AF062 /* Shortcuts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E36D25A22403469006AF062 /* Shortcuts.storyboard */; };
0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */; }; 0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */; };
0E3CAFB7229AAE770008E5C8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAF98229AAE760008E5C8 /* Localizable.strings */; };
0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */; }; 0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */; };
0E3CAFC4229AAF8E0008E5C8 /* API in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAFC3229AAF8E0008E5C8 /* API */; }; 0E3CAFC4229AAF8E0008E5C8 /* API in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAFC3229AAF8E0008E5C8 /* API */; };
0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; }; 0E3DA371215CB5BF00B40FC9 /* VersionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */; };
0E45E6E022BD793800F19312 /* App.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E45E6E222BD793800F19312 /* App.strings */; };
0E45E6E422BD799700F19312 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E45E6E322BD799700F19312 /* SwiftGen+Strings.swift */; };
0E45E6FA22BD8FC500F19312 /* Core.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAF98229AAE760008E5C8 /* Core.strings */; };
0E4C9CBB20DCF0D600A0C59C /* DestructiveTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */; }; 0E4C9CBB20DCF0D600A0C59C /* DestructiveTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */; };
0E4FD7F120D58618002221FF /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7F020D58618002221FF /* Macros.swift */; }; 0E4FD7F120D58618002221FF /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7F020D58618002221FF /* Macros.swift */; };
0E533B162258E03B00EF94FC /* PoolGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E533B152258E03B00EF94FC /* PoolGroup.swift */; }; 0E533B162258E03B00EF94FC /* PoolGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E533B152258E03B00EF94FC /* PoolGroup.swift */; };
@ -160,7 +161,6 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
09CB728874F1553EF27BAAB9 /* Pods-Passepartout-iOS-Tunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS-Tunnel/Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; sourceTree = "<group>"; }; 09CB728874F1553EF27BAAB9 /* Pods-Passepartout-iOS-Tunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS-Tunnel/Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; sourceTree = "<group>"; };
0E05C5CE20D139AF006EE732 /* FieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldTableViewCell.swift; sourceTree = "<group>"; }; 0E05C5CE20D139AF006EE732 /* FieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldTableViewCell.swift; sourceTree = "<group>"; };
0E05C5E320D1993C006EE732 /* SwiftGen+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Strings.swift"; sourceTree = "<group>"; };
0E05C61C20D27C82006EE732 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; 0E05C61C20D27C82006EE732 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
0E1066C820E0F84A004F98B7 /* Cells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cells.swift; sourceTree = "<group>"; }; 0E1066C820E0F84A004F98B7 /* Cells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cells.swift; sourceTree = "<group>"; };
0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = "<group>"; }; 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = "<group>"; };
@ -181,17 +181,28 @@
0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConnectToViewController.swift; sourceTree = "<group>"; }; 0E36D25B224034AD006AF062 /* ShortcutsConnectToViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsConnectToViewController.swift; sourceTree = "<group>"; };
0E39BCEF214B9EF10035E9DE /* WebServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebServices.swift; sourceTree = "<group>"; }; 0E39BCEF214B9EF10035E9DE /* WebServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebServices.swift; sourceTree = "<group>"; };
0E39BCF2214DA9310035E9DE /* AppConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = "<group>"; }; 0E39BCF2214DA9310035E9DE /* AppConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = "<group>"; };
0E3CAF99229AAE760008E5C8 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAF99229AAE760008E5C8 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAF9C229AAE760008E5C8 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAF9C229AAE760008E5C8 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAF9E229AAE760008E5C8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAF9E229AAE760008E5C8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFA0229AAE760008E5C8 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAFA0229AAE760008E5C8 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFAB229AAE760008E5C8 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAFAB229AAE760008E5C8 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFAE229AAE760008E5C8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; }; 0E3CAFAE229AAE760008E5C8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; };
0E3CAFB1229AAE760008E5C8 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAFB1229AAE760008E5C8 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFB3229AAE760008E5C8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAFB3229AAE760008E5C8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFB5229AAE760008E5C8 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E3CAFB5229AAE760008E5C8 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Core.strings; sourceTree = "<group>"; };
0E3CAFC3229AAF8E0008E5C8 /* API */ = {isa = PBXFileReference; lastKnownFileType = folder; path = API; sourceTree = "<group>"; }; 0E3CAFC3229AAF8E0008E5C8 /* API */ = {isa = PBXFileReference; lastKnownFileType = folder; path = API; sourceTree = "<group>"; };
0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionViewController.swift; sourceTree = "<group>"; }; 0E3DA370215CB5BF00B40FC9 /* VersionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionViewController.swift; sourceTree = "<group>"; };
0E45E6E122BD793800F19312 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/App.strings; sourceTree = "<group>"; };
0E45E6E322BD799700F19312 /* SwiftGen+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Strings.swift"; sourceTree = "<group>"; };
0E45E6F122BD897E00F19312 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F222BD898000F19312 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F322BD898200F19312 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F422BD898300F19312 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F522BD898500F19312 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F622BD898700F19312 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F722BD898800F19312 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F822BD898A00F19312 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/App.strings; sourceTree = "<group>"; };
0E45E6F922BD898B00F19312 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/App.strings; sourceTree = "<group>"; };
0E4C9CB820DB9BC600A0C59C /* TrustedNetworks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworks.swift; sourceTree = "<group>"; }; 0E4C9CB820DB9BC600A0C59C /* TrustedNetworks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworks.swift; sourceTree = "<group>"; };
0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestructiveTableViewCell.swift; sourceTree = "<group>"; }; 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestructiveTableViewCell.swift; sourceTree = "<group>"; };
0E4FD7DD20D3E49A002221FF /* StandardVPNProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardVPNProvider.swift; sourceTree = "<group>"; }; 0E4FD7DD20D3E49A002221FF /* StandardVPNProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardVPNProvider.swift; sourceTree = "<group>"; };
@ -209,11 +220,11 @@
0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = "<group>"; }; 0E5E5DE421511C5F00E318A3 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = "<group>"; };
0E66A26F225FE25800F9C779 /* PoolCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PoolCategory.swift; path = ../Model/Profiles/PoolCategory.swift; sourceTree = "<group>"; }; 0E66A26F225FE25800F9C779 /* PoolCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PoolCategory.swift; path = ../Model/Profiles/PoolCategory.swift; sourceTree = "<group>"; };
0E6ACB7722B1A57C001B3C99 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Intents.strings; sourceTree = "<group>"; }; 0E6ACB7722B1A57C001B3C99 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Intents.strings; sourceTree = "<group>"; };
0E6ACB7822B1A5BB001B3C99 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E6ACB7822B1A5BB001B3C99 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Core.strings; sourceTree = "<group>"; };
0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationError.swift; sourceTree = "<group>"; }; 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationError.swift; sourceTree = "<group>"; };
0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = "<group>"; }; 0E6BE13E20CFBAB300A6DD36 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = "<group>"; };
0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.swift; sourceTree = "<group>"; }; 0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsViewController.swift; sourceTree = "<group>"; };
0E776575229CF65D0023FA76 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; }; 0E776575229CF65D0023FA76 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Core.strings; sourceTree = "<group>"; };
0E776637229D0D9E0023FA76 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = "<group>"; }; 0E776637229D0D9E0023FA76 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = "<group>"; };
0E776638229D0D9F0023FA76 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Intents.strings; sourceTree = "<group>"; }; 0E776638229D0D9F0023FA76 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Intents.strings; sourceTree = "<group>"; };
0E776639229D0DA00023FA76 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Intents.strings; sourceTree = "<group>"; }; 0E776639229D0DA00023FA76 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Intents.strings; sourceTree = "<group>"; };
@ -374,8 +385,8 @@
0E3CAF97229AAE760008E5C8 /* Resources */ = { 0E3CAF97229AAE760008E5C8 /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0E3CAF98229AAE760008E5C8 /* Core.strings */,
0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */, 0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */,
0E3CAF98229AAE760008E5C8 /* Localizable.strings */,
); );
path = Resources; path = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
@ -528,6 +539,7 @@
0EDE8DEC20C93E3B004C739C /* Global */ = { 0EDE8DEC20C93E3B004C739C /* Global */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0E45E6E222BD793800F19312 /* App.strings */,
0EA068F3218475F800C320AD /* ConfigurationParserResult+Alerts.swift */, 0EA068F3218475F800C320AD /* ConfigurationParserResult+Alerts.swift */,
0EEB53B1225D525B00746300 /* Downloader.swift */, 0EEB53B1225D525B00746300 /* Downloader.swift */,
0EF5CF242141CE58004FF1BD /* HUD.swift */, 0EF5CF242141CE58004FF1BD /* HUD.swift */,
@ -538,6 +550,7 @@
0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */, 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */,
0EDE8DE320C89028004C739C /* SwiftGen+Scenes.swift */, 0EDE8DE320C89028004C739C /* SwiftGen+Scenes.swift */,
0EF56BBA2185AC8500B0C8AB /* SwiftGen+Segues.swift */, 0EF56BBA2185AC8500B0C8AB /* SwiftGen+Segues.swift */,
0E45E6E322BD799700F19312 /* SwiftGen+Strings.swift */,
0E05C61C20D27C82006EE732 /* Theme.swift */, 0E05C61C20D27C82006EE732 /* Theme.swift */,
0ECEE44F20E1182E00A6BB43 /* Theme+Cells.swift */, 0ECEE44F20E1182E00A6BB43 /* Theme+Cells.swift */,
0E2B493F20FCFF990094784C /* Theme+Titles.swift */, 0E2B493F20FCFF990094784C /* Theme+Titles.swift */,
@ -566,7 +579,6 @@
0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */, 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */,
0EDE8DED20C93E4C004C739C /* GroupConstants.swift */, 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */,
0E78179E21BE852200950C58 /* Reviewer.swift */, 0E78179E21BE852200950C58 /* Reviewer.swift */,
0E05C5E320D1993C006EE732 /* SwiftGen+Strings.swift */,
0E4FD7ED20D539A0002221FF /* Utils.swift */, 0E4FD7ED20D539A0002221FF /* Utils.swift */,
); );
path = Sources; path = Sources;
@ -791,7 +803,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0E3CAFC4229AAF8E0008E5C8 /* API in Resources */, 0E3CAFC4229AAF8E0008E5C8 /* API in Resources */,
0E3CAFB7229AAE770008E5C8 /* Localizable.strings in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -804,9 +815,11 @@
0E24273A225950450064A1A3 /* About.storyboard in Resources */, 0E24273A225950450064A1A3 /* About.storyboard in Resources */,
0E57F64620C83FC7008323CF /* LaunchScreen.storyboard in Resources */, 0E57F64620C83FC7008323CF /* LaunchScreen.storyboard in Resources */,
0E57F64320C83FC7008323CF /* Assets.xcassets in Resources */, 0E57F64320C83FC7008323CF /* Assets.xcassets in Resources */,
0E45E6FA22BD8FC500F19312 /* Core.strings in Resources */,
0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */, 0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */,
0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */, 0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */,
0E57F64120C83FC5008323CF /* Main.storyboard in Resources */, 0E57F64120C83FC5008323CF /* Main.storyboard in Resources */,
0E45E6E022BD793800F19312 /* App.strings in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -941,7 +954,6 @@
0E3152C5223FA04800F61841 /* VPNConfiguration.swift in Sources */, 0E3152C5223FA04800F61841 /* VPNConfiguration.swift in Sources */,
0E3152C8223FA04D00F61841 /* Infrastructure.swift in Sources */, 0E3152C8223FA04D00F61841 /* Infrastructure.swift in Sources */,
0E3152D8223FA05400F61841 /* TrustPolicy.swift in Sources */, 0E3152D8223FA05400F61841 /* TrustPolicy.swift in Sources */,
0E3152BF223FA03D00F61841 /* SwiftGen+Strings.swift in Sources */,
0E3152DC223FA05800F61841 /* ProviderConnectionProfile.swift in Sources */, 0E3152DC223FA05800F61841 /* ProviderConnectionProfile.swift in Sources */,
0E3152D9223FA05800F61841 /* HostConnectionProfile.swift in Sources */, 0E3152D9223FA05800F61841 /* HostConnectionProfile.swift in Sources */,
0E3152D6223FA05400F61841 /* TransientStore.swift in Sources */, 0E3152D6223FA05400F61841 /* TransientStore.swift in Sources */,
@ -976,6 +988,7 @@
0EBE3A79213C4E5500BFA2F5 /* OrganizerViewController.swift in Sources */, 0EBE3A79213C4E5500BFA2F5 /* OrganizerViewController.swift in Sources */,
0E4FD7F120D58618002221FF /* Macros.swift in Sources */, 0E4FD7F120D58618002221FF /* Macros.swift in Sources */,
0EF5CF252141CE58004FF1BD /* HUD.swift in Sources */, 0EF5CF252141CE58004FF1BD /* HUD.swift in Sources */,
0E45E6E422BD799700F19312 /* SwiftGen+Strings.swift in Sources */,
0E05C5D720D1645F006EE732 /* ToggleTableViewCell.swift in Sources */, 0E05C5D720D1645F006EE732 /* ToggleTableViewCell.swift in Sources */,
0EFB901A2276D7F1006405E4 /* NetworkSettingsViewController.swift in Sources */, 0EFB901A2276D7F1006405E4 /* NetworkSettingsViewController.swift in Sources */,
0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */, 0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */,
@ -1059,7 +1072,7 @@
name = Shortcuts.storyboard; name = Shortcuts.storyboard;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
0E3CAF98229AAE760008E5C8 /* Localizable.strings */ = { 0E3CAF98229AAE760008E5C8 /* Core.strings */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
children = ( children = (
0E3CAF99229AAE760008E5C8 /* de */, 0E3CAF99229AAE760008E5C8 /* de */,
@ -1073,7 +1086,7 @@
0E776575229CF65D0023FA76 /* es */, 0E776575229CF65D0023FA76 /* es */,
0E6ACB7822B1A5BB001B3C99 /* pt */, 0E6ACB7822B1A5BB001B3C99 /* pt */,
); );
name = Localizable.strings; name = Core.strings;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */ = { 0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */ = {
@ -1094,6 +1107,23 @@
name = Intents.intentdefinition; name = Intents.intentdefinition;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
0E45E6E222BD793800F19312 /* App.strings */ = {
isa = PBXVariantGroup;
children = (
0E45E6E122BD793800F19312 /* en */,
0E45E6F122BD897E00F19312 /* it */,
0E45E6F222BD898000F19312 /* de */,
0E45E6F322BD898200F19312 /* ru */,
0E45E6F422BD898300F19312 /* nl */,
0E45E6F522BD898500F19312 /* el */,
0E45E6F622BD898700F19312 /* sv */,
0E45E6F722BD898800F19312 /* fr */,
0E45E6F822BD898A00F19312 /* es */,
0E45E6F922BD898B00F19312 /* pt */,
);
name = App.strings;
sourceTree = "<group>";
};
0E57F63F20C83FC5008323CF /* Main.storyboard */ = { 0E57F63F20C83FC5008323CF /* Main.storyboard */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
children = ( children = (

@ -1 +1 @@
Subproject commit 766a328ac407b9c84aedf82268500c325930380a Subproject commit b58dbe713459f631220fd903bc17bd99748c750c

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
DIR="Passepartout/Resources" DIR="Passepartout-iOS/Global"
FILENAME="Localizable.strings" FILENAME="App.strings"
LANG_BASE="en" LANG_BASE="en"
LANG_TARGET="$1" LANG_TARGET="$1"
STRINGS_BASE="$DIR/$LANG_BASE.lproj/$FILENAME" STRINGS_BASE="$DIR/$LANG_BASE.lproj/$FILENAME"

View File

@ -1,3 +1,11 @@
strings:
inputs:
- Submodules/Core/Passepartout/Resources/en.lproj/Core.strings
- Passepartout-iOS/Global/en.lproj/App.strings
outputs:
- templateName: structured-swift4
output: Passepartout-iOS/Global/SwiftGen+Strings.swift
ib: ib:
inputs: inputs:
- Passepartout-iOS/Base.lproj/About.storyboard - Passepartout-iOS/Base.lproj/About.storyboard