From b06fd8af26682f394ad1f075fce41ce9aeea04a1 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 17 Sep 2018 17:42:04 +1000 Subject: Hold a share open if its timer hsa expired but a file is still uploading. Don't allow other uploads during this time --- onionshare/web.py | 176 +++++++++++++++++--------------- onionshare_gui/receive_mode/__init__.py | 11 ++ share/locale/en.json | 1 + 3 files changed, 106 insertions(+), 82 deletions(-) diff --git a/onionshare/web.py b/onionshare/web.py index 221c2c53..9c3d52ba 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -118,6 +118,7 @@ class Web(object): self.download_in_progress = False self.done = False + self.can_upload = True # If the client closes the OnionShare window while a download is in progress, # it should immediately stop serving the file. The client_cancel global is @@ -343,96 +344,104 @@ class Web(object): """ Upload files. """ - # Make sure downloads_dir exists - valid = True - try: - self.common.validate_downloads_dir() - except DownloadsDirErrorCannotCreate: - self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path) - print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir'))) - valid = False - except DownloadsDirErrorNotWritable: - self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path) - print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir'))) - valid = False - if not valid: - flash('Error uploading, please inform the OnionShare user', 'error') - if self.common.settings.get('public_mode'): - return redirect('/') - else: - return redirect('/{}'.format(slug_candidate)) + while self.can_upload: + # Make sure downloads_dir exists + valid = True + try: + self.common.validate_downloads_dir() + except DownloadsDirErrorCannotCreate: + self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path) + print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir'))) + valid = False + except DownloadsDirErrorNotWritable: + self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path) + print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir'))) + valid = False + if not valid: + flash('Error uploading, please inform the OnionShare user', 'error') + if self.common.settings.get('public_mode'): + return redirect('/') + else: + return redirect('/{}'.format(slug_candidate)) + + files = request.files.getlist('file[]') + filenames = [] + print('') + for f in files: + if f.filename != '': + # Automatically rename the file, if a file of the same name already exists + filename = secure_filename(f.filename) + filenames.append(filename) + local_path = os.path.join(self.common.settings.get('downloads_dir'), filename) + if os.path.exists(local_path): + if '.' in filename: + # Add "-i", e.g. change "foo.txt" to "foo-2.txt" + parts = filename.split('.') + name = parts[:-1] + ext = parts[-1] + + i = 2 + valid = False + while not valid: + new_filename = '{}-{}.{}'.format('.'.join(name), i, ext) + local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) + if os.path.exists(local_path): + i += 1 + else: + valid = True + else: + # If no extension, just add "-i", e.g. change "foo" to "foo-2" + i = 2 + valid = False + while not valid: + new_filename = '{}-{}'.format(filename, i) + local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) + if os.path.exists(local_path): + i += 1 + else: + valid = True + + basename = os.path.basename(local_path) + if f.filename != basename: + # Tell the GUI that the file has changed names + self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, { + 'id': request.upload_id, + 'old_filename': f.filename, + 'new_filename': basename + }) - files = request.files.getlist('file[]') - filenames = [] - print('') - for f in files: - if f.filename != '': - # Automatically rename the file, if a file of the same name already exists - filename = secure_filename(f.filename) - filenames.append(filename) - local_path = os.path.join(self.common.settings.get('downloads_dir'), filename) - if os.path.exists(local_path): - if '.' in filename: - # Add "-i", e.g. change "foo.txt" to "foo-2.txt" - parts = filename.split('.') - name = parts[:-1] - ext = parts[-1] - - i = 2 - valid = False - while not valid: - new_filename = '{}-{}.{}'.format('.'.join(name), i, ext) - local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) - if os.path.exists(local_path): - i += 1 - else: - valid = True - else: - # If no extension, just add "-i", e.g. change "foo" to "foo-2" - i = 2 - valid = False - while not valid: - new_filename = '{}-{}'.format(filename, i) - local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) - if os.path.exists(local_path): - i += 1 - else: - valid = True - - basename = os.path.basename(local_path) - if f.filename != basename: - # Tell the GUI that the file has changed names - self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, { - 'id': request.upload_id, - 'old_filename': f.filename, - 'new_filename': basename - }) + self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path)) + print(strings._('receive_mode_received_file').format(local_path)) + f.save(local_path) - self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path)) - print(strings._('receive_mode_received_file').format(local_path)) - f.save(local_path) + # Note that flash strings are on English, and not translated, on purpose, + # to avoid leaking the locale of the OnionShare user + if len(filenames) == 0: + flash('No files uploaded', 'info') + else: + for filename in filenames: + flash('Sent {}'.format(filename), 'info') - # Note that flash strings are on English, and not translated, on purpose, - # to avoid leaking the locale of the OnionShare user - if len(filenames) == 0: - flash('No files uploaded', 'info') - else: - for filename in filenames: - flash('Sent {}'.format(filename), 'info') - if self.common.settings.get('public_mode'): - return redirect('/') - else: - return redirect('/{}'.format(slug_candidate)) + # Register that uploads were sent (for shutdown timer) + self.done = True + + if self.common.settings.get('public_mode'): + return redirect('/') + else: + return redirect('/{}'.format(slug_candidate)) @self.app.route("//upload", methods=['POST']) def upload(slug_candidate): self.check_slug_candidate(slug_candidate) - return upload_logic(slug_candidate) + if self.can_upload: + return upload_logic(slug_candidate) + else: + return self.error404() @self.app.route("/upload", methods=['POST']) def upload_public(): - if not self.common.settings.get('public_mode'): + if not self.common.settings.get('public_mode') or not self.can_upload: return self.error404() return upload_logic() @@ -449,11 +458,14 @@ class Web(object): @self.app.route("//close", methods=['POST']) def close(slug_candidate): self.check_slug_candidate(slug_candidate) - return close_logic(slug_candidate) + if self.can_upload: + return close_logic(slug_candidate) + else: + return self.error404() @self.app.route("/close", methods=['POST']) def close_public(): - if not self.common.settings.get('public_mode'): + if not self.common.settings.get('public_mode') or not self.can_upload: return self.error404() return close_logic() @@ -745,7 +757,7 @@ class ReceiveModeRequest(Request): # Is this a valid upload request? self.upload_request = False - if self.method == 'POST': + if self.method == 'POST' and self.web.can_upload: if self.path == '/{}/upload'.format(self.web.slug): self.upload_request = True else: diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 623d3986..a9f15749 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -98,6 +98,17 @@ class ReceiveMode(Mode): The shutdown timer expired, should we stop the server? Returns a bool """ # TODO: wait until the final upload is done before stoppign the server? + # If there were no attempts to upload files, or all uploads are done, we can stop + if self.web.upload_count == 0 or self.web.done: + self.server_status.stop_server() + self.server_status_label.setText(strings._('close_on_timeout', True)) + return True + # An upload is probably still running - hold off on stopping the share, but block new shares. + else: + self.server_status_label.setText(strings._('timeout_upload_still_running', True)) + self.web.can_upload = False + return False + return True def start_server_custom(self): diff --git a/share/locale/en.json b/share/locale/en.json index cc39bba7..beebac77 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -15,6 +15,7 @@ "close_on_timeout": "Stopped because timer expired", "closing_automatically": "Stopped because download finished", "timeout_download_still_running": "Waiting for download to complete", + "timeout_upload_still_running": "Waiting for upload to complete", "large_filesize": "Warning: Sending large files could take hours", "systray_menu_exit": "Quit", "systray_download_started_title": "OnionShare Download Started", -- cgit v1.2.3-54-g00ecf From 7e875e021a34bc63ddee8d48b32c918d9561f7c0 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 18 Sep 2018 08:35:58 +1000 Subject: Remove unnecessary loop. Remove the Close route/setting which can DoS another running upload. Fix detecting whether any uploads are still in progress before terminating the service after timer expires. Don't register 404s for uploads after expiry has finished (throw a 403 instead)" --- onionshare/settings.py | 3 +- onionshare/web.py | 208 +++++++++++++++----------------- onionshare_gui/receive_mode/__init__.py | 2 +- onionshare_gui/settings_dialog.py | 13 -- share/locale/en.json | 1 - share/templates/403.html | 16 +++ share/templates/receive.html | 9 -- test/test_onionshare_settings.py | 3 +- test/test_onionshare_web.py | 30 ----- 9 files changed, 114 insertions(+), 171 deletions(-) create mode 100644 share/templates/403.html diff --git a/onionshare/settings.py b/onionshare/settings.py index ef75be2f..6cc70954 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -72,8 +72,7 @@ class Settings(object): 'public_mode': False, 'slug': '', 'hidservauth_string': '', - 'downloads_dir': self.build_default_downloads_dir(), - 'receive_allow_receiver_shutdown': True + 'downloads_dir': self.build_default_downloads_dir() } self._settings = {} self.fill_in_defaults() diff --git a/onionshare/web.py b/onionshare/web.py index 9c3d52ba..c197caf1 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -119,6 +119,7 @@ class Web(object): self.done = False self.can_upload = True + self.uploads_in_progress = [] # If the client closes the OnionShare window while a download is in progress, # it should immediately stop serving the file. The client_cancel global is @@ -323,9 +324,7 @@ class Web(object): r = make_response(render_template( 'receive.html', - upload_action=upload_action, - close_action=close_action, - receive_allow_receiver_shutdown=self.common.settings.get('receive_allow_receiver_shutdown'))) + upload_action=upload_action)) return self.add_security_headers(r) @self.app.route("/") @@ -344,131 +343,103 @@ class Web(object): """ Upload files. """ - while self.can_upload: - # Make sure downloads_dir exists - valid = True - try: - self.common.validate_downloads_dir() - except DownloadsDirErrorCannotCreate: - self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path) - print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir'))) - valid = False - except DownloadsDirErrorNotWritable: - self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path) - print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir'))) - valid = False - if not valid: - flash('Error uploading, please inform the OnionShare user', 'error') - if self.common.settings.get('public_mode'): - return redirect('/') - else: - return redirect('/{}'.format(slug_candidate)) - - files = request.files.getlist('file[]') - filenames = [] - print('') - for f in files: - if f.filename != '': - # Automatically rename the file, if a file of the same name already exists - filename = secure_filename(f.filename) - filenames.append(filename) - local_path = os.path.join(self.common.settings.get('downloads_dir'), filename) - if os.path.exists(local_path): - if '.' in filename: - # Add "-i", e.g. change "foo.txt" to "foo-2.txt" - parts = filename.split('.') - name = parts[:-1] - ext = parts[-1] - - i = 2 - valid = False - while not valid: - new_filename = '{}-{}.{}'.format('.'.join(name), i, ext) - local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) - if os.path.exists(local_path): - i += 1 - else: - valid = True - else: - # If no extension, just add "-i", e.g. change "foo" to "foo-2" - i = 2 - valid = False - while not valid: - new_filename = '{}-{}'.format(filename, i) - local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) - if os.path.exists(local_path): - i += 1 - else: - valid = True - - basename = os.path.basename(local_path) - if f.filename != basename: - # Tell the GUI that the file has changed names - self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, { - 'id': request.upload_id, - 'old_filename': f.filename, - 'new_filename': basename - }) - - self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path)) - print(strings._('receive_mode_received_file').format(local_path)) - f.save(local_path) - - # Note that flash strings are on English, and not translated, on purpose, - # to avoid leaking the locale of the OnionShare user - if len(filenames) == 0: - flash('No files uploaded', 'info') - else: - for filename in filenames: - flash('Sent {}'.format(filename), 'info') - - - # Register that uploads were sent (for shutdown timer) - self.done = True - + # Make sure downloads_dir exists + valid = True + try: + self.common.validate_downloads_dir() + except DownloadsDirErrorCannotCreate: + self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path) + print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir'))) + valid = False + except DownloadsDirErrorNotWritable: + self.add_request(Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path) + print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir'))) + valid = False + if not valid: + flash('Error uploading, please inform the OnionShare user', 'error') if self.common.settings.get('public_mode'): return redirect('/') else: return redirect('/{}'.format(slug_candidate)) + files = request.files.getlist('file[]') + filenames = [] + print('') + for f in files: + if f.filename != '': + # Automatically rename the file, if a file of the same name already exists + filename = secure_filename(f.filename) + filenames.append(filename) + local_path = os.path.join(self.common.settings.get('downloads_dir'), filename) + if os.path.exists(local_path): + if '.' in filename: + # Add "-i", e.g. change "foo.txt" to "foo-2.txt" + parts = filename.split('.') + name = parts[:-1] + ext = parts[-1] + + i = 2 + valid = False + while not valid: + new_filename = '{}-{}.{}'.format('.'.join(name), i, ext) + local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) + if os.path.exists(local_path): + i += 1 + else: + valid = True + else: + # If no extension, just add "-i", e.g. change "foo" to "foo-2" + i = 2 + valid = False + while not valid: + new_filename = '{}-{}'.format(filename, i) + local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename) + if os.path.exists(local_path): + i += 1 + else: + valid = True + + basename = os.path.basename(local_path) + if f.filename != basename: + # Tell the GUI that the file has changed names + self.add_request(Web.REQUEST_UPLOAD_FILE_RENAMED, request.path, { + 'id': request.upload_id, + 'old_filename': f.filename, + 'new_filename': basename + }) + self.common.log('Web', 'receive_routes', '/upload, uploaded {}, saving to {}'.format(f.filename, local_path)) + print(strings._('receive_mode_received_file').format(local_path)) + f.save(local_path) + + # Note that flash strings are on English, and not translated, on purpose, + # to avoid leaking the locale of the OnionShare user + if len(filenames) == 0: + flash('No files uploaded', 'info') + else: + for filename in filenames: + flash('Sent {}'.format(filename), 'info') + + if self.common.settings.get('public_mode'): + return redirect('/') + else: + return redirect('/{}'.format(slug_candidate)) + @self.app.route("//upload", methods=['POST']) def upload(slug_candidate): + if not self.can_upload: + return self.error403() self.check_slug_candidate(slug_candidate) - if self.can_upload: - return upload_logic(slug_candidate) - else: - return self.error404() + return upload_logic(slug_candidate) @self.app.route("/upload", methods=['POST']) def upload_public(): - if not self.common.settings.get('public_mode') or not self.can_upload: + if not self.common.settings.get('public_mode'): return self.error404() + if not self.can_upload: + return self.error403() return upload_logic() - def close_logic(slug_candidate=''): - if self.common.settings.get('receive_allow_receiver_shutdown'): - self.force_shutdown() - r = make_response(render_template('closed.html')) - self.add_request(Web.REQUEST_CLOSE_SERVER, request.path) - return self.add_security_headers(r) - else: - return redirect('/{}'.format(slug_candidate)) - - @self.app.route("//close", methods=['POST']) - def close(slug_candidate): - self.check_slug_candidate(slug_candidate) - if self.can_upload: - return close_logic(slug_candidate) - else: - return self.error404() - - @self.app.route("/close", methods=['POST']) - def close_public(): - if not self.common.settings.get('public_mode') or not self.can_upload: - return self.error404() - return close_logic() - def common_routes(self): """ Common web app routes between sending and receiving @@ -504,6 +475,12 @@ class Web(object): r = make_response(render_template('404.html'), 404) return self.add_security_headers(r) + def error403(self): + self.add_request(Web.REQUEST_OTHER, request.path) + + r = make_response(render_template('403.html'), 403) + return self.add_security_headers(r) + def add_security_headers(self, r): """ Add security headers to a request @@ -783,6 +760,8 @@ class ReceiveModeRequest(Request): datetime.now().strftime("%b %d, %I:%M%p"), strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) )) + # append to self.uploads_in_progress + self.web.uploads_in_progress.append(self.upload_id) # Tell the GUI self.web.add_request(Web.REQUEST_STARTED, self.path, { @@ -816,6 +795,9 @@ class ReceiveModeRequest(Request): 'id': self.upload_id }) + # remove from self.uploads_in_progress + self.web.uploads_in_progress.remove(self.upload_id) + def file_write_func(self, filename, length): """ This function gets called when a specific file is written to. diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index a9f15749..8c360d19 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -99,7 +99,7 @@ class ReceiveMode(Mode): """ # TODO: wait until the final upload is done before stoppign the server? # If there were no attempts to upload files, or all uploads are done, we can stop - if self.web.upload_count == 0 or self.web.done: + if self.web.upload_count == 0 or not self.web.uploads_in_progress: self.server_status.stop_server() self.server_status_label.setText(strings._('close_on_timeout', True)) return True diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index c4e6b752..c23f8ad8 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -101,15 +101,9 @@ class SettingsDialog(QtWidgets.QDialog): downloads_layout.addWidget(self.downloads_dir_lineedit) downloads_layout.addWidget(downloads_button) - # Allow the receiver to shutdown the server - self.receive_allow_receiver_shutdown_checkbox = QtWidgets.QCheckBox() - self.receive_allow_receiver_shutdown_checkbox.setCheckState(QtCore.Qt.Checked) - self.receive_allow_receiver_shutdown_checkbox.setText(strings._("gui_settings_receive_allow_receiver_shutdown_checkbox", True)) - # Receiving options layout receiving_group_layout = QtWidgets.QVBoxLayout() receiving_group_layout.addLayout(downloads_layout) - receiving_group_layout.addWidget(self.receive_allow_receiver_shutdown_checkbox) receiving_group = QtWidgets.QGroupBox(strings._("gui_settings_receiving_label", True)) receiving_group.setLayout(receiving_group_layout) @@ -421,12 +415,6 @@ class SettingsDialog(QtWidgets.QDialog): downloads_dir = self.old_settings.get('downloads_dir') self.downloads_dir_lineedit.setText(downloads_dir) - receive_allow_receiver_shutdown = self.old_settings.get('receive_allow_receiver_shutdown') - if receive_allow_receiver_shutdown: - self.receive_allow_receiver_shutdown_checkbox.setCheckState(QtCore.Qt.Checked) - else: - self.receive_allow_receiver_shutdown_checkbox.setCheckState(QtCore.Qt.Unchecked) - public_mode = self.old_settings.get('public_mode') if public_mode: self.public_mode_checkbox.setCheckState(QtCore.Qt.Checked) @@ -802,7 +790,6 @@ class SettingsDialog(QtWidgets.QDialog): # Also unset the HidServAuth if we are removing our reusable private key settings.set('hidservauth_string', '') settings.set('downloads_dir', self.downloads_dir_lineedit.text()) - settings.set('receive_allow_receiver_shutdown', self.receive_allow_receiver_shutdown_checkbox.isChecked()) settings.set('public_mode', self.public_mode_checkbox.isChecked()) settings.set('use_stealth', self.stealth_checkbox.isChecked()) # Always unset the HidServAuth if Stealth mode is unset diff --git a/share/locale/en.json b/share/locale/en.json index beebac77..98addae9 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -168,7 +168,6 @@ "gui_settings_receiving_label": "Receiving options", "gui_settings_downloads_label": "Save files to", "gui_settings_downloads_button": "Browse", - "gui_settings_receive_allow_receiver_shutdown_checkbox": "Receive mode can be stopped by the sender", "gui_settings_public_mode_checkbox": "OnionShare is open to the public\n(don't prevent people from guessing the OnionShare address)", "systray_close_server_title": "OnionShare Server Closed", "systray_close_server_message": "A user closed the server", diff --git a/share/templates/403.html b/share/templates/403.html new file mode 100644 index 00000000..df81f3e7 --- /dev/null +++ b/share/templates/403.html @@ -0,0 +1,16 @@ + + + + OnionShare: 403 Forbidden + + + + +
+
+

+

You are not allowed to perform that action at this time.

+
+
+ + diff --git a/share/templates/receive.html b/share/templates/receive.html index d8b02f73..e85b6ff9 100644 --- a/share/templates/receive.html +++ b/share/templates/receive.html @@ -34,14 +34,5 @@ - {% if receive_allow_receiver_shutdown %} - {% with messages = get_flashed_messages() %} - {% if messages %} -
- -
- {% endif %} - {% endwith %} - {% endif %} diff --git a/test/test_onionshare_settings.py b/test/test_onionshare_settings.py index 1521492d..fb9e1f69 100644 --- a/test/test_onionshare_settings.py +++ b/test/test_onionshare_settings.py @@ -63,8 +63,7 @@ class TestSettings: 'private_key': '', 'slug': '', 'hidservauth_string': '', - 'downloads_dir': os.path.expanduser('~/OnionShare'), - 'receive_allow_receiver_shutdown': True, + 'downloads_dir': os.path.expanduser('~/OnionShare') 'public_mode': False } diff --git a/test/test_onionshare_web.py b/test/test_onionshare_web.py index 2209a0fd..d523ea96 100644 --- a/test/test_onionshare_web.py +++ b/test/test_onionshare_web.py @@ -138,36 +138,6 @@ class TestWeb: res.get_data() assert res.status_code == 200 - def test_receive_mode_allow_receiver_shutdown_on(self, common_obj): - web = web_obj(common_obj, True) - - common_obj.settings.set('receive_allow_receiver_shutdown', True) - - assert web.running == True - - with web.app.test_client() as c: - # Load close page - res = c.post('/{}/close'.format(web.slug)) - res.get_data() - # Should return ok, and server should stop - assert res.status_code == 200 - assert web.running == False - - def test_receive_mode_allow_receiver_shutdown_off(self, common_obj): - web = web_obj(common_obj, True) - - common_obj.settings.set('receive_allow_receiver_shutdown', False) - - assert web.running == True - - with web.app.test_client() as c: - # Load close page - res = c.post('/{}/close'.format(web.slug)) - res.get_data() - # Should redirect to index, and server should still be running - assert res.status_code == 302 - assert web.running == True - def test_public_mode_on(self, common_obj): web = web_obj(common_obj, True) common_obj.settings.set('public_mode', True) -- cgit v1.2.3-54-g00ecf From 4434e4c920428f2487f9f2d4658d1ff1f8835087 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 18 Sep 2018 09:59:06 +1000 Subject: Fix test --- test/test_onionshare_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_onionshare_settings.py b/test/test_onionshare_settings.py index fb9e1f69..937288d1 100644 --- a/test/test_onionshare_settings.py +++ b/test/test_onionshare_settings.py @@ -63,7 +63,7 @@ class TestSettings: 'private_key': '', 'slug': '', 'hidservauth_string': '', - 'downloads_dir': os.path.expanduser('~/OnionShare') + 'downloads_dir': os.path.expanduser('~/OnionShare'), 'public_mode': False } -- cgit v1.2.3-54-g00ecf From 997e2f87ee003616388b96e65471500490a773ba Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Thu, 20 Sep 2018 11:33:37 +1000 Subject: Throw a 403 on the index pages if the timer has run out but an upload is in progress --- onionshare/web.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/onionshare/web.py b/onionshare/web.py index 1c285ea7..f52d9dd6 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -340,10 +340,14 @@ class Web(object): @self.app.route("/") def index(slug_candidate): self.check_slug_candidate(slug_candidate) + if not self.can_upload: + return self.error403() return index_logic() @self.app.route("/") def index_public(): + if not self.can_upload: + return self.error403() if not self.common.settings.get('public_mode'): return self.error404() return index_logic() -- cgit v1.2.3-54-g00ecf From 3f32db2ccac6007255bff5eb0afad4fe11582389 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 1 Oct 2018 18:42:53 +1000 Subject: Fix logic for handling an upload still in progress when timer runs out. Show thankyou page for last uploader post-timer expiry --- onionshare/web/receive_mode.py | 74 ++++++++++++++++++++------------- onionshare_gui/receive_mode/__init__.py | 8 +++- share/templates/closed.html | 22 ---------- share/templates/thankyou.html | 22 ++++++++++ 4 files changed, 75 insertions(+), 51 deletions(-) delete mode 100644 share/templates/closed.html create mode 100644 share/templates/thankyou.html diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 73762573..5035f68a 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -19,6 +19,7 @@ class ReceiveModeWeb(object): self.web = web self.can_upload = True + self.can_stop_share_now = False self.upload_count = 0 self.uploads_in_progress = [] @@ -39,6 +40,7 @@ class ReceiveModeWeb(object): r = make_response(render_template( 'receive.html', upload_action=upload_action)) + return self.web.add_security_headers(r) @self.web.app.route("/") @@ -138,10 +140,24 @@ class ReceiveModeWeb(object): for filename in filenames: flash('Sent {}'.format(filename), 'info') - if self.common.settings.get('public_mode'): - return redirect('/') + if self.can_upload: + if self.common.settings.get('public_mode'): + path = '/' + else: + path = '/{}'.format(slug_candidate) + + return redirect('{}'.format(path)) else: - return redirect('/{}'.format(slug_candidate)) + # It was the last upload and the timer ran out + if self.common.settings.get('public_mode'): + return thankyou_logic(slug_candidate) + else: + return thankyou_logic() + + def thankyou_logic(slug_candidate=''): + r = make_response(render_template( + 'thankyou.html')) + return self.web.add_security_headers(r) @self.web.app.route("//upload", methods=['POST']) def upload(slug_candidate): @@ -231,39 +247,36 @@ class ReceiveModeRequest(Request): if self.path == '/upload': self.upload_request = True - if self.upload_request: + if self.upload_request and self.web.receive_mode.can_upload: # A dictionary that maps filenames to the bytes uploaded so far self.progress = {} # Create an upload_id, attach it to the request self.upload_id = self.web.receive_mode.upload_count - if self.web.receive_mode.can_upload: - self.web.receive_mode.upload_count += 1 + self.web.receive_mode.upload_count += 1 - # Figure out the content length - try: - self.content_length = int(self.headers['Content-Length']) - except: - self.content_length = 0 + # Figure out the content length + try: + self.content_length = int(self.headers['Content-Length']) + except: + self.content_length = 0 - print("{}: {}".format( - datetime.now().strftime("%b %d, %I:%M%p"), - strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) - )) + print("{}: {}".format( + datetime.now().strftime("%b %d, %I:%M%p"), + strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) + )) - # append to self.uploads_in_progress - self.web.receive_mode.uploads_in_progress.append(self.upload_id) + # append to self.uploads_in_progress + self.web.receive_mode.uploads_in_progress.append(self.upload_id) - # Tell the GUI - self.web.add_request(self.web.REQUEST_STARTED, self.path, { - 'id': self.upload_id, - 'content_length': self.content_length - }) + # Tell the GUI + self.web.add_request(self.web.REQUEST_STARTED, self.path, { + 'id': self.upload_id, + 'content_length': self.content_length + }) - self.previous_file = None - else: - self.upload_rejected = True + self.previous_file = None def _get_file_stream(self, total_content_length, content_type, filename=None, content_length=None): """ @@ -284,14 +297,19 @@ class ReceiveModeRequest(Request): """ super(ReceiveModeRequest, self).close() if self.upload_request: - if not self.upload_rejected: + try: + upload_id = self.upload_id # Inform the GUI that the upload has finished self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { - 'id': self.upload_id + 'id': upload_id }) # remove from self.uploads_in_progress - self.web.receive_mode.uploads_in_progress.remove(self.upload_id) + self.web.receive_mode.uploads_in_progress.remove(upload_id) + + except AttributeError: + # We may not have got an upload_id (e.g uploads were rejected) + pass def file_write_func(self, filename, length): """ diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index faa65ffe..c10622e4 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -51,6 +51,7 @@ class ReceiveMode(Mode): self.uploads_in_progress = 0 self.uploads_completed = 0 self.new_upload = False # For scrolling to the bottom of the uploads list + self.can_stop_server = False # for communicating to the auto-stop timer # Information about share, and show uploads button self.info_in_progress_uploads_count = QtWidgets.QLabel() @@ -93,7 +94,7 @@ class ReceiveMode(Mode): The shutdown timer expired, should we stop the server? Returns a bool """ # If there were no attempts to upload files, or all uploads are done, we can stop - if self.web.receive_mode.upload_count == 0 or not self.web.receive_mode.uploads_in_progress: + if self.web.receive_mode.upload_count == 0 or self.can_stop_server: self.server_status.stop_server() self.server_status_label.setText(strings._('close_on_timeout', True)) return True @@ -110,7 +111,9 @@ class ReceiveMode(Mode): Starting the server. """ # Reset web counters + self.can_stop_server = False self.web.receive_mode.upload_count = 0 + self.web.receive_mode.can_upload = True self.web.error404_count = 0 # Hide and reset the uploads if we have previously shared @@ -144,6 +147,7 @@ class ReceiveMode(Mode): self.uploads.add(event["data"]["id"], event["data"]["content_length"]) self.uploads_in_progress += 1 self.update_uploads_in_progress() + self.can_stop_server = False self.system_tray.showMessage(strings._('systray_upload_started_title', True), strings._('systray_upload_started_message', True)) @@ -177,6 +181,8 @@ class ReceiveMode(Mode): # Update the 'in progress uploads' info self.uploads_in_progress -= 1 self.update_uploads_in_progress() + if self.uploads_in_progress == 0: + self.can_stop_server = True def on_reload_settings(self): """ diff --git a/share/templates/closed.html b/share/templates/closed.html deleted file mode 100644 index 64c8b369..00000000 --- a/share/templates/closed.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - OnionShare is closed - - - - -
- -

OnionShare

-
- -
-
-

-

Thank you for using OnionShare

-

You may now close this window.

-
-
- - diff --git a/share/templates/thankyou.html b/share/templates/thankyou.html new file mode 100644 index 00000000..64c8b369 --- /dev/null +++ b/share/templates/thankyou.html @@ -0,0 +1,22 @@ + + + + OnionShare is closed + + + + +
+ +

OnionShare

+
+ +
+
+

+

Thank you for using OnionShare

+

You may now close this window.

+
+
+ + -- cgit v1.2.3-54-g00ecf From d104af11dce68d85c8c4cc2b5796af24040b99ba Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 1 Oct 2018 19:15:58 +1000 Subject: remove unused variable, whitespace --- onionshare/web/receive_mode.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 5035f68a..7fa274d5 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -19,7 +19,6 @@ class ReceiveModeWeb(object): self.web = web self.can_upload = True - self.can_stop_share_now = False self.upload_count = 0 self.uploads_in_progress = [] @@ -40,7 +39,6 @@ class ReceiveModeWeb(object): r = make_response(render_template( 'receive.html', upload_action=upload_action)) - return self.web.add_security_headers(r) @self.web.app.route("/") -- cgit v1.2.3-54-g00ecf From 9e14514d25a864c154cbf17e70b64cffbd8631a7 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 1 Oct 2018 19:17:50 +1000 Subject: Another unused variable --- onionshare/web/receive_mode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 7fa274d5..8602e98a 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -236,7 +236,6 @@ class ReceiveModeRequest(Request): # Is this a valid upload request? self.upload_request = False - self.upload_rejected = False if self.method == 'POST': if self.path == '/{}/upload'.format(self.web.slug): self.upload_request = True -- cgit v1.2.3-54-g00ecf From 7d140f384ff64952f1c656cb8c349a284fa312a0 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 1 Oct 2018 19:18:50 +1000 Subject: remove uploads_in_progress list from web side --- onionshare/web/receive_mode.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 8602e98a..bc5e1734 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -20,7 +20,6 @@ class ReceiveModeWeb(object): self.can_upload = True self.upload_count = 0 - self.uploads_in_progress = [] self.define_routes() @@ -264,9 +263,6 @@ class ReceiveModeRequest(Request): strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) )) - # append to self.uploads_in_progress - self.web.receive_mode.uploads_in_progress.append(self.upload_id) - # Tell the GUI self.web.add_request(self.web.REQUEST_STARTED, self.path, { 'id': self.upload_id, @@ -301,9 +297,6 @@ class ReceiveModeRequest(Request): 'id': upload_id }) - # remove from self.uploads_in_progress - self.web.receive_mode.uploads_in_progress.remove(upload_id) - except AttributeError: # We may not have got an upload_id (e.g uploads were rejected) pass -- cgit v1.2.3-54-g00ecf From e9148ddb49a982033eee575d19bbc741e0616b48 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 2 Oct 2018 07:33:13 +1000 Subject: remove unused variable --- onionshare/web/web.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/onionshare/web/web.py b/onionshare/web/web.py index 2885e87f..45d021c0 100644 --- a/onionshare/web/web.py +++ b/onionshare/web/web.py @@ -66,8 +66,6 @@ class Web(object): # Use a custom Request class to track upload progess self.app.request_class = ReceiveModeRequest - self.can_upload = True - # Starting in Flask 0.11, render_template_string autoescapes template variables # by default. To prevent content injection through template variables in # earlier versions of Flask, we force autoescaping in the Jinja2 template -- cgit v1.2.3-54-g00ecf From 61d2e6cc5f70f9761b2988d9bb5c1a4e52593a86 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 2 Oct 2018 08:22:08 +1000 Subject: Try to fix logic handling last upload after timer expiry --- onionshare/web/receive_mode.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index bc5e1734..60909a23 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -243,7 +243,11 @@ class ReceiveModeRequest(Request): if self.path == '/upload': self.upload_request = True - if self.upload_request and self.web.receive_mode.can_upload: + # Prevent new uploads if we've said so (timer expired) + if not self.web.receive_mode.can_upload: + self.upload_request = False + + if self.upload_request: # A dictionary that maps filenames to the bytes uploaded so far self.progress = {} @@ -290,16 +294,11 @@ class ReceiveModeRequest(Request): """ super(ReceiveModeRequest, self).close() if self.upload_request: - try: - upload_id = self.upload_id - # Inform the GUI that the upload has finished - self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { - 'id': upload_id - }) - - except AttributeError: - # We may not have got an upload_id (e.g uploads were rejected) - pass + # Inform the GUI that the upload has finished + self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { + 'id': self.upload_id + }) + def file_write_func(self, filename, length): """ -- cgit v1.2.3-54-g00ecf From 875b538347a421f23b6ef5f667f68b74d31984ed Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 2 Oct 2018 15:41:29 +1000 Subject: Make auto-stop timer work on CLI when an upload is still in progress on expiry --- onionshare/__init__.py | 7 +++++++ onionshare/web/receive_mode.py | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/onionshare/__init__.py b/onionshare/__init__.py index 715c5571..42294ec1 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -198,6 +198,13 @@ def main(cwd=None): print(strings._("close_on_timeout")) web.stop(app.port) break + if mode == 'receive': + if web.receive_mode.upload_count == 0 or not web.receive_mode.uploads_in_progress: + print(strings._("close_on_timeout")) + web.stop(app.port) + break + else: + web.receive_mode.can_upload = False # Allow KeyboardInterrupt exception to be handled with threads # https://stackoverflow.com/questions/3788208/python-threading-ignores-keyboardinterrupt-exception time.sleep(0.2) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 60909a23..4ea95201 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -20,6 +20,7 @@ class ReceiveModeWeb(object): self.can_upload = True self.upload_count = 0 + self.uploads_in_progress = [] self.define_routes() @@ -273,6 +274,8 @@ class ReceiveModeRequest(Request): 'content_length': self.content_length }) + self.web.receive_mode.uploads_in_progress.append(self.upload_id) + self.previous_file = None def _get_file_stream(self, total_content_length, content_type, filename=None, content_length=None): @@ -298,6 +301,7 @@ class ReceiveModeRequest(Request): self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { 'id': self.upload_id }) + self.web.receive_mode.uploads_in_progress.remove(self.upload_id) def file_write_func(self, filename, length): -- cgit v1.2.3-54-g00ecf From db8548c35bd5d0236c3083e9e860b82a1dbca808 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 13 Nov 2018 14:42:26 +1100 Subject: Try and fix closing the request for a valid upload post-timer expiry, whilst still rejecting subsequent uploads --- onionshare/web/receive_mode.py | 56 ++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 4ea95201..6ac96f8e 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -244,39 +244,38 @@ class ReceiveModeRequest(Request): if self.path == '/upload': self.upload_request = True - # Prevent new uploads if we've said so (timer expired) - if not self.web.receive_mode.can_upload: - self.upload_request = False - if self.upload_request: # A dictionary that maps filenames to the bytes uploaded so far self.progress = {} - # Create an upload_id, attach it to the request - self.upload_id = self.web.receive_mode.upload_count + # Prevent new uploads if we've said so (timer expired) + if self.web.receive_mode.can_upload: - self.web.receive_mode.upload_count += 1 + # Create an upload_id, attach it to the request + self.upload_id = self.web.receive_mode.upload_count - # Figure out the content length - try: - self.content_length = int(self.headers['Content-Length']) - except: - self.content_length = 0 + self.web.receive_mode.upload_count += 1 - print("{}: {}".format( - datetime.now().strftime("%b %d, %I:%M%p"), - strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) - )) + # Figure out the content length + try: + self.content_length = int(self.headers['Content-Length']) + except: + self.content_length = 0 - # Tell the GUI - self.web.add_request(self.web.REQUEST_STARTED, self.path, { - 'id': self.upload_id, - 'content_length': self.content_length - }) + print("{}: {}".format( + datetime.now().strftime("%b %d, %I:%M%p"), + strings._("receive_mode_upload_starting").format(self.web.common.human_readable_filesize(self.content_length)) + )) - self.web.receive_mode.uploads_in_progress.append(self.upload_id) + # Tell the GUI + self.web.add_request(self.web.REQUEST_STARTED, self.path, { + 'id': self.upload_id, + 'content_length': self.content_length + }) - self.previous_file = None + self.web.receive_mode.uploads_in_progress.append(self.upload_id) + + self.previous_file = None def _get_file_stream(self, total_content_length, content_type, filename=None, content_length=None): """ @@ -296,13 +295,16 @@ class ReceiveModeRequest(Request): Closing the request. """ super(ReceiveModeRequest, self).close() - if self.upload_request: + try: + upload_id = self.upload_id + self.web.common.log('ReceiveModeWeb', 'We finished our upload') # Inform the GUI that the upload has finished self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { - 'id': self.upload_id + 'id': upload_id }) - self.web.receive_mode.uploads_in_progress.remove(self.upload_id) - + self.web.receive_mode.uploads_in_progress.remove(upload_id) + except AttributeError: + pass def file_write_func(self, filename, length): """ -- cgit v1.2.3-54-g00ecf From 09976353931eff4992428d84d27e68ba0bf27352 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 13 Nov 2018 14:59:29 +1100 Subject: remove obsolete settings in test that related to allowing receiver to shutdown service --- tests/local_onionshare_settings_dialog_test.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/local_onionshare_settings_dialog_test.py b/tests/local_onionshare_settings_dialog_test.py index 6d8923b6..c1e48122 100644 --- a/tests/local_onionshare_settings_dialog_test.py +++ b/tests/local_onionshare_settings_dialog_test.py @@ -85,11 +85,6 @@ class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): # receive mode self.gui.downloads_dir_lineedit.setText('/tmp/OnionShareSettingsTest') - # allow receiver shutdown is on - self.assertTrue(self.gui.receive_allow_receiver_shutdown_checkbox.isChecked()) - # disable receiver shutdown - QtTest.QTest.mouseClick(self.gui.receive_allow_receiver_shutdown_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.receive_allow_receiver_shutdown_checkbox.height()/2)) - self.assertFalse(self.gui.receive_allow_receiver_shutdown_checkbox.isChecked()) # bundled mode is enabled @@ -168,7 +163,6 @@ class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): self.assertTrue(data["save_private_key"]) self.assertTrue(data["use_stealth"]) self.assertEqual(data["downloads_dir"], "/tmp/OnionShareSettingsTest") - self.assertFalse(data["receive_allow_receiver_shutdown"]) self.assertFalse(data["close_after_first_download"]) self.assertEqual(data["connection_type"], "bundled") self.assertFalse(data["tor_bridges_use_obfs4"]) -- cgit v1.2.3-54-g00ecf From 17aa34edd912dd7dae95fc3d65d86c6cfb54fa83 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 13 Nov 2018 15:06:28 +1100 Subject: remove debug log --- onionshare/web/receive_mode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py index 274ee138..6985f38a 100644 --- a/onionshare/web/receive_mode.py +++ b/onionshare/web/receive_mode.py @@ -305,7 +305,6 @@ class ReceiveModeRequest(Request): super(ReceiveModeRequest, self).close() try: upload_id = self.upload_id - self.web.common.log('ReceiveModeWeb', 'We finished our upload') # Inform the GUI that the upload has finished self.web.add_request(self.web.REQUEST_UPLOAD_FINISHED, self.path, { 'id': upload_id -- cgit v1.2.3-54-g00ecf From f32af3ca7e60378b7a741fbfd0c084a9f206b729 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Mon, 26 Nov 2018 17:14:44 -0800 Subject: Update pip dependencies --- install/requirements-tests.txt | 6 +++--- install/requirements.txt | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/install/requirements-tests.txt b/install/requirements-tests.txt index 57e98ce1..89f37572 100644 --- a/install/requirements-tests.txt +++ b/install/requirements-tests.txt @@ -1,10 +1,10 @@ atomicwrites==1.2.1 attrs==18.2.0 more-itertools==4.3.0 -pluggy==0.7.1 +pluggy==0.8.0 py==1.7.0 -pytest==3.8.2 +pytest==4.0.1 pytest-faulthandler==1.5.0 pytest-qt==3.2.1 six==1.11.0 -urllib3==1.23 +urllib3==1.24.1 diff --git a/install/requirements.txt b/install/requirements.txt index 20811f7b..81430398 100644 --- a/install/requirements.txt +++ b/install/requirements.txt @@ -1,26 +1,26 @@ altgraph==0.16.1 asn1crypto==0.24.0 -certifi==2018.8.24 +certifi==2018.10.15 cffi==1.11.5 chardet==3.0.4 -click==6.7 -cryptography==2.3.1 +Click==7.0 +cryptography==2.4.2 Flask==1.0.2 -future==0.16.0 +future==0.17.1 idna==2.7 -itsdangerous==0.24 +itsdangerous==1.1.0 Jinja2==2.10 macholib==1.11 -MarkupSafe==1.0 +MarkupSafe==1.1.0 pefile==2018.8.8 -pycparser==2.18 -pycryptodome==3.6.6 +pycparser==2.19 +pycryptodome==3.7.2 PyInstaller==3.4 -PyQt5==5.11.2 -PyQt5-sip==4.19.12 +PyQt5==5.11.3 +PyQt5-sip==4.19.13 PySocks==1.6.8 -requests==2.19.1 +requests==2.20.1 six==1.11.0 stem==1.7.0 -urllib3==1.23 +urllib3==1.24.1 Werkzeug==0.14.1 -- cgit v1.2.3-54-g00ecf From d15e00061a4488aa3ac513671a99ce1213f90a51 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Wed, 5 Dec 2018 18:19:35 +1100 Subject: Keep the upload running in the GUI if the timer has run out --- onionshare_gui/mode/receive_mode/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/onionshare_gui/mode/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py index d6c0c351..c53f1ea1 100644 --- a/onionshare_gui/mode/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -96,8 +96,16 @@ class ReceiveMode(Mode): """ The shutdown timer expired, should we stop the server? Returns a bool """ - # TODO: wait until the final upload is done before stoppign the server? - return True + # If there were no attempts to upload files, or all uploads are done, we can stop + if self.web.receive_mode.upload_count == 0 or not self.web.receive_mode.uploads_in_progress: + self.server_status.stop_server() + self.server_status_label.setText(strings._('close_on_timeout')) + return True + # An upload is probably still running - hold off on stopping the share, but block new shares. + else: + self.server_status_label.setText(strings._('timeout_upload_still_running')) + self.web.receive_mode.can_upload = False + return False def start_server_custom(self): """ -- cgit v1.2.3-54-g00ecf From aadb2a01f0ced1f31268adb6237f9ddd0bbc849a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 5 Dec 2018 20:14:52 -0800 Subject: Only show onion settings if there is a Tor connection --- onionshare/common.py | 5 +++++ onionshare_gui/settings_dialog.py | 32 ++++++++++++++++++++++++++------ share/locale/en.json | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/onionshare/common.py b/onionshare/common.py index ffa6529f..250972f9 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -373,6 +373,11 @@ class Common(object): 'settings_whats_this': """ QLabel { font-size: 12px; + }""", + + 'settings_connect_to_tor': """ + QLabel { + font-style: italic; }""" } diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 958d49fd..37cc9105 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -88,6 +88,10 @@ class SettingsDialog(QtWidgets.QDialog): self.shutdown_timeout_widget = QtWidgets.QWidget() self.shutdown_timeout_widget.setLayout(shutdown_timeout_layout) + # Label telling user to connect to Tor for onion service settings + connect_to_tor_label = QtWidgets.QLabel(strings._("gui_connect_to_tor_for_onion_settings")) + connect_to_tor_label.setStyleSheet(self.common.css['settings_connect_to_tor']) + # Whether or not to use legacy v2 onions self.use_legacy_v2_onions_checkbox = QtWidgets.QCheckBox() self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Unchecked) @@ -149,16 +153,32 @@ class SettingsDialog(QtWidgets.QDialog): self.hidservauth_copy_button.clicked.connect(self.hidservauth_copy_button_clicked) self.hidservauth_copy_button.hide() + # Onion settings widget + onion_settings_layout = QtWidgets.QVBoxLayout() + onion_settings_layout.setContentsMargins(0, 0, 0, 0) + onion_settings_layout.addWidget(self.use_legacy_v2_onions_widget) + onion_settings_layout.addWidget(self.save_private_key_widget) + onion_settings_layout.addWidget(self.use_stealth_widget) + onion_settings_layout.addWidget(hidservauth_details) + onion_settings_layout.addWidget(self.hidservauth_copy_button) + onion_settings_widget = QtWidgets.QWidget() + onion_settings_widget.setLayout(onion_settings_layout) + + # If we're connected to Tor, show onion service settings, show label if not + if self.onion.is_authenticated(): + connect_to_tor_label.hide() + onion_settings_widget.show() + else: + connect_to_tor_label.show() + onion_settings_widget.hide() + + # General options layout general_group_layout = QtWidgets.QVBoxLayout() general_group_layout.addWidget(self.public_mode_widget) general_group_layout.addWidget(self.shutdown_timeout_widget) - general_group_layout.addWidget(self.use_legacy_v2_onions_widget) - general_group_layout.addWidget(self.save_private_key_widget) - general_group_layout.addWidget(self.use_stealth_widget) - general_group_layout.addWidget(hidservauth_details) - general_group_layout.addWidget(self.hidservauth_copy_button) - + general_group_layout.addWidget(connect_to_tor_label) + general_group_layout.addWidget(onion_settings_widget) general_group = QtWidgets.QGroupBox(strings._("gui_settings_general_label")) general_group.setLayout(general_group_layout) diff --git a/share/locale/en.json b/share/locale/en.json index 7fb30df8..c38bfdff 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -135,6 +135,7 @@ "gui_server_started_after_timeout": "The auto-stop timer ran out before the server started.\nPlease make a new share.", "gui_server_timeout_expired": "The auto-stop timer already ran out.\nPlease update it to start sharing.", "share_via_onionshare": "OnionShare it", + "gui_connect_to_tor_for_onion_settings": "Connect to Tor to see onion service settings", "gui_use_legacy_v2_onions_checkbox": "Use legacy addresses", "gui_save_private_key_checkbox": "Use a persistent address (legacy)", "gui_share_url_description": "Anyone with this OnionShare address can download your files using the Tor Browser: ", -- cgit v1.2.3-54-g00ecf From 1d1efb7e54bcc6dbfc56703a257f1de9f1ca3265 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 5 Dec 2018 20:33:45 -0800 Subject: Require tor 0.4.0.0 for v3 onion services (will change in the future). And update settings dialog so if the connected version of tor doesn't support v3 onions, then always show legacy options. If it does support v3 onions, allow 'Use legacy addresses' --- onionshare/onion.py | 5 ++++- onionshare_gui/settings_dialog.py | 31 +++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/onionshare/onion.py b/onionshare/onion.py index 6066f059..6673f8ee 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -387,6 +387,7 @@ class Onion(object): # Get the tor version self.tor_version = self.c.get_version().version_str + self.common.log('Onion', 'connect', 'Connected to tor {}'.format(self.tor_version)) # Do the versions of stem and tor that I'm using support ephemeral onion services? list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None) @@ -403,7 +404,9 @@ class Onion(object): self.supports_stealth = False # Does this version of Tor support next-gen ('v3') onions? - self.supports_next_gen_onions = self.tor_version > Version('0.3.3.1') + # Note, this is the version of Tor where this bug was fixed: + # https://trac.torproject.org/projects/tor/ticket/28619 + self.supports_v3_onions = self.tor_version > Version('0.4.0.0') def is_authenticated(self): """ diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 37cc9105..53fd8351 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -164,15 +164,6 @@ class SettingsDialog(QtWidgets.QDialog): onion_settings_widget = QtWidgets.QWidget() onion_settings_widget.setLayout(onion_settings_layout) - # If we're connected to Tor, show onion service settings, show label if not - if self.onion.is_authenticated(): - connect_to_tor_label.hide() - onion_settings_widget.show() - else: - connect_to_tor_label.show() - onion_settings_widget.hide() - - # General options layout general_group_layout = QtWidgets.QVBoxLayout() general_group_layout.addWidget(self.public_mode_widget) @@ -480,6 +471,7 @@ class SettingsDialog(QtWidgets.QDialog): self.setLayout(layout) self.cancel_button.setFocus() + # Load settings, and fill them in self.old_settings = Settings(self.common, self.config) self.old_settings.load() @@ -599,6 +591,25 @@ class SettingsDialog(QtWidgets.QDialog): new_bridges = ''.join(new_bridges) self.tor_bridges_use_custom_textbox.setPlainText(new_bridges) + # If we're connected to Tor, show onion service settings, show label if not + if self.onion.is_authenticated(): + connect_to_tor_label.hide() + onion_settings_widget.show() + + # If v3 onion services are supported, allow using legacy mode + if self.onion.supports_v3_onions: + self.common.log('SettingsDialog', '__init__', 'v3 onions are supported') + self.use_legacy_v2_onions_checkbox.show() + else: + self.common.log('SettingsDialog', '__init__', 'v3 onions are not supported') + self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Checked) + self.use_legacy_v2_onions_widget.hide() + self.use_legacy_v2_onions_checkbox_clicked(True) + else: + connect_to_tor_label.show() + onion_settings_widget.hide() + + def connection_type_bundled_toggled(self, checked): """ Connection type bundled was toggled. If checked, hide authentication fields. @@ -774,7 +785,7 @@ class SettingsDialog(QtWidgets.QDialog): onion.connect(custom_settings=settings, config=self.config, tor_status_update_func=tor_status_update_func) # If an exception hasn't been raised yet, the Tor settings work - Alert(self.common, strings._('settings_test_success').format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth, onion.supports_next_gen_onions)) + Alert(self.common, strings._('settings_test_success').format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth, onion.supports_v3_onions)) # Clean up onion.cleanup() -- cgit v1.2.3-54-g00ecf From 657806a003a2fc2fb074f149ac8802ef99ad090e Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 5 Dec 2018 20:46:01 -0800 Subject: Only allow starting v3 onion services if the tor that we're connected to supports it --- onionshare/onion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onionshare/onion.py b/onionshare/onion.py index 6673f8ee..3aeffe91 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -406,7 +406,7 @@ class Onion(object): # Does this version of Tor support next-gen ('v3') onions? # Note, this is the version of Tor where this bug was fixed: # https://trac.torproject.org/projects/tor/ticket/28619 - self.supports_v3_onions = self.tor_version > Version('0.4.0.0') + self.supports_v3_onions = self.tor_version >= Version('0.4.0.0') def is_authenticated(self): """ @@ -464,7 +464,7 @@ class Onion(object): else: key_type = "NEW" # Work out if we can support v3 onion services, which are preferred - if Version(self.tor_version) >= Version('0.3.3.1') and not self.settings.get('use_legacy_v2_onions'): + if self.supports_v3_onions and not self.settings.get('use_legacy_v2_onions'): key_content = "ED25519-V3" else: # fall back to v2 onion services -- cgit v1.2.3-54-g00ecf From 16e301af8d42c7a911539ed0945db2c6918063de Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 5 Dec 2018 20:53:03 -0800 Subject: Don't actually check the 'Use legacy addresses' checkbox when it's hidden --- onionshare_gui/settings_dialog.py | 1 - 1 file changed, 1 deletion(-) diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 53fd8351..1ff20b31 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -602,7 +602,6 @@ class SettingsDialog(QtWidgets.QDialog): self.use_legacy_v2_onions_checkbox.show() else: self.common.log('SettingsDialog', '__init__', 'v3 onions are not supported') - self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Checked) self.use_legacy_v2_onions_widget.hide() self.use_legacy_v2_onions_checkbox_clicked(True) else: -- cgit v1.2.3-54-g00ecf From 300434e5ec452a5c622419a929694f698a83414c Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 5 Dec 2018 23:05:25 -0800 Subject: Update settings dialog tests to use an OnionStub instead of an Onion, and test different states of tor (authenticate and not, supports v3 and not) --- onionshare/onion.py | 3 + onionshare_gui/settings_dialog.py | 22 ++- tests/SettingsGuiBaseTest.py | 202 ++++++++++++++++++++- ...l_onionshare_settings_dialog_legacy_tor_test.py | 27 +++ ...local_onionshare_settings_dialog_no_tor_test.py | 27 +++ tests/local_onionshare_settings_dialog_test.py | 172 ------------------ ...local_onionshare_settings_dialog_v3_tor_test.py | 26 +++ 7 files changed, 295 insertions(+), 184 deletions(-) create mode 100644 tests/local_onionshare_settings_dialog_legacy_tor_test.py create mode 100644 tests/local_onionshare_settings_dialog_no_tor_test.py delete mode 100644 tests/local_onionshare_settings_dialog_test.py create mode 100644 tests/local_onionshare_settings_dialog_v3_tor_test.py diff --git a/onionshare/onion.py b/onionshare/onion.py index 3aeffe91..3d7b4514 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -146,6 +146,9 @@ class Onion(object): # The tor process self.tor_proc = None + # The Tor controller + self.c = None + # Start out not connected to Tor self.connected_to_tor = False diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 1ff20b31..92c84262 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -89,8 +89,8 @@ class SettingsDialog(QtWidgets.QDialog): self.shutdown_timeout_widget.setLayout(shutdown_timeout_layout) # Label telling user to connect to Tor for onion service settings - connect_to_tor_label = QtWidgets.QLabel(strings._("gui_connect_to_tor_for_onion_settings")) - connect_to_tor_label.setStyleSheet(self.common.css['settings_connect_to_tor']) + self.connect_to_tor_label = QtWidgets.QLabel(strings._("gui_connect_to_tor_for_onion_settings")) + self.connect_to_tor_label.setStyleSheet(self.common.css['settings_connect_to_tor']) # Whether or not to use legacy v2 onions self.use_legacy_v2_onions_checkbox = QtWidgets.QCheckBox() @@ -161,15 +161,15 @@ class SettingsDialog(QtWidgets.QDialog): onion_settings_layout.addWidget(self.use_stealth_widget) onion_settings_layout.addWidget(hidservauth_details) onion_settings_layout.addWidget(self.hidservauth_copy_button) - onion_settings_widget = QtWidgets.QWidget() - onion_settings_widget.setLayout(onion_settings_layout) + self.onion_settings_widget = QtWidgets.QWidget() + self.onion_settings_widget.setLayout(onion_settings_layout) # General options layout general_group_layout = QtWidgets.QVBoxLayout() general_group_layout.addWidget(self.public_mode_widget) general_group_layout.addWidget(self.shutdown_timeout_widget) - general_group_layout.addWidget(connect_to_tor_label) - general_group_layout.addWidget(onion_settings_widget) + general_group_layout.addWidget(self.connect_to_tor_label) + general_group_layout.addWidget(self.onion_settings_widget) general_group = QtWidgets.QGroupBox(strings._("gui_settings_general_label")) general_group.setLayout(general_group_layout) @@ -471,7 +471,9 @@ class SettingsDialog(QtWidgets.QDialog): self.setLayout(layout) self.cancel_button.setFocus() + self.reload_settings() + def reload_settings(self): # Load settings, and fill them in self.old_settings = Settings(self.common, self.config) self.old_settings.load() @@ -593,8 +595,8 @@ class SettingsDialog(QtWidgets.QDialog): # If we're connected to Tor, show onion service settings, show label if not if self.onion.is_authenticated(): - connect_to_tor_label.hide() - onion_settings_widget.show() + self.connect_to_tor_label.hide() + self.onion_settings_widget.show() # If v3 onion services are supported, allow using legacy mode if self.onion.supports_v3_onions: @@ -605,8 +607,8 @@ class SettingsDialog(QtWidgets.QDialog): self.use_legacy_v2_onions_widget.hide() self.use_legacy_v2_onions_checkbox_clicked(True) else: - connect_to_tor_label.show() - onion_settings_widget.hide() + self.connect_to_tor_label.show() + self.onion_settings_widget.hide() def connection_type_bundled_toggled(self, checked): diff --git a/tests/SettingsGuiBaseTest.py b/tests/SettingsGuiBaseTest.py index e59a58a8..57626d1d 100644 --- a/tests/SettingsGuiBaseTest.py +++ b/tests/SettingsGuiBaseTest.py @@ -1,5 +1,7 @@ import json import os +import unittest +from PyQt5 import QtCore, QtTest from onionshare import strings from onionshare.common import Common @@ -8,10 +10,27 @@ from onionshare.onion import Onion from onionshare_gui import Application, OnionShare from onionshare_gui.settings_dialog import SettingsDialog + +class OnionStub(object): + def __init__(self, is_authenticated, supports_v3_onions=False): + self._is_authenticated = is_authenticated + self.supports_v3_onions = True + + def is_authenticated(self): + return self._is_authenticated + + class SettingsGuiBaseTest(object): @staticmethod - def set_up(test_settings): + def set_up(): '''Create the GUI''' + + # Default settings for the settings GUI tests + test_settings = { + "no_bridges": False, + "tor_bridges_use_custom_bridges": "Bridge 1.2.3.4:56 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 5.6.7.8:910 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 11.12.13.14:1516 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n", + } + # Create our test file testfile = open('/tmp/test.txt', 'w') testfile.write('onionshare') @@ -37,8 +56,187 @@ class SettingsGuiBaseTest(object): gui = SettingsDialog(common, testonion, qtapp, '/tmp/settings.json', True) return gui - @staticmethod def tear_down(): '''Clean up after tests''' os.remove('/tmp/settings.json') + + def run_settings_gui_tests(self): + self.gui.show() + self.gui.qtapp.processEvents() + + # Window is shown + self.assertTrue(self.gui.isVisible()) + self.assertEqual(self.gui.windowTitle(), strings._('gui_settings_window_title')) + + # Check for updates button is hidden + self.assertFalse(self.gui.check_for_updates_button.isVisible()) + + # public mode is off + self.assertFalse(self.gui.public_mode_checkbox.isChecked()) + # enable public mode + QtTest.QTest.mouseClick(self.gui.public_mode_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.public_mode_checkbox.height()/2)) + self.assertTrue(self.gui.public_mode_checkbox.isChecked()) + + # shutdown timer is off + self.assertFalse(self.gui.shutdown_timeout_checkbox.isChecked()) + # enable shutdown timer + QtTest.QTest.mouseClick(self.gui.shutdown_timeout_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.shutdown_timeout_checkbox.height()/2)) + self.assertTrue(self.gui.shutdown_timeout_checkbox.isChecked()) + + # legacy mode checkbox and related widgets + if self.gui.onion.is_authenticated(): + if self.gui.onion.supports_v3_onions: + # legacy mode is off + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isChecked()) + # persistence, stealth is hidden and disabled + self.assertFalse(self.gui.save_private_key_widget.isVisible()) + self.assertFalse(self.gui.save_private_key_checkbox.isChecked()) + self.assertFalse(self.gui.use_stealth_widget.isVisible()) + self.assertFalse(self.gui.stealth_checkbox.isChecked()) + self.assertFalse(self.gui.hidservauth_copy_button.isVisible()) + + # enable legacy mode + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isChecked()) + self.assertTrue(self.gui.save_private_key_checkbox.isVisible()) + self.assertTrue(self.gui.use_stealth_widget.isVisible()) + + # enable persistent mode + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + self.assertTrue(self.gui.save_private_key_checkbox.isChecked()) + # enable stealth mode + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + self.assertTrue(self.gui.stealth_checkbox.isChecked()) + # now that stealth, persistence are enabled, we can't turn off legacy mode + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) + # disable stealth, persistence + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + # legacy mode checkbox is enabled again + self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) + # uncheck legacy mode + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + # legacy options hidden again + self.assertFalse(self.gui.save_private_key_widget.isVisible()) + self.assertFalse(self.gui.use_stealth_widget.isVisible()) + + # re-enable legacy mode + QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) + + else: + # legacy mode setting is hidden + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isVisible()) + # legacy options are showing + self.assertTrue(self.gui.save_private_key_widget.isVisible()) + self.assertTrue(self.gui.use_stealth_widget.isVisible()) + + # enable them all again so that we can see the setting stick in settings.json + QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) + QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) + else: + # None of the onion settings should appear + self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isVisible()) + self.assertFalse(self.gui.save_private_key_widget.isVisible()) + self.assertFalse(self.gui.save_private_key_checkbox.isChecked()) + self.assertFalse(self.gui.use_stealth_widget.isVisible()) + self.assertFalse(self.gui.stealth_checkbox.isChecked()) + self.assertFalse(self.gui.hidservauth_copy_button.isVisible()) + + # stay open toggled off, on + self.assertTrue(self.gui.close_after_first_download_checkbox.isChecked()) + QtTest.QTest.mouseClick(self.gui.close_after_first_download_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.close_after_first_download_checkbox.height()/2)) + self.assertFalse(self.gui.close_after_first_download_checkbox.isChecked()) + + # receive mode + self.gui.downloads_dir_lineedit.setText('/tmp/OnionShareSettingsTest') + + + # bundled mode is enabled + self.assertTrue(self.gui.connection_type_bundled_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_bundled_radio.isChecked()) + # bridge options are shown + self.assertTrue(self.gui.connection_type_bridges_radio_group.isVisible()) + # bridges are set to custom + self.assertFalse(self.gui.tor_bridges_no_bridges_radio.isChecked()) + self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) + + # switch to obfs4 + QtTest.QTest.mouseClick(self.gui.tor_bridges_use_obfs4_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_obfs4_radio.height()/2)) + self.assertTrue(self.gui.tor_bridges_use_obfs4_radio.isChecked()) + + # custom bridges are hidden + self.assertFalse(self.gui.tor_bridges_use_custom_textbox_options.isVisible()) + # other modes are unchecked but enabled + self.assertTrue(self.gui.connection_type_automatic_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_control_port_radio.isEnabled()) + self.assertTrue(self.gui.connection_type_socket_file_radio.isEnabled()) + self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) + self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) + self.assertFalse(self.gui.connection_type_socket_file_radio.isChecked()) + + # enable automatic mode + QtTest.QTest.mouseClick(self.gui.connection_type_automatic_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_automatic_radio.height()/2)) + self.assertTrue(self.gui.connection_type_automatic_radio.isChecked()) + # bundled is off + self.assertFalse(self.gui.connection_type_bundled_radio.isChecked()) + # bridges are hidden + self.assertFalse(self.gui.connection_type_bridges_radio_group.isVisible()) + + # auth type is hidden in bundled or automatic mode + self.assertFalse(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertFalse(self.gui.authenticate_password_radio.isVisible()) + + # enable control port mode + QtTest.QTest.mouseClick(self.gui.connection_type_control_port_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_control_port_radio.height()/2)) + self.assertTrue(self.gui.connection_type_control_port_radio.isChecked()) + # automatic is off + self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) + # auth options appear + self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertTrue(self.gui.authenticate_password_radio.isVisible()) + + # enable socket mode + QtTest.QTest.mouseClick(self.gui.connection_type_socket_file_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_socket_file_radio.height()/2)) + self.assertTrue(self.gui.connection_type_socket_file_radio.isChecked()) + # control port is off + self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) + # auth options are still present + self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) + self.assertTrue(self.gui.authenticate_password_radio.isVisible()) + + # re-enable bundled mode + QtTest.QTest.mouseClick(self.gui.connection_type_bundled_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_bundled_radio.height()/2)) + # go back to custom bridges + QtTest.QTest.mouseClick(self.gui.tor_bridges_use_custom_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_custom_radio.height()/2)) + self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) + self.assertTrue(self.gui.tor_bridges_use_custom_textbox.isVisible()) + self.assertFalse(self.gui.tor_bridges_use_obfs4_radio.isChecked()) + self.gui.tor_bridges_use_custom_textbox.setPlainText('94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\n148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\n93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3') + + # Test that the Settings Dialog can save the settings and close itself + QtTest.QTest.mouseClick(self.gui.save_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.isVisible()) + + # Test our settings are reflected in the settings json + with open('/tmp/settings.json') as f: + data = json.load(f) + + self.assertTrue(data["public_mode"]) + self.assertTrue(data["shutdown_timeout"]) + + if self.gui.onion.is_authenticated(): + if self.gui.onion.supports_v3_onions: + self.assertTrue(data["use_legacy_v2_onions"]) + self.assertTrue(data["save_private_key"]) + self.assertTrue(data["use_stealth"]) + else: + self.assertFalse(data["use_legacy_v2_onions"]) + self.assertFalse(data["save_private_key"]) + self.assertFalse(data["use_stealth"]) + + self.assertEqual(data["downloads_dir"], "/tmp/OnionShareSettingsTest") + self.assertFalse(data["close_after_first_download"]) + self.assertEqual(data["connection_type"], "bundled") + self.assertFalse(data["tor_bridges_use_obfs4"]) + self.assertEqual(data["tor_bridges_use_custom_bridges"], "Bridge 94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\nBridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\nBridge 93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3\n") diff --git a/tests/local_onionshare_settings_dialog_legacy_tor_test.py b/tests/local_onionshare_settings_dialog_legacy_tor_test.py new file mode 100644 index 00000000..d08362f1 --- /dev/null +++ b/tests/local_onionshare_settings_dialog_legacy_tor_test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import json +import unittest +import time +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub + + +class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): + @classmethod + def setUpClass(cls): + cls.gui = SettingsGuiBaseTest.set_up() + + @classmethod + def tearDownClass(cls): + SettingsGuiBaseTest.tear_down() + + def test_gui_legacy_tor(self): + self.gui.onion = OnionStub(True, False) + self.gui.reload_settings() + self.run_settings_gui_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_settings_dialog_no_tor_test.py b/tests/local_onionshare_settings_dialog_no_tor_test.py new file mode 100644 index 00000000..a10c2f2e --- /dev/null +++ b/tests/local_onionshare_settings_dialog_no_tor_test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import json +import unittest +import time +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub + + +class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): + @classmethod + def setUpClass(cls): + cls.gui = SettingsGuiBaseTest.set_up() + + @classmethod + def tearDownClass(cls): + SettingsGuiBaseTest.tear_down() + + def test_gui_no_tor(self): + self.gui.onion = OnionStub(False) + self.gui.reload_settings() + self.run_settings_gui_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/local_onionshare_settings_dialog_test.py b/tests/local_onionshare_settings_dialog_test.py deleted file mode 100644 index c1e48122..00000000 --- a/tests/local_onionshare_settings_dialog_test.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python3 -import json -import unittest -from PyQt5 import QtCore, QtTest - -from onionshare import strings -from .SettingsGuiBaseTest import SettingsGuiBaseTest - -class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): - @classmethod - def setUpClass(cls): - test_settings = { - "no_bridges": False, - "tor_bridges_use_custom_bridges": "Bridge 1.2.3.4:56 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 5.6.7.8:910 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\nBridge 11.12.13.14:1516 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n", - } - cls.gui = SettingsGuiBaseTest.set_up(test_settings) - - @classmethod - def tearDownClass(cls): - SettingsGuiBaseTest.tear_down() - - def test_gui(self): - self.gui.show() - # Window is shown - self.assertTrue(self.gui.isVisible()) - self.assertEqual(self.gui.windowTitle(), strings._('gui_settings_window_title')) - # Check for updates button is hidden - self.assertFalse(self.gui.check_for_updates_button.isVisible()) - - # public mode is off - self.assertFalse(self.gui.public_mode_checkbox.isChecked()) - # enable public mode - QtTest.QTest.mouseClick(self.gui.public_mode_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.public_mode_checkbox.height()/2)) - self.assertTrue(self.gui.public_mode_checkbox.isChecked()) - - # shutdown timer is off - self.assertFalse(self.gui.shutdown_timeout_checkbox.isChecked()) - # enable shutdown timer - QtTest.QTest.mouseClick(self.gui.shutdown_timeout_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.shutdown_timeout_checkbox.height()/2)) - self.assertTrue(self.gui.shutdown_timeout_checkbox.isChecked()) - - # legacy mode checkbox and related widgets - # legacy mode is off - self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isChecked()) - # persistence, stealth is hidden and disabled - self.assertFalse(self.gui.save_private_key_widget.isVisible()) - self.assertFalse(self.gui.save_private_key_checkbox.isChecked()) - self.assertFalse(self.gui.use_stealth_widget.isVisible()) - self.assertFalse(self.gui.stealth_checkbox.isChecked()) - self.assertFalse(self.gui.hidservauth_copy_button.isVisible()) - - # enable legacy mode - QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) - self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isChecked()) - self.assertTrue(self.gui.save_private_key_checkbox.isVisible()) - self.assertTrue(self.gui.use_stealth_widget.isVisible()) - # enable persistent mode - QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) - self.assertTrue(self.gui.save_private_key_checkbox.isChecked()) - # enable stealth mode - QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) - self.assertTrue(self.gui.stealth_checkbox.isChecked()) - # now that stealth, persistence are enabled, we can't turn off legacy mode - self.assertFalse(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) - # disable stealth, persistence - QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) - QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) - # legacy mode checkbox is enabled again - self.assertTrue(self.gui.use_legacy_v2_onions_checkbox.isEnabled()) - # uncheck legacy mode - QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) - # legacy options hidden again - self.assertFalse(self.gui.save_private_key_widget.isVisible()) - self.assertFalse(self.gui.use_stealth_widget.isVisible()) - # enable them all again so that we can see the setting stick in settings.json - QtTest.QTest.mouseClick(self.gui.use_legacy_v2_onions_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.use_legacy_v2_onions_checkbox.height()/2)) - QtTest.QTest.mouseClick(self.gui.save_private_key_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.save_private_key_checkbox.height()/2)) - QtTest.QTest.mouseClick(self.gui.stealth_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.stealth_checkbox.height()/2)) - - - # stay open toggled off, on - self.assertTrue(self.gui.close_after_first_download_checkbox.isChecked()) - QtTest.QTest.mouseClick(self.gui.close_after_first_download_checkbox, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.close_after_first_download_checkbox.height()/2)) - self.assertFalse(self.gui.close_after_first_download_checkbox.isChecked()) - - # receive mode - self.gui.downloads_dir_lineedit.setText('/tmp/OnionShareSettingsTest') - - - # bundled mode is enabled - self.assertTrue(self.gui.connection_type_bundled_radio.isEnabled()) - self.assertTrue(self.gui.connection_type_bundled_radio.isChecked()) - # bridge options are shown - self.assertTrue(self.gui.connection_type_bridges_radio_group.isVisible()) - # bridges are set to custom - self.assertFalse(self.gui.tor_bridges_no_bridges_radio.isChecked()) - self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) - - # switch to obfs4 - QtTest.QTest.mouseClick(self.gui.tor_bridges_use_obfs4_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_obfs4_radio.height()/2)) - self.assertTrue(self.gui.tor_bridges_use_obfs4_radio.isChecked()) - - # custom bridges are hidden - self.assertFalse(self.gui.tor_bridges_use_custom_textbox_options.isVisible()) - # other modes are unchecked but enabled - self.assertTrue(self.gui.connection_type_automatic_radio.isEnabled()) - self.assertTrue(self.gui.connection_type_control_port_radio.isEnabled()) - self.assertTrue(self.gui.connection_type_socket_file_radio.isEnabled()) - self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) - self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) - self.assertFalse(self.gui.connection_type_socket_file_radio.isChecked()) - - # enable automatic mode - QtTest.QTest.mouseClick(self.gui.connection_type_automatic_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_automatic_radio.height()/2)) - self.assertTrue(self.gui.connection_type_automatic_radio.isChecked()) - # bundled is off - self.assertFalse(self.gui.connection_type_bundled_radio.isChecked()) - # bridges are hidden - self.assertFalse(self.gui.connection_type_bridges_radio_group.isVisible()) - - # auth type is hidden in bundled or automatic mode - self.assertFalse(self.gui.authenticate_no_auth_radio.isVisible()) - self.assertFalse(self.gui.authenticate_password_radio.isVisible()) - - # enable control port mode - QtTest.QTest.mouseClick(self.gui.connection_type_control_port_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_control_port_radio.height()/2)) - self.assertTrue(self.gui.connection_type_control_port_radio.isChecked()) - # automatic is off - self.assertFalse(self.gui.connection_type_automatic_radio.isChecked()) - # auth options appear - self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) - self.assertTrue(self.gui.authenticate_password_radio.isVisible()) - - # enable socket mode - QtTest.QTest.mouseClick(self.gui.connection_type_socket_file_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_socket_file_radio.height()/2)) - self.assertTrue(self.gui.connection_type_socket_file_radio.isChecked()) - # control port is off - self.assertFalse(self.gui.connection_type_control_port_radio.isChecked()) - # auth options are still present - self.assertTrue(self.gui.authenticate_no_auth_radio.isVisible()) - self.assertTrue(self.gui.authenticate_password_radio.isVisible()) - - # re-enable bundled mode - QtTest.QTest.mouseClick(self.gui.connection_type_bundled_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.connection_type_bundled_radio.height()/2)) - # go back to custom bridges - QtTest.QTest.mouseClick(self.gui.tor_bridges_use_custom_radio, QtCore.Qt.LeftButton, pos=QtCore.QPoint(2,self.gui.tor_bridges_use_custom_radio.height()/2)) - self.assertTrue(self.gui.tor_bridges_use_custom_radio.isChecked()) - self.assertTrue(self.gui.tor_bridges_use_custom_textbox.isVisible()) - self.assertFalse(self.gui.tor_bridges_use_obfs4_radio.isChecked()) - self.gui.tor_bridges_use_custom_textbox.setPlainText('94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\n148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\n93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3') - - # Test that the Settings Dialog can save the settings and close itself - QtTest.QTest.mouseClick(self.gui.save_button, QtCore.Qt.LeftButton) - self.assertFalse(self.gui.isVisible()) - - # Test our settings are reflected in the settings json - with open('/tmp/settings.json') as f: - data = json.load(f) - - self.assertTrue(data["public_mode"]) - self.assertTrue(data["shutdown_timeout"]) - self.assertTrue(data["use_legacy_v2_onions"]) - self.assertTrue(data["save_private_key"]) - self.assertTrue(data["use_stealth"]) - self.assertEqual(data["downloads_dir"], "/tmp/OnionShareSettingsTest") - self.assertFalse(data["close_after_first_download"]) - self.assertEqual(data["connection_type"], "bundled") - self.assertFalse(data["tor_bridges_use_obfs4"]) - self.assertEqual(data["tor_bridges_use_custom_bridges"], "Bridge 94.242.249.2:83 E25A95F1DADB739F0A83EB0223A37C02FD519306\nBridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC\nBridge 93.80.47.217:41727 A6A0D497D98097FCFE91D639548EE9E34C15CDD3\n") - -if __name__ == "__main__": - unittest.main() diff --git a/tests/local_onionshare_settings_dialog_v3_tor_test.py b/tests/local_onionshare_settings_dialog_v3_tor_test.py new file mode 100644 index 00000000..815b2f72 --- /dev/null +++ b/tests/local_onionshare_settings_dialog_v3_tor_test.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import json +import unittest +from PyQt5 import QtCore, QtTest + +from onionshare import strings +from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub + + +class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): + @classmethod + def setUpClass(cls): + cls.gui = SettingsGuiBaseTest.set_up() + + @classmethod + def tearDownClass(cls): + SettingsGuiBaseTest.tear_down() + + def test_gui_v3_tor(self): + self.gui.onion = OnionStub(True, True) + self.gui.reload_settings() + self.run_settings_gui_tests() + + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3-54-g00ecf From caf31090bf1456d9f4ff93deabeb0e98f08e282a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sat, 8 Dec 2018 11:25:06 -0800 Subject: Split pt locale into pt_BR and pt_PT --- onionshare/settings.py | 3 ++- share/locale/pt.json | 7 ------- share/locale/pt_BR.json | 7 +++++++ share/locale/pt_PT.json | 7 +++++++ 4 files changed, 16 insertions(+), 8 deletions(-) delete mode 100644 share/locale/pt.json create mode 100644 share/locale/pt_BR.json create mode 100644 share/locale/pt_PT.json diff --git a/onionshare/settings.py b/onionshare/settings.py index 02f644af..2738ae39 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -62,7 +62,8 @@ class Settings(object): 'it': 'Italiano', # Italian 'nl': 'Nederlands', # Dutch 'no': 'Norsk', # Norweigan - 'pt': 'Português', # Portuguese + 'pt_BR': 'Português Brasil', # Portuguese Brazil + 'pt_PT': 'Português Portugal', # Portuguese Portugal 'ru': 'Русский', # Russian 'tr': 'Türkçe' # Turkish } diff --git a/share/locale/pt.json b/share/locale/pt.json deleted file mode 100644 index 1b2d3139..00000000 --- a/share/locale/pt.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "give_this_url": "Passe este URL para a pessoa que deve receber o arquivo:", - "ctrlc_to_stop": "Pressione Ctrl-C para parar o servidor", - "not_a_file": "{0:s} não é um arquivo.", - "gui_copied_url": "URL foi copiado para área de transferência", - "other_page_loaded": "Outra página tem sido carregada" -} diff --git a/share/locale/pt_BR.json b/share/locale/pt_BR.json new file mode 100644 index 00000000..1b2d3139 --- /dev/null +++ b/share/locale/pt_BR.json @@ -0,0 +1,7 @@ +{ + "give_this_url": "Passe este URL para a pessoa que deve receber o arquivo:", + "ctrlc_to_stop": "Pressione Ctrl-C para parar o servidor", + "not_a_file": "{0:s} não é um arquivo.", + "gui_copied_url": "URL foi copiado para área de transferência", + "other_page_loaded": "Outra página tem sido carregada" +} diff --git a/share/locale/pt_PT.json b/share/locale/pt_PT.json new file mode 100644 index 00000000..1b2d3139 --- /dev/null +++ b/share/locale/pt_PT.json @@ -0,0 +1,7 @@ +{ + "give_this_url": "Passe este URL para a pessoa que deve receber o arquivo:", + "ctrlc_to_stop": "Pressione Ctrl-C para parar o servidor", + "not_a_file": "{0:s} não é um arquivo.", + "gui_copied_url": "URL foi copiado para área de transferência", + "other_page_loaded": "Outra página tem sido carregada" +} -- cgit v1.2.3-54-g00ecf From 1cf816b24bf61be1067f1ebff338920d76d1352a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Mon, 10 Dec 2018 07:18:25 -0800 Subject: Fixed typo in comment --- onionshare/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare/settings.py b/onionshare/settings.py index 2738ae39..fc68ffc9 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -61,7 +61,7 @@ class Settings(object): 'fr': 'Français', # French 'it': 'Italiano', # Italian 'nl': 'Nederlands', # Dutch - 'no': 'Norsk', # Norweigan + 'no': 'Norsk', # Norwegian 'pt_BR': 'Português Brasil', # Portuguese Brazil 'pt_PT': 'Português Portugal', # Portuguese Portugal 'ru': 'Русский', # Russian -- cgit v1.2.3-54-g00ecf From af57803ade92b87aaf841425bae5d6b78851f86f Mon Sep 17 00:00:00 2001 From: emma peel Date: Tue, 11 Dec 2018 07:58:44 +0000 Subject: translations mostly completed (up to 84% translated) --- share/locale/da.json | 222 ++++++++++++++++++++++++++++++++++----------------- share/locale/de.json | 168 +++++++++++++++++++++++++++++++++++--- share/locale/es.json | 190 ++++++++++++++++++++++++++++++++++++++++--- share/locale/fr.json | 164 ++++++++++++++++++++++++++++++++----- share/locale/ga.json | 185 ++++++++++++++++++++++++++++++++++++++++++ share/locale/no.json | 191 +++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 1002 insertions(+), 118 deletions(-) create mode 100644 share/locale/ga.json diff --git a/share/locale/da.json b/share/locale/da.json index d414695b..b759cdc4 100644 --- a/share/locale/da.json +++ b/share/locale/da.json @@ -1,115 +1,189 @@ { - "config_onion_service": "Konfigurerer onion-tjeneste på port {0:d}.", - "preparing_files": "Forbereder filer som skal deles.", - "give_this_url": "Giv denne URL til personen du sender filen til:", - "give_this_url_stealth": "Giv denne URL og HidServAuth-linje til personen du sender filen til:", - "ctrlc_to_stop": "Tryk på Ctrl-C for at stoppe serveren", + "config_onion_service": "Opsætter onion-tjeneste på port {0:d}.", + "preparing_files": "Komprimerer filer.", + "give_this_url": "Giv adressen til modtageren:", + "give_this_url_stealth": "Giv adressen og HidServAuth-linjen til modtageren:", + "ctrlc_to_stop": "Tryk på Ctrl+C for at stoppe serveren", "not_a_file": "{0:s} er ikke en gyldig fil.", "not_a_readable_file": "{0:s} er ikke en læsbar fil.", - "no_available_port": "Kunne ikke starte onion-tjenesten da der ikke var nogen tilgængelig port.", - "other_page_loaded": "URL indlæst", - "close_on_timeout": "Lukker automatisk da timeout er nået", - "closing_automatically": "Lukker automatisk da download er færdig", - "timeout_download_still_running": "Venter på at download skal blive færdig inden automatisk stop", - "large_filesize": "Advarsel: Det kan tage timer at sende store filer", + "no_available_port": "Kunne ikke finde en tilgængelig port til at starte onion-tjenesten", + "other_page_loaded": "Adresse indlæst", + "close_on_timeout": "Stoppede fordi timer med autostop løb ud", + "closing_automatically": "Stoppede fordi download er færdig", + "timeout_download_still_running": "Venter på at download skal blive færdig", + "large_filesize": "Advarsel: Det kan tage timer at sende en stor deling", "systray_menu_exit": "Afslut", - "systray_download_started_title": "OnionShare-download startet", - "systray_download_started_message": "En bruger startede download af dine filer", + "systray_download_started_title": "OnionShare-download begyndte", + "systray_download_started_message": "En bruger begyndte download af dine filer", "systray_download_completed_title": "OnionShare-download færdig", "systray_download_completed_message": "Brugeren er færdig med at downloade dine filer", "systray_download_canceled_title": "OnionShare-download annulleret", "systray_download_canceled_message": "Brugeren annullerede downloaden", - "help_local_only": "Undlad at bruge tor: kun til udvikling", - "help_stay_open": "Hold onion-tjeneste kørende efter download er færdig", - "help_shutdown_timeout": "Luk onion-tjenesten efter N sekunder", - "help_stealth": "Opret usynlig onion-tjeneste (avanceret)", - "help_debug": "Log programfejl til stdout, og log webfejl til disk", + "help_local_only": "Brug ikke Tor (kun til udvikling)", + "help_stay_open": "Bliv ved med at dele efter første download", + "help_shutdown_timeout": "Stop deling efter et vist antal sekunder", + "help_stealth": "Brug klientautentifikation (avanceret)", + "help_debug": "Log OnionShare-fejl til stdout, og webfejl til disk", "help_filename": "Liste over filer eller mapper som skal deles", - "help_config": "Sti til en brugerdefineret JSON-konfigurationsfil (valgfri)", - "gui_drag_and_drop": "Træk og slip\nfiler her", + "help_config": "Tilpasset placering af JSON-konfigurationsfil (valgfri)", + "gui_drag_and_drop": "Træk og slip filer og mapper her\nfor at starte deling", "gui_add": "Tilføj", "gui_delete": "Slet", "gui_choose_items": "Vælg", - "gui_share_start_server": "Start deling", + "gui_share_start_server": "Begynd at dele", "gui_share_stop_server": "Stop deling", - "gui_copy_url": "Kopiér URL", + "gui_copy_url": "Kopiér adresse", "gui_copy_hidservauth": "Kopiér HidServAuth", - "gui_downloads": "Downloads:", + "gui_downloads": "Downloadhistorik", "gui_canceled": "Annulleret", - "gui_copied_url": "Kopierede URL til udklipsholder", - "gui_copied_hidservauth": "Kopierede HidServAuth-linje til udklipsholder", - "gui_please_wait": "Vent venligst...", - "gui_download_upload_progress_complete": "%p%, tid forløbet: {0:s}", + "gui_copied_url": "OnionShare-adressen blev kopieret til udklipsholderen", + "gui_copied_hidservauth": "HidServAuth-linjen blev kopieret til udklipsholderen", + "gui_please_wait": "Starter... klik for at annullere.", + "gui_download_upload_progress_complete": ".", "gui_download_upload_progress_starting": "{0:s}, %p% (udregner anslået ankomsttid)", - "gui_download_upload_progress_eta": "{0:s}, anslået ankomsttid: {1:s}, %p%", - "version_string": "Onionshare {0:s} | https://onionshare.org/", - "gui_share_quit_warning": "Er du sikker på, at du vil afslutte?\nURL'en som du deler vil ikke eksistere længere.", + "gui_download_upload_progress_eta": "{0:s}, ETA: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_share_quit_warning": "Du er ved at afsende filer. Er du sikker på, at du vil afslutte OnionShare?", "gui_quit_warning_quit": "Afslut", - "gui_quit_warning_dont_quit": "Afslut ikke", - "error_rate_limit": "En angriber forsøger måske at gætte din URL. For at forhindre det, har OnionShare automatisk stoppet serveren. For at dele filerne skal du starte den igen og dele den nye URL.", - "zip_progress_bar_format": "Databehandler filer: %p%", - "error_stealth_not_supported": "For at oprette usynlige onion-tjenester, skal du mindst have Tor 0.2.9.1-alpha (eller Tor Browser 6.5) og mindst python3-stem 1.5.0.", - "error_ephemeral_not_supported": "OnionShare kræver mindst Tor 0.2.7.1 og mindst python3-stem 1.4.0.", + "gui_quit_warning_dont_quit": "Annuller", + "error_rate_limit": "Nogen har foretaget for mange forkerte forsøg på din adresse, hvilket kan betyde at de prøver at gætte det, så OnionShare har stoppet serveren. Start deling igen og send en ny adresse til modtageren for at dele.", + "zip_progress_bar_format": "Komprimerer: %p%", + "error_stealth_not_supported": "For at bruge klientautentifikation skal du have mindst Tor 0.2.9.1-alpha (eller Tor Browser 6.5) og python3-stem 1.5.0.", + "error_ephemeral_not_supported": "OnionShare kræver mindst både Tor 0.2.7.1 og python3-stem 1.4.0.", "gui_settings_window_title": "Indstillinger", - "gui_settings_stealth_option": "Opret usynlige onion-tjenester", - "gui_settings_stealth_hidservauth_string": "Du har gemt den private nøgle til at blive brugt igen, så din HidServAuth-streng bruges også igen.\nKlik nedenfor, for at kopiere HidServAuth.", - "gui_settings_autoupdate_label": "Søg efter opdateringer", - "gui_settings_autoupdate_option": "Giv mig besked når der findes opdateringer", + "gui_settings_stealth_option": "Brug klientautentifikation (forældet)", + "gui_settings_stealth_hidservauth_string": "Ved at have gemt din private nøgle til at blive brugt igen, betyder det at du nu\nkan klikke for at kopiere din HidServAuth.", + "gui_settings_autoupdate_label": "Søg efter ny version", + "gui_settings_autoupdate_option": "Giv mig besked når der findes en ny version", "gui_settings_autoupdate_timestamp": "Sidste søgning: {}", "gui_settings_autoupdate_timestamp_never": "Aldrig", - "gui_settings_autoupdate_check_button": "Søg efter opdateringer", - "gui_settings_sharing_label": "Valgmuligheder for deling", + "gui_settings_autoupdate_check_button": "Søg efter ny version", + "gui_settings_sharing_label": "Delingsindstillinger", "gui_settings_close_after_first_download_option": "Stop deling efter første download", "gui_settings_connection_type_label": "Hvordan skal OnionShare oprette forbindelse til Tor?", - "gui_settings_connection_type_bundled_option": "Brug Tor som er bundet med OnionShare", - "gui_settings_connection_type_automatic_option": "Prøv automatisk konfiguration med Tor Browser", + "gui_settings_connection_type_bundled_option": "Brug Tor-versionen som er indbygget i OnionShare", + "gui_settings_connection_type_automatic_option": "Prøv autokonfiguration med Tor Browser", "gui_settings_connection_type_control_port_option": "Opret forbindelse med kontrolport", "gui_settings_connection_type_socket_file_option": "Opret forbindelse med sokkelfil", - "gui_settings_connection_type_test_button": "Test Tor-indstillinger", + "gui_settings_connection_type_test_button": "Test forbindelsen til Tor", "gui_settings_control_port_label": "Kontrolport", "gui_settings_socket_file_label": "Sokkelfil", "gui_settings_socks_label": "SOCKS-port", - "gui_settings_authenticate_label": "Valgmuligheder for Tor-autentifikation", + "gui_settings_authenticate_label": "Indstillinger for Tor-autentifikation", "gui_settings_authenticate_no_auth_option": "Ingen autentifikation, eller cookieautentifikation", "gui_settings_authenticate_password_option": "Adgangskode", "gui_settings_password_label": "Adgangskode", "gui_settings_tor_bridges": "Understøttelse af Tor-bro", "gui_settings_tor_bridges_no_bridges_radio_option": "Brug ikke broer", - "gui_settings_tor_bridges_obfs4_radio_option": "Brug indbygget obfs4 udskiftelige transporter", - "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Brug indbygget obfs4 udskiftelige transporter (kræver obfs4proxy)", - "gui_settings_tor_bridges_custom_radio_option": "Brug brugerdefinerede broer", + "gui_settings_tor_bridges_obfs4_radio_option": "Brug indbyggede obfs4 udskiftelige transporter", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Brug indbyggede obfs4 udskiftelige transporter (kræver obfs4proxy)", + "gui_settings_tor_bridges_custom_radio_option": "Brug tilpassede broer", "gui_settings_tor_bridges_custom_label": "Du kan få broer fra https://bridges.torproject.org", - "gui_settings_tor_bridges_invalid": "Ingen af broerne du leverede ser ud til at være gyldige, så de ignoreres.\nPrøv venligst igen med gyldige broer.", + "gui_settings_tor_bridges_invalid": "Ingen at de broer du tilføjede virker.\nDobbeltklik på dem eller tilføj andre.", "gui_settings_button_save": "Gem", "gui_settings_button_cancel": "Annuller", "gui_settings_button_help": "Hjælp", "gui_settings_shutdown_timeout": "Stop delingen ved:", "settings_saved": "Indstillinger gemt til {}", - "settings_error_unknown": "Kan ikke oprette forbindelse til Tor-kontroller da indstillingerne ikke giver mening.", - "settings_error_automatic": "Kan ikke oprette forbindelse til Tor-kontroller. Kører Tor Browser i baggrunden? Hvis du ikke har den kan du få den fra:\nhttps://www.torproject.org/.", - "settings_error_socket_port": "Kan ikke oprette forbindelse til Tor-kontroller på {}:{}", - "settings_error_socket_file": "Kan ikke oprette forbindelse til Tor-kontroller med sokkelfilen {}", - "settings_error_auth": "Forbundet til {}:{}, men kan ikke autentificere. Er det en Tor-kontroller?", - "settings_error_missing_password": "Forbundet til Tor-kontroller, men den kræver en adgangskode for at autentificere", - "settings_error_unreadable_cookie_file": "Forbundet til Tor-kontroller, men kan ikke autentificere da din adgangskode kan være forkert, og din bruger ikke har tilladelse til at læse cookiefilen.", - "settings_error_bundled_tor_not_supported": "Bundet Tor understøttes ikke når der ikke bruges udviklertilstand i Windows eller MacOS.", - "settings_error_bundled_tor_timeout": "Det tager for længe at oprette forbindelse til Tor. Din computer er måske offline, eller dit ur går forkert.", - "settings_error_bundled_tor_broken": "Der er noget galt med OnionShare som opretter forbindelse til Tor i baggrunden:\n{}", - "settings_test_success": "Tillykke, OnionShare kan oprette forbindelse til Tor-kontrolleren.\n\nTor version: {}\nUnderstøtter kortvarige onion-tjenester: {}\nUnderstøtter usynlige onion-tjenester: {}", - "error_tor_protocol_error": "Fejl under snak med Tor-kontrolleren.\nHvis du bruger Whonix, så tjek https://www.whonix.org/wiki/onionshare for at få OnionShare til at virke.", - "connecting_to_tor": "Forbundet til Tor-netværket", - "update_available": "Der findes en OnionShare-opdatering. Klik her for at downloade den.

Installeret version: {}
Seneste version: {}", - "update_error_check_error": "Fejl under søgning efter opdateringer: Du er måske ikke forbundet til Tor, eller måske er OnionShare-webstedet nede.", - "update_error_invalid_latest_version": "Fejl under søgning efter opdateringer: OnionShare-webstedet svarende ved at sige at den seneste version er '{}', men det ser ikke ud til at være en gyldig versionsstreng.", - "update_not_available": "Du kører den seneste version af OnionShare.", - "gui_tor_connection_ask": "Vil du åbne OnionShare-indstillinger for at fejlsøge forbindelsen til Tor?", - "gui_tor_connection_ask_open_settings": "Åbn indstillinger", + "settings_error_unknown": "Kan ikke oprette forbindelse til Tor-kontroller da dine indstillingerne ikke giver mening.", + "settings_error_automatic": "Kunne ikke oprette forbindelse til Tor-kontrolleren. Kører Tor Browser (tilgængelige fra torproject.org) i baggrunden?", + "settings_error_socket_port": "Kan ikke oprette forbindelse til Tor-kontrolleren på {}:{}.", + "settings_error_socket_file": "Kan ikke oprette forbindelse til Tor-kontrolleren med sokkelfilen {}.", + "settings_error_auth": "Forbundet til {}:{}, men kan ikke autentificere. Er det fordi det ikke er en Tor-kontroller?", + "settings_error_missing_password": "Forbundet til Tor-kontroller, men den kræver en adgangskode for at autentificere.", + "settings_error_unreadable_cookie_file": "Forbundet til Tor-kontrolleren, men adgangskoden kan være forkert, eller din bruger har ikke tilladelse til at læse cookiefilen.", + "settings_error_bundled_tor_not_supported": "Brug af Tor-versionen som kom med OnionShare virker ikke i udviklertilstand på Windows eller macOS.", + "settings_error_bundled_tor_timeout": "For længe om at oprette forbindelse til Tor. Måske har du ikke forbindelse til internettet, eller går dit systems ur forkert?", + "settings_error_bundled_tor_broken": "OnionShare kunne ikke oprette forbindelse til Tor i baggrunden:\n{}", + "settings_test_success": "Forbundet til Tor-kontrolleren.\n\nTor version: {}\nUnderstøtter kortvarige onion-tjenester: {}.\nUnderstøtter klientautentifikation: {}.\nUnderstøtter næste generations .onion-adresser: {}.", + "error_tor_protocol_error": "Der opstod en fejl med Tor: {}", + "connecting_to_tor": "Opretter forbindelse til Tor-netværket", + "update_available": "Der findes en ny OnionShare. Klik her for at hente den.

Du bruger {} og den seneste er {}.", + "update_error_check_error": "Kunne ikke søge efter nye versioner: OnionShare-webstedet siger at den seneste version er den ugenkendte '{}'…", + "update_error_invalid_latest_version": "Kunne ikke søge efter ny version: Måske har du ikke forbindelse til Tor, eller er OnionShare-webstedet nede?", + "update_not_available": "Du kører den seneste OnionShare.", + "gui_tor_connection_ask": "Åbn indstillingerne for at rette forbindelsen til Tor?", + "gui_tor_connection_ask_open_settings": "Ja", "gui_tor_connection_ask_quit": "Afslut", - "gui_tor_connection_error_settings": "Prøv at justere måden hvorpå OnionShare opretter forbindelse til Tor-netværket i Indstillinger.", - "gui_tor_connection_canceled": "OnionShare kan ikke oprette forbindelse til Tor.\n\nSørg for at du har forbindelse til internettet, og åbn herefter OnionShare igen for at konfigurere Tor-forbindelsen.", - "gui_tor_connection_lost": "Afbryder forbindelsen fra Tor.", - "gui_server_started_after_timeout": "Serveren startede efter dit valgte automatiske timeout.\nStart venligst en ny deling.", - "gui_server_timeout_expired": "Den valgte timeout er allerede udløbet.\nOpdater venligst timeouten og herefter kan du starte deling.", + "gui_tor_connection_error_settings": "Prøv at ændre måden hvorpå OnionShare opretter forbindelse til Tor-netværket, i indstillingerne.", + "gui_tor_connection_canceled": "Kunne ikke oprette forbindelse til Tor.\n\nSørg for at du har forbindelse til internettet, og åbn herefter OnionShare igen for at opsætte dens forbindelse til Tor.", + "gui_tor_connection_lost": "Der er ikke oprettet forbindelse til Tor.", + "gui_server_started_after_timeout": "Timeren med autostop løb ud inden serveren startede.\nOpret venligst en ny deling.", + "gui_server_timeout_expired": "Timeren med autostop er allerede løbet ud.\nOpdater den venligst for at starte deling.", "share_via_onionshare": "Del via OnionShare", - "gui_save_private_key_checkbox": "Brug en vedvarende URL\n(fravalg vil slette gemte URL)" + "gui_save_private_key_checkbox": "Brug en vedvarende adresse (udgået)", + "gui_copied_url_title": "Kopierede OnionShare-adresse", + "gui_copied_hidservauth_title": "Kopierede HidServAuth", + "gui_quit_title": "Klap lige hesten", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Brug indbyggede meek_lite (Azure) udskiftelige transporter", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Brug indbyggede meek_lite (Azure) udskiftelige transporter (kræver obfs4proxy)", + "gui_settings_shutdown_timeout_checkbox": "Brug timer med autostop", + "gui_url_label_persistent": "Delingen stopper ikke automatisk.

Hver efterfølgende deling bruger den samme adresse igen (hvis du vil bruge engangsadresser, så deaktivér \"Brug vedvarende adresse\", i indstillingerne).", + "gui_url_label_stay_open": "Delingen stopper ikke automatisk.", + "gui_url_label_onetime": "Delingen stopper efter den første download.", + "gui_url_label_onetime_and_persistent": "Delingen stopper ikke automatisk.

Hver efterfølgende deling bruger den samme adresse igen (hvis du vil bruge engangsadresser, så deaktivér \"Brug vedvarende adresse\", i indstillingerne).", + "gui_file_info": "{} filer, {}", + "gui_file_info_single": "{} fil, {}", + "info_in_progress_downloads_tooltip": "{} igangværende downloads", + "info_completed_downloads_tooltip": "{} færdige downloads", + "give_this_url_receive": "Giv adressen til afsenderen:", + "give_this_url_receive_stealth": "Giv adressen og HidServAuth til afsenderen:", + "systray_upload_started_title": "OnionShare-upload begyndte", + "systray_upload_started_message": "En bruger begyndte at uploade filer til din computer", + "help_receive": "Modtager aktier i stedet for at sende dem", + "gui_share_stop_server_shutdown_timeout": "Stop deling ({}s tilbage)", + "gui_receive_quit_warning": "Du er i færd med at modtage filer. Er du sikker på du ønsker at stoppe med at OnionShare?", + "gui_settings_whats_this": "Hvad er dette?", + "gui_settings_general_label": "Generel opsætning", + "gui_upload_in_progress": "Upload begyndte {}", + "gui_download_in_progress": "Download begyndte {}", + "gui_share_stop_server_shutdown_timeout_tooltip": "Timer med autostop slutter ved {}", + "gui_receive_start_server": "Start modtagetilstand", + "gui_receive_stop_server": "Stop modtagetilstand", + "gui_receive_stop_server_shutdown_timeout": "Stop modtagetilstand ({}s tilbage)", + "gui_receive_stop_server_shutdown_timeout_tooltip": "Timer med autostop slutter ved {}", + "gui_no_downloads": "Ingen downloads endnu", + "error_tor_protocol_error_unknown": "Der opstod en ukendt fejl med Tor", + "error_invalid_private_key": "Den private nøgletype understøttes ikke", + "gui_use_legacy_v2_onions_checkbox": "Brug forældede adresser", + "gui_status_indicator_share_stopped": "Klar til at dele", + "gui_status_indicator_share_working": "Starter…", + "gui_status_indicator_share_started": "Deler", + "gui_status_indicator_receive_stopped": "Klar til at modtage", + "gui_status_indicator_receive_working": "Starter…", + "gui_status_indicator_receive_started": "Modtager", + "receive_mode_received_file": "Modtaget: {}", + "gui_mode_share_button": "Del filer", + "gui_mode_receive_button": "Modtag filer", + "gui_settings_receiving_label": "Modtagelsesindstillinger", + "gui_settings_downloads_label": "Gem filer til", + "gui_settings_downloads_button": "Gennemse", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "Modtagetilstand kan ikke stoppes af afsenderen", + "gui_settings_public_mode_checkbox": "Offentlig tilstand", + "systray_close_server_title": "OnionShare-server lukket", + "systray_close_server_message": "En bruger lukkede serveren", + "systray_page_loaded_title": "OnionShare-side indlæst", + "systray_download_page_loaded_message": "En bruger indlæste downloadsiden", + "systray_upload_page_loaded_message": "En bruger indlæste uploadsiden", + "gui_uploads": "Uploadhistorik", + "gui_no_uploads": "Ingen uploads endnu", + "gui_clear_history": "Ryd alle", + "gui_upload_finished_range": "Uploadede {} til {}", + "gui_upload_finished": "Uploadet {}", + "gui_settings_language_label": "Foretrukne sprog", + "gui_settings_language_changed_notice": "Genstart OnionShare for at din ændring af sprog skal træder i kraft.", + "gui_settings_meek_lite_expensive_warning": "Advarsel: meek_lite-broerne er meget dyre at køre for Tor-projektet.

Brug dem kun hvis du ikke er i stand til at oprette forbindelse til Tor direkte, via obfs4-transporter eller andre normale broer.", + "gui_share_url_description": "Alle med OnionShare-adressen kan downloade dine filer med Tor Browser: ", + "gui_receive_url_description": "Alle med OnionShare-adressen kan uploade filer til din computer med Tor Browser: ", + "history_in_progress_tooltip": "{} igangværende", + "history_completed_tooltip": "{} færdige", + "info_in_progress_uploads_tooltip": "{} igangværende upload(s)", + "info_completed_uploads_tooltip": "{} upload(s) færdige", + "error_cannot_create_downloads_dir": "Kunne ikke oprette modtagetilstand-mappe: {}", + "receive_mode_downloads_dir": "Filer som sendes til dig vises i denne mappe: {}", + "receive_mode_warning": "Advarsel: Modtagetilstand lader folk uploade filer til din computer. Nogle filer kan potentielt tage kontrol over din computer hvis du åbner dem. Åbn kun ting fra folk du har tillid til, eller hvis du ved hvad du har gang i.", + "gui_receive_mode_warning": "Modtagetilstand lader folk uploade filer til din computer.

Nogle filer kan potentielt tage kontrol over din computer hvis du åbner dem. Åbn kun ting fra folk du har tillid til, eller hvis du ved hvad du har gang i.", + "receive_mode_upload_starting": "Upload med samlet størrelse på {} starter", + "gui_open_folder_error_nautilus": "Kan ikke åbne mappe fordi nautilus ikke er tilgængelig. Filen er her: {}", + "timeout_upload_still_running": "Venter på at upload skal blive færdig" } diff --git a/share/locale/de.json b/share/locale/de.json index 1d0436a0..30f5eed0 100644 --- a/share/locale/de.json +++ b/share/locale/de.json @@ -1,23 +1,173 @@ { "preparing_files": "Dateien werden vorbereitet.", - "give_this_url": "Geben Sie diese URL der Person, der Sie die Datei zusenden möchten:", - "ctrlc_to_stop": "Drücken Sie Strg+C um den Server anzuhalten", + "give_this_url": "Gib diese URL an den Empfänger:", + "ctrlc_to_stop": "Drücke Strg+C um den Server anzuhalten", "not_a_file": "{0:s} ist keine Datei.", "other_page_loaded": "URL geladen", - "closing_automatically": "Halte automatisch an, da der Download beendet wurde", + "closing_automatically": "Gestoppt, da der Download beendet wurde", "large_filesize": "Warnung: Das Senden von großen Dateien kann Stunden dauern", - "help_local_only": "Nicht mit Tor benutzen, nur für Entwicklung", - "help_stay_open": "Den onion service nicht anhalten nachdem ein Download beendet wurde", - "help_debug": "Fehler auf Festplatte schreiben", + "help_local_only": "Tor nicht benutzen (nur für Entwicklung)", + "help_stay_open": "Den OnionService nicht anhalten nachdem ein Download beendet wurde", + "help_debug": "Schreibe Fehler von OnionShare nach stdout und Webfehler aus die Festplatte", "help_filename": "Liste der zu teilenden Dateien oder Verzeichnisse", - "gui_drag_and_drop": "Drag & drop\nDateien hier", + "gui_drag_and_drop": "Dateien und Ordner hierher ziehen\num sie zu teilen", "gui_add": "Hinzufügen", "gui_delete": "Löschen", "gui_choose_items": "Auswählen", "gui_share_start_server": "Server starten", "gui_share_stop_server": "Server anhalten", "gui_copy_url": "URL kopieren", - "gui_downloads": "Downloads:", + "gui_downloads": "Bisherige Downloads", "gui_copied_url": "URL wurde in die Zwischenablage kopiert", - "gui_please_wait": "Bitte warten..." + "gui_please_wait": "Starte... Klicken zum Abbrechen.", + "timeout_download_still_running": "Warte auf Beendigung des Downloads", + "systray_menu_exit": "Beenden", + "gui_settings_authenticate_password_option": "Passwort", + "gui_settings_password_label": "Passwort", + "gui_settings_button_save": "Speichern", + "gui_settings_button_cancel": "Abbrechen", + "gui_settings_button_help": "Hilfe", + "gui_settings_shutdown_timeout": "Stoppe den Server bei:", + "systray_download_started_title": "OnionShareDownload begonnen", + "systray_download_started_message": "Ein Nutzer hat begonnen deine Dateien herunterzuladen", + "systray_download_completed_title": "OnionShare Download beendet", + "systray_download_completed_message": "Der Benutzer hat deine Dateien heruntergeladen", + "systray_download_canceled_title": "OnionShareDownload abgebrochen", + "systray_download_canceled_message": "Der Benutzer hat den Download abgebrochen", + "gui_copy_hidservauth": "HidServAuth kopieren", + "gui_canceled": "Abgebrochen", + "gui_copied_hidservauth_title": "HidServAuth kopiert", + "gui_quit_warning_quit": "Beenden", + "gui_quit_warning_dont_quit": "Abbrechen", + "gui_settings_window_title": "Eintellungen", + "gui_settings_autoupdate_timestamp": "Letzte Überprüfung: {}", + "gui_settings_autoupdate_timestamp_never": "Niemals", + "gui_settings_close_after_first_download_option": "Server nach dem ersten Download stoppen", + "gui_settings_connection_type_label": "Wie soll sich OnionShare mit Tor verbinden?", + "config_onion_service": "Richte den Onionservice auf Port {0:d} ein.", + "give_this_url_stealth": "Gib dem Empfänger diese URL und die HidServAuth-Zeile:", + "give_this_url_receive": "Gib diese URL dem Sender:", + "give_this_url_receive_stealth": "Gib diese URL und die HidServAuth-Zeile an den Sender:", + "not_a_readable_file": "{0:s} kann nicht gelesen werden.", + "no_available_port": "Konnte keinen freien Port finden, um den Onionservice zu starten", + "close_on_timeout": "Wegen Zeitablaufs gestoppt", + "systray_upload_started_title": "OnionShare Upload gestartet", + "systray_upload_started_message": "Ein Nutzer hat begonnen Dateien auf deinen Computer zu laden", + "help_shutdown_timeout": "Den Server nach einer bestimmten Zeit anhalten", + "help_receive": "Empfange Dateien anstatt sie zu senden", + "gui_share_stop_server_shutdown_timeout": "Server stoppen (läuft noch {} Sekunden)", + "gui_share_stop_server_shutdown_timeout_tooltip": "Zeit läuft in {} Sekunden ab", + "gui_settings_connection_type_control_port_option": "Verbinde über den control port", + "gui_settings_connection_type_socket_file_option": "Verbinde über ein socket file", + "gui_settings_control_port_label": "Control port", + "gui_settings_socket_file_label": "Socket file", + "gui_settings_socks_label": "SOCKS Port", + "gui_settings_authenticate_no_auth_option": "Keine Authentifizierung, oder Authentifizierung per cookie", + "gui_settings_tor_bridges_no_bridges_radio_option": "Benutze keine bridges", + "gui_settings_tor_bridges_obfs4_radio_option": "Benutze eingebaute obfs4 pluggable transports", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Benutze eingebaute obfs4 pluggable transports (benötigt obfs4proxy)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Benutze eingebaute meek_lite (Amazon) pluggable transports", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Benutze eingebaute meek_lite (Azure) pluggable transports (benötigt obfs4proxy)", + "gui_settings_tor_bridges_custom_radio_option": "Benutze benutzerdefinierte bridges", + "gui_settings_tor_bridges_custom_label": "Bridges findest du unter https://bridges.torproject.org", + "gui_settings_shutdown_timeout_checkbox": "Stoppe nach einer bestimmten Zeit", + "settings_error_auth": "Mit {}:{} verbinden aber nicht authentifiziert. Eventuell handelt es sich nicht um einen Tor controller?", + "settings_error_missing_password": "Mit dem Tor controller verbunden, aber er benötigt ein Passwort zur Authentifizierung.", + "connecting_to_tor": "Verbinde mit dem Tornetzwerk", + "gui_tor_connection_ask_quit": "Beenden", + "gui_tor_connection_lost": "Verbindung zu Tor getrennt.", + "help_stealth": "Nutze Klientauthorisierung (fortgeschritten)", + "gui_receive_start_server": "Starte den Empfängermodus", + "gui_receive_stop_server": "Stoppe den Empfängermodus", + "gui_receive_stop_server_shutdown_timeout": "Stoppe den Empfängermodus (stoppt automatisch in {})", + "gui_receive_stop_server_shutdown_timeout_tooltip": "Zeit läuft in {} Sekunden ab", + "gui_no_downloads": "Bisher keine Downloads", + "gui_copied_url_title": "OnionShareadresse kopiert", + "gui_copied_hidservauth": "HidServAuth-Zeile in die Zwischenablage kopiert", + "gui_download_upload_progress_complete": "%p%, {0:s} vergangen.", + "gui_download_upload_progress_starting": "{0:s}, %p% (berechne)", + "gui_download_upload_progress_eta": "{0:s}, Voraussichtliche Dauer: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_quit_title": "Nicht so schnell", + "gui_share_quit_warning": "Du versendest gerade Dateien. Bist du sicher, dass du OnionShare beenden willst?", + "gui_receive_quit_warning": "Du empfängst gerade Dateien. Bist du sicher, dass du OnionShare beenden willst?", + "error_rate_limit": "Jemand hat deine Adresse zu oft falsch eingegeben, das heißt, jemand könnte versuchen, sie zu erraten. Deswegen hat OnionShare den Server gestoppt. Starte den Server erneut und schicke dem Empfänger die neue Adresse, um die Dateien zu verschicken.", + "zip_progress_bar_format": "Packe: %p%", + "error_stealth_not_supported": "Um Klientauthorisierung zu nutzen, benötigst du mindestens Tor 0.2.9.1-alpha (or Tor Browser 6.5) und python3-stem 1.5.0.", + "error_ephemeral_not_supported": "OnionShare benötigt mindestens Tor 0.2.7.1 als auch python3-stem 1.4.0.", + "gui_settings_whats_this": "Was ist das?", + "gui_settings_stealth_option": "Nutze Klientauthorisierung (Alt)", + "gui_settings_autoupdate_label": "Suche nach einer neueren Version", + "gui_settings_autoupdate_option": "Benachrichtige mich, wenn eine neuere Version verfügbar ist", + "gui_settings_autoupdate_check_button": "Suche nach neuerer Version", + "gui_settings_general_label": "Allgemeine Einstellungen", + "gui_settings_sharing_label": "Servereinstellungen", + "gui_settings_connection_type_automatic_option": "Versuche mit dem Tor Browser automatisch zu konfigurieren", + "gui_settings_connection_type_test_button": "Teste Verbindung zum Tornetzwerk", + "gui_settings_authenticate_label": "Autentifizierungseinstellungen für Tor", + "gui_settings_tor_bridges": "Einstellungen für Tor bridges", + "gui_settings_meek_lite_expensive_warning": "Achtung: Die meek_lite bridges sind für das Tor Projekt sehr kostspielig.

Nutze sie nur, wenn du dich nicht direkt, per obfs4 Transport oder über andere, normale bridges zum Tornetzwerk verbinden kannst.", + "gui_settings_tor_bridges_invalid": "Keine der bridges, die du angegeben hast, funktionieren.\nÜberprüfe sie oder gebe Andere an.", + "settings_error_unknown": "Kann nicht zum Tor controller verbinden, weil deine Einstellungen keinen Sinn ergeben.", + "settings_error_automatic": "Kann nicht zum Tor controller verbinden. Läuft der Tor Browser (zum Download unter torproject.org) im Hintergrund?", + "settings_error_socket_port": "Kann unter {}:{} nicht zum Tor controller verbinden.", + "settings_error_unreadable_cookie_file": "Verbindung zum Tor controller hergestellt, aber dein Passwort ist falsch oder dein Nutzer hat keine Rechte, die Cookiedatei zu lesen.", + "settings_error_bundled_tor_not_supported": "Im Entwicklermodus auf Windows oder macOS kannst du die Torversion, die mit OnionShare gekoppelt ist nicht nutzen.", + "settings_error_bundled_tor_timeout": "Die Verbindung zum Tornetzwerk braucht zu lang. Bist du vielleicht nicht mit dem Internet verbunden oder geht die Uhr auf deinem System falsch?", + "settings_error_bundled_tor_broken": "OnionShare konnte nicht zu Tor im Hintergrund verbinden:\n{}", + "settings_test_success": "Verbunden mit dem Tor controller.\n\nTorversion: {}\nUnterstützt flüchtige onion services: {}.\nUnterstützt Klientauthorisierung: {}.\nUnterstützt .onion Adressen der nächsten Generation: {}.", + "error_tor_protocol_error": "Es gab eine Fehler mit Tor: {}", + "error_tor_protocol_error_unknown": "Es gab einen unbekannten Fehler mit Tor", + "error_invalid_private_key": "Diese Art von privatem Schlüssel wird nicht unterstützt", + "update_available": "Es gibt eine neue Version von OnionShare. Klicke hier um sie herunterzuladen.

Du benutzt {} und die neueste Version ist {}.", + "update_error_check_error": "Konnte nicht nach neueren Versionen suchen: Die OnionShareSeite sagt, die letzte Version ist die unkenntliche '{}'…", + "update_error_invalid_latest_version": "Konnte nicht nach neueren Versionen suchen: Bist du vielleicht nicht mit dem Tornetzwerk verbunden oder ist die OnionShareSeite offline?", + "update_not_available": "Du benutzt bereits die neueste Version von OnionShare.", + "gui_tor_connection_ask": "Einstellungen öffnen, um die Verbindung zum Tornetzwerk zu ermöglichen?", + "gui_tor_connection_ask_open_settings": "Ja", + "gui_tor_connection_error_settings": "Versuche in den Einstellung zu ändern, wie sich OnionShare mit dem Tornetzwerk verbindet.", + "gui_tor_connection_canceled": "Konnte keine Verbindung zu Tor herstellen.\n\nStelle sicher, dass du mit dem Internet verbunden bist, öffne OnionShare erneut und richte die Verbindung zu Tor ein.", + "share_via_onionshare": "Teile es per OnionShare", + "gui_use_legacy_v2_onions_checkbox": "Nutze das alte Adressformat", + "gui_save_private_key_checkbox": "Nutze eine gleichbleibende Adresse (alt)", + "gui_share_url_description": "Jeder mit dieser OnionShareAdresse kann deine Dateien mit dem Tor Browser herunterladen: ", + "gui_receive_url_description": "Jeder mit dieser OnionShareAdresse kann mit dem Tor Browser Dateien auf deinen Computer hochladen: ", + "gui_url_label_persistent": "Dieser Server wird nicht automatisch stoppen.

Jeder folgende Server wird die Adresse erneut nutzen. (Um Adressen nur einmal zu nutzen, schalte \"Nutze beständige Adressen\" in den Einstellungen aus.)", + "gui_url_label_stay_open": "Dieser Server wird nicht automatisch stoppen.", + "gui_url_label_onetime": "Dieser Server wird nach dem ersten vollständigen Download stoppen.", + "gui_status_indicator_share_working": "Starte…", + "gui_status_indicator_share_started": "Läuft", + "gui_status_indicator_receive_stopped": "Bereit zum Empfangen", + "gui_status_indicator_receive_working": "Starte…", + "gui_status_indicator_receive_started": "Empfange", + "gui_file_info": "{} Dateien, {}", + "gui_file_info_single": "{} Datei, {}", + "history_completed_tooltip": "{} vollständige", + "info_in_progress_uploads_tooltip": "{} Upload(s) laufen", + "info_completed_uploads_tooltip": "{} Upload(s) vollständig", + "error_cannot_create_downloads_dir": "Konnte den Ordner für den Empfängermodus nicht erstellen: {}", + "receive_mode_downloads_dir": "Dateien, die dir geschickt werden, findest du in diesem Ordner: {}", + "receive_mode_warning": "Achtung: Im Empfängermodus können Leute Dateien auf deinen Computer laden. Einige Dateien können die Kontrolle über deinen Computer übernehmen, wenn du sie öffnest. Öffne nur Dateien von Personen, denen du vertraust oder wenn du genau weißt, was du tust.", + "gui_receive_mode_warning": "Im Empfängermodus können Leute Dateien auf deinen Computer laden.

Einige Dateien können die Kontrolle über deinen Computer übernehmen, wenn du sie öffnest. Öffne nur Dateien von Personen, denen du vertraust oder wenn du genau weißt, was du tust.", + "receive_mode_received_file": "Empfangen: {}", + "gui_mode_share_button": "Versende Dateien", + "gui_mode_receive_button": "Empfange Dateien", + "gui_settings_receiving_label": "Empfangseinstellungen", + "gui_settings_downloads_label": "Speichere Dateien in", + "gui_settings_downloads_button": "Durchsuchen", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "Der Empfängermodus kann vom Versender gestoppt werden", + "gui_settings_public_mode_checkbox": "Öffentlich", + "systray_close_server_title": "OnionShareServer gestoppt", + "systray_close_server_message": "Ein Nutzer hat den Server gestoppt", + "systray_download_page_loaded_message": "Ein Nutzer hat die Downloadseite geöffnet", + "systray_upload_page_loaded_message": "Ein Nutzer hat die Uploadseite geöffnet", + "gui_uploads": "Uploadhistorie", + "gui_no_uploads": "Bisher keine Uploads", + "gui_clear_history": "Alle löschen", + "gui_upload_in_progress": "Upload gestartet {}", + "gui_download_in_progress": "Download gestartet {}", + "gui_open_folder_error_nautilus": "Kann den Ordner nicht öffnen, weil Nautilus nicht verfügbar ist. Die Datei ist hier: {}", + "gui_settings_language_label": "Bevorzugte Sprache", + "gui_settings_language_changed_notice": "Starte OnionShare neu, damit die Sprache geändert wird.", + "help_config": "Ort deiner eigenen JSON Konfigurationsdatei (optional)" } diff --git a/share/locale/es.json b/share/locale/es.json index 8c9945a8..3477fd3b 100644 --- a/share/locale/es.json +++ b/share/locale/es.json @@ -1,21 +1,189 @@ { - "preparing_files": "Preparando los archivos para compartir.", - "give_this_url": "Entregue esta URL a la persona a la que está enviando el archivo:", - "ctrlc_to_stop": "Pulse Ctrl-C para detener el servidor", + "preparing_files": "Comprimiendo los archivos.", + "give_this_url": "Entrega esta URL al receptor:", + "ctrlc_to_stop": "Pulsa Ctrl-C para detener el servidor", "not_a_file": "{0:s} no es un archivo.", - "other_page_loaded": "La URL está lista.", + "other_page_loaded": "La URL está lista", "closing_automatically": "Apagando automáticamente porque la descarga finalizó", - "help_local_only": "No intentar usar Tor: sólo para desarrollo", - "help_stay_open": "Mantener el servicio oculto ejecutando después de que la descarga haya finalizado", - "help_debug": "Guardar registro de errores en el disco", + "help_local_only": "No usar Tor (sólo para desarrollo)", + "help_stay_open": "Mantener el servicio después de que la primera descarga haya finalizado", + "help_debug": "Enviar los errores de OnionShare a stdout, y los errores web al disco", "help_filename": "Lista de archivos o carpetas para compartir", "gui_drag_and_drop": "Arrastre\narchivos aquí", "gui_add": "Añadir", "gui_delete": "Eliminar", "gui_choose_items": "Elegir", - "gui_share_start_server": "Encender el Servidor", - "gui_share_stop_server": "Detener el Servidor", + "gui_share_start_server": "Comenzar a compartir", + "gui_share_stop_server": "Dejar de compartir", "gui_copy_url": "Copiar URL", - "gui_downloads": "Descargas:", - "gui_copied_url": "Se copió la URL en el portapapeles" + "gui_downloads": "Historial de descargas", + "gui_copied_url": "Dirección OnionShare copiada al portapapeles", + "config_onion_service": "Configurando el servicio cebolla en el puerto {0:d}.", + "give_this_url_stealth": "Dale esta dirección y la línea de HidServAuth a la persona a la que le estás enviando el archivo:", + "no_available_port": "No se pudo iniciar el servicio cebolla porque no había puerto disponible", + "close_on_timeout": "Parado porque el temporizador expiró", + "timeout_download_still_running": "Esperando a que se complete la descarga", + "large_filesize": "Advertencia: Enviar un archivo tan grande podría llevar horas", + "help_shutdown_timeout": "Dejar de compartir después de una determinada cantidad de segundos", + "help_stealth": "Usar autorización de cliente (avanzada)", + "help_config": "Ubicación del archivo de configuración JSON personalizado (opcional)", + "gui_copied_url_title": "Dirección de OnionShare copiada", + "gui_copied_hidservauth": "Línea HidServAuth copiada al portapapeles", + "gui_please_wait": "Comenzando.... Haz clic para cancelar.", + "gui_quit_title": "No tan rápido", + "error_rate_limit": "Alguien ha hecho demasiados intentos equivocados en tu dirección, lo que significa que podrían estar intentando adivinarlo, así que OnionShare ha detenido el servidor. Comienza a compartir de nuevo y envía al destinatario la nueva dirección para compartir.", + "zip_progress_bar_format": "Comprimiendo: %p%", + "error_stealth_not_supported": "Para crear servicios de cebolla sigilosos, necesitas al menos Tor 0.2.9.1-alfa (o Navegador Tor 6.5) y python3-stem 1.5.0.", + "error_ephemeral_not_supported": "OnionShare requiere al menos Tor 0.2.7.1 y al menos python3-stem 1.4.0.", + "gui_settings_window_title": "Configuración", + "gui_settings_stealth_option": "Utilizar la autorización del cliente (antigua)", + "gui_settings_stealth_hidservauth_string": "Después de haber guardado su clave privada para volver a utilizarla, ahora puedes\nhacer clic para copiar tu HidServAuth.", + "gui_settings_autoupdate_label": "Control para versión nueva", + "gui_settings_autoupdate_option": "Notificarme cuando haya una nueva versión disponible", + "gui_settings_autoupdate_check_button": "Buscar una Nueva Versión", + "gui_settings_connection_type_bundled_option": "Use la versión Tor incorporada en OnionShare", + "gui_settings_connection_type_automatic_option": "Intentar la autoconfiguración con el Navegador Tor", + "gui_settings_connection_type_test_button": "Probar la conexión a Tor", + "gui_settings_tor_bridges": "Soporte de puentes de Tor", + "gui_settings_tor_bridges_invalid": "Ninguno de los puentes que has añadido funciona.\nVuelve a verificarlos o añade otros.", + "settings_saved": "Ajustes guardados en {}", + "give_this_url_receive": "Dale esta dirección al remitente:", + "give_this_url_receive_stealth": "Dar esta dirección y HidServAuth al remitente:", + "not_a_readable_file": "{0:s} no es un archivo legible.", + "systray_menu_exit": "Salir", + "systray_download_started_title": "Iniciada la descarga de OnionShare", + "systray_download_started_message": "Alguien comenzó a descargar tus archivos", + "systray_download_completed_title": "Descarga de OnionShare finalizada", + "systray_download_completed_message": "Alguien ha terminado de descargar tus archivos", + "systray_download_canceled_title": "Descarga de OnionShare Cancelada", + "systray_download_canceled_message": "El usuario canceló la descarga", + "systray_upload_started_title": "Subida OnionShare Iniciada", + "systray_upload_started_message": "Un usuario comenzó a subir archivos a tu computadora", + "help_receive": "Recibir recursos compartidos en lugar de enviarlos", + "gui_share_stop_server_shutdown_timeout": "Dejar de Compartir ({}s restantes)", + "gui_share_stop_server_shutdown_timeout_tooltip": "El temporizador de parada automática termina en {}", + "gui_receive_start_server": "Iniciar el modo de recepción", + "gui_receive_stop_server": "Detener el modo de recepción", + "gui_receive_stop_server_shutdown_timeout": "Detener el modo de recepción ({}s restantes)", + "gui_receive_stop_server_shutdown_timeout_tooltip": "El temporizador de parada automática termina en {}", + "gui_copy_hidservauth": "Copiar HidServAuth", + "gui_no_downloads": "Ninguna Descarga Todavía", + "gui_canceled": "Cancelado", + "gui_copied_hidservauth_title": "Se ha copiado el token de HidServAuth", + "settings_error_unknown": "No se puede conectar al controlador Tor porque la configuración no tiene sentido.", + "settings_error_automatic": "No se puede conectar al controlador Tor. ¿Se está ejecutando el Navegador Tor (disponible en https://www.torproject.org/) en segundo plano?", + "settings_error_socket_port": "No se puede conectar al controlador Tor en {}:{}.", + "settings_error_socket_file": "No se puede conectar al controlador Tor usando el archivo de socket {}.", + "settings_error_auth": "Conectado a {}:{}, pero no se puede autentificar. ¿Quizás este no sea un controlador Tor?", + "settings_error_missing_password": "Conectado al controlador Tor, pero requiere una contraseña para autenticarse.", + "settings_error_unreadable_cookie_file": "Conectado al controlador Tor, pero no puedo autenticarme porque la contraseña parece estar equivocada, y tu usuario no tiene permiso para leer el archivo cookie.", + "settings_error_bundled_tor_not_supported": "Bundled Tor no sepuede usar si no se usa el modo de desarrollo en Windows o macOS.", + "settings_error_bundled_tor_timeout": "Conectarse con Tor está llevando demasiado tiempo. ¿Quizás el equipo está desconectado, o el reloj no está en hora?", + "settings_error_bundled_tor_broken": "OnionShare no pudo conectarse a Tor en segundo plano:\n{}", + "settings_test_success": "Conectado al *Tor controlador.\n\n*Tor Versión: {}\nSoporte servicios de cebolla efímeros: {}.\nAutentificación de cliente de los soportes: {}.\nSoporte direcciones de cebolla de nueva generación: {}.", + "error_tor_protocol_error": "Hubo un error con Tor: {}", + "error_tor_protocol_error_unknown": "Hubo un error desconocido con Tor", + "error_invalid_private_key": "Este tipo de clave privada no es compatible", + "connecting_to_tor": "Conexión a la red Tor", + "update_available": "Hay un nuevo OnionShare. Haz clic aquí para obtenerlo.

Br>Estás usando {} y el último es {}.", + "update_error_check_error": "No se han podido comprobar las nuevas versiones: El sitio web de OnionShare dice que la última versión es la irreconocible '{}'.…", + "update_error_invalid_latest_version": "No se ha podido comprobar la nueva versión: ¿Quizás no estás conectado a Tor, o el sitio web de OnionShare está caído?", + "update_not_available": "Estás ejecutando la última versión de OnionShare.", + "gui_tor_connection_ask": "Abrir la configuración para arrreglar la conexión a Tor?", + "gui_tor_connection_ask_open_settings": "sí", + "gui_tor_connection_ask_quit": "Salir", + "gui_tor_connection_error_settings": "Intenta cambiando la forma en que OnionShare se conecta a la red Tor en tu configuración.", + "gui_tor_connection_canceled": "No se pudo conectar con Tor.\n\nAsegúrate de estar conectado a Internet, luego vuelve a abrir OnionShare y configura tu conexión a Tor.", + "gui_tor_connection_lost": "Desconectado de Tor.", + "gui_server_started_after_timeout": "El temporizador de parada automática se agotó antes de que se iniciara el servidor.\nPor favor, haz una nueva porción.", + "gui_server_timeout_expired": "El temporizador de parada automática ya se ha agotado.\nPor favor, actualízalo para comenzar a compartir.", + "share_via_onionshare": "Compártelo con OnionShare", + "gui_use_legacy_v2_onions_checkbox": "Usar direcciones de legado", + "gui_save_private_key_checkbox": "Usar una dirección persistente (legado)", + "gui_share_url_description": "Cualquier persona con esta dirección de OnionShare puede descargar tus archivos usando el Tor Browser: ", + "gui_receive_url_description": "Con esta dirección de OnionShare, cualquier persona puede subir archivos a tu ordenador usando el Tor Browser: ", + "gui_url_label_persistent": "Este recurso compartido no se detendrá automáticamente.

Cada recurso compartido subsiguiente reutilizará la dirección. (Para usar direcciones una sola vez, desactiva la opción \"Usar dirección persistente\" en los ajustes.)", + "gui_url_label_stay_open": "Este recurso compartido no se detendrá automáticamente.", + "gui_url_label_onetime": "Este recurso compartido se detendrá después de la primera descarga.", + "gui_url_label_onetime_and_persistent": "Este recurso compartido no se detendrá automáticamente.

Cada recurso compartido subsiguiente reutilizará la dirección. (Para usar direcciones una sola vez, desactiva la opción \"Usar dirección persistente\" en los ajustes.)", + "gui_status_indicator_share_stopped": "Listo para compartir", + "gui_status_indicator_share_working": "Comenzando.…", + "gui_status_indicator_share_started": "Compartir", + "gui_status_indicator_receive_stopped": "Listo para recibir", + "gui_status_indicator_receive_working": "Comenzando.…", + "gui_status_indicator_receive_started": "Recibiendo", + "gui_file_info": "{} archivos, {}", + "gui_file_info_single": "{} archivo, {}", + "info_in_progress_downloads_tooltip": "{} descarga(s) en curso", + "info_completed_downloads_tooltip": "{} descarga(s) completada(s)", + "info_in_progress_uploads_tooltip": "{} subida(s) en curso", + "info_completed_uploads_tooltip": "{} subida(s) completada(s)", + "receive_mode_downloads_dir": "Los archivos enviados a ti aparecen en esta carpeta: {}", + "receive_mode_warning": "Advertencia: El modo de recepción permite a la gente subir archivos a su ordenador. Algunos archivos, si los abres, podrían tomar el control de tu ordenador. Abre sólo cosas de personas en las que confíes, o si sabes lo que estás haciendo.", + "gui_download_upload_progress_complete": "%p%, {0:s} transcurrido.", + "gui_download_upload_progress_starting": "{0:s}, %p% (calculando)", + "gui_download_upload_progress_eta": "{0:s}, tiempo restante: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_share_quit_warning": "Estás enviando archivos. ¿Quieres realmente cerrar OnionShare?", + "gui_quit_warning_quit": "Salir", + "gui_quit_warning_dont_quit": "Cancelar", + "gui_settings_whats_this": "¿Qué es esto?", + "gui_settings_autoupdate_timestamp": "Última comprobación: {}", + "gui_settings_autoupdate_timestamp_never": "Nunca", + "gui_settings_general_label": "Ajustes generales", + "gui_settings_sharing_label": "Configuración de uso compartido", + "gui_settings_close_after_first_download_option": "Dejar de compartir después de la primera descarga", + "gui_settings_connection_type_label": "¿Cómo debería conectarse OnionShare a Tor?", + "gui_settings_connection_type_control_port_option": "Conectar usando el puerto de control", + "gui_settings_connection_type_socket_file_option": "Conectar usando archivo de socket", + "gui_settings_control_port_label": "Puerto de control", + "gui_settings_socket_file_label": "Archivo Socket", + "gui_settings_socks_label": "Puerto SOCKS", + "gui_settings_authenticate_label": "Configuración de autenticación Tor", + "gui_settings_authenticate_no_auth_option": "Sin autenticación, o autenticación por cookies", + "gui_settings_authenticate_password_option": "Contraseña", + "gui_settings_password_label": "Contraseña", + "gui_settings_tor_bridges_no_bridges_radio_option": "No usar puentes", + "gui_receive_quit_warning": "Estás recibiendo archivos. ¿Quieres cerrar OnionShare igualmente?", + "gui_settings_tor_bridges_obfs4_radio_option": "Usar transportes enchufables obfs4 incorporados", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Usar transportes enchufables obfs4 incorporados (requiere obfs4proxy)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Utilizar transporte enchufable incorporado meek_lite (Azure)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Usar transporte enchufable meek_lite (Azure) incorporado (requiere obfs4proxy)", + "gui_settings_meek_lite_expensive_warning": "Advertencia: Los puentes meek_lite son caros para el Proyecto Tor.

Úsalos sólo si no puedes conectarte a Tor directamente, a través de transportes obfs4, u otros puentes normales.", + "gui_settings_tor_bridges_custom_radio_option": "Usar puentes personalizados", + "gui_settings_tor_bridges_custom_label": "Puedes obtener puentes en https://bridges.torproject.org", + "gui_settings_button_save": "Guardar", + "gui_settings_button_cancel": "Cancelar", + "gui_settings_button_help": "Ayuda", + "gui_settings_shutdown_timeout_checkbox": "Usar temporizador de parada automática", + "gui_settings_shutdown_timeout": "Detener el compartir en:", + "history_in_progress_tooltip": "{} En progreso", + "history_completed_tooltip": "{} completado", + "error_cannot_create_downloads_dir": "No se ha podido crear la carpeta del modo de recepción: {}", + "error_downloads_dir_not_writable": "La carpeta del modo de recepción está protegida contra escritura: {}", + "gui_receive_mode_warning": "El modo de recepción permite a la gente subir archivos a su ordenador.


Algunos archivos pueden potencialmente tomar el control de su ordenador si usted los abre. Sólo abra cosas de personas en las que confíe, o si sabe lo que está haciendo.", + "receive_mode_upload_starting": "La carga del tamaño total {} está comenzando", + "receive_mode_received_file": "Recibido: {}", + "gui_mode_share_button": "Compartir archivos", + "gui_mode_receive_button": "Recibir archivos", + "gui_settings_receiving_label": "Ajustes de recepción", + "gui_settings_downloads_label": "Guardar archivos en", + "gui_settings_downloads_button": "Examinar", + "gui_settings_public_mode_checkbox": "Modo público", + "systray_close_server_title": "Servidor OnionShare cerrado", + "systray_close_server_message": "Un usuario cerró el servidor", + "systray_page_loaded_title": "Página de OnionShare Cargada", + "systray_download_page_loaded_message": "Un usuario cargó la página de descarga", + "systray_upload_page_loaded_message": "Un usuario cargó la página de carga", + "gui_uploads": "Historial de carga", + "gui_no_uploads": "No hay subidas todavía", + "gui_clear_history": "Limpiar todo", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "El modo de recepción puede ser detenido por el remitente", + "gui_upload_in_progress": "Subida Iniciada {}", + "gui_upload_finished": "Subido {}", + "gui_download_in_progress": "Descarga iniciada {}", + "gui_open_folder_error_nautilus": "No se puede abrir la carpeta porque nautilus no está disponible. El archivo está aquí: {}", + "gui_settings_language_label": "Idioma preferido", + "gui_settings_language_changed_notice": "Reinicia OnionShare para que el cambio de idioma surta efecto.", + "gui_upload_finished_range": "Cargado {} a {}" } diff --git a/share/locale/fr.json b/share/locale/fr.json index ee206662..eecf1481 100644 --- a/share/locale/fr.json +++ b/share/locale/fr.json @@ -1,34 +1,158 @@ { - "preparing_files": "Préparation des fichiers à partager.", - "give_this_url": "Donnez cette URL à la personne qui doit recevoir le fichier :", - "ctrlc_to_stop": "Ctrl-C arrête le serveur", - "not_a_file": "{0:s} n'est pas un fichier.", - "other_page_loaded": "URL chargée", - "closing_automatically": "Fermeture automatique car le téléchargement est fini", + "preparing_files": "Compression des fichiers.", + "give_this_url": "Donnez cette adresse au destinataire :", + "ctrlc_to_stop": "Appuyez sur Ctrl+c pour arrêter le serveur", + "not_a_file": "{0:s} n'est pas un fichier valide.", + "other_page_loaded": "Adresse chargée", + "closing_automatically": "Arrêt automatique car le téléchargement est fini", "systray_menu_exit": "Quitter", - "systray_download_started_title": "Téléchargement OnionShare Démarré", + "systray_download_started_title": "Téléchargement OnionShare démarré", "systray_download_started_message": "Un utilisateur télécharge vos fichiers", - "systray_download_completed_title": "Téléchargement OnionShare Complete", - "systray_download_canceled_title": "Téléchargement OnionShare Annulé", + "systray_download_completed_title": "Téléchargement OnionShare terminé", + "systray_download_canceled_title": "Téléchargement OnionShare annulé", "systray_download_canceled_message": "L'utilisateur a annulé le téléchargement", - "help_local_only": "Ne tentez pas d'utiliser Tor, uniquement pour développement", - "help_stay_open": "Laisser tourner le onion service après que le téléchargment soit fini", - "help_debug": "Enregistrer les erreurs sur le disque", + "help_local_only": "Ne pas utiliser Tor (uniquement pour le développement)", + "help_stay_open": "Continuer le partage après le premier téléchargement", + "help_debug": "Enregistrer les erreurs OnionShare sur la sortie standard, et les erreurs web sur le disque", "help_filename": "Liste des fichiers ou dossiers à partager", "gui_drag_and_drop": "Glissez déposez\nles fichiers ici", "gui_add": "Ajouter", "gui_delete": "Supprimer", "gui_choose_items": "Sélectionnez", - "gui_share_start_server": "Démarrer le serveur", - "gui_share_stop_server": "Arrêter le serveur", - "gui_copy_url": "Copier URL", + "gui_share_start_server": "Commencer à partager", + "gui_share_stop_server": "Arrêter le partage", + "gui_copy_url": "Copier l'adresse", "gui_copy_hidservauth": "Copier HidServAuth", - "gui_downloads": "Téléchargements :", + "gui_downloads": "Historique de téléchargement", "gui_canceled": "Annulé", - "gui_copied_url": "URL copié dans le presse-papier", - "gui_please_wait": "Attendez-vous...", + "gui_copied_url": "Adresse OnionShare copiée dans le presse-papiers", + "gui_please_wait": "Démarrage… Cliquez pour annuler.", "gui_quit_warning_quit": "Quitter", - "gui_quit_warning_dont_quit": "Ne quitter pas", + "gui_quit_warning_dont_quit": "Annuler", "gui_settings_autoupdate_timestamp_never": "Jamais", - "gui_settings_language_changed_notice": "Redémarrez OnionShare pour que votre changement de langue prenne effet" + "gui_settings_language_changed_notice": "Redémarrez OnionShare pour que votre changement de langue prenne effet.", + "config_onion_service": "Mise en place du service oignon sur le port {0:d}.", + "give_this_url_stealth": "Donnez cette adresse et cette ligne HidServAuth au destinataire :", + "give_this_url_receive": "Donnez cette adresse à l'expéditeur :", + "give_this_url_receive_stealth": "Donnez cette adresse et HidServAuth à l'expéditeur :", + "not_a_readable_file": "{0:s} n'est pas un fichier lisible.", + "timeout_download_still_running": "En attente de la fin du téléchargement", + "systray_download_completed_message": "L'utilisateur a terminé de télécharger vos fichiers", + "gui_copied_hidservauth_title": "HidServAuth copié", + "gui_settings_window_title": "Paramètres", + "gui_settings_autoupdate_timestamp": "Dernière vérification : {}", + "gui_settings_close_after_first_download_option": "Arrêt du partage après le premier téléchargement", + "gui_settings_connection_type_label": "Comment OnionShare doit se connecter à Tor ?", + "gui_settings_connection_type_control_port_option": "Se connecter avec le port de contrôle", + "gui_settings_connection_type_socket_file_option": "Se connecter à l'aide d'un fichier socket", + "gui_settings_socket_file_label": "Fichier socket", + "gui_settings_socks_label": "Port SOCKS", + "gui_settings_authenticate_no_auth_option": "Pas d'authentification ou authentification par cookie", + "gui_settings_authenticate_password_option": "Mot de passe", + "gui_settings_password_label": "Mot de passe", + "gui_settings_tor_bridges_no_bridges_radio_option": "Ne pas utiliser de bridge", + "gui_settings_button_save": "Sauvegarder", + "gui_settings_button_cancel": "Annuler", + "gui_settings_button_help": "Aide", + "gui_settings_shutdown_timeout": "Arrêter le partage à :", + "connecting_to_tor": "Connexion au réseau Tor", + "help_config": "Emplacement du fichier de configuration JSON personnalisé (optionnel)", + "large_filesize": "Avertissement : envoyer un gros fichier peut prendre plusieurs heures", + "gui_copied_hidservauth": "Ligne HidServAuth copiée dans le presse-papiers", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "zip_progress_bar_format": "Compression : %p%", + "error_ephemeral_not_supported": "OnionShare nécessite au moins Tor 0.2.7.1 et python3-stem 1.4.0.", + "help_shutdown_timeout": "Arrêter le partage après un certain nombre de secondes", + "gui_tor_connection_error_settings": "Essayez de modifier dans les paramètres la façon dont OnionShare se connecte au réseau Tor.", + "no_available_port": "Impossible de trouver un port disponible pour démarrer le service oignon", + "gui_share_stop_server_shutdown_timeout": "Arrêter le partage ({}s restantes)", + "systray_upload_started_title": "Envoi OnionShare démarré", + "systray_upload_started_message": "Une personne a commencé à envoyer des fichiers vers votre ordinateur", + "gui_no_downloads": "Pas encore de téléchargements", + "gui_copied_url_title": "Adresse OnionShare copiée", + "gui_quit_title": "Pas si vite", + "gui_share_quit_warning": "Vous êtes en train d'envoyer des fichiers. Voulez-vous vraiment quitter OnionShare ?", + "gui_receive_quit_warning": "Vous êtes en train de recevoir des fichiers. Voulez-vous vraiment quitter OnionShare ?", + "gui_settings_whats_this": "Qu'est-ce que c'est ?", + "gui_settings_autoupdate_label": "Rechercher des mises à jour", + "gui_settings_autoupdate_option": "Me notifier lorsque des mises à jour sont disponibles", + "gui_settings_general_label": "Paramètres généraux", + "gui_settings_sharing_label": "Paramètres de partage", + "gui_settings_connection_type_bundled_option": "Utiliser la version de Tor inclue dans OnionShare", + "gui_settings_connection_type_automatic_option": "Essayer la configuration automatique avec le navigateur Tor", + "gui_settings_connection_type_test_button": "Tester la connexion à Tor", + "gui_settings_control_port_label": "Port de contrôle", + "gui_settings_authenticate_label": "Paramètres d'authentification de Tor", + "gui_settings_tor_bridges": "Support des bridges Tor", + "gui_settings_tor_bridges_custom_radio_option": "Utiliser des bridges personnalisés", + "gui_settings_tor_bridges_custom_label": "Vous pouvez obtenir des bridges à l'adresse https://bridges.torproject.org", + "gui_settings_tor_bridges_invalid": "Aucun des bridges que vous avez ajouté ne fonctionne.\nVérifiez les à nouveau ou ajoutez-en d'autres.", + "settings_error_unknown": "Impossible de se connecter au contrôleur Tor car les paramètres n'ont pas de sens.", + "settings_error_automatic": "Impossible de se connecter au contrôleur Tor. Est-ce que le navigateur Tor (disponible sur torproject.org) fonctionne en arrière-plan ?", + "settings_error_socket_port": "Impossible de se connecter au contrôleur Tor à {}:{}.", + "settings_error_socket_file": "Impossible de se connecter au contrôleur Tor en utilisant le fichier socket {}.", + "settings_error_auth": "Connecté à {}:{} mais impossible de s'authentifier. Peut-être que ce n'est pas un contrôleur Tor ?", + "settings_error_missing_password": "Connecté au contrôleur Tor mais il demande un mot de passe pour s'authentifier.", + "settings_error_unreadable_cookie_file": "Connecté au contrôleur Tor, mais le mot de passe est peut-être faux ou l'utilisateur n'a pas la permission de lire le fichier cookie.", + "settings_error_bundled_tor_not_supported": "L'utilisation de la version de Tor inclue avec OnionShare ne marche pas dans le mode développement sous Windows ou macOS.", + "settings_error_bundled_tor_timeout": "La connexion à Tor prend trop de temps. Peut-être qu'il n'y a pas de connexion à Internet ou que l'horloge système est inexacte ?", + "settings_error_bundled_tor_broken": "OnionShare n'a pas pu se connecter à Tor en arrière-plan :\n{}", + "error_tor_protocol_error": "Il y a eu une erreur avec Tor : {}", + "error_tor_protocol_error_unknown": "Il y a eu une erreur inconnue avec Tor", + "error_invalid_private_key": "Ce type de clé privée n'est pas supporté", + "update_available": "Une nouvelle version de OnionShare est disponible. Cliquez ici pour l'obtenir.

Vous utilisez actuellement la version {} et la dernière version est la {}.", + "update_not_available": "Vous utilisez la dernière version d'OnionShare.", + "gui_tor_connection_ask_open_settings": "Oui", + "gui_tor_connection_ask_quit": "Quitter", + "gui_tor_connection_lost": "Déconnecté de Tor.", + "share_via_onionshare": "Partager via OnionShare", + "gui_save_private_key_checkbox": "Utiliser une adresse persistante (legacy)", + "gui_share_url_description": "Avec cette adresse OnionShare n'importe qui peut télécharger vos fichiers en utilisant le navigateur Tor : ", + "gui_receive_url_description": "Avec cette adresse OnionShare n'importe qui peut envoyer des fichiers vers votre ordinateur en utilisant le navigateur Tor : ", + "gui_url_label_persistent": "Ce partage ne s'arrêtera pas automatiquement.

Tous les partages suivants réutiliseront l'adresse. (Pour utiliser des adresses uniques, désactivez \"Utiliser une adresse persistante\" dans les paramètres.)", + "gui_url_label_stay_open": "Ce partage ne s'arrêtera pas automatiquement.", + "gui_url_label_onetime": "Ce partage s'arrêtera après le premier téléchargement complété.", + "gui_url_label_onetime_and_persistent": "Ce partage ne s'arrêtera pas automatiquement.

Tous les partages suivants devraient réutiliser l'adresse. (Pour utiliser des adresses uniques, désactivez \"Utiliser une adresse persistante\" dans les paramètres.)", + "gui_status_indicator_share_stopped": "Prêt à partager", + "gui_status_indicator_share_working": "Démarrage…", + "gui_status_indicator_share_started": "Partage", + "gui_status_indicator_receive_stopped": "Prêt à recevoir", + "gui_status_indicator_receive_working": "Démarrage…", + "gui_status_indicator_receive_started": "Réception", + "gui_file_info": "{} fichiers, {}", + "gui_file_info_single": "{} fichier, {}", + "history_in_progress_tooltip": "{} en cours", + "history_completed_tooltip": "{} terminé", + "receive_mode_downloads_dir": "Les fichiers qui vous sont envoyés apparaissent dans ce dossier : {}", + "receive_mode_warning": "Avertissement : le mode réception permet à des personnes d'envoyer des fichiers vers votre ordinateur. Certains fichiers peuvent potentiellement prendre le contrôle de votre ordinateur si vous les ouvrez. Ouvrez uniquement des choses provenant de personnes de confiance ou si vous savez ce que vous faites.", + "gui_receive_mode_warning": "Le mode réception permet à des personnes d'envoyer des fichiers vers votre ordinateur.

Certains fichiers peuvent potentiellement prendre le contrôle de votre ordinateur si vous les ouvrez. Ouvrez uniquement des choses provenant de personnes de confiance ou si vous savez ce que vous faites.", + "receive_mode_received_file": "Reçu : {}", + "gui_mode_share_button": "Fichiers partagés", + "gui_mode_receive_button": "Fichiers reçus", + "gui_settings_receiving_label": "Paramètres de réception", + "gui_settings_downloads_label": "Enregistrer les fichiers sous", + "gui_settings_downloads_button": "Parcourir", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "Le mode réception peut-être arrêté par l'expéditeur", + "gui_settings_public_mode_checkbox": "Mode public", + "systray_close_server_title": "Serveur OnionShare arrêté", + "gui_uploads": "Historique d'envoi", + "gui_no_uploads": "Pas encore d'envoi", + "gui_clear_history": "Tout effacer", + "gui_upload_in_progress": "Envoi démarré {}", + "gui_upload_finished_range": "Envoyé {} de {}", + "gui_upload_finished": "{} envoyé", + "gui_download_in_progress": "Téléchargement démarré {}", + "gui_open_folder_error_nautilus": "Impossible d'ouvrir le dossier car nautilus n'est pas disponible. Le fichier est ici : {}", + "gui_settings_language_label": "Langue préférée", + "help_stealth": "Utilisation de l'autorisation client (avancé)", + "help_receive": "Recevoir des partages au lieu de les envoyer", + "gui_receive_start_server": "Démarrer le mode réception", + "gui_receive_stop_server": "Arrêter le mode réception", + "gui_receive_stop_server_shutdown_timeout": "Arrêter le mode réception ({}s restantes)", + "gui_download_upload_progress_complete": "%p%, {0:s} écoulées.", + "gui_download_upload_progress_starting": "{0:s}, %p% (estimation)", + "gui_download_upload_progress_eta": "{0:s}, Fin : {1:s}, %p%", + "error_rate_limit": "Une personne a effectué sur votre adresse beaucoup de tentatives qui ont échouées, ce qui veut dire qu'elle essayait de la deviner, ainsi OnionShare a arrêté le serveur. Démarrez le partage à nouveau et envoyez une nouvelle adresse au destinataire pour pouvoir partager.", + "error_stealth_not_supported": "Pour utiliser l’autorisation client, vous avez besoin d'au moins Tor 0.2.9.1-alpha (ou le navigateur Tor 6.5) et python3-stem 1.5.0.", + "gui_settings_stealth_option": "Utiliser l'autorisation client (legacy)" } diff --git a/share/locale/ga.json b/share/locale/ga.json new file mode 100644 index 00000000..114661d2 --- /dev/null +++ b/share/locale/ga.json @@ -0,0 +1,185 @@ +{ + "config_onion_service": "Seirbhís onion á shocrú ar phort {0:d}.", + "preparing_files": "Comhaid á gcomhbhrú.", + "give_this_url": "Tabhair an seoladh seo don fhaighteoir:", + "give_this_url_stealth": "Tabhair an seoladh seo agus an líne HidServAuth seo don fhaighteoir:", + "give_this_url_receive": "Tabhair an seoladh seo don seoltóir:", + "give_this_url_receive_stealth": "Tabhair an seoladh seo agus an líne HidServAuth seo don seoltóir:", + "ctrlc_to_stop": "Brúigh Ctrl+C chun stop a chur leis an bhfreastalaí", + "not_a_file": "Ní comhad bailí é {0:s}.", + "not_a_readable_file": "Ní comhad inléite é {0:s}.", + "no_available_port": "Níorbh fhéidir port a aimsiú chun an tseirbhís onion a thosú", + "other_page_loaded": "Seoladh lódáilte", + "close_on_timeout": "Cuireadh stop leis toisc go bhfuil an t-amadóir caite", + "closing_automatically": "Cuireadh stop leis toisc go bhfuil an íoslódáil críochnaithe", + "timeout_download_still_running": "Ag fanacht go gcríochnódh an íoslódáil", + "large_filesize": "Rabhadh: D'fhéadfadh go dtógfadh sé tamall fada comhad mór a sheoladh", + "systray_menu_exit": "Scoir", + "systray_download_started_title": "Tosaíodh Íoslódáil OnionShare", + "systray_download_started_message": "Thosaigh úsáideoir ag íoslódáil do chuid comhad", + "systray_download_completed_title": "Críochnaíodh Íoslódáil OnionShare", + "systray_download_completed_message": "Tá do chuid comhad íoslódáilte ag an úsáideoir", + "systray_download_canceled_title": "Cuireadh Íoslódáil OnionShare ar ceal", + "systray_download_canceled_message": "Chuir an t-úsáideoir an íoslódáil ar ceal", + "systray_upload_started_title": "Tosaíodh Uaslódáil OnionShare", + "systray_upload_started_message": "Thosaigh úsáideoir ag uaslódáil comhad go dtí do ríomhaire", + "help_local_only": "Ná húsáid Tor (tástáil amháin)", + "help_stay_open": "Lean ort ag comhroinnt tar éis an chéad íoslódáil", + "help_shutdown_timeout": "Stop ag comhroinnt tar éis líon áirithe soicindí", + "help_stealth": "Úsáid údarú cliaint (ardleibhéal)", + "help_receive": "Glac le comhaid chomhroinnte in áit iad a sheoladh", + "help_debug": "Déan tuairisc ar earráidí OnionShare ar stdout, agus earráidí Gréasáin ar an diosca", + "help_filename": "Liosta comhad nó fillteán le comhroinnt", + "help_config": "Suíomh saincheaptha don chomhad cumraíochta JSON (roghnach)", + "gui_drag_and_drop": "Tarraing agus scaoil comhaid agus fillteáin\nchun iad a chomhroinnt", + "gui_add": "Cuir Leis", + "gui_delete": "Scrios", + "gui_choose_items": "Roghnaigh", + "gui_share_start_server": "Comhroinn", + "gui_share_stop_server": "Stop ag comhroinnt", + "gui_share_stop_server_shutdown_timeout": "Stop ag Comhroinnt ({}s fágtha)", + "gui_share_stop_server_shutdown_timeout_tooltip": "Amadóir uathstoptha caite {}", + "gui_receive_start_server": "Tosaigh an Mód Glactha", + "gui_receive_stop_server": "Stop an Mód Glactha", + "gui_receive_stop_server_shutdown_timeout": "Stop an Mód Glactha ({}s fágtha)", + "gui_receive_stop_server_shutdown_timeout_tooltip": "Amadóir uathstoptha caite {}", + "gui_copy_url": "Cóipeáil an Seoladh", + "gui_copy_hidservauth": "Cóipeáil HidServAuth", + "gui_downloads": "Stair Íoslódála", + "gui_no_downloads": "Níl aon rud íoslódáilte agat fós", + "gui_canceled": "Curtha ar ceal", + "gui_copied_url_title": "Cóipeáladh an Seoladh OnionShare", + "gui_copied_url": "Cóipeáladh an seoladh OnionShare go dtí an ghearrthaisce", + "gui_copied_hidservauth_title": "Cóipeáladh HidServAuth", + "gui_copied_hidservauth": "Cóipeáladh an líne HidServAuth go dtí an ghearrthaisce", + "gui_please_wait": "Ag tosú... Cliceáil lena chur ar ceal.", + "gui_download_upload_progress_complete": "%[%, {0:s} caite.", + "gui_download_upload_progress_starting": "{0:s}, %p% (á áireamh)", + "gui_download_upload_progress_eta": "{0:s}, am teachta measta: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_quit_title": "Fan soic", + "gui_share_quit_warning": "Tá tú le linn roinnt comhad a sheoladh. An bhfuil tú cinnte gur mhaith leat OnionShare a scor?", + "gui_receive_quit_warning": "Tá tú le linn roinnt comhad a íoslódáil. An bhfuil tú cinnte gur mhaith leat OnionShare a scor?", + "gui_quit_warning_quit": "Scoir", + "gui_quit_warning_dont_quit": "Cealaigh", + "error_rate_limit": "Rinne duine éigin an iomarca iarrachtaí míchearta ar do sheoladh, agus dá bharr sin stop OnionShare an freastalaí. Tosaigh ag comhroinnt arís agus cuir seoladh nua chuig an bhfaighteoir.", + "zip_progress_bar_format": "Á chomhbhrú: %p%", + "error_stealth_not_supported": "Chun údarú cliaint a úsáid, teastaíonn uait Tor 0.2.9.1-alpha (nó Brabhsálaí 6.5) agus python3-stem 1.5.0.", + "error_ephemeral_not_supported": "Teastaíonn uait ar a laghad Tor 0.2.7.1 agus python3-stem 1.4.0 chun OnionShare a úsáid.", + "gui_settings_window_title": "Socruithe", + "gui_settings_whats_this": "Cad é seo", + "gui_settings_stealth_option": "Úsáid údarú cliaint (seanleagan)", + "gui_settings_stealth_hidservauth_string": "Toisc gur shábháil tú d'eochair phríobháideach, anois is féidir leat\ncliceáil chun an HidServAuth a chóipeáil.", + "gui_settings_autoupdate_label": "Lorg nuashonruithe", + "gui_settings_autoupdate_option": "Cuir in iúl dom nuair a bheidh leagan nua ar fáil", + "gui_settings_autoupdate_timestamp": "Seiceáilte: {}", + "gui_settings_autoupdate_timestamp_never": "Níor seiceáladh riamh", + "gui_settings_autoupdate_check_button": "Lorg Nuashonrú", + "gui_settings_general_label": "Socruithe ginearálta", + "gui_settings_sharing_label": "Socruithe comhroinnte", + "gui_settings_close_after_first_download_option": "Stop ag comhroinnt tar éis an chéad íoslódáil", + "gui_settings_connection_type_label": "Cén chaoi ar chóir do OnionShare ceangal le Tor?", + "gui_settings_connection_type_bundled_option": "Úsáid an leagan de Tor ionsuite in OnionShare", + "gui_settings_connection_type_automatic_option": "Déan cumraíocht uathoibríoch le Brabhsálaí Tor", + "gui_settings_connection_type_control_port_option": "Ceangal trí phort rialaithe", + "gui_settings_connection_type_socket_file_option": "Ceangal trí chomhad soicéid", + "gui_settings_connection_type_test_button": "Tástáil an Ceangal le Tor", + "gui_settings_control_port_label": "Port rialaithe", + "gui_settings_socket_file_label": "Comhad soicéid", + "gui_settings_socks_label": "Port SOCKS", + "gui_settings_authenticate_label": "Socruithe fíordheimhnithe Tor", + "gui_settings_authenticate_no_auth_option": "Gan fíordheimhniú, nó fíordheimhniú le fianán", + "gui_settings_authenticate_password_option": "Focal faire", + "gui_settings_password_label": "Focal faire", + "gui_settings_tor_bridges": "Tacaíocht do dhroichid Tor", + "gui_settings_tor_bridges_no_bridges_radio_option": "Ná húsáid droichid", + "gui_settings_tor_bridges_obfs4_radio_option": "Bain úsáid as córais iompair ionphlugáilte ionsuite obfs4", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Bain úsáid as córais iompair ionphlugáilte ionsuite obfs4 (obfs4proxy de dhíth)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Bain úsáid as córais iompair ionphlugáilte ionsuite meek_lite(Azure)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Bain úsáid as córais iompair ionphlugáilte ionsuite meek_lite (Azure) (obfs4proxy de dhíth)", + "gui_settings_meek_lite_expensive_warning": "Rabhadh: Tá sé an-chostasach ar Thionscadal Tor na droichid meek_lite a chur ar fáil.

Iarraimid ort gan iad a úsáid má tá tú in ann ceangal díreach a bhunú le Tor, nó trí chóras iompair obfs4, nó trí dhroichead eile.", + "gui_settings_tor_bridges_custom_radio_option": "Úsáid droichid shaincheaptha", + "gui_settings_tor_bridges_custom_label": "Is féidir leat droichid a fháil ó https://bridges.torproject.org", + "gui_settings_tor_bridges_invalid": "Níl aon cheann de na droichid ag obair.\nSeiceáil arís iad, nó bain triail as droichid eile.", + "gui_settings_button_save": "Sábháil", + "gui_settings_button_cancel": "Cealaigh", + "gui_settings_button_help": "Cabhair", + "gui_settings_shutdown_timeout_checkbox": "Úsáid amadóir uathstoptha", + "gui_settings_shutdown_timeout": "Stop ag comhroinnt ag:", + "settings_error_unknown": "Ní féidir ceangal a bhunú leis an rialaitheoir Tor toisc nach féidir linn ciall a bhaint as na socruithe.", + "settings_error_automatic": "Níorbh fhéidir ceangal a bhunú leis an rialaitheoir Tor. An bhfuil Brabhsálaí Tor (ar fáil ó torproject.org) ag rith sa gcúlra?", + "settings_error_socket_port": "Ní féidir ceangal a bhunú leis an rialaitheoir Tor ag {}:{}.", + "settings_error_socket_file": "Ní féidir ceangal a bhunú leis an rialaitheoir Tor trí chomhad soicéid {}.", + "settings_error_auth": "Ceangailte le {}:{}, ach ní féidir an ceangal a fhíordheimhniú. B'fhéidir nach rialaitheoir Tor é seo?", + "settings_error_missing_password": "Ceangailte le rialaitheoir Tor, ach teastaíonn focal faire uaidh.", + "settings_error_unreadable_cookie_file": "Ceangailte le rialaitheoir Tor, ach seans go bhfuil an focal faire mícheart, nó níl cead ag an úsáideoir an comhad ina bhfuil na fianáin a léamh.", + "settings_error_bundled_tor_not_supported": "Ní féidir an leagan de Tor a thagann le OnionShare a úsáid sa mód forbartha ar Windows nó ar macOS.", + "settings_error_bundled_tor_timeout": "An iomarca ama ag ceangal le Tor. B'fhéidir nach bhfuil ceangailte leis an Idirlíon, nó nach bhfuil clog do chórais socraithe mar is ceart?", + "settings_error_bundled_tor_broken": "Níorbh fhéidir le OnionShare ceangal le Tor sa gcúlra:\n{}", + "settings_test_success": "Ceangailte leis an rialaitheoir Tor.\n\nLeagan de Tor: {}\nTacaíonn sé le seirbhísí onion gearrshaolacha: {}.\nTacaíonn sé le fíordheimhniú cliaint: {}.\nTacaíonn sé le seoltaí .onion den chéad ghlúin eile: {}.", + "error_tor_protocol_error": "Tharla earráid le Tor: {}", + "error_tor_protocol_error_unknown": "Tharla earráid anaithnid le Tor", + "error_invalid_private_key": "Ní thacaítear le heochair phríobháideach den sórt seo", + "connecting_to_tor": "Ag ceangal le líonra Tor", + "update_available": "Leagan nua de OnionShare ar fáil. Cliceáil anseo lena íoslódáil.

Tá {} agat agus is é {} an leagan is déanaí.", + "update_error_check_error": "Theip orainn nuashonruithe a lorg: Deir suíomh Gréasáin OnionShare gurb é '{}' an leagan is déanaí, leagan nach n-aithnímid…", + "update_error_invalid_latest_version": "Theip orainn nuashonruithe a lorg: B'fhéidir nach bhfuil ceangailte le Tor, nó nach bhfuil suíomh OnionShare ag obair faoi láthair?", + "update_not_available": "Tá an leagan is déanaí de OnionShare agat cheana.", + "gui_tor_connection_ask": "An bhfuil fonn ort na socruithe líonra a oscailt chun an fhadhb a réiteach?", + "gui_tor_connection_ask_open_settings": "Tá", + "gui_tor_connection_ask_quit": "Scoir", + "gui_tor_connection_error_settings": "Bain triail as na socruithe líonra a athrú chun ceangal le líonra Tor ó OnionShare.", + "gui_tor_connection_canceled": "Níorbh fhéidir ceangal a bhunú le Tor.\n\nDeimhnigh go bhfuil tú ceangailte leis an Idirlíon, ansin oscail OnionShare arís agus socraigh an ceangal le Tor.", + "gui_tor_connection_lost": "Dícheangailte ó Tor.", + "gui_server_started_after_timeout": "Bhí an t-amadóir uathstoptha caite sular thosaigh an freastalaí.\nCaithfidh tú comhroinnt nua a chruthú.", + "gui_server_timeout_expired": "Tá an t-amadóir uathstoptha caite cheana.\nCaithfidh tú é a athshocrú sular féidir leat comhaid a chomhroinnt.", + "share_via_onionshare": "Comhroinn trí OnionShare é", + "gui_use_legacy_v2_onions_checkbox": "Úsáid seoltaí sean-nóis", + "gui_save_private_key_checkbox": "Úsáid seoladh seasmhach (seanleagan)", + "gui_share_url_description": "Tá aon duine a bhfuil an seoladh OnionShare aige/aici in ann do chuid comhad a íoslódáil le Brabhsálaí Tor: ", + "gui_receive_url_description": "Tá aon duine a bhfuil an seoladh OnionShare aige/aici in ann comhaid a uaslódáil go dtí do ríomhaire le Brabhsálaí Tor: ", + "gui_url_label_persistent": "Ní stopfaidh an chomhroinnt seo go huathoibríoch.

Úsáidfear an seoladh seo arís gach uair a dhéanfaidh tú comhroinnt. (Chun seoladh aon uaire a úsáid, múch \"Úsáid seoladh seasmhach\" sna socruithe.)", + "gui_url_label_stay_open": "Ní stopfaidh an chomhroinnt seo go huathoibríoch.", + "gui_url_label_onetime": "Stopfaidh an chomhroinnt seo nuair a chríochnóidh sé den chéad uair.", + "gui_url_label_onetime_and_persistent": "Ní stopfaidh an chomhroinnt seo go huathoibríoch.

Úsáidfear an seoladh seo arís gach uair a dhéanfaidh tú comhroinnt. (Chun seoladh aon uaire a úsáid, múch \"Úsáid seoladh seasmhach\" sna socruithe.)", + "gui_status_indicator_share_stopped": "Réidh le comhroinnt", + "gui_status_indicator_share_working": "Á thosú…", + "gui_status_indicator_share_started": "Comhroinnt", + "gui_status_indicator_receive_stopped": "Réidh le glacadh le comhaid", + "gui_status_indicator_receive_working": "Á thosú…", + "gui_status_indicator_receive_started": "Glacadh", + "gui_file_info": "{} comhad, {}", + "gui_file_info_single": "{} chomhad, {}", + "history_in_progress_tooltip": "{} ar siúl", + "history_completed_tooltip": "{} críochnaithe", + "info_in_progress_uploads_tooltip": "{} uaslódáil ar siúl faoi láthair", + "info_completed_uploads_tooltip": "{} uaslódáil críochnaithe", + "error_cannot_create_downloads_dir": "Níorbh fhéidir fillteán a chruthú do chomhaid a nglacann tú leo: {}", + "receive_mode_downloads_dir": "Cuirfear comhaid a sheoltar chugat san fhillteán seo: {}", + "receive_mode_warning": "Rabhadh: Sa mód glactha, beidh daoine in ann comhaid a uaslódáil ar do ríomhaire, fiú comhaid chontúirteacha a dhéanfadh dochar do do ríomhaire dá n-osclófá iad. Ná hoscail ach comhaid ó dhaoine iontaofa mura bhfuil tú i do shaineolaí cruthanta slándála.", + "gui_receive_mode_warning": "Sa mód glactha, beidh daoine in ann comhaid a uaslódáil ar do ríomhaire.

Tá comhaid áirithe an-chontúirteach agus dhéanfaidís dochar do do ríomhaire dá n-osclófá iad. Ná hoscail ach comhaid ó dhaoine iontaofa mura bhfuil tú i do shaineolaí cruthanta slándála.", + "receive_mode_upload_starting": "Uaslódáil, méid iomlán {}, á tosú", + "receive_mode_received_file": "Faighte: {}", + "gui_mode_share_button": "Comhroinn Comhaid", + "gui_mode_receive_button": "Glac le Comhaid", + "gui_settings_receiving_label": "Socruithe glactha", + "gui_settings_downloads_label": "Sábháil comhaid i", + "gui_settings_downloads_button": "Brabhsáil", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "Tá cead ag an seoltóir stop a chur leis an mód glactha", + "gui_settings_public_mode_checkbox": "Mód poiblí", + "systray_close_server_title": "Tá an freastalaí OnionShare dúnta", + "systray_close_server_message": "Dhún úsáideoir an freastalaí", + "systray_page_loaded_title": "Lódáladh leathanach OnionShare", + "systray_download_page_loaded_message": "Lódáil úsáideoir an leathanach íoslódála", + "systray_upload_page_loaded_message": "Lódáil úsáideoir an leathanach uaslódála", + "gui_uploads": "Stair Uaslódála", + "gui_no_uploads": "Níl aon rud uaslódáilte agat fós", + "gui_clear_history": "Glan Uile", + "gui_upload_in_progress": "Tosaíodh an Uaslódáil {}", + "gui_upload_finished_range": "Uaslódáladh {} go {}", + "gui_upload_finished": "Uaslódáladh {}", + "gui_download_in_progress": "Tosaíodh an Íoslódáil {}", + "gui_open_folder_error_nautilus": "Ní féidir an fillteán a oscailt toisc nach bhfuil nautilus ar fáil. Tá an comhad anseo: {}", + "gui_settings_language_label": "Do rogha teanga", + "gui_settings_language_changed_notice": "Atosaigh OnionShare chun an teanga nua a chur i bhfeidhm." +} diff --git a/share/locale/no.json b/share/locale/no.json index a04710d2..4d474cea 100644 --- a/share/locale/no.json +++ b/share/locale/no.json @@ -1,7 +1,190 @@ { - "give_this_url": "Gi personen du vil sende filen til denne URL-en:", - "ctrlc_to_stop": "Trykk Ctrl+C for å stoppe serveren.", + "give_this_url": "Gi denne adressen til mottakeren:", + "ctrlc_to_stop": "Trykk Ctrl+C for å stoppe serveren.", "not_a_file": "{0:s} er ikke en fil.", - "gui_copied_url": "Kopierte URL-en til utklippstavlen", - "other_page_loaded": "En annen side har blitt lastet" + "gui_copied_url": "OnionShare-adresse kopiert til utklippstavle", + "other_page_loaded": "En annen side har blitt lastet", + "config_onion_service": "Setter opp løk-tjeneste på port {0:d}.", + "preparing_files": "Pakker sammen filer.", + "give_this_url_stealth": "Gi denne adressen og HidServAuth-linjen til mottakeren:", + "give_this_url_receive": "Gi denne adressen til avsenderen:", + "give_this_url_receive_stealth": "Gi denne adressen og HidServAuth-linjen til avsenderen:", + "not_a_readable_file": "{0:s} er ikke en lesbar fil.", + "no_available_port": "Fant ikke tilgjengelig port for oppstart av løktjenesten", + "close_on_timeout": "Stoppet fordi tidsavbruddsuret gikk ut", + "closing_automatically": "Stoppet fordi nedlasting fullførtes", + "timeout_download_still_running": "Venter på at nedlastingen skal fullføres", + "large_filesize": "Advarsel: forsendelse av stor deling kan ta timer", + "systray_menu_exit": "Avslutt", + "systray_download_started_title": "OnionShare-nedlasting startet", + "systray_download_started_message": "En bruker startet nedlasting av filene dine", + "systray_download_completed_title": "OnionShare-nedlasting fullført", + "systray_download_completed_message": "Brukeren fullførte nedlasting av filene dine", + "systray_download_canceled_title": "OnionShare-nedlasting avbrutt", + "systray_download_canceled_message": "Brukeren avbrøt nedlastingen", + "systray_upload_started_title": "OnionShare-opplasting startet", + "systray_upload_started_message": "En bruker startet opplasting av filer til din datamaskin", + "help_local_only": "Ikke bruk Tor (kun i utviklingsøyemed)", + "help_stay_open": "Fortsett å dele etter første nedlasting", + "help_shutdown_timeout": "Stopp deling etter et gitt antall sekunder", + "help_stealth": "Bruk klientidentifisering (avansert)", + "help_receive": "Motta delinger istedenfor å sende dem", + "help_debug": "Log OnionShare-feil til stdout, og vev-feil til disk", + "help_filename": "Liste over filer eller mapper å dele", + "help_config": "Egendefinert JSON-oppsettsfil (valgfri)", + "gui_drag_and_drop": "Dra og slipp filer og mapper\nfor å starte deling", + "gui_add": "Legg til", + "gui_delete": "Slett", + "gui_choose_items": "Velg", + "gui_share_start_server": "Start deling", + "gui_share_stop_server": "Stopp deling", + "gui_share_stop_server_shutdown_timeout": "Stopp deling ({}s gjenstår)", + "gui_share_stop_server_shutdown_timeout_tooltip": "Tidsavbruddsuret går ut {}", + "gui_receive_start_server": "Start mottaksmodus", + "gui_receive_stop_server": "Stopp mottaksmodus", + "gui_receive_stop_server_shutdown_timeout": "Stopp mottaksmodus ({}s gjenstår)", + "gui_receive_stop_server_shutdown_timeout_tooltip": "Tidsavbruddsuret går ut {}", + "gui_copy_url": "Kopier nettadresse", + "gui_copy_hidservauth": "Kopier HidServAuth", + "gui_downloads": "Nedlastingshistorikk", + "gui_no_downloads": "Ingen nedlastinger enda.", + "gui_canceled": "Avbrutt", + "gui_copied_url_title": "Kopierte OnionShare-adressen", + "gui_copied_hidservauth_title": "Kopierte HidServAuth-linje", + "gui_copied_hidservauth": "HidServAuth-linje kopiert til utklippstavle", + "gui_please_wait": "Starter… Klikk for å avbryte.", + "gui_download_upload_progress_complete": "%p%, {0:s} forløpt.", + "gui_download_upload_progress_starting": "{0:s}, %p% (regner ut)", + "gui_download_upload_progress_eta": "{0:s}, anslått ferdigstilt: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_quit_title": "Hold an", + "gui_share_quit_warning": "Filer er i ferd med å bli sendt. Er du sikker på at du ønsker å avslutte OnionShare?", + "gui_receive_quit_warning": "Du har ikke fått overført alle filene til deg enda. Er du sikker på at du ønsker å avslutte OnionShare?", + "gui_quit_warning_quit": "Avslutt", + "gui_quit_warning_dont_quit": "Avbryt", + "error_rate_limit": "Noen har prøvd adressen din for mange ganger, som kan betyr at de prøver å gjette seg fram til den, OnionShare har derfor stoppet tjeneren. Start deling igjen, og send mottakeren en ny adresse å dele.", + "zip_progress_bar_format": "Pakker sammen: %p%", + "error_stealth_not_supported": "For å bruke klientidentitetsbekreftelse, trenger du minst Tor 0.2.9.1-alpha (eller Tor-nettleseren 6.5) og python3-stem 1.5.0.", + "error_ephemeral_not_supported": "OnionShare krever minst både Tor 0.2.7.1 og pything3-stem 1.4.0.", + "gui_settings_window_title": "Innstillinger", + "gui_settings_whats_this": "Hva er dette?", + "gui_settings_stealth_option": "Bruk klientidentifisering (gammeldags)", + "gui_settings_stealth_hidservauth_string": "Siden du har lagret din private nøkkel for gjenbruk, kan du nå\nklikke for å kopiere din HidServAuth-linje.", + "gui_settings_autoupdate_label": "Se etter ny versjon", + "gui_settings_autoupdate_option": "Gi meg beskjed når en ny versjon er tilgjengelig", + "gui_settings_autoupdate_timestamp": "Sist sjekket: {}", + "gui_settings_autoupdate_timestamp_never": "Aldri", + "gui_settings_autoupdate_check_button": "Se etter ny versjon", + "gui_settings_general_label": "Hovedinnstillinger", + "gui_settings_sharing_label": "Delingsinnstillinger", + "gui_settings_close_after_first_download_option": "Stopp deling etter første nedlasting", + "gui_settings_connection_type_label": "Hvordan skal OnionShare koble seg til Tor?", + "gui_settings_connection_type_bundled_option": "Bruk Tor-versjonen som kommer med OnionShare", + "gui_settings_connection_type_automatic_option": "Forsøk automatisk oppsett med Tor-nettleser", + "gui_settings_connection_type_control_port_option": "Koble til ved bruk av kontrollport", + "gui_settings_connection_type_socket_file_option": "Koble til ved bruk av socket-fil", + "gui_settings_connection_type_test_button": "Test tilkobling til Tor", + "gui_settings_control_port_label": "Kontrollport", + "gui_settings_socket_file_label": "Socket-fil", + "gui_settings_socks_label": "SOCKS-port", + "gui_settings_authenticate_label": "Tor-identitetsbekreftelsesinnstillinger", + "gui_settings_authenticate_no_auth_option": "Ingen identitetsbekreftelse, eller kakeidentifiseringsbekreftelse", + "gui_settings_authenticate_password_option": "Passord", + "gui_settings_password_label": "Passord", + "gui_settings_tor_bridges": "Støtte for Tor-bro", + "gui_settings_tor_bridges_no_bridges_radio_option": "Ikke benytt broer", + "gui_settings_tor_bridges_obfs4_radio_option": "Bruk innebygd pluggbare obfs4-transporter", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Bruk innebygd pluggbare obfs4-transporter (krever obfs4proxy)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Bruk innebygd pluggbare meek_lite (Azure) transporter", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Bruk innebygd pluggbare meek_lite (Azure) transporter (krever obfs4proxy)", + "gui_settings_meek_lite_expensive_warning": "Advarsel: Meek-lite-broene er veldig kostbare å kjøre for Tor-prosjektet.

Kun bruk dem hvis direkte tilkobling til Tor ikke virker, via obfs-transporter, eller andre normale broer.", + "gui_settings_tor_bridges_custom_radio_option": "Bruk egendefinerte broer", + "gui_settings_tor_bridges_custom_label": "Du kan hente broer fra https://bridges.torproject.org", + "gui_settings_tor_bridges_invalid": "Ingen av broene du la til virker.\nDobbeltsjekk dem eller legg til andre.", + "gui_settings_button_save": "Lagre", + "gui_settings_button_cancel": "Avbryt", + "gui_settings_button_help": "Hjelp", + "gui_settings_shutdown_timeout_checkbox": "Bruk tidsavbruddsur", + "gui_settings_shutdown_timeout": "Stopp deling ved:", + "settings_saved": "Innstillinger lagret i {}", + "settings_error_unknown": "Kan ikke koble til Tor-kontroller fordi innstillingene dine ikke gir mening.", + "settings_error_automatic": "Kunne ikke koble til Tor-kontrolleren. Kjører Tor-nettleseren (tilgjengelig fra torproject.org) i bakgrunnen?", + "settings_error_socket_port": "Kan ikke koble til Tor-kontroller på {}:{}.", + "settings_error_socket_file": "Kan ikke koble til Tor-kontroller ved bruk av socket-fil {}.", + "settings_error_auth": "Tilkoblet til {}:{}, men kan ikke identitetsbekrefte. Kanskje dette ikke er en Tor-kontroller?", + "settings_error_missing_password": "Tilkoblet til Tor-kontroller, men den krever et passord for å identitetsbekrefte.", + "settings_error_unreadable_cookie_file": "Tilkoblet til Tor-kontrolleren, men passordet kan være galt, eller så har ikke brukeren din tilgang til å lese fra kakefilen.", + "settings_error_bundled_tor_not_supported": "Bruk av Tor-versjonen som kommer med OnionShare fungerer ikke i utviklermodus på Windows eller macOS.", + "settings_error_bundled_tor_timeout": "Det tar for lang tid å koble til Tor. Kanskje du ikke er koblet til Internett, eller har du kanskje en unøyaktig systemklokke?", + "settings_error_bundled_tor_broken": "OnionShare kunne ikke koble til Tor i bakgrunnen:\n{}", + "settings_test_success": "Koblet til Tor-kontrolleren.\n\nTor-versjon: {}.\nStøtter flyktige løktjenester: {}.\nStøtter klientidentifisering: {}.\nStøtter nestegenerasjons .onion-adresser: {}.", + "error_tor_protocol_error": "Feil med Tor: {}", + "error_tor_protocol_error_unknown": "Ukjent feil med Tor", + "error_invalid_private_key": "Denne private nøkkeltypen er ikke støttet", + "connecting_to_tor": "Kobler til Tor-nettverket", + "update_available": "Ny OnionShare lansert. Klikk her for å hente det.

Du bruker {} og nyeste versjon er {}.", + "update_error_check_error": "Kunne ikke sjekke etter nye versjoner: OnionShare-nettsiden sier at siste versjon er det ugjenkjennelige \"{}\"…", + "update_error_invalid_latest_version": "Kunne ikke sjekke etter ny versjon: Kanskje du ikke er koblet til Tor, eller kanskje OnionShare-nettsiden er nede?", + "update_not_available": "Du kjører siste OnionShare.", + "gui_tor_connection_ask": "Åpne innstillingene for å ordne opp i tilkoblingen til Tor?", + "gui_tor_connection_ask_open_settings": "Ja", + "gui_tor_connection_ask_quit": "Avslutt", + "gui_tor_connection_error_settings": "Prøv å endre hvordan OnionShare kobler til Tor-nettverket i innstillingene.", + "gui_tor_connection_canceled": "Kunne ikke koble til Tor.\n\nForsikre deg om at du er koblet til Internett, åpne så OnionShare igjen, og sett opp dets tilkobling til Tor.", + "gui_tor_connection_lost": "Frakoblet fra Tor.", + "gui_server_started_after_timeout": "Tidsavbruddsuret gikk ut før tjeneren startet.\nLag en ny deling.", + "gui_server_timeout_expired": "Tidsavbruddsuret har gått ut allerede.\nOppdater det for å starte deling.", + "share_via_onionshare": "OnionShare det", + "gui_use_legacy_v2_onions_checkbox": "Bruk gammeldagse adresser", + "gui_save_private_key_checkbox": "Bruk en vedvarende adresse (gammeldags)", + "gui_share_url_description": "Alle som har denne OnionShare-adressen kan Laste ned filene dine ved bruk av Tor-nettleseren: ", + "gui_receive_url_description": "Alle som har denne OnionShare-adressen kan Laste opp filer til din datamaskin ved bruk av Tor-nettleseren: ", + "gui_url_label_persistent": "Delingen vil ikke stoppe automatisk.

Hver påfølgende deling vil gjenbruke adressen. (For engangsadresser, skru av \"Bruk vedvarende adresse\" i innstillingene.)", + "gui_url_label_stay_open": "Denne delingen vil ikke stoppe automatisk.", + "gui_url_label_onetime": "Denne delingen vil stoppe etter første fullføring.", + "gui_url_label_onetime_and_persistent": "Delingen vil ikke stoppe automatisk.

Hver påfølgende deling vil gjenbruke adressen. (For å bruke engangsadresser, skru av \"Bruk vedvarende adresse\" i innstillingene.)", + "gui_status_indicator_share_stopped": "Klar til å dele", + "gui_status_indicator_share_working": "Starter…", + "gui_status_indicator_share_started": "Deler", + "gui_status_indicator_receive_stopped": "Klar til mottak", + "gui_status_indicator_receive_working": "Starter…", + "gui_status_indicator_receive_started": "Mottar", + "gui_file_info": "{} filer, {}", + "gui_file_info_single": "{} fil, {}", + "info_in_progress_downloads_tooltip": "{} nedlasting(er) underveis", + "info_completed_downloads_tooltip": "{} nedlasting(er) fullført", + "info_in_progress_uploads_tooltip": "{} opplasting(er) underveis", + "info_completed_uploads_tooltip": "{} nedlasting(er) fullført", + "error_cannot_create_downloads_dir": "Kunne ikke opprette mottaksmodusmappe: {}", + "error_downloads_dir_not_writable": "Mottaksmodusmappen er skrivebeskyttet: {}", + "receive_mode_downloads_dir": "Filer sendt til deg vil vises i denne mappen: {}", + "receive_mode_warning": "Advarsel: Mottaksmodus lar folk laste opp filer til din datamaskin. Noen filer kan potensielt ta over datamaskinen din hvis du åpner dem. Kun åpne ting fra folk du stoler på, eller hvis du vet hva du gjør.", + "gui_receive_mode_warning": "Mottaksmodus lar folk laste opp filer til din datamaskin.

Noen filer kan potensielt ta over datamaskinen din hvis du åpner dem. Kun åpne ting fra folk du stoler på, eller hvis du vet hva du gjør.", + "receive_mode_upload_starting": "Opplasting av total størrelse {} starter", + "receive_mode_received_file": "Mottatt: {}", + "gui_mode_share_button": "Del filer", + "gui_mode_receive_button": "Motta filer", + "gui_settings_receiving_label": "Mottaksinnstillinger", + "gui_settings_downloads_label": "Lagre filer i", + "gui_settings_downloads_button": "Utforstk", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "Mottaksmodus kan stoppes av avsenderen", + "gui_settings_public_mode_checkbox": "Offentlig modus", + "systray_close_server_title": "OnionShare-tjener lukket", + "systray_close_server_message": "En bruker stengte tjeneren", + "systray_page_loaded_title": "OnionShare-side lastet", + "systray_download_page_loaded_message": "En bruker lastet inn nedlastingssiden", + "systray_upload_page_loaded_message": "En bruker lastet inn opplastingssiden", + "gui_uploads": "Opplastingshistorikk", + "gui_no_uploads": "Ingen opplastinger enda.", + "gui_clear_history": "Tøm alt", + "gui_upload_in_progress": "Opplasting startet {}", + "gui_upload_finished_range": "Lastet opp {} til {}", + "gui_upload_finished": "Lastet opp {}", + "gui_open_folder_error_nautilus": "Kan ikke åpne mappe fordi nautilus ikke er tilgjengelig. Filen er her: {}", + "history_in_progress_tooltip": "{} underveis", + "history_completed_tooltip": "{} fullført", + "gui_download_in_progress": "Nedlasting startet {}", + "gui_settings_language_label": "Foretrukket språk", + "gui_settings_language_changed_notice": "Start OnionShare på ny for å se nytt språkvalg.", + "timeout_upload_still_running": "Venter på at opplastingen fullføres" } -- cgit v1.2.3-54-g00ecf From 919fdeb096b957e29382113e41270bbaf533b0fb Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 11 Dec 2018 07:16:44 -0800 Subject: When debug mode is enabled, don't log flask errors to disk --- onionshare/web.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/onionshare/web.py b/onionshare/web.py index 702ba686..e9c4d43b 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -178,12 +178,19 @@ def set_gui_mode(): def debug_mode(): """ Turn on debugging mode, which will log flask errors to a debug file. + + This is commented out (it's only needed for debugging, and not needed + for OnionShare 1.3.2) as a hotfix to resolve this issue: + https://github.com/micahflee/onionshare/issues/837 + """ + pass """ temp_dir = tempfile.gettempdir() log_handler = logging.FileHandler( os.path.join(temp_dir, 'onionshare_server.log')) log_handler.setLevel(logging.WARNING) app.logger.addHandler(log_handler) + """ def check_slug_candidate(slug_candidate, slug_compare=None): -- cgit v1.2.3-54-g00ecf From d8246ded81f1ea8f661ff98df65f267cab18a6b5 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 20:51:07 -0800 Subject: Fix test_load_strings_loads_other_languages test --- tests/test_onionshare_strings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_onionshare_strings.py b/tests/test_onionshare_strings.py index ea57e3a9..3ac22a11 100644 --- a/tests/test_onionshare_strings.py +++ b/tests/test_onionshare_strings.py @@ -51,7 +51,7 @@ class TestLoadStrings: common_obj.settings = Settings(common_obj) common_obj.settings.set('locale', 'fr') strings.load_strings(common_obj) - assert strings._('preparing_files') == "Préparation des fichiers à partager." + assert strings._('preparing_files') == "Compression des fichiers." def test_load_invalid_locale( self, common_obj, locale_invalid, sys_onionshare_dev_mode): -- cgit v1.2.3-54-g00ecf From a0e0b71da4d08f645d133caf4e4f4d8f12e68d4a Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 20:58:13 -0800 Subject: Remove "(legacy) from v2-only settings dialog options" --- share/locale/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/locale/en.json b/share/locale/en.json index c38bfdff..43c7cfe3 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -69,7 +69,7 @@ "error_ephemeral_not_supported": "OnionShare requires at least both Tor 0.2.7.1 and python3-stem 1.4.0.", "gui_settings_window_title": "Settings", "gui_settings_whats_this": "What's this?", - "gui_settings_stealth_option": "Use client authorization (legacy)", + "gui_settings_stealth_option": "Use client authorization", "gui_settings_stealth_hidservauth_string": "Having saved your private key for reuse, means you can now\nclick to copy your HidServAuth.", "gui_settings_autoupdate_label": "Check for new version", "gui_settings_autoupdate_option": "Notify me when a new version is available", @@ -137,7 +137,7 @@ "share_via_onionshare": "OnionShare it", "gui_connect_to_tor_for_onion_settings": "Connect to Tor to see onion service settings", "gui_use_legacy_v2_onions_checkbox": "Use legacy addresses", - "gui_save_private_key_checkbox": "Use a persistent address (legacy)", + "gui_save_private_key_checkbox": "Use a persistent address", "gui_share_url_description": "Anyone with this OnionShare address can download your files using the Tor Browser: ", "gui_receive_url_description": "Anyone with this OnionShare address can upload files to your computer using the Tor Browser: ", "gui_url_label_persistent": "This share will not auto-stop.

Every subsequent share reuses the address. (To use one-time addresses, turn off \"Use persistent address\" in the settings.)", -- cgit v1.2.3-54-g00ecf From f9e6e6964cdc34b685ac1a0d6a7e82540b654a31 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 21:07:23 -0800 Subject: Remove unnecessary imports from settings dialog tests --- tests/local_onionshare_settings_dialog_legacy_tor_test.py | 3 --- tests/local_onionshare_settings_dialog_no_tor_test.py | 3 --- tests/local_onionshare_settings_dialog_v3_tor_test.py | 2 -- 3 files changed, 8 deletions(-) diff --git a/tests/local_onionshare_settings_dialog_legacy_tor_test.py b/tests/local_onionshare_settings_dialog_legacy_tor_test.py index d08362f1..ae6ce272 100644 --- a/tests/local_onionshare_settings_dialog_legacy_tor_test.py +++ b/tests/local_onionshare_settings_dialog_legacy_tor_test.py @@ -1,8 +1,5 @@ #!/usr/bin/env python3 -import json import unittest -import time -from PyQt5 import QtCore, QtTest from onionshare import strings from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub diff --git a/tests/local_onionshare_settings_dialog_no_tor_test.py b/tests/local_onionshare_settings_dialog_no_tor_test.py index a10c2f2e..9519f77e 100644 --- a/tests/local_onionshare_settings_dialog_no_tor_test.py +++ b/tests/local_onionshare_settings_dialog_no_tor_test.py @@ -1,8 +1,5 @@ #!/usr/bin/env python3 -import json import unittest -import time -from PyQt5 import QtCore, QtTest from onionshare import strings from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub diff --git a/tests/local_onionshare_settings_dialog_v3_tor_test.py b/tests/local_onionshare_settings_dialog_v3_tor_test.py index 815b2f72..cb10f8c9 100644 --- a/tests/local_onionshare_settings_dialog_v3_tor_test.py +++ b/tests/local_onionshare_settings_dialog_v3_tor_test.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -import json import unittest -from PyQt5 import QtCore, QtTest from onionshare import strings from .SettingsGuiBaseTest import SettingsGuiBaseTest, OnionStub -- cgit v1.2.3-54-g00ecf From dc24b5ecd37cf9559dc6efd9dccb8a4cb52354ba Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 21:08:51 -0800 Subject: Fix bug in OnionStub, the stub used in settings dialog tests --- tests/SettingsGuiBaseTest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SettingsGuiBaseTest.py b/tests/SettingsGuiBaseTest.py index 57626d1d..aea19c68 100644 --- a/tests/SettingsGuiBaseTest.py +++ b/tests/SettingsGuiBaseTest.py @@ -14,7 +14,7 @@ from onionshare_gui.settings_dialog import SettingsDialog class OnionStub(object): def __init__(self, is_authenticated, supports_v3_onions=False): self._is_authenticated = is_authenticated - self.supports_v3_onions = True + self.supports_v3_onions = supports_v3_onions def is_authenticated(self): return self._is_authenticated -- cgit v1.2.3-54-g00ecf From 7f335efaa3bca15d8cfb59cdda17fe1a0059db1f Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 21:15:18 -0800 Subject: Always pass in both is_authenticated and supports_v3_onions to OnionStub --- tests/SettingsGuiBaseTest.py | 2 +- tests/local_onionshare_settings_dialog_no_tor_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/SettingsGuiBaseTest.py b/tests/SettingsGuiBaseTest.py index aea19c68..00056219 100644 --- a/tests/SettingsGuiBaseTest.py +++ b/tests/SettingsGuiBaseTest.py @@ -12,7 +12,7 @@ from onionshare_gui.settings_dialog import SettingsDialog class OnionStub(object): - def __init__(self, is_authenticated, supports_v3_onions=False): + def __init__(self, is_authenticated, supports_v3_onions): self._is_authenticated = is_authenticated self.supports_v3_onions = supports_v3_onions diff --git a/tests/local_onionshare_settings_dialog_no_tor_test.py b/tests/local_onionshare_settings_dialog_no_tor_test.py index 9519f77e..f01e049d 100644 --- a/tests/local_onionshare_settings_dialog_no_tor_test.py +++ b/tests/local_onionshare_settings_dialog_no_tor_test.py @@ -15,7 +15,7 @@ class SettingsGuiTest(unittest.TestCase, SettingsGuiBaseTest): SettingsGuiBaseTest.tear_down() def test_gui_no_tor(self): - self.gui.onion = OnionStub(False) + self.gui.onion = OnionStub(False, False) self.gui.reload_settings() self.run_settings_gui_tests() -- cgit v1.2.3-54-g00ecf From bf337b5e34aa3a160938acaf6a2c4f1bcba0db27 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 13 Dec 2018 21:44:47 -0800 Subject: Remove qtapp.processEvents() call from settings dialog tests, because they cause a segfault in circleci for some reason --- tests/SettingsGuiBaseTest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/SettingsGuiBaseTest.py b/tests/SettingsGuiBaseTest.py index 00056219..47d698f3 100644 --- a/tests/SettingsGuiBaseTest.py +++ b/tests/SettingsGuiBaseTest.py @@ -63,7 +63,6 @@ class SettingsGuiBaseTest(object): def run_settings_gui_tests(self): self.gui.show() - self.gui.qtapp.processEvents() # Window is shown self.assertTrue(self.gui.isVisible()) -- cgit v1.2.3-54-g00ecf From 2b44e52fa91511c64f1f79c8fd44293746a57769 Mon Sep 17 00:00:00 2001 From: emma peel Date: Sat, 15 Dec 2018 10:34:38 +0000 Subject: Add weblate versions of this files, to see if it stops complaining without a real merge. A real merge from weblate will include more files yet not translated. --- share/locale/pt_BR.json | 189 ++++++++++++++++++++++++++++++++++++++++++++++-- share/locale/pt_PT.json | 188 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 367 insertions(+), 10 deletions(-) diff --git a/share/locale/pt_BR.json b/share/locale/pt_BR.json index 1b2d3139..abe7c795 100644 --- a/share/locale/pt_BR.json +++ b/share/locale/pt_BR.json @@ -1,7 +1,186 @@ { - "give_this_url": "Passe este URL para a pessoa que deve receber o arquivo:", - "ctrlc_to_stop": "Pressione Ctrl-C para parar o servidor", - "not_a_file": "{0:s} não é um arquivo.", - "gui_copied_url": "URL foi copiado para área de transferência", - "other_page_loaded": "Outra página tem sido carregada" + "config_onion_service": "Configurando o serviço onion na porta {0:d}.", + "preparing_files": "Comprimindo arquivos.", + "give_this_url": "Dar este endereço ao destinatário:", + "give_this_url_stealth": "Dar este endereço e linha HidServAuth ao destinatário:", + "give_this_url_receive": "Dar este endereço ao remetente:", + "give_this_url_receive_stealth": "Dar este endereço e HidServAuth ao remetente:", + "ctrlc_to_stop": "Pressione Ctrl+C para interromper o servidor", + "not_a_file": "{0:s} não é um ficheiro válido.", + "not_a_readable_file": "{0:s} não é um ficheiro legível.", + "no_available_port": "Não foi possível encontrar um pórtico disponível para iniciar o serviço onion", + "other_page_loaded": "Endereço carregado", + "close_on_timeout": "Interrompido ao final da contagem do cronômetro automático", + "closing_automatically": "Interrompido porque o download terminou", + "timeout_download_still_running": "Esperando que o download termine", + "large_filesize": "Aviso: O envio de arquivos grandes pode levar várias horas", + "systray_menu_exit": "Sair", + "systray_download_started_title": "O download de OnionShare começou", + "systray_download_started_message": "Alguém começou fazer o download dos seus arquivos", + "systray_download_completed_title": "O download de OnionShare terminou", + "systray_download_completed_message": "Essa pessoa terminou de fazer o download dos seus arquivos", + "systray_download_canceled_title": "O download de OnionShare foi cancelado", + "systray_download_canceled_message": "Essa pessoa cancelou o download", + "systray_upload_started_title": "OnionShare começou a carregar", + "systray_upload_started_message": "Alguém começou a carregar arquivos no seu computador", + "help_local_only": "Não use Tor (unicamente para programação)", + "help_stay_open": "Continuar a compartilhar depois do primeiro download", + "help_shutdown_timeout": "Parar de compartilhar após um número determinado de segundos", + "help_stealth": "Usar autorização de cliente (avançado)", + "help_receive": "Receber compartilhamentos ao invés de enviá-los", + "help_debug": "Registrar erros do OnionShare no stdout e erros de rede, no disco", + "help_filename": "Lista de arquivos ou pastas a compartilhar", + "help_config": "Personalizar a configuração JSON de localização de arquivos (opcional)", + "gui_drag_and_drop": "Arrastar arquivos e pastas\npara começar a compartilhá-los", + "gui_add": "Adicionar", + "gui_delete": "Apagar", + "gui_choose_items": "Escolher", + "gui_share_start_server": "Começar a compartilhar", + "gui_share_stop_server": "Parar de compartilhar", + "gui_share_stop_server_shutdown_timeout": "Parar de compartilhar ({}segundos para terminar)", + "gui_share_stop_server_shutdown_timeout_tooltip": "O cronômetro automático termina às", + "gui_receive_start_server": "Modo Começar a Receber", + "gui_receive_stop_server": "Modo Parar de Receber", + "gui_receive_stop_server_shutdown_timeout": "Modo Parar de Receber ({}segundos para terminar)", + "gui_receive_stop_server_shutdown_timeout_tooltip": "O cronômetro automático termina às {}", + "gui_copy_url": "Copiar endereço", + "gui_copy_hidservauth": "Copiar HidServAuth", + "gui_downloads": "Histórico de download", + "gui_no_downloads": "Nenhum download por enquanto", + "gui_canceled": "Cancelado", + "gui_copied_url_title": "Endereço OnionShare copiado", + "gui_copied_url": "URL foi copiado na área de transferência", + "gui_copied_hidservauth_title": "HidServAuth copiado", + "gui_copied_hidservauth": "Linha HidServAuth copiada na área de transferência", + "gui_please_wait": "Começando...Clique para cancelar.", + "gui_download_upload_progress_complete": "%p%, {0:s} decorridos.", + "gui_download_upload_progress_starting": "{0:s}, %p% (calculando)", + "gui_download_upload_progress_eta": "{0:s}, tempo estimado para término: {1:s}, %p%", + "version_string": "OnionShare {0:s} | https://onionshare.org/", + "gui_quit_title": "Mais devagar", + "gui_share_quit_warning": "O envio dos seus arquivos ainda não terminou . Você tem certeza de que quer sair de OnionShare?", + "gui_receive_quit_warning": "O recebimento dos seus arquivos ainda não terminou. Você tem certeza de que quer sair do OnionShare?", + "gui_quit_warning_quit": "Sair", + "gui_quit_warning_dont_quit": "Cancelar", + "error_rate_limit": "Alguém tentou por várias vezes acessar seu endereço, o que talvez signifique que essa pessoa esteja tentando adivinhá-lo. Por isso, OnionShare interrompeu o servidor. Recomece a compartilhar e envie um novo endereço ao seu destinatário para continuar a compartilhar.", + "zip_progress_bar_format": "Comprimindo: %p%", + "error_stealth_not_supported": "Para usar uma autorização de cliente, você precisa de ao menos de Tor 0.2.9.1-alpha (ou navegador Tor 6.5) e de python3-stem 1.5.0.", + "error_ephemeral_not_supported": "OnionShare requer ao menos Tor 0.2.7.1 e python3-stem 1.4.0.", + "gui_settings_window_title": "Configurações", + "gui_settings_whats_this": "O que é isso?", + "gui_settings_stealth_option": "Usar autorização de cliente (legacy)", + "gui_settings_stealth_hidservauth_string": "Após salvar a sua chave privada para reutilização, você pode\nclicar para copiar o seu HidServAuth.", + "gui_settings_autoupdate_label": "Procurar a nova versão", + "gui_settings_autoupdate_option": "Notificar-me quando uma nova versão estiver disponível", + "gui_settings_autoupdate_timestamp": "Última atualização: {}", + "gui_settings_autoupdate_timestamp_never": "Nunca", + "gui_settings_autoupdate_check_button": "Procurar a nova versão", + "gui_settings_general_label": "Configurações gerais", + "gui_settings_sharing_label": "Compartilhando configurações", + "gui_settings_close_after_first_download_option": "Parar de compartilhar depois do primeiro download", + "gui_settings_connection_type_label": "Como OnionShare normalmente conecta-se a Tor?", + "gui_settings_connection_type_bundled_option": "Use a versão de Tor que vem junto com OnionShare", + "gui_settings_connection_type_automatic_option": "Tentar configuração automática com o Navegador Tor", + "gui_settings_connection_type_control_port_option": "Conectar usando entrada de controle", + "gui_settings_connection_type_socket_file_option": "Conectar usando um ficheiro socket", + "gui_settings_connection_type_test_button": "Testar a conexão a Tor", + "gui_settings_control_port_label": "Entrada de controle", + "gui_settings_socket_file_label": "Ficheiro socket", + "gui_settings_socks_label": "Entrada SOCKS", + "gui_settings_authenticate_label": "Configurações de autenticação do Tor", + "gui_settings_authenticate_no_auth_option": "Sem autenticação nem cookie de autenticação", + "gui_settings_authenticate_password_option": "Palavra-passe", + "gui_settings_password_label": "Palavra-passe", + "gui_settings_tor_bridges": "Ajuda para pontes Tor", + "gui_settings_tor_bridges_no_bridges_radio_option": "Não usar pontes", + "gui_settings_tor_bridges_obfs4_radio_option": "Usar transportadores plugáveis obfs4 já instalados", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "Usar transportadores plugáveis obfs4 já instalados (requer obfs4proxy)", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "Usar transportadores plugáveis meek_lite (Azure) instalados", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Usar transportadores plugáveis meek_lite (Azure) instalados (requer obfs4proxy)", + "gui_settings_meek_lite_expensive_warning": "Aviso: As pontes meek_lite são muito custosas para o Projeto Tor.

Use-as somente se você não conseguir se conectar a Tor diretamente, via transportadores obfs4 ou outras pontes comuns.", + "gui_settings_tor_bridges_custom_radio_option": "Usar pontes personalizadas", + "gui_settings_tor_bridges_custom_label": "Você pode obter pontes em https://bridges.torproject.org", + "gui_settings_tor_bridges_invalid": "Nenhumas ponte adicionada funciona.\nTente usá-las de novo ou adicione outras.", + "gui_settings_button_save": "Salvar", + "gui_settings_button_cancel": "Cancelar", + "gui_settings_button_help": "Ajuda", + "gui_settings_shutdown_timeout_checkbox": "Usar cronômetro para encerrar automaticamente", + "gui_settings_shutdown_timeout": "Encerrar o compartilhamento às:", + "settings_error_unknown": "Impossível conectar-se ao controlador do Tor, porque as suas configurações estão confusas.", + "settings_error_automatic": "Não foi possível conectar ao controlador do Tor. O Navegador Tor (disponível no site torproject.org) está rodando em segundo plano?", + "settings_error_socket_port": "Não pode ligar ao controlador do Tor em {}:{}.", + "settings_error_socket_file": "Não foi possível conectar ao controlador Tor usando o arquivo de socket {}.", + "settings_error_auth": "Conectado a {}:{}, mas não foi possível autenticar. Talvez este não seja um controlador Tor?", + "settings_error_missing_password": "Conectado ao controlador Tor, mas é preciso ter uma senha para autenticar.", + "settings_error_unreadable_cookie_file": "Conectado ao controlador Tor, mas talvez a palavra-passe esteja incorreta, ou o seu usuário não possui autorização para ler o ficheiro de cookie.", + "settings_error_bundled_tor_not_supported": "Não é possível usar a versão de Tor que vem junto com OnionShare, em modo 'programação', com Windows ou macOS.", + "settings_error_bundled_tor_timeout": "A conexão a Tor está demorando muito. O seu computado está conectado à Internet e o seu relógio de sistema, ajustado?", + "settings_error_bundled_tor_broken": "OnionShare não pôde se conectar a Tor em segundo plano:\n{}", + "settings_test_success": "Conectado ao controlador Tor.\n\nVersão do Tor: {}\nPossui suporte para serviços onion efêmeros: {}.\nPossui suporte para autenticação de cliente: {}.\nPossui suporte para a próxima geração de endereços .onion: {}.", + "error_tor_protocol_error": "Houve um erro com Tor: {}", + "error_tor_protocol_error_unknown": "Ocorreu um erro desconhecido com Tor", + "error_invalid_private_key": "Este tipo de chave privada não possui suporte", + "connecting_to_tor": "Conectando à rede Tor", + "update_available": "Atualização de OnionShare disponível. Clique aqui para obtê-la.

Você está usando a versão {} e a última é {}.", + "update_error_check_error": "Não foi possível verificar por novas versões: o website do OnionShare está dizendo que a última versão é a irreconhecível '{}'…", + "update_error_invalid_latest_version": "Não foi possível verificar por uma nova versão: talvez você não esteja conectada ao Tor, ou talvez o website do OnionShare esteja fora do ar?", + "update_not_available": "Você está rodando a última versão de OnionShare.", + "gui_tor_connection_ask": "Abrir as configurações para consertar a conexão ao Tor?", + "gui_tor_connection_ask_open_settings": "Sim", + "gui_tor_connection_ask_quit": "Sair", + "gui_tor_connection_error_settings": "Tente mudar nas configurações a forma como OnionShare se conecta à rede Tor.", + "gui_tor_connection_canceled": "Não foi possível conectar à rede Tor.\n\nVerifique se você está conectada à Internet, e então abra OnionShare novamente e configure sua conexão à rede Tor.", + "gui_tor_connection_lost": "Desconectado do Tor.", + "gui_server_started_after_timeout": "O tempo se esgotou antes do servidor iniciar.\nPor favor, crie um novo compartilhamento.", + "gui_server_timeout_expired": "O temporizador já se esgotou.\nPor favor, atualize-o antes de começar a compartilhar.", + "share_via_onionshare": "Compartilhar por meio de OnionShare", + "gui_use_legacy_v2_onions_checkbox": "Usar endereços do tipo antigo", + "gui_save_private_key_checkbox": "Usar um endereço persistente (modo antigo)", + "gui_share_url_description": "Qualquer pessoa com este endereço do OnionShare pode baixar seus arquivos usando o Tor Browser: ", + "gui_receive_url_description": "Qualquer pessoa com este endereço do OnionShare pode fazer upload de arquivos para o seu computador usando o Tor Browser: ", + "gui_url_label_persistent": "Este compartilhamento não vai ser encerrado automaticamente.

Todos os compartilhamentos posteriores reutilizarão este endereço. (Para usar um endereço novo a cada vez, desligue a opção \"Usar endereço persistente\" nas configurações.)", + "gui_url_label_stay_open": "Este compartilhamento não sera encerrado automaticamente.", + "gui_url_label_onetime": "Este compartilhamento será encerrado depois da primeira vez que for utilizado.", + "gui_url_label_onetime_and_persistent": "Este compartilhamento não será encerrado automaticamente.

Todos os compartilhamentos posteriores reutilizarão este endereço. (Para usar endereços únicos a cada compartilhamento, desligue a opção \"Usar endereço persistente\" nas configurações.)", + "gui_status_indicator_share_stopped": "Pronto para compartilhar", + "gui_status_indicator_share_working": "Começando…", + "gui_status_indicator_share_started": "Compartilhando", + "gui_status_indicator_receive_stopped": "Pronto para receber", + "gui_status_indicator_receive_working": "Começando…", + "gui_status_indicator_receive_started": "Recebendo", + "gui_file_info": "{} arquivos, {}", + "gui_file_info_single": "{} ficheiro, {}", + "history_in_progress_tooltip": "{} em progresso", + "history_completed_tooltip": "{} completado", + "info_in_progress_uploads_tooltip": "{} upload(s) em progresso", + "info_completed_uploads_tooltip": "{} upload(s) completado(s)", + "error_cannot_create_downloads_dir": "Não foi possível a pasta do modo de recepção: {}", + "receive_mode_downloads_dir": "Os arquivos enviados para você aparecem na seguinte pasta: {}", + "receive_mode_warning": "Atenção: O modo de recepção permite que as pessoas enviem arquivos para o seu computador. Alguns arquivos podem tomar o controle do seu computador se você abrí-los. Apenas abra arquivos enviados por pessoas que você confia, ou se você souber o que está fazendo.", + "gui_receive_mode_warning": "O modo de recepção permite que pessoas enviem arquivos para o seu computador.

Alguns arquivos podem tomar o controle do seu computador se você abrí-los. Apenas abra arquivos enviados por pessoas que você confia, ou se você souber o que está fazendo.", + "receive_mode_upload_starting": "Um upload de tamanho total {} está sendo iniciado", + "receive_mode_received_file": "Recebido: {}", + "gui_mode_share_button": "Compartilhar Arquivos", + "gui_mode_receive_button": "Receber Arquivos", + "gui_settings_receiving_label": "Configurações de recepção", + "gui_settings_downloads_label": "Armazenar arquivos em", + "gui_settings_downloads_button": "", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "", + "gui_settings_public_mode_checkbox": "Modo público", + "systray_close_server_title": "Servidor OnionShare encerrado", + "systray_close_server_message": "Um usuário encerrou o servidor", + "systray_page_loaded_title": "Página OnionShare Carregada", + "systray_download_page_loaded_message": "Um usuário carregou a página de download", + "systray_upload_page_loaded_message": "Um usuário carregou a página de upload", + "gui_uploads": "Histórico de Uploads", + "gui_no_uploads": "Nenhum upload realizado", + "gui_clear_history": "Limpar Tudo", + "gui_upload_in_progress": "Upload Iniciado {}", + "gui_upload_finished_range": "Upload de {} feito para {}", + "gui_upload_finished": "", + "gui_download_in_progress": "Download Iniciado {}", + "gui_open_folder_error_nautilus": "Não foi possível abrir a pasta porque o nautilus não está disponível. O arquivo está aqui: {}", + "gui_settings_language_label": "Idioma preferido", + "gui_settings_language_changed_notice": "Reinicie o OnionShare para que sua alteração de idioma tenha efeito.", + "timeout_upload_still_running": "Esperando o término do upload" } diff --git a/share/locale/pt_PT.json b/share/locale/pt_PT.json index 1b2d3139..a67a5f75 100644 --- a/share/locale/pt_PT.json +++ b/share/locale/pt_PT.json @@ -1,7 +1,185 @@ { - "give_this_url": "Passe este URL para a pessoa que deve receber o arquivo:", - "ctrlc_to_stop": "Pressione Ctrl-C para parar o servidor", - "not_a_file": "{0:s} não é um arquivo.", - "gui_copied_url": "URL foi copiado para área de transferência", - "other_page_loaded": "Outra página tem sido carregada" + "config_onion_service": "", + "preparing_files": "", + "give_this_url": "", + "give_this_url_stealth": "", + "give_this_url_receive": "", + "give_this_url_receive_stealth": "", + "ctrlc_to_stop": "", + "not_a_file": "", + "not_a_readable_file": "", + "no_available_port": "", + "other_page_loaded": "", + "close_on_timeout": "", + "closing_automatically": "", + "timeout_download_still_running": "", + "large_filesize": "", + "systray_menu_exit": "", + "systray_download_started_title": "", + "systray_download_started_message": "", + "systray_download_completed_title": "", + "systray_download_completed_message": "", + "systray_download_canceled_title": "", + "systray_download_canceled_message": "", + "systray_upload_started_title": "", + "systray_upload_started_message": "", + "help_local_only": "", + "help_stay_open": "", + "help_shutdown_timeout": "", + "help_stealth": "", + "help_receive": "", + "help_debug": "", + "help_filename": "", + "help_config": "", + "gui_drag_and_drop": "", + "gui_add": "", + "gui_delete": "", + "gui_choose_items": "", + "gui_share_start_server": "", + "gui_share_stop_server": "", + "gui_share_stop_server_shutdown_timeout": "", + "gui_share_stop_server_shutdown_timeout_tooltip": "", + "gui_receive_start_server": "", + "gui_receive_stop_server": "", + "gui_receive_stop_server_shutdown_timeout": "", + "gui_receive_stop_server_shutdown_timeout_tooltip": "", + "gui_copy_url": "", + "gui_copy_hidservauth": "", + "gui_downloads": "", + "gui_no_downloads": "", + "gui_canceled": "", + "gui_copied_url_title": "", + "gui_copied_url": "", + "gui_copied_hidservauth_title": "", + "gui_copied_hidservauth": "", + "gui_please_wait": "", + "gui_download_upload_progress_complete": "", + "gui_download_upload_progress_starting": "", + "gui_download_upload_progress_eta": "", + "version_string": "", + "gui_quit_title": "", + "gui_share_quit_warning": "", + "gui_receive_quit_warning": "", + "gui_quit_warning_quit": "", + "gui_quit_warning_dont_quit": "", + "error_rate_limit": "", + "zip_progress_bar_format": "", + "error_stealth_not_supported": "", + "error_ephemeral_not_supported": "", + "gui_settings_window_title": "", + "gui_settings_whats_this": "", + "gui_settings_stealth_option": "", + "gui_settings_stealth_hidservauth_string": "", + "gui_settings_autoupdate_label": "", + "gui_settings_autoupdate_option": "", + "gui_settings_autoupdate_timestamp": "", + "gui_settings_autoupdate_timestamp_never": "", + "gui_settings_autoupdate_check_button": "", + "gui_settings_general_label": "", + "gui_settings_sharing_label": "", + "gui_settings_close_after_first_download_option": "", + "gui_settings_connection_type_label": "", + "gui_settings_connection_type_bundled_option": "", + "gui_settings_connection_type_automatic_option": "", + "gui_settings_connection_type_control_port_option": "", + "gui_settings_connection_type_socket_file_option": "", + "gui_settings_connection_type_test_button": "", + "gui_settings_control_port_label": "", + "gui_settings_socket_file_label": "", + "gui_settings_socks_label": "", + "gui_settings_authenticate_label": "", + "gui_settings_authenticate_no_auth_option": "", + "gui_settings_authenticate_password_option": "", + "gui_settings_password_label": "", + "gui_settings_tor_bridges": "", + "gui_settings_tor_bridges_no_bridges_radio_option": "", + "gui_settings_tor_bridges_obfs4_radio_option": "", + "gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy": "", + "gui_settings_tor_bridges_meek_lite_azure_radio_option": "", + "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "", + "gui_settings_meek_lite_expensive_warning": "", + "gui_settings_tor_bridges_custom_radio_option": "", + "gui_settings_tor_bridges_custom_label": "", + "gui_settings_tor_bridges_invalid": "", + "gui_settings_button_save": "", + "gui_settings_button_cancel": "", + "gui_settings_button_help": "", + "gui_settings_shutdown_timeout_checkbox": "", + "gui_settings_shutdown_timeout": "", + "settings_error_unknown": "", + "settings_error_automatic": "", + "settings_error_socket_port": "", + "settings_error_socket_file": "", + "settings_error_auth": "", + "settings_error_missing_password": "", + "settings_error_unreadable_cookie_file": "", + "settings_error_bundled_tor_not_supported": "", + "settings_error_bundled_tor_timeout": "", + "settings_error_bundled_tor_broken": "", + "settings_test_success": "", + "error_tor_protocol_error": "", + "error_tor_protocol_error_unknown": "", + "error_invalid_private_key": "", + "connecting_to_tor": "", + "update_available": "", + "update_error_check_error": "", + "update_error_invalid_latest_version": "", + "update_not_available": "", + "gui_tor_connection_ask": "", + "gui_tor_connection_ask_open_settings": "", + "gui_tor_connection_ask_quit": "", + "gui_tor_connection_error_settings": "", + "gui_tor_connection_canceled": "", + "gui_tor_connection_lost": "", + "gui_server_started_after_timeout": "", + "gui_server_timeout_expired": "", + "share_via_onionshare": "", + "gui_use_legacy_v2_onions_checkbox": "", + "gui_save_private_key_checkbox": "", + "gui_share_url_description": "", + "gui_receive_url_description": "", + "gui_url_label_persistent": "", + "gui_url_label_stay_open": "", + "gui_url_label_onetime": "", + "gui_url_label_onetime_and_persistent": "", + "gui_status_indicator_share_stopped": "", + "gui_status_indicator_share_working": "", + "gui_status_indicator_share_started": "", + "gui_status_indicator_receive_stopped": "", + "gui_status_indicator_receive_working": "", + "gui_status_indicator_receive_started": "", + "gui_file_info": "", + "gui_file_info_single": "", + "history_in_progress_tooltip": "", + "history_completed_tooltip": "", + "info_in_progress_uploads_tooltip": "", + "info_completed_uploads_tooltip": "", + "error_cannot_create_downloads_dir": "", + "receive_mode_downloads_dir": "", + "receive_mode_warning": "", + "gui_receive_mode_warning": "", + "receive_mode_upload_starting": "", + "receive_mode_received_file": "", + "gui_mode_share_button": "", + "gui_mode_receive_button": "", + "gui_settings_receiving_label": "", + "gui_settings_downloads_label": "", + "gui_settings_downloads_button": "", + "gui_settings_receive_allow_receiver_shutdown_checkbox": "", + "gui_settings_public_mode_checkbox": "", + "systray_close_server_title": "", + "systray_close_server_message": "", + "systray_page_loaded_title": "", + "systray_download_page_loaded_message": "", + "systray_upload_page_loaded_message": "", + "gui_uploads": "", + "gui_no_uploads": "", + "gui_clear_history": "", + "gui_upload_in_progress": "", + "gui_upload_finished_range": "", + "gui_upload_finished": "", + "gui_download_in_progress": "", + "gui_open_folder_error_nautilus": "", + "gui_settings_language_label": "", + "gui_settings_language_changed_notice": "" } -- cgit v1.2.3-54-g00ecf From 1f3728e8c55389122f1d692d129980ec03b43780 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 16 Dec 2018 10:55:13 -0800 Subject: If a locale file includes a blank string, fallback to English instead of using the blank string --- onionshare/strings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onionshare/strings.py b/onionshare/strings.py index b730933d..643186dd 100644 --- a/onionshare/strings.py +++ b/onionshare/strings.py @@ -45,7 +45,7 @@ def load_strings(common): current_locale = common.settings.get('locale') strings = {} for s in translations[default_locale]: - if s in translations[current_locale]: + if s in translations[current_locale] and translations[current_locale][s] != "": strings[s] = translations[current_locale][s] else: strings[s] = translations[default_locale][s] -- cgit v1.2.3-54-g00ecf