mirror of
https://github.com/OutlineFoundation/outline-server.git
synced 2026-08-04 14:37:34 +00:00
i18n: extract strings (#446)
This commit is contained in:
parent
a986a75780
commit
34b2c708be
25 changed files with 1478 additions and 383 deletions
|
|
@ -16,12 +16,14 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"app-layout": "PolymerElements/app-layout#^2.0.4",
|
||||
"app-localize-behavior": "PolymerElements/app-localize-behavior#^2.0.1",
|
||||
"font-roboto": "PolymerElements/font-roboto-local#^1.1.0",
|
||||
"iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^2.1.1",
|
||||
"iron-icons": "PolymerElements/iron-icons#^2.0.1",
|
||||
"iron-collapse": "PolymerElements/iron-collapse#^2.2.1",
|
||||
"iron-fit-behavior": "PolymerElements/iron-fit-behavior#^2.1.0",
|
||||
"iron-pages": "PolymerElements/iron-pages#^2.0.1",
|
||||
"outline-i18n": "Jigsaw-Code/outline-i18n#^0.0.7",
|
||||
"paper-button": "PolymerElements/paper-button#^2.0.0",
|
||||
"paper-checkbox": "PolymerElements/paper-checkbox#^2.0.4",
|
||||
"paper-dialog": "PolymerElements/paper-dialog#^2.0.1",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
|
||||
|
||||
<link rel="shortcut icon" href="/ui_components/images/favicon.png">
|
||||
|
|
@ -26,6 +25,7 @@
|
|||
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
|
||||
<link rel="import" href="/bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||
<link rel="import" href="/ui_components/app-root.html">
|
||||
<script src="/bower_components/outline-i18n/index.js"></script>
|
||||
<script src="server_manager/web_app/main.js"></script>
|
||||
|
||||
<!-- TODO: Add Outline servers to connect-src on-demand (in addition to the DigitalOcean API). -->
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
<title>Outline Manager</title>
|
||||
</head>
|
||||
|
||||
<body dir='ltr' class='page-cloud-install'>
|
||||
<body dir="ltr">
|
||||
<app-root id="appRoot"></app-root>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
196
src/server_manager/messages/en.json
Normal file
196
src/server_manager/messages/en.json
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
{
|
||||
"about-outline": "Outline is an open source project created by <a href={jigsawUrl}>Jigsaw</a> to provide a safer way for news organizations and journalists to access the internet.<br><br> Outline is powered by <a href={shadowsocksUrl}>Shadowsocks</a> and is still an early stage product. You can contribute to the code on <a href={gitHubUrl}>GitHub</a>, and follow us on <a href={redditUrl}>Reddit</a> and <a href={mediumUrl}>Medium</a> to hear when we expand to more platforms and add new features.",
|
||||
"about-version": "Version {version}",
|
||||
"aws-group-assign-0": "Navigate to {openLink}Instances{closeLink}.",
|
||||
"aws-group-assign-1": "Click 'Actions' > 'Networking' > 'Change Security Groups' at the top of the 'Instances' screen.",
|
||||
"aws-group-assign-2": "Select the 'outline' Security Group, unselect other security groups.",
|
||||
"aws-group-assign-3": "Click 'Assign Security Groups'.",
|
||||
"aws-group-create-0": "Once you've created your EC2 instance, open the {openLink}EC2 Management Console{closeLink}.",
|
||||
"aws-group-create-1": "Under 'Network & Security', select 'Security Groups'.",
|
||||
"aws-group-create-2": "Click on 'Create Security Group'.",
|
||||
"aws-group-create-3": "Type 'outline' in the 'Security group name' and 'Description' fields.",
|
||||
"aws-group-create-4": "Click 'Add Rule'.",
|
||||
"aws-group-create-5": "Select 'All traffic' under 'Type', and 'Anywhere' under 'Source'.",
|
||||
"cancel": "Cancel",
|
||||
"city-ams": "Amsterdam",
|
||||
"city-blr": "Bangalore",
|
||||
"city-fra": "Frankfurt",
|
||||
"city-lon": "London",
|
||||
"city-nyc": "New York",
|
||||
"city-sfo": "San Francisco",
|
||||
"city-sgp": "Singapore",
|
||||
"city-tor": "Toronto",
|
||||
"close": "Close",
|
||||
"confirmation-server-destroy": "Existing users will lose access. This action cannot be undone.",
|
||||
"confirmation-server-destroy-title": "Destroy Server?",
|
||||
"confirmation-server-remove": "This action removes your server from the Outline Manager, but does not block proxy access to users. You will still need to manually delete the Outline server from your host machine.",
|
||||
"confirmation-server-remove-title": "Remove Server?",
|
||||
"destroy": "Destroy",
|
||||
"digitalocean-disconnect": "Disconnect",
|
||||
"digitalocean-disconnect-account": "Disconnect DigitalOcean account",
|
||||
"digitalocean-unreachable": "This error may be due to a firewall on your network or temporary connectivity issues with digitalocean.com.",
|
||||
"done": "Done",
|
||||
"error-connectivity": "We're having trouble connecting to your DigitalOcean account. This is sometimes a temporary problem with DigitalOcean or with your internet connection. If retrying doesn't work, logging into DigitalOcean again should fix the problem.",
|
||||
"error-connectivity-title": "Connection problem",
|
||||
"error-do-account-info": "Failed to get DigitalOcean account information",
|
||||
"error-do-auth": "Authentication with DigitalOcean failed",
|
||||
"error-do-regions": "Failed to get list of available regions",
|
||||
"error-feedback": "Failed to submit feedback. Please try again.",
|
||||
"error-key-add": "Failed to add key",
|
||||
"error-key-remove": "Failed to remove key",
|
||||
"error-key-rename": "Failed to rename key",
|
||||
"error-keys-get": "Could not load keys",
|
||||
"error-licenses": "Could not load licenses.",
|
||||
"error-metrics": "Error setting metrics enabled",
|
||||
"error-server-creation": "There was an error creating your Outline server.",
|
||||
"error-server-destroy": "Failed to destroy server",
|
||||
"error-server-removed": "{serverName} no longer present in your DigitalOcean account.",
|
||||
"error-server-rename": "Failed to rename server",
|
||||
"error-server-unreachable": "Your Outline Server was installed correctly, but we are not able to connect to it. Most likely this is because your server's firewall rules are blocking incoming connections. Please review them and make sure to allow incoming TCP connections on ports ranging from 1024 to 65535.",
|
||||
"error-server-unreachable-title": "Unable to connect to your Outline Server",
|
||||
"error-servers-removed": "{serverNames} no longer present in your DigitalOcean account.",
|
||||
"feedback-cloud-provider": "Select cloud provider",
|
||||
"feedback-cloud-provider-error": "Please select a cloud provider.",
|
||||
"feedback-connection": "Can't connect to my server",
|
||||
"feedback-connection-others": "Others can't connect to my server",
|
||||
"feedback-disclaimer": "Please note that our team is only able to answer feedback in English.",
|
||||
"feedback-email": "Email address (optional)",
|
||||
"feedback-error": "Please enter feedback.",
|
||||
"feedback-explanation-install": "An error occurred while attempting to install Outline on your server. If you haven't been able to figure out a solution, please consider sending us feedback and telling us your email address (optional) so that we can get back to you.",
|
||||
"feedback-general": "General feedback",
|
||||
"feedback-install": "Having trouble installing Outline",
|
||||
"feedback-label": "Your feedback",
|
||||
"feedback-management": "Having trouble managing my server",
|
||||
"feedback-other": "Other",
|
||||
"feedback-privacy": "Your feedback, email address (if provided) and additional information referred to in the {openLink}privacy policy{closeLink} will be sent to the Outline team.",
|
||||
"feedback-submit": "Submit",
|
||||
"feedback-suggestion": "Suggestions",
|
||||
"feedback-title-generic": "Send Feedback",
|
||||
"feedback-title-install": "Outline Server Installation Failed",
|
||||
"gcp-firewall-assign-0": "Navigate to the {openLink}VM instances screen{closeLink}.",
|
||||
"gcp-firewall-assign-1": "Click on the instance where you want to host Outline.",
|
||||
"gcp-firewall-assign-2": "Click 'EDIT' at the top of the VM Instance details screen.",
|
||||
"gcp-firewall-assign-3": "Type 'outline' in the 'Network tags' field.",
|
||||
"gcp-firewall-assign-4": "Click 'SAVE'.",
|
||||
"gcp-firewall-create-0": "{openLink}Add a new firewall rule{closeLink} to your Compute Engine project.",
|
||||
"gcp-firewall-create-1": "Type 'outline' in the 'Name' field.",
|
||||
"gcp-firewall-create-2": "Type 'outline' in the 'Target tags' field.",
|
||||
"gcp-firewall-create-3": "Type '0.0.0.0/0' in the 'Source IP ranges' field.",
|
||||
"gcp-firewall-create-4": "Select 'Allow all' under 'Protocols and ports'.",
|
||||
"gcp-firewall-create-5": "Click 'Create'.",
|
||||
"key": "Key",
|
||||
"manual-server-assign-firewall": "Assign firewall rule",
|
||||
"manual-server-assign-group": "Assign Security Group",
|
||||
"manual-server-create-firewall": "Create a firewall rule",
|
||||
"manual-server-create-group": "Create a Security Group",
|
||||
"manual-server-description": "These steps will help you install Outline on a {cloudProvider} Linux server.",
|
||||
"manual-server-firewall": "Configure your firewall",
|
||||
"manual-server-install-paste": "Paste your installation output here.",
|
||||
"manual-server-install-run": "Log into your server, and run this command.",
|
||||
"manual-server-instructions": "Instructions",
|
||||
"manual-server-show-me": "Show me where",
|
||||
"manual-server-title": "Follow the instructions below",
|
||||
"metrics-description": "Share anonymized metrics to help improve the reliability and performance of Outline, for you and for those you share your server with. {openLink}Learn more.{closeLink}",
|
||||
"metrics-share": "Share metrics",
|
||||
"metrics-skip": "Skip",
|
||||
"metrics-title": "Metrics sharing",
|
||||
"nav-about": "About",
|
||||
"nav-data-collection": "Data collection",
|
||||
"nav-feedback": "Feedback",
|
||||
"nav-help": "Help",
|
||||
"nav-licenses": "Licenses",
|
||||
"nav-privacy": "Privacy",
|
||||
"nav-terms": "Terms",
|
||||
"notification-app-update": "An updated version of the Outline Manager has been downloaded. It will be installed when you restart the application.",
|
||||
"notification-feedback-thanks": "Thanks for helping us improve! We love hearing from you.",
|
||||
"notification-key-added": "Key added",
|
||||
"notification-key-removed": "Key removed",
|
||||
"notification-server-destroyed": "Server destroyed",
|
||||
"notification-server-exists": "Server already added",
|
||||
"notification-server-removed": "Server removed",
|
||||
"oauth-account-active": "Your DigitalOcean account has been activated.",
|
||||
"oauth-account-active-tag": "Account activated! Loading server locations...",
|
||||
"oauth-activate-account": "Activate you DigitalOcean account.",
|
||||
"oauth-billing": "Enter your billing information on digitalocean.com and return to the app once you are done.",
|
||||
"oauth-billing-tag": "Enter billing information...",
|
||||
"oauth-connect-description": "With your account, Outline makes it easy to create a server and get connected.",
|
||||
"oauth-connect-tag": "Waiting to connect your account...",
|
||||
"oauth-connect-title": "Sign in or create an account with DigitalOcean.",
|
||||
"oauth-sign-out": "Sign Out",
|
||||
"oauth-verify": "Check your inbox for an email from DigitalOcean, and click the link in it to confirm your account.",
|
||||
"oauth-verify-tag": "Confirm your email...",
|
||||
"oauth-verify-title": "Activate you DigitalOcean account.",
|
||||
"okay": "OK",
|
||||
"region-description": "This is where your internet experience will come from.",
|
||||
"region-setup": "Set up Outline",
|
||||
"region-title": "Select the location of your server.",
|
||||
"remove": "Remove",
|
||||
"retry": "Retry",
|
||||
"server-access": "Server access",
|
||||
"server-access-key-new": "Add new key",
|
||||
"server-access-key-rename": "Rename",
|
||||
"server-access-keys": "Access keys",
|
||||
"server-connect-devices": "Connect your devices",
|
||||
"server-connections": "Connections",
|
||||
"server-data-transfer": "Data transferred / 30 days",
|
||||
"server-data-used": "Allowance used / 30 days",
|
||||
"server-destroy": "Destroy server",
|
||||
"server-help-access-key-description": "Share access keys with friends, so they can connect to your Outline server. They can use the same access key on all their devices.",
|
||||
"server-help-access-key-next": "Next",
|
||||
"server-help-access-key-title": "Create keys, share access",
|
||||
"server-help-connection-description": "Click here to install the Outline client app, using your personal access key to your Outline server.",
|
||||
"server-help-connection-ok": "Okay, got it!",
|
||||
"server-help-connection-title": "You are not connected yet!",
|
||||
"server-keys": "Keys",
|
||||
"server-my-access-key": "My access key",
|
||||
"server-name": "Outline Server {serverLocation}",
|
||||
"server-remove": "Remove server",
|
||||
"server-settings": "Settings",
|
||||
"server-unreachable": "Server unreachable",
|
||||
"server-unreachable-description": "We're having issues connecting to this server.",
|
||||
"server-unreachable-managed-description": "Try again or remove this server from the application.",
|
||||
"server-unreachable-manual-description": "Try again or destroy this server and the virtual host.",
|
||||
"server-usage": "Usage / 30 days",
|
||||
"servers-add": "Add server",
|
||||
"servers-digitalocean": "DigitalOcean servers",
|
||||
"servers-manual": "Servers",
|
||||
"settings-access-key-port": "Port for new access keys",
|
||||
"settings-metrics-header": "Share anonymous metrics",
|
||||
"settings-server-api-url": "Management API URL",
|
||||
"settings-server-cost": "Monthly cost",
|
||||
"settings-server-creation": "Created",
|
||||
"settings-server-hostname": "Hostname",
|
||||
"settings-server-id": "Server ID",
|
||||
"settings-server-info": "Server Information",
|
||||
"settings-server-location": "Server location",
|
||||
"settings-server-name": "Name",
|
||||
"settings-server-rename": "Set a new name for your server. Note that this will not be reflected on the devices of the users that you invited to connect to it.",
|
||||
"settings-transfer-limit": "Data transfer allowance",
|
||||
"setup-action": "Set up",
|
||||
"setup-advanced": "Advanced",
|
||||
"setup-anywhere": "Set up Outline anywhere",
|
||||
"setup-create": "Create server",
|
||||
"setup-description": "Don't have a server? Create an account with DigitalOcean.",
|
||||
"setup-do-cancel": "Cancel at anytime",
|
||||
"setup-do-cost": "Only US$5 a month",
|
||||
"setup-do-create": "Create a new server with your DigitalOcean account for an additional US$5/30 days for 1 TB of data transfer.",
|
||||
"setup-do-data": "1 TB data transfer allowance",
|
||||
"setup-do-description": "This could take up to two minutes. You can destroy this server at anytime.",
|
||||
"setup-do-easiest": "Easiest setup process",
|
||||
"setup-do-title": "Setting up Outline.",
|
||||
"setup-firewall-instructions": "Firewall instructions",
|
||||
"setup-recommended": "Recommended",
|
||||
"setup-simple-commands": "Simple install commands",
|
||||
"setup-step-by-step": "Step-by-step set-up guide",
|
||||
"setup-tested": "Tested on VULTR, Linode, and Liquid Web",
|
||||
"setup-title": "Choose a cloud service to set up Outline.",
|
||||
"share-description": "Copy this invitation and send it from a communication tool you trust. {openLink}Need help?{closeLink}",
|
||||
"share-invite": "You\u2019re invited to connect to my Outline server. Use it to access the open internet, no matter where you are. Follow the instructions on your invitation link below to download the Outline App and get connected.",
|
||||
"share-invite-copied": "Copied to clipboard",
|
||||
"share-invite-copy": "Copy invitation",
|
||||
"share-invite-copy-access-key": "Copy your access key:",
|
||||
"share-invite-instructions": "Follow our invitation instructions on GitHub:",
|
||||
"share-invite-trouble": "Having trouble accessing the invitation link?",
|
||||
"share-title": "Share access",
|
||||
"terms-of-service": "I have read and understood the {openLink}Outline Terms of Service{closeLink}"
|
||||
}
|
||||
892
src/server_manager/messages/master_messages.json
Normal file
892
src/server_manager/messages/master_messages.json
Normal file
|
|
@ -0,0 +1,892 @@
|
|||
{
|
||||
"about_outline": {
|
||||
"message": "Outline is an open source project created by $JIGSAW$ to provide a safer way for news organizations and journalists to access the internet.$NEW_LINE$$NEW_LINE$ Outline is powered by $SHADOWSOCKS$ and is still an early stage product. You can contribute to the code on $GITHUB$, and follow us on $REDDIT$ and $MEDIUM$ to hear when we expand to more platforms and add new features.",
|
||||
"description": "This string appears in a dialog as a paragraph to provide a description of the product. Outline is the product name and should not be translated.",
|
||||
"placeholders": {
|
||||
"GITHUB": {
|
||||
"content": "<a href={gitHubUrl}>GitHub</a>"
|
||||
},
|
||||
"JIGSAW": {
|
||||
"content": "<a href={jigsawUrl}>Jigsaw</a>"
|
||||
},
|
||||
"MEDIUM": {
|
||||
"content": "<a href={mediumUrl}>Medium</a>"
|
||||
},
|
||||
"NEW_LINE": {
|
||||
"content": "<br>"
|
||||
},
|
||||
"REDDIT": {
|
||||
"content": "<a href={redditUrl}>Reddit</a>"
|
||||
},
|
||||
"SHADOWSOCKS": {
|
||||
"content": "<a href={shadowsocksUrl}>Shadowsocks</a>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"about_version": {
|
||||
"message": "Version $VERSION$",
|
||||
"description": "This string appears in a dialog as a header to indicate the version of the application.",
|
||||
"placeholders": {
|
||||
"VERSION": {
|
||||
"content": "{version}",
|
||||
"example": "1.0.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_group_assign_0": {
|
||||
"message": "Navigate to $START_OF_LINK$Instances$END_OF_LINK$.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_group_assign_1": {
|
||||
"message": "Click 'Actions' > 'Networking' > 'Change Security Groups' at the top of the 'Instances' screen.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. Words in quotes should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_assign_2": {
|
||||
"message": "Select the 'outline' Security Group, unselect other security groups.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. 'Security Group' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_assign_3": {
|
||||
"message": "Click 'Assign Security Groups'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. 'Assign Security Groups' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_create_0": {
|
||||
"message": "Once you've created your EC2 instance, open the $START_OF_LINK$EC2 Management Console$END_OF_LINK$.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. EC2 is a product name and should not be translated.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_group_create_1": {
|
||||
"message": "Under 'Network & Security', select 'Security Groups'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. Phrases in quotes should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_create_2": {
|
||||
"message": "Click on 'Create Security Group'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. 'Create Security Group' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_create_3": {
|
||||
"message": "Type 'outline' in the 'Security group name' and 'Description' fields.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. Phrases in quotes should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_create_4": {
|
||||
"message": "Click 'Add Rule'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. 'Add rule' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"aws_group_create_5": {
|
||||
"message": "Select 'All traffic' under 'Type', and 'Anywhere' under 'Source'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a security group in Amazon Web Services. Phrases in quotes should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"cancel": {
|
||||
"message": "Cancel",
|
||||
"description": "This string appears across the application as a button. Clicking it aborts the current flow."
|
||||
},
|
||||
"city_ams": {
|
||||
"message": "Amsterdam",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in the Netherlands."
|
||||
},
|
||||
"city_blr": {
|
||||
"message": "Bangalore",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in India."
|
||||
},
|
||||
"city_fra": {
|
||||
"message": "Frankfurt",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in Germany."
|
||||
},
|
||||
"city_lon": {
|
||||
"message": "London",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in England."
|
||||
},
|
||||
"city_nyc": {
|
||||
"message": "New York",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in the United States."
|
||||
},
|
||||
"city_sfo": {
|
||||
"message": "San Francisco",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in the United States."
|
||||
},
|
||||
"city_sgp": {
|
||||
"message": "Singapore",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the capital of Singapore."
|
||||
},
|
||||
"city_tor": {
|
||||
"message": "Toronto",
|
||||
"description": "This string appears in a card as part of the server creation flow. It allows the user to select the location to deploy a server. Refers to the city in Canada."
|
||||
},
|
||||
"close": {
|
||||
"message": "Close",
|
||||
"description": "This string appears in dialogs as a button. Clicking it dismisses the dialog."
|
||||
},
|
||||
"confirmation_server_destroy": {
|
||||
"message": "Existing users will lose access. This action cannot be undone.",
|
||||
"description": "This string appears in a dialog that requests user confirmation for destroying a server. It informs the user about the consequences of destroying a server. 'Destroy' in this context implies that the server will be deleted."
|
||||
},
|
||||
"confirmation_server_destroy_title": {
|
||||
"message": "Destroy Server?",
|
||||
"description": "This string appears in a dialog that requests user confirmation for destroying a server. 'Destroy' in this context implies that the server will be deleted."
|
||||
},
|
||||
"confirmation_server_remove": {
|
||||
"message": "This action removes your server from the Outline Manager, but does not block proxy access to users. You will still need to manually delete the Outline server from your host machine.",
|
||||
"description": "This string appears in a dialog that requests user confirmation for removing a server from the application. It informs the user about the consequences of removing a server. 'Remove' in this context does not imply server deletion."
|
||||
},
|
||||
"confirmation_server_remove_title": {
|
||||
"message": "Remove Server?",
|
||||
"description": "This string appears in a dialog that requests user confirmation for removing a server from the application. 'Remove' in this context does not imply server deletion."
|
||||
},
|
||||
"destroy": {
|
||||
"message": "Destroy",
|
||||
"description": "This string appears as a button in a dialog that requests user confirmation for destroying a server. Clicking the button causes the server to be deleted."
|
||||
},
|
||||
"digitalocean_disconnect": {
|
||||
"message": "Disconnect",
|
||||
"description": "This string appears as a button in a dialog to disconnect the user's DigitalOcean account from the application. Clicking it signs the user out of DigitalOcean, a cloud server provider."
|
||||
},
|
||||
"digitalocean_disconnect_account": {
|
||||
"message": "Disconnect DigitalOcean account",
|
||||
"description": "This string appears as a header in a dialog to disconnect the user's DigitalOcean account from the application. DigitalOcean is a cloud server provider name and should not be translated."
|
||||
},
|
||||
"digitalocean_unreachable": {
|
||||
"message": "This error may be due to a firewall on your network or temporary connectivity issues with digitalocean.com.",
|
||||
"description": "This string appears in a dialog as a paragraph. It is shown when a DigitalOcean server cannot be reached. DigitalOcean is a cloud server provider."
|
||||
},
|
||||
"done": {
|
||||
"message": "Done",
|
||||
"description": "This string appears across the application as a button. It lets the user indicate that an action, such as entering text or reading a dialog, has been completed."
|
||||
},
|
||||
"error_connectivity": {
|
||||
"message": "We're having trouble connecting to your DigitalOcean account. This is sometimes a temporary problem with DigitalOcean or with your internet connection. If retrying doesn't work, logging into DigitalOcean again should fix the problem.",
|
||||
"description": "This string appears in a dialog as a paragraph. The dialog is shown when an operation on a DigitalOcean server fails due to connectivity issues. The dialog displays buttons that allow the user to retry the operation. DigitalOcean is a cloud server provider name and should not be translated."
|
||||
},
|
||||
"error_connectivity_title": {
|
||||
"message": "Connection problem",
|
||||
"description": "This string appears in a dialog as a header. The dialog is shown when an operation on a server fails due to connectivity issues. The dialog displays buttons that allow the user to retry the operation."
|
||||
},
|
||||
"error_do_account_info": {
|
||||
"message": "Failed to get DigitalOcean account information",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error retrieving the user's DigitalOcean account. DigitalOcean is a cloud server provider name and should not be translated."
|
||||
},
|
||||
"error_do_auth": {
|
||||
"message": "Authentication with DigitalOcean failed",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error when logging in to the user's DigitalOcean account. DigitalOcean is a cloud server provider name and should not be translated."
|
||||
},
|
||||
"error_do_regions": {
|
||||
"message": "Failed to get list of available regions",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error retrieving the regions available for server deployment."
|
||||
},
|
||||
"error_feedback": {
|
||||
"message": "Failed to submit feedback. Please try again.",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error submitting the user's feedback."
|
||||
},
|
||||
"error_key_add": {
|
||||
"message": "Failed to add key",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error creating a server access key."
|
||||
},
|
||||
"error_key_remove": {
|
||||
"message": "Failed to remove key",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error deleting a server access key."
|
||||
},
|
||||
"error_key_rename": {
|
||||
"message": "Failed to rename key",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error renaming a server access key."
|
||||
},
|
||||
"error_keys_get": {
|
||||
"message": "Could not load keys",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error retrieving a server access keys."
|
||||
},
|
||||
"error_licenses": {
|
||||
"message": "Could not load licenses.",
|
||||
"description": "This string appears in a dialog that shows the application's software licenses. It is shown instead of the licenses' text when loading them fails."
|
||||
},
|
||||
"error_metrics": {
|
||||
"message": "Error setting metrics enabled",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error enabling or disabling a server's metrics reporting."
|
||||
},
|
||||
"error_server_creation": {
|
||||
"message": "There was an error creating your Outline server.",
|
||||
"description": "This string appears in an dialog as a paragraph. The dialog is shown when there is an creating a server; the user can retry the operation or destroy the server."
|
||||
},
|
||||
"error_server_destroy": {
|
||||
"message": "Failed to destroy server",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error destroying a server."
|
||||
},
|
||||
"error_server_removed": {
|
||||
"message": "$SERVER_NAME$ no longer present in your DigitalOcean account.",
|
||||
"description": "This string appears in an error notification toast. It is shown when a DigitalOcean server was destroyed outside the application to let the user know that it will not be displayed in the UI. DigitalOcean is a cloud server provider name and should not be translated.",
|
||||
"placeholders": {
|
||||
"SERVER_NAME": {
|
||||
"content": "{serverName}",
|
||||
"example": "New York Outline Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error_server_rename": {
|
||||
"message": "Failed to rename server",
|
||||
"description": "This string appears in an error notification toast. It is shown when there is an error renaming a server."
|
||||
},
|
||||
"error_server_unreachable": {
|
||||
"message": "Your Outline Server was installed correctly, but we are not able to connect to it. Most likely this is because your server's firewall rules are blocking incoming connections. Please review them and make sure to allow incoming TCP connections on ports ranging from 1024 to 65535.",
|
||||
"description": "This string appears in dialog as a paragraph. The dialog is shown when a server is installed successfully but cannot be reached. The dialog provides possible solutions and displays buttons that allow the user to retry reaching the server."
|
||||
},
|
||||
"error_server_unreachable_title": {
|
||||
"message": "Unable to connect to your Outline Server",
|
||||
"description": "This string appears in dialog as a header. The dialog is shown when a server is installed successfully but cannot be reached."
|
||||
},
|
||||
"error_servers_removed": {
|
||||
"message": "$SERVER_NAMES$ no longer present in your DigitalOcean account.",
|
||||
"description": "This string appears in an error notification toast. It is shown when multiple DigitalOcean servers were destroyed outside the application to let the user know that they will not be displayed in the UI. DigitalOcean is a cloud server provider name and should not be translated.",
|
||||
"placeholders": {
|
||||
"SERVER_NAMES": {
|
||||
"content": "{serverNames}",
|
||||
"example": "New York Outline Server, Amsterdam Outline Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
"feedback_cloud_provider": {
|
||||
"message": "Select cloud provider",
|
||||
"description": "This string appears in the feedback dialog as an placeholder within a drop-down. Allows the user to select a cloud provider for certain feedback categories."
|
||||
},
|
||||
"feedback_cloud_provider_error": {
|
||||
"message": "Please select a cloud provider.",
|
||||
"description": "This string appears in the feedback dialog as an error message within a drop-down. The string appears when the user attempts to submit feedback without selecting a cloud provider."
|
||||
},
|
||||
"feedback_connection": {
|
||||
"message": "Can't connect to my server",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that the user cannot connect to their server."
|
||||
},
|
||||
"feedback_connection_others": {
|
||||
"message": "Others can't connect to my server",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that users who have been given access keys cannot connect to the server."
|
||||
},
|
||||
"feedback_disclaimer": {
|
||||
"message": "Please note that our team is only able to answer feedback in English.",
|
||||
"description": "This string appears in the feedback dialog as a paragraph under the feedback form. Lets the user know that, although the application is localized, our team can only respond to feedback in English."
|
||||
},
|
||||
"feedback_email": {
|
||||
"message": "Email address (optional)",
|
||||
"description": "This string appears in the feedback dialog as a label of the email input form."
|
||||
},
|
||||
"feedback_error": {
|
||||
"message": "Please enter feedback.",
|
||||
"description": "This string appears in the feedback dialog as a paragraph below the feedback input form. It is displayed when the user clicks the submit button without having entered feedback in the input form."
|
||||
},
|
||||
"feedback_explanation_install": {
|
||||
"message": "An error occurred while attempting to install Outline on your server. If you haven't been able to figure out a solution, please consider sending us feedback and telling us your email address (optional) so that we can get back to you.",
|
||||
"description": "This string appears in the feedback dialog as a paragraph above the feedback input form. The feedback dialog gets automatically displayed with this message when a server installation fails."
|
||||
},
|
||||
"feedback_general": {
|
||||
"message": "General feedback",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that the user is providing general feedback."
|
||||
},
|
||||
"feedback_install": {
|
||||
"message": "Having trouble installing Outline",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that the user cannot install Outline on their server."
|
||||
},
|
||||
"feedback_label": {
|
||||
"message": "Your feedback",
|
||||
"description": "This string appears in the feedback dialog as a placeholder of the feedback input form."
|
||||
},
|
||||
"feedback_management": {
|
||||
"message": "Having trouble managing my server",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that the user is having issues managing their server."
|
||||
},
|
||||
"feedback_other": {
|
||||
"message": "Other",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of cloud providers. Indicates that the user has a server on an unlisted cloud provider."
|
||||
},
|
||||
"feedback_privacy": {
|
||||
"message": "Your feedback, email address (if provided) and additional information referred to in the $START_OF_LINK$privacy policy$END_OF_LINK$ will be sent to the Outline team.",
|
||||
"description": "This string appears in the feedback dialog as paragraph below the feedback input form. Lets the user know how their feedback and personal information will be handled.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"feedback_submit": {
|
||||
"message": "Submit",
|
||||
"description": "This string appears in the feedback dialog as a button. Clicking it submits the feedback form."
|
||||
},
|
||||
"feedback_suggestion": {
|
||||
"message": "Suggestions",
|
||||
"description": "This string appears in the feedback dialog as an option within a drop-down of feedback categories. Indicates that the user is providing a product suggestion."
|
||||
},
|
||||
"feedback_title_generic": {
|
||||
"message": "Send Feedback",
|
||||
"description": "This string appears in the feedback dialog as a header."
|
||||
},
|
||||
"feedback_title_install": {
|
||||
"message": "Outline Server Installation Failed",
|
||||
"description": "This string appears in the feedback dialog as a header. The feedback dialog gets automatically displayed with this header when a server installation fails."
|
||||
},
|
||||
"gcp_firewall_assign_0": {
|
||||
"message": "Navigate to the $START_OF_LINK$VM instances screen$END_OF_LINK$.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gcp_firewall_assign_1": {
|
||||
"message": "Click on the instance where you want to host Outline.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform."
|
||||
},
|
||||
"gcp_firewall_assign_2": {
|
||||
"message": "Click 'EDIT' at the top of the VM Instance details screen.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'EDIT' should be translated and included untranslated in parentheses. VM is an acronym for virtual machine."
|
||||
},
|
||||
"gcp_firewall_assign_3": {
|
||||
"message": "Type 'outline' in the 'Network tags' field.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Network tags' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_assign_4": {
|
||||
"message": "Click 'SAVE'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'SAVE' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_create_0": {
|
||||
"message": "$START_OF_LINK$Add a new firewall rule$END_OF_LINK$ to your Compute Engine project.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. Compute Engine is a product of Google Cloud Platform and should not be translated.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gcp_firewall_create_1": {
|
||||
"message": "Type 'outline' in the 'Name' field.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Name' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_create_2": {
|
||||
"message": "Type 'outline' in the 'Target tags' field.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Target tags' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_create_3": {
|
||||
"message": "Type '0.0.0.0/0' in the 'Source IP ranges' field.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Source IP ranges' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_create_4": {
|
||||
"message": "Select 'Allow all' under 'Protocols and ports'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Allow all' and 'Protocols and ports' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"gcp_firewall_create_5": {
|
||||
"message": "Click 'Create'.",
|
||||
"description": "This string appears within the server setup view as an item of a list that provides instructions to configure a firewall in Google Cloud Platform. 'Create' should be translated and included untranslated in parentheses."
|
||||
},
|
||||
"key": {
|
||||
"message": "Key",
|
||||
"description": "This string appears in the server view as a placeholder for a newly created access key."
|
||||
},
|
||||
"manual_server_assign_firewall": {
|
||||
"message": "Assign firewall rule",
|
||||
"description": "This string appears in the server setup view as a sub-header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_assign_group": {
|
||||
"message": "Assign Security Group",
|
||||
"description": "This string appears in the server setup view as a sub-header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_create_firewall": {
|
||||
"message": "Create a firewall rule",
|
||||
"description": "This string appears in the server setup view as a sub-header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_create_group": {
|
||||
"message": "Create a Security Group",
|
||||
"description": "This string appears in the server setup view as a sub-header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_description": {
|
||||
"message": "These steps will help you install Outline on a $CLOUD_PROVIDER$ Linux server.",
|
||||
"description": "This string appears in the server setup view as a header. Lets the user know that the following sections provide instructions on how to install Outline on their server.",
|
||||
"placeholders": {
|
||||
"CLOUD_PROVIDER": {
|
||||
"content": "{cloudProvider}",
|
||||
"example": "Amazon Web Services"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manual_server_firewall": {
|
||||
"message": "Configure your firewall",
|
||||
"description": "This string appears in the server setup view as the header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_install_paste": {
|
||||
"message": "Paste your installation output here.",
|
||||
"description": "This string appears in the server setup view as a header of a section that contains an input form. The user must enter the output of the server installation script to manage their server in the application."
|
||||
},
|
||||
"manual_server_install_run": {
|
||||
"message": "Log into your server, and run this command.",
|
||||
"description": "This string appears in the server setup view as a header of a section that displays a command to install Outline on their server."
|
||||
},
|
||||
"manual_server_instructions": {
|
||||
"message": "Instructions",
|
||||
"description": "This string appears in the server setup view as a toggle of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"manual_server_show_me": {
|
||||
"message": "Show me where",
|
||||
"description": "This string appears in the server setup view as a button. Clicking the button opens a link to the cloud server provider management console."
|
||||
},
|
||||
"manual_server_title": {
|
||||
"message": "Follow the instructions below",
|
||||
"description": "This string appears in the server setup view as a header. Communicates to the user that they need to perform a series of actions to install Outline on their server."
|
||||
},
|
||||
"metrics_description": {
|
||||
"message": "Share anonymized metrics to help improve the reliability and performance of Outline, for you and for those you share your server with. $START_OF_LINK$Learn more.$END_OF_LINK$",
|
||||
"description": "This string appears in the server settings view as a paragraph next to a toggle that enables/disables server metrics reporting.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metrics_share": {
|
||||
"message": "Share metrics",
|
||||
"description": "This string appears as a button of a dialog that prompts the user to share server metrics. Clicking it enables server metrics reporting."
|
||||
},
|
||||
"metrics_skip": {
|
||||
"message": "Skip",
|
||||
"description": "This string appears as a button of a dialog that prompts the user to share server metrics. Clicking it dismisses the dialog."
|
||||
},
|
||||
"metrics_title": {
|
||||
"message": "Metrics sharing",
|
||||
"description": "This string appears as the header of a dialog that prompts the user to share server metrics."
|
||||
},
|
||||
"nav_about": {
|
||||
"message": "About",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens a dialog with information about Outline."
|
||||
},
|
||||
"nav_data_collection": {
|
||||
"message": "Data collection",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens Outline's data collection policy in the browser."
|
||||
},
|
||||
"nav_feedback": {
|
||||
"message": "Feedback",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens a dialog that allows the user to submit feedback."
|
||||
},
|
||||
"nav_help": {
|
||||
"message": "Help",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens Outline's support website."
|
||||
},
|
||||
"nav_licenses": {
|
||||
"message": "Licenses",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens a dialog listing Outline's software licenses."
|
||||
},
|
||||
"nav_privacy": {
|
||||
"message": "Privacy",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens Outline's privacy policy in the browser."
|
||||
},
|
||||
"nav_terms": {
|
||||
"message": "Terms",
|
||||
"description": "This string appears in an application drawer as a navigation link. Clicking it opens Outline's terms of service in the browser."
|
||||
},
|
||||
"notification_app_update": {
|
||||
"message": "An updated version of the Outline Manager has been downloaded. It will be installed when you restart the application.",
|
||||
"description": "This string appears in a transient notification toast. It is shown when an update to the application is ready to install."
|
||||
},
|
||||
"notification_feedback_thanks": {
|
||||
"message": "Thanks for helping us improve! We love hearing from you.",
|
||||
"description": "This string appears in a transient notification toast. It is shown when the user has successfully submitted feedback."
|
||||
},
|
||||
"notification_key_added": {
|
||||
"message": "Key added",
|
||||
"description": "This string appears in a transient notification toast. It is shown when a server access key has been successfully created."
|
||||
},
|
||||
"notification_key_removed": {
|
||||
"message": "Key removed",
|
||||
"description": "This string appears in a transient notification toast. It is shown when a server access key has been successfully removed."
|
||||
},
|
||||
"notification_server_destroyed": {
|
||||
"message": "Server destroyed",
|
||||
"description": "This string appears in a transient notification toast. It is shown when a server has been successfully destroyed."
|
||||
},
|
||||
"notification_server_exists": {
|
||||
"message": "Server already added",
|
||||
"description": "This string appears in a transient notification toast. It is shown when the user attempts to add server that is already present in the application."
|
||||
},
|
||||
"notification_server_removed": {
|
||||
"message": "Server removed",
|
||||
"description": "This string appears in a transient notification toast. It is shown when a server has been successfully removed from the application."
|
||||
},
|
||||
"oauth_account_active": {
|
||||
"message": "Your DigitalOcean account has been activated.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a sub-header. Lets the user know their DigitalOcean account is active. DigitalOcean is a cloud provider name and should not be translated."
|
||||
},
|
||||
"oauth_account_active_tag": {
|
||||
"message": "Account activated! Loading server locations...",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a paragraph. Displayed when the user's DigitalOcean account has been successfully activated."
|
||||
},
|
||||
"oauth_activate_account": {
|
||||
"message": "Activate you DigitalOcean account.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a header. Displayed when the account has been created but not yet active. DigitalOcean is a cloud provider name and should not be translated."
|
||||
},
|
||||
"oauth_billing": {
|
||||
"message": "Enter your billing information on digitalocean.com and return to the app once you are done.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a sub-header. Prompts the user to enter their billing information on DigitalOcean's website."
|
||||
},
|
||||
"oauth_billing_tag": {
|
||||
"message": "Enter billing information...",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a paragraph. Prompts the user to enter their billing information on DigitalOcean's website."
|
||||
},
|
||||
"oauth_connect_description": {
|
||||
"message": "With your account, Outline makes it easy to create a server and get connected.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a sub-header. Displayed when the user has not yet authorized Outline to access their DigitalOcean account."
|
||||
},
|
||||
"oauth_connect_tag": {
|
||||
"message": "Waiting to connect your account...",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a paragraph. Displayed when the user has not yet authorized Outline to access their DigitalOcean account."
|
||||
},
|
||||
"oauth_connect_title": {
|
||||
"message": "Sign in or create an account with DigitalOcean.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a header. Displayed when the user has not yet signed in to DigitalOcean or created an account."
|
||||
},
|
||||
"oauth_sign_out": {
|
||||
"message": "Sign Out",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a button. Displayed when the user has authorized Outline to access their account. Clicking it aborts the account creation flow and signs out the user."
|
||||
},
|
||||
"oauth_verify": {
|
||||
"message": "Check your inbox for an email from DigitalOcean, and click the link in it to confirm your account.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a sub-header. Displayed when the user has not yet entered billing information to activate their DigitalOcean account. DigitalOcean is a cloud provider name and should not be translated."
|
||||
},
|
||||
"oauth_verify_tag": {
|
||||
"message": "Confirm your email...",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a paragraph. Displayed when the user has not yet confirmed the registered email for their DigitalOcean account."
|
||||
},
|
||||
"oauth_verify_title": {
|
||||
"message": "Activate you DigitalOcean account.",
|
||||
"description": "This string appears in the DigitalOcean account creation flow as a title. Displayed when the user has not yet activated their DigitalOcean account."
|
||||
},
|
||||
"okay": {
|
||||
"message": "OK",
|
||||
"description": "This string appears across the application as a button. It lets the user acknowledge displayed information. Clicking dismisses the enclosing UI element."
|
||||
},
|
||||
"region_description": {
|
||||
"message": "This is where your internet experience will come from.",
|
||||
"description": "This string appears within the server creation flow, as a sub-header of the server selection view. Lets the user know about the implications of selecting a server location."
|
||||
},
|
||||
"region_setup": {
|
||||
"message": "Set up Outline",
|
||||
"description": "This string appears within the server creation flow, as a button of the server selection view. Clicking it creates an Outline server at the selected location. 'Set up' means install and run the Outline server software."
|
||||
},
|
||||
"region_title": {
|
||||
"message": "Select the location of your server.",
|
||||
"description": "This string appears within the server creation flow, as the header of the server selection view."
|
||||
},
|
||||
"remove": {
|
||||
"message": "Remove",
|
||||
"description": "This string appears across the application as a button. It allows the user to confirm the removal of a server or access key."
|
||||
},
|
||||
"retry": {
|
||||
"message": "Retry",
|
||||
"description": "This string appears across the application as a button. It allows the user to retry a failed operation."
|
||||
},
|
||||
"server_access": {
|
||||
"message": "Server access",
|
||||
"description": "This string appears within the server view as the header of a card that displays the number of server access keys."
|
||||
},
|
||||
"server_access_key_new": {
|
||||
"message": "Add new key",
|
||||
"description": "This string appears within the server view as a button. Clicking it creates a new server access key."
|
||||
},
|
||||
"server_access_key_rename": {
|
||||
"message": "Rename",
|
||||
"description": "This string appears within the server view as a button of a drop-down to manage a server access key. Clicking it renames the access key."
|
||||
},
|
||||
"server_access_keys": {
|
||||
"message": "Access keys",
|
||||
"description": "This string appears within the server view as a header of a table column that displays server access keys."
|
||||
},
|
||||
"server_connect_devices": {
|
||||
"message": "Connect your devices",
|
||||
"description": "This string appears within the server view as a sub-header for the default server access key. This key is meant to be used by the server administrator."
|
||||
},
|
||||
"server_connections": {
|
||||
"message": "Connections",
|
||||
"description": "This string appears within the server view as a header of the section that displays server information and access keys."
|
||||
},
|
||||
"server_data_transfer": {
|
||||
"message": "Data transferred / 30 days",
|
||||
"description": "This string appears within the server view as the header of a card that displays the amount of data transferred by the server."
|
||||
},
|
||||
"server_data_used": {
|
||||
"message": "Allowance used / 30 days",
|
||||
"description": "This string appears within the server view as the header of a card that displays the amount of data transferred by the server as a percentage of the total available data."
|
||||
},
|
||||
"server_destroy": {
|
||||
"message": "Destroy server",
|
||||
"description": "This string appears within the server view as a button of a drop-down to manage a server. Clicking it opens a confirmation dialog to destroy the server."
|
||||
},
|
||||
"server_help_access_key_description": {
|
||||
"message": "Share access keys with friends, so they can connect to your Outline server. They can use the same access key on all their devices.",
|
||||
"description": "This string appears within a help bubble as a paragraph. The help bubble is displayed when a server is installed. Informs to the user how to share access to their server."
|
||||
},
|
||||
"server_help_access_key_next": {
|
||||
"message": "Next",
|
||||
"description": "This string appears within a help bubble as a button. Clicking it displays the next help bubble."
|
||||
},
|
||||
"server_help_access_key_title": {
|
||||
"message": "Create keys, share access",
|
||||
"description": "This string appears within a help bubble as a header. The help bubble provides information about sharing access to the server through access keys."
|
||||
},
|
||||
"server_help_connection_description": {
|
||||
"message": "Click here to install the Outline client app, using your personal access key to your Outline server.",
|
||||
"description": "This string appears within a help bubble as a paragraph. Informs the user how to install the Outline clients and get connected to the server."
|
||||
},
|
||||
"server_help_connection_ok": {
|
||||
"message": "Okay, got it!",
|
||||
"description": "This string appears within a help bubble as a button. Clicking it dismisses the help bubble."
|
||||
},
|
||||
"server_help_connection_title": {
|
||||
"message": "You are not connected yet!",
|
||||
"description": "This string appears within a help bubble as a header. The help bubble provides information about connecting to the server."
|
||||
},
|
||||
"server_keys": {
|
||||
"message": "Keys",
|
||||
"description": "This string appears within the server view as the unit of a card that displays the number of server access keys."
|
||||
},
|
||||
"server_my_access_key": {
|
||||
"message": "My access key",
|
||||
"description": "This string appears within the server view as the header for the default server access key. This key is meant to be used by the server administrator."
|
||||
},
|
||||
"server_name": {
|
||||
"message": "Outline Server $SEVER_LOCATION$",
|
||||
"description": "This string appears within the server view and in the application drawer. It is the default name for a newly created server.",
|
||||
"placeholders": {
|
||||
"SEVER_LOCATION": {
|
||||
"content": "{serverLocation}",
|
||||
"example": "New York"
|
||||
}
|
||||
}
|
||||
},
|
||||
"server_remove": {
|
||||
"message": "Remove server",
|
||||
"description": "This string appears within the server view as a button of a drop-down to manage a server. Clicking it opens a confirmation dialog to remove the server from the application."
|
||||
},
|
||||
"server_settings": {
|
||||
"message": "Settings",
|
||||
"description": "This string appears within the server view as a header of the section that displays server settings."
|
||||
},
|
||||
"server_unreachable": {
|
||||
"message": "Server unreachable",
|
||||
"description": "This string appears within a server view as a header. Displayed when a server's information cannot be displayed because it is not reachable."
|
||||
},
|
||||
"server_unreachable_description": {
|
||||
"message": "We're having issues connecting to this server.",
|
||||
"description": "This string appears within a server view as a paragraph. Informs the user that a server's information cannot be displayed because it is not reachable."
|
||||
},
|
||||
"server_unreachable_managed_description": {
|
||||
"message": "Try again or remove this server from the application.",
|
||||
"description": "This string appears within a server view as a header. Displayed when a server's information cannot be displayed because it is not reachable. Prompts the user to retry contacting the server or remove it from the application."
|
||||
},
|
||||
"server_unreachable_manual_description": {
|
||||
"message": "Try again or destroy this server and the virtual host.",
|
||||
"description": "This string appears within a server view as a header. Displayed when a server's information cannot be displayed because it is not reachable. Prompts the user to retry contacting the server or destroy it."
|
||||
},
|
||||
"server_usage": {
|
||||
"message": "Usage / 30 days",
|
||||
"description": "This string appears within the server view as a header of a table column that displays the breakdown of data usage by access key."
|
||||
},
|
||||
"servers_add": {
|
||||
"message": "Add server",
|
||||
"description": "This string appears in an application drawer as a button. Clicking it starts the server setup flow."
|
||||
},
|
||||
"servers_digitalocean": {
|
||||
"message": "DigitalOcean servers",
|
||||
"description": "This string appears in an application drawer as the header of a section that displays the list of DigitalOcean servers. DigitalOcean is a cloud server provider name and should not be translated."
|
||||
},
|
||||
"servers_manual": {
|
||||
"message": "Servers",
|
||||
"description": "This string appears in an application drawer as the header of a section that displays a list of servers."
|
||||
},
|
||||
"settings_access_key_port": {
|
||||
"message": "Port for new access keys",
|
||||
"description": "This string appears in the server settings view as a label for the server port number used to create new access keys."
|
||||
},
|
||||
"settings_metrics_header": {
|
||||
"message": "Share anonymous metrics",
|
||||
"description": "This string appears in the server settings view as a header of the section to configure server metrics reporting."
|
||||
},
|
||||
"settings_server_api_url": {
|
||||
"message": "Management API URL",
|
||||
"description": "This string appears in the server settings view as a label for the server's management API URL. API stands for application programming interface; the acronym should not be translated."
|
||||
},
|
||||
"settings_server_cost": {
|
||||
"message": "Monthly cost",
|
||||
"description": "This string appears in the server settings view as a label for the server's monthly cost."
|
||||
},
|
||||
"settings_server_creation": {
|
||||
"message": "Created",
|
||||
"description": "This string appears in the server settings view as a label for the server's creation date."
|
||||
},
|
||||
"settings_server_hostname": {
|
||||
"message": "Hostname",
|
||||
"description": "This string appears in the server settings view as a label for the server's IP address or domain name."
|
||||
},
|
||||
"settings_server_id": {
|
||||
"message": "Server ID",
|
||||
"description": "This string appears in the server settings view as a label for the server's unique identifier."
|
||||
},
|
||||
"settings_server_info": {
|
||||
"message": "Server Information",
|
||||
"description": "This string appears in the server settings view as a header of the section that displays server details."
|
||||
},
|
||||
"settings_server_location": {
|
||||
"message": "Server location",
|
||||
"description": "This string appears in the server settings view as a label for the server's location."
|
||||
},
|
||||
"settings_server_name": {
|
||||
"message": "Name",
|
||||
"description": "This string appears in the server settings view as a label for the server's name."
|
||||
},
|
||||
"settings_server_rename": {
|
||||
"message": "Set a new name for your server. Note that this will not be reflected on the devices of the users that you invited to connect to it.",
|
||||
"description": "This string appears in the server settings view as a paragraph below the server's name. Informs the user about the implications of renaming a server."
|
||||
},
|
||||
"settings_transfer_limit": {
|
||||
"message": "Data transfer allowance",
|
||||
"description": "This string appears in the server settings view as a label for the server's data transfer allowance."
|
||||
},
|
||||
"setup_action": {
|
||||
"message": "Set up",
|
||||
"description": "This string appears in the server setup view as a button. Clicking it starts the server setup flow. 'Set up' means install and run the Outline server software."
|
||||
},
|
||||
"setup_advanced": {
|
||||
"message": "Advanced",
|
||||
"description": "This string appears in the server setup view as a label. Advanced in this context implies that the user will have to follow technical instructions to install Outline."
|
||||
},
|
||||
"setup_anywhere": {
|
||||
"message": "Set up Outline anywhere",
|
||||
"description": "This string appears in the server setup view as a header within a card. The card provides information about installing Outline on an arbitrary cloud server provider."
|
||||
},
|
||||
"setup_create": {
|
||||
"message": "Create server",
|
||||
"description": "This string appears in the server setup view as a button. Clicking it starts the server creation flow."
|
||||
},
|
||||
"setup_description": {
|
||||
"message": "Don't have a server? Create an account with DigitalOcean.",
|
||||
"description": "This string appears in the server setup view as a sub-header. Prompts the user to create a DigitalOcean account to deploy Outline servers. DigitalOcean is a cloud provider name and should not be translated."
|
||||
},
|
||||
"setup_do_cancel": {
|
||||
"message": "Cancel at anytime",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features."
|
||||
},
|
||||
"setup_do_cost": {
|
||||
"message": "Only US$5 a month",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features."
|
||||
},
|
||||
"setup_do_create": {
|
||||
"message": "Create a new server with your DigitalOcean account for an additional US$5/30 days for 1 TB of data transfer.",
|
||||
"description": "This string appears in the server setup view as a paragraph within a card. Describes Outline servers' features when deployed on DigitalOcean. DigitalOcean is a cloud provider name and should not be translated; TB is an abbreviation for terabyte and should not be translated"
|
||||
},
|
||||
"setup_do_data": {
|
||||
"message": "1 TB data transfer allowance",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features. Refers to the monthly amount of transfer data offered by a cloud server provider. TB is an abbreviation for terabyte and should not be translated."
|
||||
},
|
||||
"setup_do_description": {
|
||||
"message": "This could take up to two minutes. You can destroy this server at anytime.",
|
||||
"description": "This string appears in the server setup view as a sub-header. Displayed when a server is being created along a progress bar."
|
||||
},
|
||||
"setup_do_easiest": {
|
||||
"message": "Easiest setup process",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features."
|
||||
},
|
||||
"setup_do_title": {
|
||||
"message": "Setting up Outline.",
|
||||
"description": "This string appears in the server setup view as a header. Displayed when a server is being created along a progress bar."
|
||||
},
|
||||
"setup_firewall_instructions": {
|
||||
"message": "Firewall instructions",
|
||||
"description": "This string appears in the server setup view as the header of a section that provides instructions to configure the server's firewall."
|
||||
},
|
||||
"setup_recommended": {
|
||||
"message": "Recommended",
|
||||
"description": "This string appears in the server setup view as a label. Describes Outline servers deployment on DigitalOcean, which is easier from a user perspective."
|
||||
},
|
||||
"setup_simple_commands": {
|
||||
"message": "Simple install commands",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features."
|
||||
},
|
||||
"setup_step-by-step": {
|
||||
"message": "Step-by-step set-up guide",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features."
|
||||
},
|
||||
"setup_tested": {
|
||||
"message": "Tested on VULTR, Linode, and Liquid Web",
|
||||
"description": "This string appears in the server setup view as an item of a list describing Outline's features. VULTR, Linode, and Liquid Web a cloud provider names and should not be translated."
|
||||
},
|
||||
"setup_title": {
|
||||
"message": "Choose a cloud service to set up Outline.",
|
||||
"description": "This string appears in the server setup view as a header. Prompts the user to create deploy Outline servers on the cloud provider of their choice. 'Set up' means install and run the Outline server software."
|
||||
},
|
||||
"share_description": {
|
||||
"message": "Copy this invitation and send it from a communication tool you trust. $START_OF_LINK$Need help?$END_OF_LINK$",
|
||||
"description": "This string appears as a sub-header of a dialog that provides instructions on how to share access to a server.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"share_invite": {
|
||||
"message": "You\u2019re invited to connect to my Outline server. Use it to access the open internet, no matter where you are. Follow the instructions on your invitation link below to download the Outline App and get connected.",
|
||||
"description": "This string appears as a paragraph within a dialog that provides an invitation to share access to a server. Belongs to the instructions for the user with whom access is being shared."
|
||||
},
|
||||
"share_invite_copied": {
|
||||
"message": "Copied to clipboard",
|
||||
"description": "This string appears as a label within a dialog that provides an invitation to share access to a server. Displayed when the user clicks a button to copy the invitation text to the clipboard."
|
||||
},
|
||||
"share_invite_copy": {
|
||||
"message": "Copy invitation",
|
||||
"description": "This string appears as a button within a dialog that provides an invitation to share access to a server. Clicking it copies the invitation instructions text to the clipboard."
|
||||
},
|
||||
"share_invite_copy_access_key": {
|
||||
"message": "Copy your access key:",
|
||||
"description": "This string appears as a paragraph within a dialog that provides an invitation to share access to a server. Belongs to the instructions for the user with whom access is being shared."
|
||||
},
|
||||
"share_invite_instructions": {
|
||||
"message": "Follow our invitation instructions on GitHub:",
|
||||
"description": "This string appears as a list item within a dialog that provides an invitation to share access to a server. Belongs to the instructions for the user with whom access is being shared."
|
||||
},
|
||||
"share_invite_trouble": {
|
||||
"message": "Having trouble accessing the invitation link?",
|
||||
"description": "This string appears as a paragraph within a dialog that provides an invitation to share access to a server. Belongs to the instructions for the user with whom access is being shared."
|
||||
},
|
||||
"share_title": {
|
||||
"message": "Share access",
|
||||
"description": "This string appears as the header of a dialog that provides an invitation to share access to a server."
|
||||
},
|
||||
"terms_of_service": {
|
||||
"message": "I have read and understood the $START_OF_LINK$Outline Terms of Service$END_OF_LINK$",
|
||||
"description": "This string appears within an overlay the first time the user runs the app. Prompts the user to review and accept Outline's terms of service.",
|
||||
"placeholders": {
|
||||
"END_OF_LINK": {
|
||||
"content": "{closeLink}"
|
||||
},
|
||||
"START_OF_LINK": {
|
||||
"content": "{openLink}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ export interface ManagedServerRepository {
|
|||
getRegionMap(): Promise<Readonly<RegionMap>>;
|
||||
// Creates a server and returning it when it becomes active (i.e. the server has
|
||||
// created, not necessarily once shadowbox installation has finished).
|
||||
createServer(region: RegionId): Promise<ManagedServer>;
|
||||
createServer(region: RegionId, name: string): Promise<ManagedServer>;
|
||||
}
|
||||
|
||||
// Configuration for manual servers. This is the output emitted from the
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
<link rel='import' href='../bower_components/polymer/polymer.html'>
|
||||
<link rel="import" href="../bower_components/app-layout/app-drawer/app-drawer.html">
|
||||
<link rel="import" href="../bower_components/app-layout/app-drawer-layout/app-drawer-layout.html">
|
||||
<link rel="import" href="../bower_components/app-localize-behavior/app-localize-behavior.html">
|
||||
<link rel='import' href='../bower_components/iron-icon/iron-icon.html'>
|
||||
<link rel='import' href='../bower_components/iron-icons/iron-icons.html'>
|
||||
<link rel='import' href='../bower_components/iron-pages/iron-pages.html'>
|
||||
|
|
@ -288,7 +289,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<outline-tos-view id="tosView" has-accepted-terms-of-service={{userAcceptedTos}} hidden$="{{hasAcceptedTos}}"></outline-tos-view>
|
||||
<outline-tos-view id="tosView" has-accepted-terms-of-service={{userAcceptedTos}} hidden$="{{hasAcceptedTos}}" localize="[[localize]]"></outline-tos-view>
|
||||
|
||||
<div hidden$="{{!hasAcceptedTos}}">
|
||||
<!-- This responsive width sets the minimum layout area to 648px. -->
|
||||
|
|
@ -304,13 +305,13 @@
|
|||
<!-- DigitalOcean servers -->
|
||||
<div class="servers-section" hidden$="{{!isSignedInToDigitalOcean}}">
|
||||
<div class="servers-header">
|
||||
<span>DigitalOcean servers</span>
|
||||
<span>[[localize('servers-digitalocean')]]</span>
|
||||
<paper-menu-button horizontal-align="left" class="" close-on-activate no-animations dynamic-align no-overlap>
|
||||
<paper-icon-button icon="more-vert" slot="dropdown-trigger"></paper-icon-button>
|
||||
<div class="do-overflow-menu" slot="dropdown-content">
|
||||
<h4>Disconnect DigitalOcean account</h4>
|
||||
<h4>[[localize('digitalocean-disconnect-account')]]</h4>
|
||||
<div class="account-info"><img src="images/digital_ocean_logo.svg" />{{adminEmail}}</div>
|
||||
<div class="sign-out-button" on-tap="signOutTapped">Disconnect</div>
|
||||
<div class="sign-out-button" on-tap="signOutTapped">[[localize('digitalocean-disconnect')]]</div>
|
||||
</div>
|
||||
</paper-menu-button>
|
||||
</div>
|
||||
|
|
@ -326,7 +327,7 @@
|
|||
<!-- Manual servers -->
|
||||
<div class="servers-section" hidden$="{{!hasManualServers}}">
|
||||
<div class="servers-header">
|
||||
<span>Servers</span>
|
||||
<span>[[localize('servers-manual')]]</span>
|
||||
</div>
|
||||
<div class="servers-container">
|
||||
<template is="dom-repeat" items="{{serverList}}" as="server" filter="_isServerManual" sort="_sortServersByName">
|
||||
|
|
@ -342,20 +343,20 @@
|
|||
<!-- Add server -->
|
||||
<div class="add-server-section" on-tap="showIntro">
|
||||
<paper-icon-item>
|
||||
<iron-icon icon="add" slot="item-icon"></iron-icon>Add server
|
||||
<iron-icon icon="add" slot="item-icon"></iron-icon>[[localize('servers-add')]]
|
||||
</paper-icon-item>
|
||||
</div>
|
||||
|
||||
<!-- Links section -->
|
||||
<paper-listbox on-tap="maybeCloseDrawer">
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection">Data collection</a>
|
||||
<span on-tap="submitFeedbackTapped">Feedback</span>
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/">Help</a>
|
||||
<span on-tap="aboutTapped">About</span>
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection">[[localize('nav-data-collection')]]</a>
|
||||
<span on-tap="submitFeedbackTapped">[[localize('nav-feedback')]]</span>
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/">[[localize('nav-help')]]</a>
|
||||
<span on-tap="aboutTapped">[[localize('nav-about')]]</span>
|
||||
<div class="legal-links">
|
||||
<a href="https://www.google.com/policies/privacy/">Privacy</a>
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/static_downloads/Outline-Terms-of-Service.html">Terms</a>
|
||||
<span on-tap="showLicensesTapped">Licenses</span>
|
||||
<a href="https://www.google.com/policies/privacy/">[[localize('nav-privacy')]]</a>
|
||||
<a href="https://s3.amazonaws.com/outline-vpn/static_downloads/Outline-Terms-of-Service.html">[[localize('nav-terms')]]</a>
|
||||
<span on-tap="showLicensesTapped">[[localize('nav-licenses')]]</span>
|
||||
</div>
|
||||
</paper-listbox>
|
||||
</app-drawer>
|
||||
|
|
@ -363,14 +364,14 @@
|
|||
<app-header-layout>
|
||||
<div class="app-container">
|
||||
<iron-pages attr-for-selected='id' selected='{{ currentPage }}'>
|
||||
<outline-intro-step id='intro' is-signed-in-to-digital-ocean='{{isSignedInToDigitalOcean}}' digital-ocean-email='{{adminEmail}}'></outline-intro-step>
|
||||
<outline-do-oauth-step id='digitalOceanOauth'></outline-do-oauth-step>
|
||||
<outline-manual-server-entry id='manualEntry'></outline-manual-server-entry>
|
||||
<outline-region-picker-step id='regionPicker'></outline-region-picker-step>
|
||||
<outline-server-progress-step id='serverProgressStep'></outline-server-progress-step>
|
||||
<outline-intro-step id='intro' is-signed-in-to-digital-ocean='{{isSignedInToDigitalOcean}}' digital-ocean-email='{{adminEmail}}' localize="[[localize]]"></outline-intro-step>
|
||||
<outline-do-oauth-step id="digitalOceanOauth" localize="[[localize]]"></outline-do-oauth-step>
|
||||
<outline-manual-server-entry id="manualEntry" localize="[[localize]]"></outline-manual-server-entry>
|
||||
<outline-region-picker-step id="regionPicker" localize="[[localize]]"></outline-region-picker-step>
|
||||
<outline-server-progress-step id="serverProgressStep" localize="[[localize]]"></outline-server-progress-step>
|
||||
<div id="serverView">
|
||||
<template is="dom-repeat" items="{{serverList}}" as="server">
|
||||
<outline-server-view id="serverView-{{_base64Encode(server.id)}}" hidden$="{{!_isServerSelected(selectedServer, server)}}"></outline-server-view>
|
||||
<outline-server-view id="serverView-{{_base64Encode(server.id)}}" localize="[[localize]]" hidden$="{{!_isServerSelected(selectedServer, server)}}"></outline-server-view>
|
||||
</template>
|
||||
</div>
|
||||
</iron-pages>
|
||||
|
|
@ -415,27 +416,27 @@
|
|||
<paper-toast id='toast'><paper-icon-button icon='icons:close' on-tap='closeError'></paper-icon-button></paper-toast>
|
||||
|
||||
<!-- Modal dialogs must be outside the app container; otherwise the backdrop covers them. -->
|
||||
<outline-feedback-dialog id='feedbackDialog'></outline-feedback-dialog>
|
||||
<outline-about-dialog id='aboutDialog' outline-version='[[outlineVersion]]'></outline-about-dialog>
|
||||
<outline-modal-dialog id='modalDialog'></outline-modal-dialog>
|
||||
<outline-share-dialog id="shareDialog"></outline-share-dialog>
|
||||
<outline-metrics-option-dialog id="metricsDialog"></outline-metrics-option-dialog>
|
||||
<outline-feedback-dialog id="feedbackDialog" localize="[[localize]]"></outline-feedback-dialog>
|
||||
<outline-about-dialog id="aboutDialog" outline-version="[[outlineVersion]]" localize="[[localize]]"></outline-about-dialog>
|
||||
<outline-modal-dialog id="modalDialog"></outline-modal-dialog>
|
||||
<outline-share-dialog id="shareDialog" localize="[[localize]]"></outline-share-dialog>
|
||||
<outline-metrics-option-dialog id="metricsDialog" localize="[[localize]]"></outline-metrics-option-dialog>
|
||||
|
||||
<paper-dialog id="getConnectedDialog" modal>
|
||||
<!-- iframe gets inserted here once we are given the invite URL. -->
|
||||
<div class="buttons">
|
||||
<paper-button on-tap="closeGetConnectedDialog" autofocus>Close</paper-button>
|
||||
<paper-button on-tap="closeGetConnectedDialog" autofocus>[[localize('close')]]</paper-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
|
||||
<paper-dialog id="licenses" modal restoreFocusOnClose>
|
||||
<paper-dialog-scrollable>
|
||||
<code id="licensesText">
|
||||
Could not load license.txt.
|
||||
[[localize('error-licenses')]]
|
||||
</code>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="buttons">
|
||||
<paper-button dialog-dismiss autofocus>Close</paper-button>
|
||||
<paper-button dialog-dismiss autofocus>[[localize('close')]]</paper-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
|
||||
|
|
@ -445,7 +446,19 @@
|
|||
const TOS_ACK_LOCAL_STORAGE_KEY = 'tos-ack';
|
||||
Polymer({
|
||||
is: 'app-root',
|
||||
behaviors: [
|
||||
Polymer.AppLocalizeBehavior
|
||||
],
|
||||
properties: {
|
||||
useKeyIfMissing: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
readonly: true,
|
||||
value: 'en'
|
||||
},
|
||||
serverList: {
|
||||
type: Array,
|
||||
value: [],
|
||||
|
|
@ -497,6 +510,11 @@
|
|||
'SetUpGcpRequested': 'handleSetUpGcpRequested',
|
||||
'ManualServerEntryCancelled': 'handleManualCancelled'
|
||||
},
|
||||
ready: function() {
|
||||
// TODO(alalama): detect language
|
||||
const messagesUrl = `/messages/${this.language}.json`;
|
||||
this.loadResources(messagesUrl, this.language);
|
||||
},
|
||||
showIntro: function () {
|
||||
this.maybeCloseDrawer();
|
||||
this.selectedServer = undefined;
|
||||
|
|
@ -566,9 +584,8 @@
|
|||
showError: function (errorMsg) {
|
||||
this.showToast(errorMsg, Infinity);
|
||||
},
|
||||
showNotification: function (message) {
|
||||
const NOTIFICATION_TOAST_DURATION_MS = 3000;
|
||||
this.showToast(message, NOTIFICATION_TOAST_DURATION_MS);
|
||||
showNotification: function (message, durationMs=3000) {
|
||||
this.showToast(message, durationMs);
|
||||
},
|
||||
showToast: function(message, duration) {
|
||||
const toast = this.$.toast;
|
||||
|
|
@ -589,15 +606,15 @@
|
|||
// cb is a function which accepts a single boolean which is true iff
|
||||
// the user chose to retry the failing operation.
|
||||
showConnectivityDialog: function (cb) {
|
||||
const dialogTitle = 'Connection problem';
|
||||
const dialogText = 'We\'re having trouble connecting to your DigitalOcean account. This is sometimes a temporary problem with DigitalOcean or with your internet connection. If retrying doesn\`t work, logging into DigitalOcean again should fix the problem.';
|
||||
this.showModalDialog(dialogTitle, dialogText, ['cancel', 'retry'])
|
||||
const dialogTitle = this.localize('error-connectivity-title');
|
||||
const dialogText = this.localize('error-connectivity');
|
||||
this.showModalDialog(dialogTitle, dialogText, [this.localize('cancel'), this.localize('retry')])
|
||||
.then((clickedButtonIndex) => {
|
||||
cb(clickedButtonIndex === 1); // pass true if user clicked retry
|
||||
});
|
||||
},
|
||||
getConfirmation: function(title, text, confirmButtonText, continueFunc) {
|
||||
this.showModalDialog(title, text, ['Cancel', confirmButtonText])
|
||||
this.showModalDialog(title, text, [this.localize('cancel'), confirmButtonText])
|
||||
.then((clickedButtonIndex) => {
|
||||
if (clickedButtonIndex === 1) { // user clicked to confirm.
|
||||
continueFunc();
|
||||
|
|
@ -605,7 +622,7 @@
|
|||
});
|
||||
},
|
||||
showManualServerError: function (errorTitle, errorText) {
|
||||
this.showModalDialog(errorTitle, errorText, ['cancel', 'retry'])
|
||||
this.showModalDialog(errorTitle, errorText, [this.localize('cancel'), this.localize('retry')])
|
||||
.then((clickedButtonIndex) => {
|
||||
if (clickedButtonIndex == 1) {
|
||||
this.$.manualEntry.retryTapped();
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<!--
|
||||
Copyright 2018 The Outline Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<script>
|
||||
// TODO: translate this
|
||||
const cityEnglishNameById = {
|
||||
ams: 'Amsterdam',
|
||||
sgp: 'Singapore',
|
||||
blr: 'Bangalore',
|
||||
fra: 'Frankfurt',
|
||||
lon: 'London',
|
||||
sfo: 'San Francisco',
|
||||
tor: 'Toronto',
|
||||
nyc: 'New York'
|
||||
};
|
||||
</script>
|
||||
|
|
@ -62,16 +62,15 @@
|
|||
<div>
|
||||
<img id="outlineLogo" src="images/manager-about-logo2x.png">
|
||||
</div>
|
||||
<p id='version'>Version [[outlineVersion]]</p>
|
||||
<p>Outline is an open source project created by <a href="https://jigsaw.google.com/">Jigsaw</a> to provide a safer way for news organizations and journalists to access the internet. Learn more about Outline on <a href="https://s3.amazonaws.com/outline-vpn/index.html">our website</a>.</p>
|
||||
<p>Outline is powered by <a href="https://shadowsocks.org">Shadowsocks</a> and is still an early stage project. You can contribute to the code on <a href="https://github.com/jigsaw-Code/?q=outline">GitHub</a>, and follow us on <a href="https://www.reddit.com/r/outlinevpn/">Reddit</a> and <a href="https://medium.com/jigsaw">Medium</a> to hear when we expand to more platforms and add new features.</p>
|
||||
<p id='version' inner-h-t-m-l="[[localize('about-version', 'version', outlineVersion)]]"></p>
|
||||
<p inner-h-t-m-l="[[localize('about-outline', 'jigsawUrl', 'https://jigsaw.google.com', 'shadowsocksUrl', 'https://shadowsocks.org', 'gitHubUrl', 'https://github.com/jigsaw-Code/?q=outline', 'redditUrl', 'https://www.reddit.com/r/outlinevpn', 'mediumUrl', 'https://medium.com/jigsaw')]]">></p>
|
||||
<p>
|
||||
<a href="https://jigsaw.google.com/">
|
||||
<img src="images/jigsaw-logo.svg">
|
||||
</a>
|
||||
</p>
|
||||
<div class="buttons">
|
||||
<paper-button dialog-dismiss autofocus>Close</paper-button>
|
||||
<paper-button dialog-dismiss autofocus>[[localize('close')]]</paper-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
</template>
|
||||
|
|
@ -80,6 +79,7 @@
|
|||
Polymer({
|
||||
is: 'outline-about-dialog',
|
||||
properties: {
|
||||
localize: {type: Function, readonly: true},
|
||||
outlineVersion: String
|
||||
},
|
||||
open: function () {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="title">[[title]]</div>
|
||||
<div class="showme" on-tap="_openImage">Show me where<iron-icon icon="open-in-new"></iron-icon></div>
|
||||
<div class="showme" on-tap="_openImage">[[localize('manual-server-show-me')]]<iron-icon icon="open-in-new"></iron-icon></div>
|
||||
</div>
|
||||
<div class="thumbnail overlay" on-tap="_openImage">
|
||||
<iron-icon icon="open-in-new"></iron-icon>
|
||||
|
|
@ -93,7 +93,8 @@
|
|||
title: String,
|
||||
imagePath: String,
|
||||
thumbnailPath: String,
|
||||
instructions: Array
|
||||
instructions: Array,
|
||||
localize: {type: Function, readonly: true},
|
||||
},
|
||||
_openImage: function() {
|
||||
this.fire('OpenImageRequested', {imagePath: this.imagePath});
|
||||
|
|
|
|||
|
|
@ -71,50 +71,50 @@
|
|||
|
||||
<iron-pages id='pages' attr-for-selected='id' selected='{{ currentPage }}'>
|
||||
<outline-step-view id="connectAccount">
|
||||
<span slot="step-title">Sign in or create an account with DigitalOcean.</span>
|
||||
<span slot="step-description">With your account, Outline makes it easy to create a server and get connected.</span>
|
||||
<span slot="step-title">[[localize('oauth-connect-title')]]</span>
|
||||
<span slot="step-description">[[localize('oauth-connect-description')]]</span>
|
||||
<paper-card class="card">
|
||||
<div class="container">
|
||||
<img src="images/digital_ocean_logo.svg" />
|
||||
<p>Waiting to connect your account...</p>
|
||||
<p>[[localize('oauth-connect-tag')]]</p>
|
||||
</div>
|
||||
<paper-button on-tap="_cancelTapped">Cancel</paper-button>
|
||||
<paper-button on-tap="_cancelTapped">[[localize('cancel')]]</paper-button>
|
||||
</paper-card>
|
||||
</outline-step-view>
|
||||
|
||||
<outline-step-view id="verifyEmail">
|
||||
<span slot="step-title">Activate you DigitalOcean account.</span>
|
||||
<span slot="step-description">Check your inbox for an email from DigitalOcean, and click the link in it to confirm your account.</span>
|
||||
<span slot="step-title">[[localize('oauth-activate-account')]]</span>
|
||||
<span slot="step-description">[[localize('oauth-verify')]]</span>
|
||||
<paper-card class="card">
|
||||
<div class="container">
|
||||
<img src="images/do_oauth_email.svg" />
|
||||
<p>Confirm your email...</p>
|
||||
<p>[[localize('oauth-verify-tag')]]</p>
|
||||
</div>
|
||||
<paper-button on-tap="_cancelTapped">Sign Out</paper-button>
|
||||
<paper-button on-tap="_cancelTapped">[[localize('oauth-sign-out')]]</paper-button>
|
||||
</paper-card>
|
||||
</outline-step-view>
|
||||
|
||||
<outline-step-view id="enterBilling">
|
||||
<span slot="step-title">Activate you DigitalOcean account.</span>
|
||||
<span slot="step-description">Enter your billing information on digitalocean.com and return to the app once you are done.</span>
|
||||
<span slot="step-title">[[localize('oauth-activate-account')]]</span>
|
||||
<span slot="step-description">[[localize('oauth-billing')]]</span>
|
||||
<paper-card class="card">
|
||||
<div class="container">
|
||||
<img src="images/do_oauth_billing.svg" />
|
||||
<p>Enter billing information...</p>
|
||||
<p>[[localize('oauth-billing-tag')]]</p>
|
||||
</div>
|
||||
<paper-button on-tap="_cancelTapped">Sign Out</paper-button>
|
||||
<paper-button on-tap="_cancelTapped">[[localize('oauth-sign-out')]]</paper-button>
|
||||
</paper-card>
|
||||
</outline-step-view>
|
||||
|
||||
<outline-step-view id="accountActive">
|
||||
<span slot="step-title">Activate you DigitalOcean account.</span>
|
||||
<span slot="step-description">Your DigitalOcean account has been activated.</span>
|
||||
<span slot="step-title">[[localize('oauth-activate-account')]]</span>
|
||||
<span slot="step-description">[[localize('oauth-account-active')]]</span>
|
||||
<paper-card class="card">
|
||||
<div class="container">
|
||||
<img src="images/do_oauth_done.svg" />
|
||||
<p>Account activated! Loading server locations...</p>
|
||||
<p>[[localize('oauth-account-active-tag')]]</p>
|
||||
</div>
|
||||
<paper-button disabled>Sign Out</paper-button>
|
||||
<paper-button disabled>[[localize('oauth-sign-out')]]</paper-button>
|
||||
</paper-card>
|
||||
</outline-step-view>
|
||||
</iron-pages>
|
||||
|
|
@ -132,6 +132,10 @@
|
|||
type: String,
|
||||
value: 'Cancel'
|
||||
},
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true
|
||||
},
|
||||
onCancel: Function
|
||||
},
|
||||
_cancelTapped: function() {
|
||||
|
|
|
|||
|
|
@ -88,34 +88,31 @@ see https://github.com/PolymerElements/paper-swatch-picker/issues/36 -->
|
|||
<p id='feedbackExplanation'>[[feedbackExplanation]]</p>
|
||||
<paper-dropdown-menu id='feedbackCategory' horizontal-align='left' on-selected-item-changed='feedbackCategoryChanged'>
|
||||
<paper-listbox id='feedbackCategoryListbox' slot='dropdown-content' class='dropdown-content' selected='0'>
|
||||
<paper-item>General feedback</paper-item>
|
||||
<paper-item>Having trouble installing Outline</paper-item>
|
||||
<paper-item>Can't connect to my server</paper-item>
|
||||
<paper-item>Others can't connect to my server</paper-item>
|
||||
<paper-item>Having trouble managing my server</paper-item>
|
||||
<paper-item>Suggestions</paper-item>
|
||||
<paper-item>[[localize('feedback-general')]]</paper-item>
|
||||
<paper-item>[[localize('feedback-install')]]</paper-item>
|
||||
<paper-item>[[localize('feedback-connection')]]</paper-item>
|
||||
<paper-item>[[localize('feedback-connection-others')]]</paper-item>
|
||||
<paper-item>[[localize('feedback-management')]]</paper-item>
|
||||
<paper-item>[[localize('feedback-suggestion')]]</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu id='cloudProvider' horizontal-align='left' placeholder='Select cloud provider' hidden$="[[!shouldShowCloudProvider]]" error-message="Please select a cloud provider">
|
||||
<paper-dropdown-menu id="cloudProvider" horizontal-align="left" placeholder="[[localize('feedback-cloud-provider')]]" hidden$="[[!shouldShowCloudProvider]]" error-message="[[localize('feedback-cloud-provider-error')]]">
|
||||
<paper-listbox id='cloudProviderListbox' slot='dropdown-content' class='dropdown-content'>
|
||||
<paper-item>DigitalOcean</paper-item>
|
||||
<paper-item>Amazon Web Services</paper-item>
|
||||
<paper-item>Google Cloud Platform</paper-item>
|
||||
<paper-item>Other</paper-item>
|
||||
<paper-item>[[localize('feedback-other')]]</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-input id='userEmail' type='text' placeholder='Email address (optional)' on-value-changed='userEmailValueChanged'></paper-input>
|
||||
<p class="disclaimer" hidden$=[[!shouldShowLanguageDisclaimer]]>Please note that our team is only able to answer feedback in English.</p>
|
||||
<paper-textarea id='userFeedback' type='text' label='Your feedback' always-float-label rows="4" error-message='Please enter feedback.' on-value-changed='userFeedbackValueChanged'></paper-textarea>
|
||||
<p>
|
||||
Your feedback, email address (if provided) and additional information
|
||||
referred to in the <a href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection">privacy policy</a>
|
||||
will be sent to the Outline team.
|
||||
<paper-input id="userEmail" type="text" placeholder="[[localize('feedback-email')]]" on-value-changed="userEmailValueChanged"></paper-input>
|
||||
<p class="disclaimer" hidden$=[[!shouldShowLanguageDisclaimer]]>[[localize('feedback-disclaimer')]]</p>
|
||||
<paper-textarea id="userFeedback" type="text" label="[[localize('feedback-label')]]" always-float-label rows="4" error-message="[[localize('feedback-error')]]" on-value-changed="userFeedbackValueChanged"></paper-textarea>
|
||||
<p inner-h-t-m-l="[[localize('feedback-privacy', 'openLink', '<a href=https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection>', 'closeLink', '</a>')]]">
|
||||
</p>
|
||||
</div> <!-- end of #feedbackWrapper -->
|
||||
<p class="buttons">
|
||||
<paper-button dialog-dismiss>Cancel</paper-button>
|
||||
<paper-button autofocus on-tap='submitTappedHandler'>Submit</paper-button>
|
||||
<paper-button dialog-dismiss>[[localize('cancel')]]</paper-button>
|
||||
<paper-button autofocus on-tap='submitTappedHandler'>[[localize('feedback-submit')]]</paper-button>
|
||||
</p>
|
||||
</paper-dialog>
|
||||
</template>
|
||||
|
|
@ -149,19 +146,25 @@ see https://github.com/PolymerElements/paper-swatch-picker/issues/36 -->
|
|||
type: Boolean,
|
||||
computed: '_computeShouldShowLanguageDisclaimer(hasEnteredEmail)',
|
||||
},
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
open: function(prepopulatedMessage, showInstallationFailed, feedbackCategory = 0) {
|
||||
open: function(prepopulatedMessage, showInstallationFailed) {
|
||||
// Clear all fields, in case feedback had already been entered.
|
||||
if (showInstallationFailed) {
|
||||
this.title = 'Outline Server Installation Failed';
|
||||
this.feedbackExplanation = 'An error occurred while attempting to install Outline on your server. If you haven\'t been able to figure out a solution, please consider sending us feedback and telling us your email address (optional) so that we can get back to you.';
|
||||
this.title = this.localize('feedback-title-install');
|
||||
this.feedbackExplanation = this.localize('feedback-explanation-install');
|
||||
this.$.dialog.classList.add('installationFailed');
|
||||
this.$.feedbackCategoryListbox.selected = this.feedbackCategories.INSTALLATION;
|
||||
} else {
|
||||
this.title = 'Send Feedback';
|
||||
this.title = this.localize('feedback-title-generic');
|
||||
this.feedbackExplanation = '';
|
||||
this.$.dialog.classList.remove('installationFailed');
|
||||
this.$.feedbackCategoryListbox.selected = feedbackCategory;
|
||||
// TODO(alalama): figure out why the localized category doesn't get displayed the first
|
||||
// time opening the dialog.
|
||||
this.$.feedbackCategoryListbox.selected = this.feedbackCategories.GENERAL;
|
||||
}
|
||||
this.$.userFeedback.invalid = false;
|
||||
this.$.userFeedback.value = prepopulatedMessage || '';
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
font-weight: 500;
|
||||
letter-spacing: .05em;
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.card#digital-ocean .tag, .card#digital-ocean .email, .card p {
|
||||
color: var(--medium-gray);
|
||||
|
|
@ -155,13 +156,13 @@
|
|||
</style>
|
||||
|
||||
<outline-step-view>
|
||||
<span slot="step-title">Choose a cloud service, set up Outline.</span>
|
||||
<span slot="step-description">Don't have a server? Create an account with DigitalOcean.</span>
|
||||
<span slot="step-title">[[localize('setup-title')]]</span>
|
||||
<span slot="step-description">[[localize('setup-description')]]</span>
|
||||
|
||||
<div class="container">
|
||||
<div id="digital-ocean" class="card" on-tap="connectToDigitalOceanTapped">
|
||||
<div class="card-header">
|
||||
<div class="tag" hidden$="{{isSignedInToDigitalOcean}}">RECOMMENDED</div>
|
||||
<div class="tag" hidden$="{{isSignedInToDigitalOcean}}">[[localize('setup-recommended')]]</div>
|
||||
<div class="email" hidden$="{{!isSignedInToDigitalOcean}}">{{digitalOceanEmail}}</div>
|
||||
<img src="images/do_white_logo.svg">
|
||||
</div>
|
||||
|
|
@ -169,78 +170,78 @@
|
|||
<div class="card-body">
|
||||
<div class="description">
|
||||
<ul hidden$="{{isSignedInToDigitalOcean}}">
|
||||
<li>Easiest setup process</li>
|
||||
<li>Only $5 a month</li>
|
||||
<li>1 TB of data transfer</li>
|
||||
<li>Cancel at anytime</li>
|
||||
<li>[[localize('setup-do-easiest')]]</li>
|
||||
<li>[[localize('setup-do-cost')]]</li>
|
||||
<li>[[localize('setup-do-data')]]</li>
|
||||
<li>[[localize('setup-do-cancel')]]</li>
|
||||
</ul>
|
||||
<p hidden$="{{!isSignedInToDigitalOcean}}">
|
||||
Create a new server with your DigitalOcean account for an additional $5 USD/30 days for 1TB of data transfer.
|
||||
[[localize('setup-do-create')]]
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<paper-button class="primary" hidden$="{{isSignedInToDigitalOcean}}">Set up</paper-button>
|
||||
<paper-button class="primary" hidden$="{{!isSignedInToDigitalOcean}}">Create server</paper-button>
|
||||
<paper-button class="primary" hidden$="{{isSignedInToDigitalOcean}}">[[localize('setup-action')]]</paper-button>
|
||||
<paper-button class="primary" hidden$="{{!isSignedInToDigitalOcean}}">[[localize('setup-create')]]</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="gcp" class="card" on-tap="setUpGcpTapped">
|
||||
<div class="card-header">
|
||||
<div class="tag">ADVANCED</div>
|
||||
<div class="tag">[[localize('setup-advanced')]]</div>
|
||||
<img src="images/gcp-logo.svg">
|
||||
</div>
|
||||
<div class="card-title">Google Cloud Platform</div>
|
||||
<div class="card-body">
|
||||
<div class="description">
|
||||
<ul>
|
||||
<li>Step-by-step set-up guide</li>
|
||||
<li>Firewall instructions</li>
|
||||
<li>Simple install commands</li>
|
||||
<li>[[localize('setup-step-by-step')]]</li>
|
||||
<li>[[localize('setup-firewall-instructions')]]</li>
|
||||
<li>[[localize('setup-simple-commands')]]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<paper-button on-tap="setUpGcpTapped" class="primary">Set up</paper-button>
|
||||
<paper-button on-tap="setUpGcpTapped" class="primary">[[localize('setup-action')]]</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="aws" class="card" on-tap="setUpAwsTapped">
|
||||
<div class="card-header">
|
||||
<div class="tag">ADVANCED</div>
|
||||
<div class="tag">[[localize('setup-advanced')]]</div>
|
||||
<img src="images/aws-logo.svg">
|
||||
</div>
|
||||
<div class="card-title">Amazon Web Services</div>
|
||||
<div class="card-body">
|
||||
<div class="description">
|
||||
<ul>
|
||||
<li>Step-by-step set-up guide</li>
|
||||
<li>EC2 firewall instructions</li>
|
||||
<li>Simple install commands</li>
|
||||
<li>[[localize('setup-step-by-step')]]</li>
|
||||
<li>[[localize('setup-firewall-instructions')]]</li>
|
||||
<li>[[localize('setup-simple-commands')]]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<paper-button on-tap="setUpAwsTapped" class="primary">Set up</paper-button>
|
||||
<paper-button on-tap="setUpAwsTapped" class="primary">[[localize('setup-action')]]</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="manual-server" class="card" on-tap="setUpGenericCloudProviderTapped">
|
||||
<div class="card-header">
|
||||
<div class="tag">ADVANCED</div>
|
||||
<div class="tag">[[localize('setup-advanced')]]</div>
|
||||
<img src="images/cloud.svg">
|
||||
</div>
|
||||
<div class="card-title">Set up Outline anywhere</div>
|
||||
<div class="card-title">[[localize('setup-anywhere')]]</div>
|
||||
<div class="card-body">
|
||||
<div class='description'>
|
||||
<ul>
|
||||
<li>Tested on VULTR, Linode, and Liquid Web</li>
|
||||
<li>Simple install commands</li>
|
||||
<li>[[localize('setup-tested')]]</li>
|
||||
<li>[[localize('setup-simple-commands')]]</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<paper-button on-tap="setUpGenericCloudProviderTapped">Set up</paper-button>
|
||||
<paper-button on-tap="setUpGenericCloudProviderTapped">[[localize('setup-action')]]</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -254,6 +255,10 @@
|
|||
properties: {
|
||||
isSignedInToDigitalOcean: Boolean,
|
||||
digitalOceanEmail: String,
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true,
|
||||
},
|
||||
},
|
||||
connectToDigitalOceanTapped: function() {
|
||||
this.fire('ConnectToDigitalOcean');
|
||||
|
|
|
|||
|
|
@ -162,42 +162,43 @@
|
|||
}
|
||||
</style>
|
||||
<outline-step-view>
|
||||
<span slot="step-title">Follow the instructions below</span>
|
||||
<span slot="step-description">These steps will help you install Outline on a [[cloudProviderName]] Linux server.</span>
|
||||
<span slot="step-title">[[localize('manual-server-title')]]</span>
|
||||
<span slot="step-description">[[localize('manual-server-description', 'cloudProvider', cloudProviderName)]]</span>
|
||||
|
||||
<div class="card">
|
||||
<!-- GCP -->
|
||||
<div class="section" hidden$="[[!isCloudProviderGcp]]">
|
||||
<div class="section-header">
|
||||
<!-- TODO(alalama): localize numbers -->
|
||||
<span class="stepcircle">1</span>
|
||||
<div class="instructions">Configure your firewall</div>
|
||||
<div class="instructions">[[localize('manual-server-firewall')]]</div>
|
||||
<div class="drop-down" on-tap="_toggleGcpDropDown">
|
||||
<img src="images/gcp-logo.svg" />
|
||||
<span>Instructions</span>
|
||||
<span>[[localize('manual-server-instructions')]]</span>
|
||||
<iron-icon id="gcpDropDownIcon" icon="arrow-drop-down"></iron-icon>
|
||||
</div>
|
||||
</div>
|
||||
<iron-collapse id="gcpDropDown">
|
||||
<div class="section-content-instructions">
|
||||
<outline-cloud-instructions-view title="Create a firewall rule" thumbnail-path="images/gcp-thumbnail-1.png" image-path="images/gcp-screenshot-1.png">
|
||||
<outline-cloud-instructions-view title="[[localize('manual-server-create-firewall')]]" thumbnail-path="images/gcp-thumbnail-1.png" image-path="images/gcp-screenshot-1.png" localize="[[localize]]">
|
||||
<ol>
|
||||
<li><a href="https://console.cloud.google.com/networking/firewalls/add">Add a new firewall rule<iron-icon icon="open-in-new"></iron-icon></a> to your Compute Engine project.</li>
|
||||
<li>Type 'outline' in the 'Name' field.</li>
|
||||
<li>Type 'outline' in the 'Target tags' field.</li>
|
||||
<li>Type '0.0.0.0/0' in the 'Source IP ranges' field.</li>
|
||||
<li>Select 'Allow all' under 'Protocols and ports'.</li>
|
||||
<li>Click 'Create'.</li>
|
||||
<li inner-h-t-m-l="[[localize('gcp-firewall-create-0', 'openLink', '<a href=https://console.cloud.google.com/networking/firewalls/add>', 'closeLink', '<iron-icon icon=open-in-new></iron-icon></a>')]]"></li>
|
||||
<li>[[localize('gcp-firewall-create-1')]]</li>
|
||||
<li>[[localize('gcp-firewall-create-2')]]</li>
|
||||
<li>[[localize('gcp-firewall-create-3')]]</li>
|
||||
<li>[[localize('gcp-firewall-create-4')]]</li>
|
||||
<li>[[localize('gcp-firewall-create-5')]]</li>
|
||||
</ol>
|
||||
</outline-cloud-instructions-view>
|
||||
</div>
|
||||
<div class="section-content-instructions">
|
||||
<outline-cloud-instructions-view title="Assign firewall rule" thumbnail-path="images/gcp-thumbnail-2.png" image-path="images/gcp-screenshot-2.png"">
|
||||
<outline-cloud-instructions-view title="[[localize('manual-server-assign-firewall')]]" thumbnail-path="images/gcp-thumbnail-2.png" image-path="images/gcp-screenshot-2.png"" localize="[[localize]]">
|
||||
<ol>
|
||||
<li>Navigate to the <a href="https://console.cloud.google.com/compute/instances">VM instances screen<iron-icon icon="open-in-new"></iron-icon></a>.</li>
|
||||
<li>Click on the instance where you want to host Outline.</li>
|
||||
<li>Click 'EDIT' at the top of the VM Instance details screen.</li>
|
||||
<li>Type 'outline' in the 'Network tags' field.</li>
|
||||
<li>Click 'SAVE'.</li>
|
||||
<li inner-h-t-m-l="[[localize('gcp-firewall-assign-0', 'openLink', '<a href=https://console.cloud.google.com/compute/instances>', 'closeLink', '<iron-icon icon=open-in-new></iron-icon></a>')]]"></li>
|
||||
<li>[[localize('gcp-firewall-assign-1')]]</li>
|
||||
<li>[[localize('gcp-firewall-assign-2')]]</li>
|
||||
<li>[[localize('gcp-firewall-assign-3')]]</li>
|
||||
<li>[[localize('gcp-firewall-assign-4')]]</li>
|
||||
</ol>
|
||||
</outline-cloud-instructions-view>
|
||||
</div>
|
||||
|
|
@ -207,33 +208,33 @@
|
|||
<div class="section" hidden$="[[!isCloudProviderAws]]">
|
||||
<div class="section-header">
|
||||
<span class="stepcircle">1</span>
|
||||
<div class="instructions">Configure your firewall</div>
|
||||
<div class="instructions">[[localize('manual-server-firewall')]]</div>
|
||||
<div class="drop-down" on-tap="_toggleAwsDropDown">
|
||||
<img id="aws-logo" src="images/aws-logo.svg" />
|
||||
<span>Instructions</span>
|
||||
<span>[[localize('manual-server-instructions')]]</span>
|
||||
<iron-icon id="awsDropDownIcon" icon="arrow-drop-down"></iron-icon>
|
||||
</div>
|
||||
</div>
|
||||
<iron-collapse id="awsDropDown">
|
||||
<div class="section-content-instructions">
|
||||
<outline-cloud-instructions-view title="Create a Security Group" thumbnail-path="images/aws-thumbnail-1.png" image-path="images/aws-screenshot-1.png">
|
||||
<outline-cloud-instructions-view title="[[localize('manual-server-create-group')]]" thumbnail-path="images/aws-thumbnail-1.png" image-path="images/aws-screenshot-1.png" localize="[[localize]]">
|
||||
<ol>
|
||||
<li>Once you've created your EC2 instance, open the <a href="https://console.aws.amazon.com/ec2/v2/home">EC2 Management Console<iron-icon icon="open-in-new"></iron-icon></a>.</li>
|
||||
<li>Under 'Network & Security', select 'Security Groups'.</li>
|
||||
<li>Click on 'Create Security Group'.</li>
|
||||
<li>Type 'outline' in the 'Security group name' and 'Description' fields.</li>
|
||||
<li>Click 'Add Rule'.</li>
|
||||
<li>Select 'All traffic' under 'Type', and 'Anywhere' under 'Source'.</li>
|
||||
<li inner-h-t-m-l="[[localize('aws-group-create-0', 'openLink', '<a href=https://console.aws.amazon.com/ec2/v2/home>', 'closeLink', '<iron-icon icon=open-in-new></iron-icon></a>')]]"></li>
|
||||
<li>[[localize('aws-group-create-1')]]</li>
|
||||
<li>[[localize('aws-group-create-2')]]</li>
|
||||
<li>[[localize('aws-group-create-3')]]</li>
|
||||
<li>[[localize('aws-group-create-4')]]</li>
|
||||
<li>[[localize('aws-group-create-5')]]</li>
|
||||
</ol>
|
||||
</outline-cloud-instructions-view>
|
||||
</div>
|
||||
<div class="section-content-instructions">
|
||||
<outline-cloud-instructions-view title="Assign Security Group" thumbnail-path="images/aws-thumbnail-2.png" image-path="images/aws-screenshot-2.png">
|
||||
<outline-cloud-instructions-view title="[[localize('manual-server-assign-group')]]" thumbnail-path="images/aws-thumbnail-2.png" image-path="images/aws-screenshot-2.png" localize="[[localize]]">
|
||||
<ol>
|
||||
<li>Navigate to <a href="https://console.aws.amazon.com/ec2/v2/home#Instances:sort=instanceId">Instances<iron-icon icon="open-in-new"></iron-icon></a>.</li>
|
||||
<li>Click 'Actions' > 'Networking' > 'Change Security Groups' at the top of the 'Instances' screen.</li>
|
||||
<li>Select the 'outline' Security Group, unselect other security groups.</li>
|
||||
<li>Click 'Assign Security Groups'.</li>
|
||||
<li inner-h-t-m-l="[[localize('aws-group-assign-0', 'openLink', '<a href=https://console.aws.amazon.com/ec2/v2/home#Instances:sort=instanceId>', 'closeLink', '<iron-icon icon=open-in-new></iron-icon></a>')]]"></li>
|
||||
<li>[[localize('aws-group-assign-1')]]</li>
|
||||
<li>[[localize('aws-group-assign-2')]]</li>
|
||||
<li>[[localize('aws-group-assign-3')]]</li>
|
||||
</ol>
|
||||
</outline-cloud-instructions-view>
|
||||
</div>
|
||||
|
|
@ -244,7 +245,7 @@
|
|||
<div class="section-header">
|
||||
<span class="stepcircle" hidden$="[[!isGenericCloudProvider]]">1</span>
|
||||
<span class="stepcircle" hidden$="[[isGenericCloudProvider]]">2</span>
|
||||
<div class="instructions">Log into your server, and run this command.</div>
|
||||
<div class="instructions">[[localize('manual-server-install-run')]]</div>
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<div id="command">sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh)"</div>
|
||||
|
|
@ -255,15 +256,15 @@
|
|||
<div class="section-header">
|
||||
<span class="stepcircle" hidden$="[[!isGenericCloudProvider]]">2</span>
|
||||
<span class="stepcircle" hidden$="[[isGenericCloudProvider]]">3</span>
|
||||
<div class="instructions">Paste your installation output here.</div>
|
||||
<div class="instructions">[[localize('manual-server-install-paste')]]</div>
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<paper-textarea id="serverConfig" type="text" placeholder$="[[placeholderText]]" class="code" rows="4" max-rows="4" no-label-float on-value-changed='onServerConfigChanged'></paper-textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div id="button-row">
|
||||
<paper-button id="cancelButton" on-tap="cancelTapped" class="secondary">CANCEL</paper-button>
|
||||
<paper-button id="doneButton" on-tap="doneTapped" class="primary" disabled$='[[!enableDoneButton]]'>DONE</paper-button>
|
||||
<paper-button id="cancelButton" on-tap="cancelTapped" class="secondary">[[localize('cancel')]]</paper-button>
|
||||
<paper-button id="doneButton" on-tap="doneTapped" class="primary" disabled$='[[!enableDoneButton]]'>[[localize('done')]]</paper-button>
|
||||
</div>
|
||||
<paper-progress hidden$='[[!showConnection]]' indeterminate class="slow"></paper-progress>
|
||||
</div>
|
||||
|
|
@ -302,7 +303,11 @@
|
|||
enableDoneButton: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
}
|
||||
},
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true,
|
||||
},
|
||||
},
|
||||
doneTapped: function() {
|
||||
this.showConnection = true;
|
||||
|
|
|
|||
|
|
@ -22,24 +22,30 @@
|
|||
<dom-module id='outline-metrics-option-dialog'>
|
||||
<template>
|
||||
<style include='cloud-install-styles'>
|
||||
.learnMoreLink {
|
||||
.link {
|
||||
text-decoration: underline;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id='metricsEnabledDialog' modal>
|
||||
<div class='dialogBanner'><img src='images/metrics.png'></div>
|
||||
<h3>Metrics sharing</h3>
|
||||
<p>Share anonymized metrics to help improve the reliability and performance of Outline, for you and for those you share your server with. <a class="learnMoreLink" href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection">Learn more</a>.</p>
|
||||
<h3>[[localize('metrics-title')]]</h3>
|
||||
<p inner-h-t-m-l="[[localize('metrics-description', 'openLink', '<a class=link href=https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection>', 'closeLink', '</a>')]]"></p>
|
||||
<div class='buttons'>
|
||||
<paper-button dialog-dismiss on-tap='disableMetricsRequested'>Skip</paper-button>
|
||||
<paper-button autofocus dialog-dismiss on-tap='enableMetricsRequested'>Share metrics</paper-button>
|
||||
<paper-button dialog-dismiss on-tap='disableMetricsRequested'>[[localize('metrics-skip')]]</paper-button>
|
||||
<paper-button autofocus dialog-dismiss on-tap='enableMetricsRequested'>[[localize('metrics-share')]]</paper-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'outline-metrics-option-dialog',
|
||||
properties: {
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true,
|
||||
},
|
||||
},
|
||||
showMetricsOptInDialog: function() {
|
||||
this.$.metricsEnabledDialog.open();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
<link rel='import' href='../bower_components/iron-icons/iron-icons.html'>
|
||||
|
||||
<link rel="import" href="./cloud-install-styles.html">
|
||||
<link rel="import" href="./cities.html">
|
||||
<link rel="import" href="./outline-step-view.html">
|
||||
|
||||
<dom-module id="outline-region-picker-step">
|
||||
|
|
@ -91,10 +90,12 @@
|
|||
}
|
||||
</style>
|
||||
<outline-step-view display-action>
|
||||
<span slot="step-title">Select the location of your server.</span>
|
||||
<span slot="step-description">This is where your internet experience will come from.</span>
|
||||
<span slot="step-title">[[localize('region-title')]]</span>
|
||||
<span slot="step-description">[[localize('region-description')]]</span>
|
||||
<span slot="step-action">
|
||||
<paper-button id="createServerButton" on-tap='handleCreateServerTap' disabled$='[[!isCreateButtonEnabled(creatingServer, selectedCityId)]]'>Set up Outline</paper-button>
|
||||
<paper-button id="createServerButton" on-tap='handleCreateServerTap' disabled$='[[!isCreateButtonEnabled(creatingServer, selectedCityId)]]'>
|
||||
[[localize('region-setup')]]
|
||||
</paper-button>
|
||||
</span>
|
||||
<div class='card-content' id="cityContainer">
|
||||
<template is="dom-repeat" items="{{cities}}">
|
||||
|
|
@ -102,7 +103,7 @@
|
|||
<label for$='{{item}}' class='city-button'>
|
||||
<iron-icon icon="check-circle" hidden$="{{!_isSelectedCity(selectedCityId, item)}}"></iron-icon>
|
||||
<img class='flag' src$='{{getFlag(item)}}'>
|
||||
<div class="city-name">{{getCityName(item)}}</div>
|
||||
<div class="city-name">{{getCityName(item, localize)}}</div>
|
||||
</label>
|
||||
</input>
|
||||
</template>
|
||||
|
|
@ -128,21 +129,30 @@
|
|||
properties: {
|
||||
cities: {
|
||||
type: Array,
|
||||
readonly: true,
|
||||
value: Object.keys(flagById)
|
||||
},
|
||||
availableRegionIds: { // One-to-one map from cityIds to regionIds.
|
||||
type: Object,
|
||||
readonly: true,
|
||||
value: {}
|
||||
},
|
||||
selectedCityId: String,
|
||||
creatingServer: Boolean
|
||||
creatingServer: Boolean,
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true,
|
||||
},
|
||||
},
|
||||
handleCreateServerTap: function () {
|
||||
this.creatingServer = true;
|
||||
this.fire('RegionSelected');
|
||||
},
|
||||
getCityName: function (cityId) {
|
||||
return cityEnglishNameById[cityId] || '';
|
||||
getCityName: function (cityId, localize) {
|
||||
if (!this.localize) {
|
||||
return '';
|
||||
}
|
||||
return this.localize(`city-${cityId}`) || '';
|
||||
},
|
||||
getFlag: function (cityId) {
|
||||
return flagById[cityId] || '';
|
||||
|
|
@ -176,7 +186,7 @@
|
|||
},
|
||||
isCreateButtonEnabled: function(creatingServer, selectedCityId) {
|
||||
return !creatingServer && selectedCityId;
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@
|
|||
</style>
|
||||
|
||||
<outline-step-view display-action>
|
||||
<span slot="step-title">Setting up Outline.</span>
|
||||
<span slot="step-description">This could take up to two minutes. You can destroy this server at anytime.</span>
|
||||
<span slot="step-title">[[localize('setup-do-title')]]</span>
|
||||
<span slot="step-description">[[localize('setup-do-description')]]</span>
|
||||
<span slot="step-action">
|
||||
<paper-button id='cancelButton' hidden$='{{!showCancelButton}}' on-tap='handleCancelTapped'>Cancel</paper-button>
|
||||
<paper-button id='cancelButton' hidden$='{{!showCancelButton}}' on-tap='handleCancelTapped'>[[localize('cancel')]]</paper-button>
|
||||
</span>
|
||||
<div class='card'>
|
||||
<outline-progress-spinner></outline-progress-spinner>
|
||||
|
|
@ -82,7 +82,8 @@
|
|||
properties: {
|
||||
serverName: String,
|
||||
showCancelButton: Boolean,
|
||||
updateIntervalId: Number
|
||||
updateIntervalId: Number,
|
||||
localize: Function
|
||||
},
|
||||
start: function() {
|
||||
if (this.updateIntervalId) {
|
||||
|
|
|
|||
|
|
@ -120,23 +120,23 @@
|
|||
<div class="setting card-section" hidden$="[[!isServerManaged]]">
|
||||
<img class="setting-icon digital-ocean-icon" src="images/do_white_logo.svg"/>
|
||||
<div>
|
||||
<h3>Digital Ocean</h3>
|
||||
<paper-input readonly value="[[serverLocation]]" label="Server location" hidden$="[[!serverLocation]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverMonthlyCost]] USD/month" label="Monthly cost" hidden$="[[!serverMonthlyCost]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverMonthlyTransferLimit]]" label="Transfer limit" hidden$="[[!serverMonthlyTransferLimit]]" always-float-label maxlength="100"></paper-input>
|
||||
<h3>DigitalOcean</h3>
|
||||
<paper-input readonly value="[[serverLocation]]" label="[[localize('settings-server-location')]]" hidden$="[[!serverLocation]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverMonthlyCost]] USD/month" label="[[localize('settings-server-cost')]]" hidden$="[[!serverMonthlyCost]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverMonthlyTransferLimit]]" label="[[localize('settings-transfer-limit')]]" hidden$="[[!serverMonthlyTransferLimit]]" always-float-label maxlength="100"></paper-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting card-section">
|
||||
<iron-icon class="setting-icon" icon="outline-iconset:outline"></iron-icon>
|
||||
<div>
|
||||
<h3>Server Information</h3>
|
||||
<paper-input id="serverNameInput" class="server-name" value="{{name}}" label="Name" always-float-label maxlength="100" on-keydown="_handleNameInputKeyDown" on-blur="_handleNameInputBlur"></paper-input>
|
||||
<p class="detail">Set a new name for your server. Note that this will not be reflected on the devices of the users that you invited to connect to it.</p>
|
||||
<paper-input readonly value="[[serverPortForNewAccessKeys]]" label="Port for new access keys" hidden$="[[!serverPortForNewAccessKeys]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverHostname]]" label="Hostname" hidden$="[[!serverHostname]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverManagementApiUrl]]" label="Management API URL" hidden$="[[!serverManagementApiUrl]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverCreationDate]]" label="Created" hidden$="[[!serverCreationDate]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverId]]" label="Server ID" hidden$="[[!serverId]]" always-float-label maxlength="100"></paper-input>
|
||||
<h3>[[localize('settings-server-info')]]</h3>
|
||||
<paper-input id="serverNameInput" class="server-name" value="{{name}}" label="[[localize('settings-server-name')]]" always-float-label maxlength="100" on-keydown="_handleNameInputKeyDown" on-blur="_handleNameInputBlur"></paper-input>
|
||||
<p class="detail">[[localize('settings-server-rename')]]</p>
|
||||
<paper-input readonly value="[[serverPortForNewAccessKeys]]" label="[[localize('settings-access-key-port')]]" hidden$="[[!serverPortForNewAccessKeys]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverHostname]]" label="[[localize('settings-server-hostname')]]" hidden$="[[!serverHostname]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverManagementApiUrl]]" label="[[localize('settings-server-api-url')]]" hidden$="[[!serverManagementApiUrl]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverCreationDate]]" label="[[localize('settings-server-creation')]]" hidden$="[[!serverCreationDate]]" always-float-label maxlength="100"></paper-input>
|
||||
<paper-input readonly value="[[serverId]]" label="[[localize('settings-server-id')]]" hidden$="[[!serverId]]" always-float-label maxlength="100"></paper-input>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Metrics controls -->
|
||||
|
|
@ -144,10 +144,10 @@
|
|||
<iron-icon class="setting-icon" icon="editor:insert-chart"></iron-icon>
|
||||
<div>
|
||||
<div id="metricsHeader">
|
||||
<h3>Share anonymous metrics</h3>
|
||||
<h3>[[localize('settings-metrics-header')]]</h3>
|
||||
<paper-checkbox id="metricsCheckbox" checked="{{metricsEnabled}}"></paper-checkbox>
|
||||
</div>
|
||||
<p>Share anonymized metrics to help improve the reliability and performance of Outline, for you and for those you share your server with. <a class="link" href="https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection">Learn more</a>.</p>
|
||||
<p inner-h-t-m-l="[[localize('metrics-description', 'openLink', '<a class=link href=https://s3.amazonaws.com/outline-vpn/index.html#/en/support/dataCollection>', 'closeLink', '</a>')]]"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -169,6 +169,7 @@
|
|||
serverLocation: {type: String, value: null},
|
||||
serverMonthlyCost: {type: String, value: null},
|
||||
serverMonthlyTransferLimit: {type: String, value: null},
|
||||
localize: {type: Function, readonly: true},
|
||||
},
|
||||
update: function(name, metricsEnabled) {
|
||||
this.initialName = name;
|
||||
|
|
|
|||
|
|
@ -341,10 +341,10 @@
|
|||
<paper-icon-button icon="more-vert" slot="dropdown-trigger"></paper-icon-button>
|
||||
<paper-listbox slot="dropdown-content">
|
||||
<paper-item hidden$="[[!isServerManaged]]" on-tap="destroyServer">
|
||||
<iron-icon icon="icons:remove-circle-outline"></iron-icon>Destroy server
|
||||
<iron-icon icon="icons:remove-circle-outline"></iron-icon>[[localize('server-destroy')]]
|
||||
</paper-item>
|
||||
<paper-item hidden$="[[isServerManaged]]" on-tap="removeServer">
|
||||
<iron-icon icon="icons:remove-circle-outline"></iron-icon>Remove server
|
||||
<iron-icon icon="icons:remove-circle-outline"></iron-icon>[[localize('server-remove')]]
|
||||
</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-menu-button>
|
||||
|
|
@ -354,21 +354,24 @@
|
|||
<div class="tabs-container" hidden$="{{!isServerReachable}}">
|
||||
<div class="tabs-spacer"></div>
|
||||
<paper-tabs selected="{{selectedTab}}" attr-for-selected="name" noink>
|
||||
<paper-tab name="connections">Connections</paper-tab>
|
||||
<paper-tab name="settings">Settings</paper-tab>
|
||||
<paper-tab name="connections">[[localize('server-connections')]]</paper-tab>
|
||||
<paper-tab name="settings">[[localize('server-settings')]]</paper-tab>
|
||||
</paper-tabs>
|
||||
</div>
|
||||
|
||||
<!-- Unreachable server display -->
|
||||
<div class="card-section unreachable-server" hidden$="{{isServerReachable}}">
|
||||
<img class="server-img" src="images/server-unreachable.png" />
|
||||
<h3>Server unreachable</h3>
|
||||
<p hidden$="{{isServerManaged}}">We're having issues connecting to this server. Try again or remove this server from the application.</p>
|
||||
<p hidden$="{{!isServerManaged}}">We're having issues connecting to this server. Try again or destroy this server and the virtual host.</p>
|
||||
<h3>[[localize('server-unreachable')]]</h3>
|
||||
<p>
|
||||
<div>[[localize('server-unreachable-description')]]</div>
|
||||
<span hidden$="{{isServerManaged}}">[[localize('server-unreachable-managed-description')]]</span>
|
||||
<span hidden$="{{!isServerManaged}}">[[localize('server-unreachable-manual-description')]]</span>
|
||||
</p>
|
||||
<div class="button-container">
|
||||
<paper-button on-tap="removeServer" hidden$="{{isServerManaged}}">Remove server</paper-button>
|
||||
<paper-button on-tap="destroyServer" hidden$="{{!isServerManaged}}">Destroy server</paper-button>
|
||||
<paper-button on-tap="retryDisplayingServer" class="try-again-btn">Try again</paper-button>
|
||||
<paper-button on-tap="removeServer" hidden$="{{isServerManaged}}">[[localize('server-remove')]]</paper-button>
|
||||
<paper-button on-tap="destroyServer" hidden$="{{!isServerManaged}}">[[localize('server-destroy')]]</paper-button>
|
||||
<paper-button on-tap="retryDisplayingServer" class="try-again-btn">[[localize('retry')]]</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -381,7 +384,7 @@
|
|||
<h3>[[_getFormattedTransferredValue(totalInboundBytes, '0')]]</h3>
|
||||
<p>[[_getFormattedTransferredUnit(totalInboundBytes, 'B')]]</p>
|
||||
</div>
|
||||
<p>Data transferred / 30 days</p>
|
||||
<p>[[localize('server-data-transfer')]]</p>
|
||||
</div>
|
||||
<div hidden$="[[!isServerManaged]]" class="stats-card card-section">
|
||||
<div>
|
||||
|
|
@ -389,17 +392,17 @@
|
|||
</div>
|
||||
<div class="stats">
|
||||
<h3>[[managedServerUtilzationPercentage]]</h3>
|
||||
<p>of [[_formatBytesTransferred(monthlyOutboundTransferBytes)]]</p>
|
||||
<p>/[[_formatBytesTransferred(monthlyOutboundTransferBytes)]]</p>
|
||||
</div>
|
||||
<p>Data used / 30 days</p>
|
||||
<p>[[localize('server-data-used')]]</p>
|
||||
</div>
|
||||
<div class="stats-card card-section">
|
||||
<iron-icon icon="outline-iconset:key"></iron-icon>
|
||||
<div class="stats">
|
||||
<h3>[[accessKeyRows.length]]</h3>
|
||||
<p>Keys</p>
|
||||
<p>[[localize('server-keys')]]</p>
|
||||
</div>
|
||||
<p>Server access</p>
|
||||
<p>[[localize('server-access')]]</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -407,12 +410,12 @@
|
|||
<!-- header row -->
|
||||
<div class="access-key-row header-row">
|
||||
<span class="access-key-container" on-tap="_setSortByOrToggleDirection" data-sort-by="name">
|
||||
Access keys
|
||||
[[localize('server-access-keys')]]
|
||||
<iron-icon class="sort-icon" icon="arrow-drop-down" hidden$="[[!_computeShouldShowSortIcon(accessKeySortBy, accessKeySortDirection, 'name', -1)]]"></iron-icon>
|
||||
<iron-icon class="sort-icon" icon="arrow-drop-up" hidden$="[[!_computeShouldShowSortIcon(accessKeySortBy, accessKeySortDirection, 'name', 1)]]"></iron-icon>
|
||||
</span>
|
||||
<span class="measurement-container" on-tap="_setSortByOrToggleDirection" data-sort-by="usage">
|
||||
Usage / 30 days
|
||||
[[localize('server-usage')]]
|
||||
<iron-icon class="sort-icon" icon="arrow-drop-down" hidden$="[[!_computeShouldShowSortIcon(accessKeySortBy, accessKeySortDirection, 'usage', -1)]]"></iron-icon>
|
||||
<iron-icon class="sort-icon" icon="arrow-drop-up" hidden$="[[!_computeShouldShowSortIcon(accessKeySortBy, accessKeySortDirection, 'usage', 1)]]"></iron-icon>
|
||||
</span>
|
||||
|
|
@ -423,8 +426,8 @@
|
|||
<span class="access-key-container">
|
||||
<img class="manager-access-key-icon access-key-icon" src="images/manager-key-avatar.svg">
|
||||
<div class="access-key-name">
|
||||
<div>My access key</div>
|
||||
<div id="manager-access-key-description">Connect your devices</div>
|
||||
<div>[[localize('server-my-access-key')]]</div>
|
||||
<div id="manager-access-key-description">[[localize('server-connect-devices')]]</div>
|
||||
</div>
|
||||
</span>
|
||||
<span class="measurement-container">
|
||||
|
|
@ -465,10 +468,10 @@
|
|||
<paper-icon-button icon="more-vert" slot="dropdown-trigger"></paper-icon-button>
|
||||
<paper-listbox slot="dropdown-content">
|
||||
<paper-item on-tap="_handleRenameAccessKeyPressed">
|
||||
<iron-icon icon="icons:create"></iron-icon>Rename
|
||||
<iron-icon icon="icons:create"></iron-icon>[[localize('server-access-key-rename')]]
|
||||
</paper-item>
|
||||
<paper-item on-tap="_handleRemoveAccessKeyPressed">
|
||||
<iron-icon icon="icons:delete"></iron-icon>Remove
|
||||
<iron-icon icon="icons:delete"></iron-icon>[[localize('remove')]]
|
||||
</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-menu-button>
|
||||
|
|
@ -481,7 +484,7 @@
|
|||
<div class="access-key-row" id="addAccessKeyRow">
|
||||
<span class="access-key-container">
|
||||
<paper-icon-button icon="icons:add" on-tap="_handleAddAccessKeyPressed" id="addAccessKeyButton" class="access-key-icon"></paper-icon-button>
|
||||
<div class="add-new-key" on-tap="_handleAddAccessKeyPressed">Add new key</div>
|
||||
<div class="add-new-key" on-tap="_handleAddAccessKeyPressed">[[localize('server-access-key-new')]]</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -497,23 +500,24 @@
|
|||
server-monthly-cost="[[monthlyCost]]"
|
||||
server-monthly-transfer-limit="[[_formatBytesTransferred(monthlyOutboundTransferBytes)]]"
|
||||
is-server-managed="[[isServerManaged]]"
|
||||
server-location="[[serverLocation]]">
|
||||
server-location="[[serverLocation]]"
|
||||
localize="[[localize]]">
|
||||
</outline-server-settings>
|
||||
</div>
|
||||
</iron-pages>
|
||||
</div>
|
||||
|
||||
<outline-help-bubble id="getConnectedHelpBubble" vertical-align="top" horizontal-align="right">
|
||||
<outline-help-bubble id="getConnectedHelpBubble" vertical-align="bottom" horizontal-align="right">
|
||||
<img src="images/connect-tip-2x.png">
|
||||
<h3>You are not connected yet!</h3>
|
||||
<p>Click here to install the Outline client app, using your personal access key to your Outline server</p>
|
||||
<paper-button on-tap="closeGetConnectedHelpBubble">Okay, got it!</paper-button>
|
||||
<h3>[[localize('server-help-connection-title')]]</h3>
|
||||
<p>[[localize('server-help-connection-description')]]</p>
|
||||
<paper-button on-tap="closeGetConnectedHelpBubble">[[localize('server-help-connection-ok')]]</paper-button>
|
||||
</outline-help-bubble>
|
||||
<outline-help-bubble id="addAccessKeyHelpBubble" vertical-align="top" horizontal-align="left">
|
||||
<outline-help-bubble id="addAccessKeyHelpBubble" vertical-align="bottom" horizontal-align="left">
|
||||
<img src="images/key-tip-2x.png">
|
||||
<h3>Create keys, share access</h3>
|
||||
<p>Share access keys with friends, so they can connect to your Outline server. They can use the same access key on all their devices</p>
|
||||
<paper-button on-tap="showGetConnectedHelpBubble">Next</paper-button>
|
||||
<h3>[[localize('server-help-access-key-title')]]</h3>
|
||||
<p>[[localize('server-help-access-key-description')]]</p>
|
||||
<paper-button on-tap="showGetConnectedHelpBubble">[[localize('server-help-access-key-next')]]</paper-button>
|
||||
</outline-help-bubble>
|
||||
|
||||
</template>
|
||||
|
|
@ -570,6 +574,10 @@
|
|||
type: Number,
|
||||
value: 1
|
||||
},
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
observers: [
|
||||
'_accessKeysAddedOrRemoved(accessKeyRows.splices)',
|
||||
|
|
@ -751,10 +759,10 @@
|
|||
// are initialized before this point, setPosition will not work and
|
||||
// they will appear in the top left of the view.
|
||||
initHelpBubbles: function() {
|
||||
this.showHelpBubbleOnce('addAccessKeyHelpBubble', 'addAccessKeyRow', 'up', 'left');
|
||||
this.showHelpBubbleOnce('addAccessKeyHelpBubble', 'addAccessKeyRow', 'down', 'left');
|
||||
},
|
||||
showHelpBubbleOnce: function(helpBubbleId, positionTargetId,
|
||||
arrowDirection='up', arrowAlignment='right') {
|
||||
arrowDirection='down', arrowAlignment='right') {
|
||||
const storageKey = helpBubbleId + '-dismissed';
|
||||
if (window.localStorage.getItem(storageKey)) {
|
||||
// Help bubble has already been dismissed, nothing to show.
|
||||
|
|
|
|||
|
|
@ -95,38 +95,41 @@
|
|||
</style>
|
||||
<paper-dialog id="dialog" modal>
|
||||
<div id="dialog-header">
|
||||
<h3>Share access</h3>
|
||||
<p>
|
||||
Copy this invitation and send it from a communication tool you trust. <a href="https://securityplanner.org/#/all-recommendations">Need help?</a>
|
||||
</p>
|
||||
<h3>[[localize('share-title')]]</h3>
|
||||
<p inner-h-t-m-l="[[localize('share-description', 'openLink', '<a href=https://securityplanner.org/#/all-recommendations>', 'closeLink', '</a>')]]"></p>
|
||||
</div>
|
||||
<div contenteditable id="selectableText" style="-webkit-text-size-adjust: 100%;">
|
||||
<p>You’re invited to connect to my Outline server. Use it to access the open internet, no matter where you are. Follow the instructions on your invitation link below to download the Outline App and get connected.</p>
|
||||
<p>[[localize('share-invite')]]</p>
|
||||
|
||||
<p><a href$="{{s3Url}}">{{s3Url}}</a></p>
|
||||
<p>-----</p>
|
||||
<p>Having trouble accessing the invitation link?</p>
|
||||
<p>[[localize('share-invite-trouble')]]</p>
|
||||
<ol>
|
||||
<li>
|
||||
Copy your access key:
|
||||
[[localize('share-invite-copy-access-key')]]
|
||||
<a href="{{acessKey}}">{{acessKey}}</a>
|
||||
</li>
|
||||
<li>
|
||||
Follow our invitation instructions on GitHub:
|
||||
[[localize('share-invite-instructions')]]
|
||||
<a href="https://github.com/Jigsaw-Code/outline-client/blob/master/docs/invitation-instructions.md">https://github.com/Jigsaw-Code/outline-client/blob/master/docs/invitation-instructions.md</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div id="button-row">
|
||||
<paper-button id="copyButton" on-tap="copyClicked">Copy invitation</paper-button>
|
||||
<paper-button id="doneButton" dialog-confirm>Done</paper-button>
|
||||
<paper-button id="copyButton" on-tap="copyClicked">[[localize('share-invite-copy')]]</paper-button>
|
||||
<paper-button id="doneButton" dialog-confirm>[[localize('done')]]</paper-button>
|
||||
</div>
|
||||
<div id="copyText" hidden>Copied to clipboard</div>
|
||||
<div id="copyText" hidden>[[localize('share-invite-copied')]]</div>
|
||||
</paper-dialog>
|
||||
</template>
|
||||
<script>
|
||||
// TODO(alalama): add a language selector. This should be a separate instance of Polymer.AppLocalizeBehavior
|
||||
// so the app language is not changed. Consider refactoring l10n into a separate Polymer behavior.
|
||||
Polymer({
|
||||
is: 'outline-share-dialog',
|
||||
properties: {
|
||||
localize: {type: Function, readonly: true},
|
||||
},
|
||||
created: function () {
|
||||
this.clipboard = require('clipboard-polyfill');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@
|
|||
<img id="logo" src="images/launcher-icon.png" />
|
||||
</div>
|
||||
<div id="tos">
|
||||
<span>I have read and understood the <a href="https://s3.amazonaws.com/outline-vpn/static_downloads/Outline-Terms-of-Service.html">Outline Terms of Service</a>.</span>
|
||||
<paper-button on-tap="acceptTermsOfService">OK</button>
|
||||
<span inner-h-t-m-l="[[localize('terms-of-service', 'openLink', '<a href=https://s3.amazonaws.com/outline-vpn/static_downloads/Outline-Terms-of-Service.html>', 'closeLink', '</a>')]]"></span>
|
||||
<paper-button on-tap="acceptTermsOfService">[[localize('okay')]]</paper-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
|
@ -64,6 +64,10 @@
|
|||
type: Boolean,
|
||||
value: false,
|
||||
notify: true,
|
||||
},
|
||||
localize: {
|
||||
type: Function,
|
||||
readonly: true
|
||||
}
|
||||
},
|
||||
acceptTermsOfService: function() {
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
<!--
|
||||
Copyright 2018 The Outline Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script>
|
||||
let shadowsocksClients = [{
|
||||
displayName: 'Android',
|
||||
userAgentMatch: 'Android'
|
||||
}, {
|
||||
displayName: 'iPhone',
|
||||
userAgentMatch: 'iPhone'
|
||||
}, {
|
||||
displayName: 'Windows',
|
||||
userAgentMatch: 'Windows'
|
||||
}, {
|
||||
displayName: 'Mac',
|
||||
userAgentMatch: 'Macintosh'
|
||||
}, {
|
||||
displayName: 'Linux',
|
||||
userAgentMatch: 'Linux'
|
||||
}];
|
||||
</script>
|
||||
|
|
@ -318,6 +318,7 @@ class FakePolymerAppRoot {
|
|||
// and throwing an exception would result in breakage.
|
||||
setAttribute() {}
|
||||
addEventListener() {}
|
||||
localize() {}
|
||||
}
|
||||
|
||||
class FakeServer implements server.Server {
|
||||
|
|
|
|||
|
|
@ -45,23 +45,6 @@ interface UiAccessKey {
|
|||
relativeTraffic: number;
|
||||
}
|
||||
|
||||
// Converts the access key from the remote service format to the
|
||||
// format used by outline-server-view.
|
||||
function convertToUiAccessKey(remoteAccessKey: server.AccessKey): UiAccessKey {
|
||||
return {
|
||||
id: remoteAccessKey.id,
|
||||
placeholderName: 'Key ' + remoteAccessKey.id,
|
||||
name: remoteAccessKey.name,
|
||||
accessUrl: remoteAccessKey.accessUrl,
|
||||
transferredBytes: 0,
|
||||
relativeTraffic: 0
|
||||
};
|
||||
}
|
||||
|
||||
const DIGITAL_OCEAN_CREATION_ERROR_MESSAGE = `Sorry! We couldn't create a server this time.
|
||||
If this problem persists, it might be that your account needs to be reviewed by DigitalOcean.
|
||||
Please log in to www.digitalocean.com and follow their instructions.`;
|
||||
|
||||
function isManagedServer(testServer: server.Server): testServer is server.ManagedServer {
|
||||
return !!(testServer as server.ManagedServer).getHost;
|
||||
}
|
||||
|
|
@ -145,13 +128,15 @@ export class App {
|
|||
manualServerEntryEl.clear();
|
||||
})
|
||||
.catch((e: Error) => {
|
||||
// Remove the "Attempting to connect..." display.
|
||||
// Remove the progress indicator.
|
||||
manualServerEntryEl.showConnection = false;
|
||||
// Display either error dialog or feedback depending on error type.
|
||||
if (e instanceof errors.UnreachableServerError) {
|
||||
const errorTitle = 'Unable to connect to your Outline Server';
|
||||
this.appRoot.showManualServerError(errorTitle, e.message);
|
||||
const errorTitle = appRoot.localize('error-server-unreachable-title');
|
||||
const errorMessage = appRoot.localize('error-server-unreachable');
|
||||
this.appRoot.showManualServerError(errorTitle, errorMessage);
|
||||
} else {
|
||||
// TODO(alalama): with UI validation, this code path never gets executed. Remove?
|
||||
let errorMessage = '';
|
||||
if (e.message) {
|
||||
errorMessage += `${e.message}\n`;
|
||||
|
|
@ -180,9 +165,10 @@ export class App {
|
|||
user: {email: detail.userEmail},
|
||||
tags: {category: detail.feedbackCategory, cloudProvider: detail.cloudProvider}
|
||||
});
|
||||
appRoot.showNotification('Thanks for helping us improve! We love hearing from you.');
|
||||
appRoot.showNotification(appRoot.localize('notification-feedback-thanks'));
|
||||
} catch (e) {
|
||||
appRoot.showError('Failed to submit feedback. Please try again.');
|
||||
console.error(`Failed to submit feedback: ${e}`);
|
||||
appRoot.showError(appRoot.localize('error-feedback'));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -253,8 +239,14 @@ export class App {
|
|||
this.displayServerRepository.removeServer(displayServer);
|
||||
}
|
||||
const unsyncedServerNames = unsyncedServers.map(s => s.name).join(', ');
|
||||
this.appRoot.showError(
|
||||
`${unsyncedServerNames} no longer present in your DigitalOcean account.`);
|
||||
let messageKey = 'error-server-removed';
|
||||
let placeholder = 'serverName';
|
||||
if (unsyncedServers.length > 1) {
|
||||
// Pluralize localized message.
|
||||
messageKey = 'error-servers-removed';
|
||||
placeholder = 'serverNames';
|
||||
}
|
||||
this.appRoot.showError(this.appRoot.localize(messageKey, placeholder, unsyncedServerNames));
|
||||
}
|
||||
|
||||
await this.syncDisplayServersToUi();
|
||||
|
|
@ -344,7 +336,7 @@ export class App {
|
|||
// Set name to the default server name for this region. Because the server
|
||||
// is still being created, the getName REST API will not yet be available.
|
||||
const regionId = this.serverBeingCreated.getHost().getRegionId();
|
||||
const serverName = digitalocean_server.MakeEnglishNameForServer(regionId);
|
||||
const serverName = this.makeLocalizedServerName(regionId);
|
||||
return {
|
||||
// Use the droplet ID until the API URL is available.
|
||||
id: this.serverBeingCreated.getHost().getHostId(),
|
||||
|
|
@ -429,9 +421,10 @@ export class App {
|
|||
.catch((error) => {
|
||||
if (!cancelled) {
|
||||
this.showIntro();
|
||||
const msg = 'Failed to get DigitalOcean account information';
|
||||
this.displayError(msg, error);
|
||||
reject(new Error(`${msg}: ${error}`));
|
||||
const msg = `Failed to get DigitalOcean account information: ${error}`;
|
||||
console.error(msg);
|
||||
this.appRoot.showError(this.appRoot.localize('error-do-account-info'));
|
||||
reject(new Error(msg));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -508,7 +501,7 @@ export class App {
|
|||
} else {
|
||||
// Server has been deleted outside the app.
|
||||
this.appRoot.showError(
|
||||
`${displayServer.name} no longer present in your DigitalOcean account.`);
|
||||
this.appRoot.localize('error-server-removed', 'serverName', displayServer.name));
|
||||
this.removeServerFromDisplay(displayServer);
|
||||
this.selectedServer = null;
|
||||
this.appRoot.selectedServer = null;
|
||||
|
|
@ -554,25 +547,13 @@ export class App {
|
|||
});
|
||||
};
|
||||
|
||||
private displayError(message: string, cause: Error) {
|
||||
console.error(`${message}: ${cause}`);
|
||||
this.appRoot.showError(message);
|
||||
console.error(message);
|
||||
}
|
||||
|
||||
private displayNotification(message: string) {
|
||||
this.appRoot.showNotification(message);
|
||||
}
|
||||
|
||||
// Shows the intro screen with overview and options to sign in or sign up.
|
||||
private showIntro() {
|
||||
this.appRoot.showIntro();
|
||||
}
|
||||
|
||||
private displayAppUpdateNotification() {
|
||||
const msg =
|
||||
'An updated version of the Outline Manager has been downloaded. It will be installed when you restart the application.';
|
||||
this.appRoot.showToast(msg, 60000);
|
||||
this.appRoot.showNotification(this.appRoot.localize('notification-app-update'), 60000);
|
||||
}
|
||||
|
||||
private connectToDigitalOcean() {
|
||||
|
|
@ -623,7 +604,8 @@ export class App {
|
|||
if (!session.isCancelled()) {
|
||||
this.clearCredentialsAndShowIntro();
|
||||
bringToFront();
|
||||
this.displayError('Authentication with DigitalOcean failed', error);
|
||||
console.error(`DigitalOcean authentication failed: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-do-auth'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -671,7 +653,8 @@ export class App {
|
|||
regionPicker.availableRegionIds = availableRegionIds;
|
||||
},
|
||||
(e) => {
|
||||
this.displayError('Failed to get list of available regions', e);
|
||||
console.error(`Failed to get list of available regions: ${e}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-do-regions'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -700,13 +683,15 @@ export class App {
|
|||
this.serverBeingCreated = null;
|
||||
return;
|
||||
}
|
||||
const errorMessage = this.serverBeingCreated.isInstallCompleted() ?
|
||||
'We are unable to connect to your Outline server at the moment. This may be due to a firewall on your network or temporary connectivity issues with digitalocean.com.' :
|
||||
'There was an error creating your Outline server. This may be due to a firewall on your network or temporary connectivity issues with digitalocean.com.';
|
||||
let errorMessage = this.serverBeingCreated.isInstallCompleted() ?
|
||||
this.appRoot.localize('error-server-unreachable-title') :
|
||||
this.appRoot.localize('error-server-creation');
|
||||
errorMessage += ` ${this.appRoot.localize('digitalocean-unreachable')}`;
|
||||
this.appRoot
|
||||
.showModalDialog(
|
||||
null, // Don't display any title.
|
||||
errorMessage, ['Delete this server', 'Try again'])
|
||||
errorMessage,
|
||||
[this.appRoot.localize('server-destroy'), this.appRoot.localize('retry')])
|
||||
.then((clickedButtonIndex: number) => {
|
||||
if (clickedButtonIndex === 0) { // user clicked 'Delete this server'
|
||||
console.info('Deleting unreachable server');
|
||||
|
|
@ -722,12 +707,23 @@ export class App {
|
|||
});
|
||||
}
|
||||
|
||||
private getLocalizedCityName(regionId: server.RegionId) {
|
||||
const cityId = digitalocean_server.GetCityId(regionId);
|
||||
return this.appRoot.localize(`city-${cityId}`);
|
||||
}
|
||||
|
||||
private makeLocalizedServerName(regionId: server.RegionId) {
|
||||
const serverLocation = this.getLocalizedCityName(regionId);
|
||||
return this.appRoot.localize('server-name', 'serverLocation', serverLocation);
|
||||
}
|
||||
|
||||
// Returns a promise which fulfills once the DigitalOcean droplet is created.
|
||||
// Shadowbox may not be fully installed once this promise is fulfilled.
|
||||
public createDigitalOceanServer(regionId: server.RegionId) {
|
||||
const serverName = this.makeLocalizedServerName(regionId);
|
||||
return this
|
||||
.digitalOceanRetry(() => {
|
||||
return this.digitalOceanRepository.createServer(regionId);
|
||||
return this.digitalOceanRepository.createServer(regionId, serverName);
|
||||
})
|
||||
.then((server) => {
|
||||
this.syncServerCreationToUi(server);
|
||||
|
|
@ -761,6 +757,7 @@ export class App {
|
|||
view.serverHostname = selectedServer.getHostname();
|
||||
view.serverManagementApiUrl = selectedServer.getManagementApiUrl();
|
||||
view.serverPortForNewAccessKeys = selectedServer.getPortForNewAccessKeys();
|
||||
// TODO(alalama): use actual locale.
|
||||
view.serverCreationDate = selectedServer.getCreatedDate().toLocaleString(
|
||||
'en-US', {year: 'numeric', month: 'long', day: 'numeric'});
|
||||
|
||||
|
|
@ -770,7 +767,7 @@ export class App {
|
|||
view.monthlyCost = host.getMonthlyCost().usd;
|
||||
view.monthlyOutboundTransferBytes =
|
||||
host.getMonthlyOutboundTransferLimit().terabytes * (2 ** 40);
|
||||
view.serverLocation = digitalocean_server.GetEnglishCityName(host.getRegionId());
|
||||
view.serverLocation = this.getLocalizedCityName(host.getRegionId());
|
||||
} else {
|
||||
view.isServerManaged = false;
|
||||
}
|
||||
|
|
@ -783,14 +780,15 @@ export class App {
|
|||
// Load "My Connection" and other access keys.
|
||||
selectedServer.listAccessKeys()
|
||||
.then((serverAccessKeys: server.AccessKey[]) => {
|
||||
view.accessKeyRows = serverAccessKeys.map(convertToUiAccessKey);
|
||||
view.accessKeyRows = serverAccessKeys.map(this.convertToUiAccessKey.bind(this));
|
||||
// Initialize help bubbles once the page has rendered.
|
||||
setTimeout(() => {
|
||||
view.initHelpBubbles();
|
||||
}, 250);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Could not load keys', error);
|
||||
console.error(`Failed to load access keys: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-keys-get'));
|
||||
});
|
||||
|
||||
this.showTransferStats(selectedServer, view);
|
||||
|
|
@ -870,20 +868,36 @@ export class App {
|
|||
}
|
||||
|
||||
private getS3InviteUrl(accessUrl: string, isAdmin = false) {
|
||||
// TODO(alalama): display the invite in the user's preferred language.
|
||||
const adminParam = isAdmin ? '?admin_embed' : '';
|
||||
return `https://s3.amazonaws.com/outline-vpn/invite.html${adminParam}#${
|
||||
encodeURIComponent(accessUrl)}`;
|
||||
}
|
||||
|
||||
// Converts the access key from the remote service format to the
|
||||
// format used by outline-server-view.
|
||||
private convertToUiAccessKey(remoteAccessKey: server.AccessKey): UiAccessKey {
|
||||
return {
|
||||
id: remoteAccessKey.id,
|
||||
placeholderName: `${this.appRoot.localize('key')} ${remoteAccessKey.id}`,
|
||||
name: remoteAccessKey.name,
|
||||
accessUrl: remoteAccessKey.accessUrl,
|
||||
transferredBytes: 0,
|
||||
relativeTraffic: 0
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private addAccessKey() {
|
||||
this.selectedServer.addAccessKey()
|
||||
.then((serverAccessKey: server.AccessKey) => {
|
||||
const uiAccessKey = convertToUiAccessKey(serverAccessKey);
|
||||
const uiAccessKey = this.convertToUiAccessKey(serverAccessKey);
|
||||
this.appRoot.getServerView(this.appRoot.selectedServer.id).addAccessKey(uiAccessKey);
|
||||
this.displayNotification('Key added');
|
||||
this.appRoot.showNotification(this.appRoot.localize('notification-key-added'));
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Failed to add key', error);
|
||||
console.error(`Failed to add access key: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-key-add'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -893,7 +907,8 @@ export class App {
|
|||
entry.commitName();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Failed to rename key', error);
|
||||
console.error(`Failed to rename access key: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-key-rename'));
|
||||
entry.revertName();
|
||||
});
|
||||
}
|
||||
|
|
@ -906,7 +921,9 @@ export class App {
|
|||
serverConfig = parseManualServerConfig(userInput);
|
||||
} catch (e) {
|
||||
// This shouldn't happen because the UI validates the URL before enabling the DONE button.
|
||||
return Promise.reject(new Error(`could not parse server config: ${e.message}`));
|
||||
const msg = `could not parse server config: ${e.message}`;
|
||||
console.error(msg);
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
|
||||
// Don't let `ManualServerRepository.addServer` throw to avoid redundant error handling if we
|
||||
|
|
@ -914,7 +931,7 @@ export class App {
|
|||
const storedServer = this.manualServerRepository.findServer(serverConfig);
|
||||
if (!!storedServer) {
|
||||
return this.syncServerToDisplay(storedServer).then((displayServer) => {
|
||||
this.appRoot.showToast('Server already added', 5000);
|
||||
this.appRoot.showNotification(this.appRoot.localize('notification-server-exists'), 5000);
|
||||
this.showServerIfHealthy(storedServer, displayServer);
|
||||
});
|
||||
}
|
||||
|
|
@ -926,8 +943,7 @@ export class App {
|
|||
// Remove inaccessible manual server from local storage if it was just created.
|
||||
manualServer.forget();
|
||||
console.error('Manual server installed but unreachable.');
|
||||
return Promise.reject(new errors.UnreachableServerError(
|
||||
'Your Outline Server was installed correctly, but we are not able to connect to it. Most likely this is because your server\'s firewall rules are blocking incoming connections. Please review them and make sure to allow incoming TCP connections on ports ranging from 1024 to 65535.'));
|
||||
return Promise.reject(new errors.UnreachableServerError());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -937,10 +953,11 @@ export class App {
|
|||
this.selectedServer.removeAccessKey(accessKeyId)
|
||||
.then(() => {
|
||||
this.appRoot.getServerView(this.appRoot.selectedServer.id).removeAccessKey(accessKeyId);
|
||||
this.displayNotification('Key removed');
|
||||
this.appRoot.showNotification(this.appRoot.localize('notification-key-removed'));
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Failed to remove key', error);
|
||||
console.error(`Failed to remove access key: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-key-remove'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -952,9 +969,9 @@ export class App {
|
|||
throw new Error(msg);
|
||||
}
|
||||
|
||||
const confirmationTitle = 'Destroy Server?';
|
||||
const confirmationText = 'Existing users will lose access. This action cannot be undone.';
|
||||
const confirmationButton = 'DESTROY';
|
||||
const confirmationTitle = this.appRoot.localize('confirmation-server-destroy-title');
|
||||
const confirmationText = this.appRoot.localize('confirmation-server-destroy');
|
||||
const confirmationButton = this.appRoot.localize('destroy');
|
||||
this.appRoot.getConfirmation(confirmationTitle, confirmationText, confirmationButton, () => {
|
||||
this.digitalOceanRetry(() => {
|
||||
return serverToDelete.getHost().delete();
|
||||
|
|
@ -965,12 +982,14 @@ export class App {
|
|||
this.appRoot.selectedServer = null;
|
||||
this.selectedServer = null;
|
||||
this.showIntro();
|
||||
this.displayNotification('Server destroyed');
|
||||
this.appRoot.showNotification(
|
||||
this.appRoot.localize('notification-server-destroyed'));
|
||||
},
|
||||
(e) => {
|
||||
// Don't show a toast on the login screen.
|
||||
if (!(e instanceof digitalocean_api.XhrError)) {
|
||||
this.displayError('Failed to destroy server', e);
|
||||
console.error(`Failed destroy server: ${e}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-server-destroy'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -984,17 +1003,16 @@ export class App {
|
|||
throw new Error(msg);
|
||||
}
|
||||
|
||||
const confirmationTitle = 'Remove Server?';
|
||||
const confirmationText =
|
||||
'This action removes your server from the Outline Manager, but does not block proxy access to users. You will still need to manually delete the Outline server from your host machine.';
|
||||
const confirmationButton = 'REMOVE';
|
||||
const confirmationTitle = this.appRoot.localize('confirmation-server-remove-title');
|
||||
const confirmationText = this.appRoot.localize('confirmation-server-remove');
|
||||
const confirmationButton = this.appRoot.localize('remove');
|
||||
this.appRoot.getConfirmation(confirmationTitle, confirmationText, confirmationButton, () => {
|
||||
serverToForget.forget();
|
||||
this.removeServerFromDisplay(this.appRoot.selectedServer);
|
||||
this.appRoot.selectedServer = null;
|
||||
this.selectedServer = null;
|
||||
this.showIntro();
|
||||
this.displayNotification('Server removed');
|
||||
this.appRoot.showNotification(this.appRoot.localize('notification-server-removed'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1006,7 +1024,8 @@ export class App {
|
|||
metricsEnabled;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Error setting metrics enabled', error);
|
||||
console.error(`Failed to set metrics enabled: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-metrics'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1017,7 +1036,8 @@ export class App {
|
|||
return this.syncAndShowServer(this.selectedServer);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.displayError('Error renaming server', error);
|
||||
console.error(`Failed to rename server: ${error}`);
|
||||
this.appRoot.showError(this.appRoot.localize('error-server-rename'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,4 +55,4 @@ mkdir -p $STATIC_DIR
|
|||
cp -r $OUT_DIR/browserified/* $STATIC_DIR/
|
||||
|
||||
# Copy static resources
|
||||
cp -r $ROOT_DIR/src/server_manager/{bower_components,ui_components,index.html,images} $STATIC_DIR
|
||||
cp -r $ROOT_DIR/src/server_manager/{bower_components,ui_components,index.html,images,messages} $STATIC_DIR
|
||||
|
|
|
|||
|
|
@ -52,27 +52,6 @@ function makeKeyValueTag(key: string, value: string) {
|
|||
return [KEY_VALUE_TAG, key, asciiToHex(value)].join(':');
|
||||
}
|
||||
|
||||
const cityEnglishNameById: {[key: string]: string} = {
|
||||
ams: 'Amsterdam',
|
||||
sgp: 'Singapore',
|
||||
blr: 'Bangalore',
|
||||
fra: 'Frankfurt',
|
||||
lon: 'London',
|
||||
sfo: 'San Francisco',
|
||||
tor: 'Toronto',
|
||||
nyc: 'New York'
|
||||
};
|
||||
|
||||
// Returns a name for a server in the given region.
|
||||
export function MakeEnglishNameForServer(regionId: server.RegionId) {
|
||||
return `Outline Server ${cityEnglishNameById[getCityId(regionId)]}`;
|
||||
}
|
||||
|
||||
// Returns the English name of the given region.
|
||||
export function GetEnglishCityName(regionId: server.RegionId) {
|
||||
return cityEnglishNameById[getCityId(regionId)];
|
||||
}
|
||||
|
||||
// Possible install states for DigitaloceanServer.
|
||||
enum InstallState {
|
||||
// Unknown state - server may still be installing.
|
||||
|
|
@ -354,7 +333,7 @@ function startsWithCaseInsensitive(text: string, prefix: string) {
|
|||
return text.slice(0, prefix.length).toLowerCase() === prefix.toLowerCase();
|
||||
}
|
||||
|
||||
function getCityId(slug: server.RegionId): string {
|
||||
export function GetCityId(slug: server.RegionId): string {
|
||||
return slug.substr(0, 3).toLowerCase();
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +351,7 @@ export class DigitaloceanServerRepository implements server.ManagedServerReposit
|
|||
return this.digitalOcean.getRegionInfo().then((regions) => {
|
||||
const ret: server.RegionMap = {};
|
||||
regions.forEach((region) => {
|
||||
const cityId = getCityId(region.slug);
|
||||
const cityId = GetCityId(region.slug);
|
||||
if (!(cityId in ret)) {
|
||||
ret[cityId] = [];
|
||||
}
|
||||
|
|
@ -385,8 +364,7 @@ export class DigitaloceanServerRepository implements server.ManagedServerReposit
|
|||
}
|
||||
|
||||
// Creates a server and returning it when it becomes active.
|
||||
createServer(region: server.RegionId): Promise<server.ManagedServer> {
|
||||
const name = MakeEnglishNameForServer(region);
|
||||
createServer(region: server.RegionId, name: string): Promise<server.ManagedServer> {
|
||||
console.time('activeServer');
|
||||
console.time('servingServer');
|
||||
const onceKeyPair = crypto.generateKeyPair();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue