aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah Lee <micah@micahflee.com>2022-03-28 18:18:57 -0700
committerMicah Lee <micah@micahflee.com>2022-03-28 18:18:57 -0700
commit4ff23fa9bd927f7300b2ded3f44b3af17fb6780e (patch)
treead07df49cb97980cee3952324fef600ce99a8fa1
parentf08e6e98306ecf55a6caee5dd28dd643044f7241 (diff)
parent52cb5cf71aef4ad05d2345757f8e2a66abc86753 (diff)
downloadonionshare-4ff23fa9bd927f7300b2ded3f44b3af17fb6780e.tar.gz
onionshare-4ff23fa9bd927f7300b2ded3f44b3af17fb6780e.zip
Merge branch 'develop' into upgrade-flask
-rw-r--r--RELEASE.md1
-rwxr-xr-xbuild-source.sh4
-rw-r--r--cli/onionshare_cli/censorship.py229
-rw-r--r--cli/onionshare_cli/common.py37
-rw-r--r--cli/onionshare_cli/onion.py14
-rw-r--r--cli/onionshare_cli/settings.py1
-rw-r--r--cli/onionshare_cli/web/send_base_mode.py18
-rw-r--r--cli/onionshare_cli/web/web.py6
-rw-r--r--cli/tests/test_cli_settings.py1
-rw-r--r--cli/tests/test_cli_web.py5
-rw-r--r--desktop/onionshare/connection_tab.py681
-rw-r--r--desktop/onionshare/gui_common.py107
-rw-r--r--desktop/onionshare/main_window.py86
-rw-r--r--desktop/onionshare/resources/countries/ar.json1
-rw-r--r--desktop/onionshare/resources/countries/bn.json1
-rw-r--r--desktop/onionshare/resources/countries/de.json1
-rw-r--r--desktop/onionshare/resources/countries/el.json1
-rw-r--r--desktop/onionshare/resources/countries/en.json1
-rw-r--r--desktop/onionshare/resources/countries/es.json1
-rw-r--r--desktop/onionshare/resources/countries/fi.json1
-rw-r--r--desktop/onionshare/resources/countries/fr.json1
-rw-r--r--desktop/onionshare/resources/countries/gl.json1
-rw-r--r--desktop/onionshare/resources/countries/is.json1
-rw-r--r--desktop/onionshare/resources/countries/ja.json1
-rw-r--r--desktop/onionshare/resources/countries/lt.json1
-rw-r--r--desktop/onionshare/resources/countries/nb_NO.json1
-rw-r--r--desktop/onionshare/resources/countries/pl.json1
-rw-r--r--desktop/onionshare/resources/countries/pt_BR.json1
-rw-r--r--desktop/onionshare/resources/countries/pt_PT.json1
-rw-r--r--desktop/onionshare/resources/countries/ru.json1
-rw-r--r--desktop/onionshare/resources/countries/sv.json1
-rw-r--r--desktop/onionshare/resources/countries/tr.json1
-rw-r--r--desktop/onionshare/resources/countries/uk.json1
-rw-r--r--desktop/onionshare/resources/countries/zh_Hans.json1
-rw-r--r--desktop/onionshare/resources/images/dark_logo_text_bg.pngbin0 -> 9967 bytes
-rw-r--r--desktop/onionshare/resources/images/light_logo_text_bg.pngbin0 -> 15778 bytes
-rw-r--r--desktop/onionshare/resources/images/tor-connect-ship.pngbin0 -> 23640 bytes
-rw-r--r--desktop/onionshare/resources/images/tor-connect-smoke.pngbin0 -> 31638 bytes
-rw-r--r--desktop/onionshare/resources/images/tor-connect-stars.pngbin0 -> 16064 bytes
-rw-r--r--desktop/onionshare/resources/locale/en.json58
-rw-r--r--desktop/onionshare/settings_parent_tab.py72
-rw-r--r--desktop/onionshare/settings_tab.py7
-rw-r--r--desktop/onionshare/tab_widget.py149
-rw-r--r--desktop/onionshare/tor_connection.py140
-rw-r--r--desktop/onionshare/tor_settings_tab.py82
-rwxr-xr-xdesktop/scripts/countries-update-list.py42
-rwxr-xr-xdesktop/scripts/get-tor-linux.py6
-rwxr-xr-xdesktop/scripts/get-tor-osx.py6
-rw-r--r--desktop/scripts/get-tor-windows.py6
-rw-r--r--docs/source/advanced.rst55
-rw-r--r--docs/source/install.rst13
-rw-r--r--docs/source/security.rst41
52 files changed, 1436 insertions, 452 deletions
diff --git a/RELEASE.md b/RELEASE.md
index 4e8da66b..76c33a4b 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -31,6 +31,7 @@ Finalize localization:
- [ ] Merge all the translations from weblate
- [ ] In `docs` run `poetry run ./check-weblate.py [API_KEY]` to see which translations are >90% in the app and docs
- [ ] Edit `cli/onionshare_cli/settings.py`, make sure `self.available_locales` lists only locales that are >90% translated
+- [ ] From the `desktop` folder in the virtual env, run `./scripts/countries-update-list.py` to make sure the localized country list for censorship circumvention is available in all available languages
- [ ] Edit `docs/source/conf.py`, make sure `languages` lists only languages that are >90% translated
- [ ] Edit `docs/build.sh` and make sure `LOCALES=` lists the same languages as above, in `docs/source/conf.py`
- [ ] Make sure the latest documentation is built and committed:
diff --git a/build-source.sh b/build-source.sh
index 0946683d..7ca9e462 100755
--- a/build-source.sh
+++ b/build-source.sh
@@ -36,7 +36,7 @@ fi
mkdir -p build/source
mkdir -p dist
cd build/source
-git clone https://github.com/onionshare/onionshare.git
+git clone --single-branch --branch $TAG --depth 1 https://github.com/onionshare/onionshare.git
cd onionshare
# Verify tag
@@ -65,7 +65,7 @@ git checkout $TAG
# Delete .git, compress, and PGP sign
cd ..
rm -rf onionshare/.git
-tar -cf onionshare-$VERSION.tar.gz onionshare/
+tar -czf onionshare-$VERSION.tar.gz onionshare/
# Move source package to dist
cd ../..
diff --git a/cli/onionshare_cli/censorship.py b/cli/onionshare_cli/censorship.py
index c1845f6a..4ab5c366 100644
--- a/cli/onionshare_cli/censorship.py
+++ b/cli/onionshare_cli/censorship.py
@@ -22,6 +22,12 @@ import requests
from .meek import MeekNotRunning
+class CensorshipCircumventionError(Exception):
+ """
+ There was a problem connecting to the Tor CensorshipCircumvention API.
+ """
+
+
class CensorshipCircumvention(object):
"""
Connect to the Tor Moat APIs to retrieve censorship
@@ -47,7 +53,7 @@ class CensorshipCircumvention(object):
self.common.log(
"CensorshipCircumvention",
"__init__",
- "Using Meek with CensorShipCircumvention API",
+ "Using Meek with CensorshipCircumvention API",
)
self.api_proxies = self.meek.meek_proxies
if onion:
@@ -58,7 +64,7 @@ class CensorshipCircumvention(object):
self.common.log(
"CensorshipCircumvention",
"__init__",
- "Using Tor with CensorShipCircumvention API",
+ "Using Tor with CensorshipCircumvention API",
)
(socks_address, socks_port) = self.onion.get_tor_socks_port()
self.api_proxies = {
@@ -84,31 +90,34 @@ class CensorshipCircumvention(object):
if country:
data = {"country": country}
- r = requests.post(
- endpoint,
- json=data,
- headers={"Content-Type": "application/vnd.api+json"},
- proxies=self.api_proxies,
- )
- if r.status_code != 200:
- self.common.log(
- "CensorshipCircumvention",
- "censorship_obtain_map",
- f"status_code={r.status_code}",
+ try:
+ r = requests.post(
+ endpoint,
+ json=data,
+ headers={"Content-Type": "application/vnd.api+json"},
+ proxies=self.api_proxies,
)
- return False
+ if r.status_code != 200:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_map",
+ f"status_code={r.status_code}",
+ )
+ return False
- result = r.json()
+ result = r.json()
- if "errors" in result:
- self.common.log(
- "CensorshipCircumvention",
- "censorship_obtain_map",
- f"errors={result['errors']}",
- )
- return False
+ if "errors" in result:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_map",
+ f"errors={result['errors']}",
+ )
+ return False
- return result
+ return result
+ except requests.exceptions.RequestException as e:
+ raise CensorshipCircumventionError(e)
def request_settings(self, country=False, transports=False):
"""
@@ -127,45 +136,53 @@ class CensorshipCircumvention(object):
endpoint = "https://bridges.torproject.org/moat/circumvention/settings"
data = {}
if country:
- data = {"country": country}
- if transports:
- data.append({"transports": transports})
- r = requests.post(
- endpoint,
- json=data,
- headers={"Content-Type": "application/vnd.api+json"},
- proxies=self.api_proxies,
- )
- if r.status_code != 200:
self.common.log(
"CensorshipCircumvention",
"censorship_obtain_settings",
- f"status_code={r.status_code}",
+ f"Trying to obtain bridges for country={country}",
)
- return False
+ data = {"country": country}
+ if transports:
+ data.append({"transports": transports})
+ try:
+ r = requests.post(
+ endpoint,
+ json=data,
+ headers={"Content-Type": "application/vnd.api+json"},
+ proxies=self.api_proxies,
+ )
+ if r.status_code != 200:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_settings",
+ f"status_code={r.status_code}",
+ )
+ return False
- result = r.json()
+ result = r.json()
- if "errors" in result:
- self.common.log(
- "CensorshipCircumvention",
- "censorship_obtain_settings",
- f"errors={result['errors']}",
- )
- return False
+ if "errors" in result:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_settings",
+ f"errors={result['errors']}",
+ )
+ return False
- # There are no settings - perhaps this country doesn't require censorship circumvention?
- # This is not really an error, so we can just check if False and assume direct Tor
- # connection will work.
- if not "settings" in result:
- self.common.log(
- "CensorshipCircumvention",
- "censorship_obtain_settings",
- "No settings found for this country",
- )
- return False
+ # There are no settings - perhaps this country doesn't require censorship circumvention?
+ # This is not really an error, so we can just check if False and assume direct Tor
+ # connection will work.
+ if not "settings" in result:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_settings",
+ "No settings found for this country",
+ )
+ return False
- return result
+ return result
+ except requests.exceptions.RequestException as e:
+ raise CensorshipCircumventionError(e)
def request_builtin_bridges(self):
"""
@@ -174,27 +191,103 @@ class CensorshipCircumvention(object):
if not self.api_proxies:
return False
endpoint = "https://bridges.torproject.org/moat/circumvention/builtin"
- r = requests.post(
- endpoint,
- headers={"Content-Type": "application/vnd.api+json"},
- proxies=self.api_proxies,
+ try:
+ r = requests.post(
+ endpoint,
+ headers={"Content-Type": "application/vnd.api+json"},
+ proxies=self.api_proxies,
+ )
+ if r.status_code != 200:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_builtin_bridges",
+ f"status_code={r.status_code}",
+ )
+ return False
+
+ result = r.json()
+
+ if "errors" in result:
+ self.common.log(
+ "CensorshipCircumvention",
+ "censorship_obtain_builtin_bridges",
+ f"errors={result['errors']}",
+ )
+ return False
+
+ return result
+ except requests.exceptions.RequestException as e:
+ raise CensorshipCircumventionError(e)
+
+ def save_settings(self, settings, bridge_settings):
+ """
+ Checks the bridges and saves them in settings.
+ """
+ bridges_ok = False
+ self.settings = settings
+
+ # @TODO there might be several bridge types recommended.
+ # Should we attempt to iterate over each type if one of them fails to connect?
+ # But if so, how to stop it starting 3 separate Tor connection threads?
+ # for bridges in request_bridges["settings"]:
+ bridges = bridge_settings["settings"][0]["bridges"]
+ self.common.log(
+ "CensorshipCircumvention",
+ "save_settings",
+ f"Obtained bridges: {bridges}",
)
- if r.status_code != 200:
+ bridge_strings = bridges["bridge_strings"]
+ bridge_type = bridges["type"]
+ bridge_source = bridges["source"]
+
+ # If the recommended bridge source is to use the built-in
+ # bridges, set that in our settings, as if the user had
+ # selected the built-in bridges for a specific PT themselves.
+ #
+ if bridge_source == "builtin":
self.common.log(
"CensorshipCircumvention",
- "censorship_obtain_builtin_bridges",
- f"status_code={r.status_code}",
+ "save_settings",
+ "Will be using built-in bridges",
)
- return False
+ self.settings.set("bridges_type", "built-in")
+ if bridge_type == "obfs4":
+ self.settings.set("bridges_builtin_pt", "obfs4")
+ if bridge_type == "snowflake":
+ self.settings.set("bridges_builtin_pt", "snowflake")
+ if bridge_type == "meek":
+ self.settings.set("bridges_builtin_pt", "meek-azure")
+ bridges_ok = True
+ else:
+ self.common.log(
+ "CensorshipCircumvention",
+ "save_settings",
+ "Will be using custom bridges",
+ )
+ # Any other type of bridge we can treat as custom.
+ self.settings.set("bridges_type", "custom")
+
+ # Sanity check the bridges provided from the Tor API before saving
+ bridges_checked = self.common.check_bridges_valid(bridge_strings)
- result = r.json()
+ if bridges_checked:
+ self.settings.set("bridges_custom", "\n".join(bridges_checked))
+ bridges_ok = True
- if "errors" in result:
+ # If we got any good bridges, save them to settings and return.
+ if bridges_ok:
self.common.log(
"CensorshipCircumvention",
- "censorship_obtain_builtin_bridges",
- f"errors={result['errors']}",
+ "save_settings",
+ "Saving settings with automatically-obtained bridges",
+ )
+ self.settings.set("bridges_enabled", True)
+ self.settings.save()
+ return True
+ else:
+ self.common.log(
+ "CensorshipCircumvention",
+ "save_settings",
+ "Could not use any of the obtained bridges.",
)
return False
-
- return result
diff --git a/cli/onionshare_cli/common.py b/cli/onionshare_cli/common.py
index 82ac9883..ceec654d 100644
--- a/cli/onionshare_cli/common.py
+++ b/cli/onionshare_cli/common.py
@@ -28,6 +28,7 @@ import sys
import threading
import time
import shutil
+import re
from pkg_resources import resource_filename
import colorama
@@ -312,7 +313,6 @@ class Common:
"""
Returns the absolute path of a resource
"""
- self.log("Common", "get_resource_path", f"filename={filename}")
path = resource_filename("onionshare_cli", os.path.join("resources", filename))
self.log("Common", "get_resource_path", f"filename={filename}, path={path}")
return path
@@ -467,6 +467,40 @@ class Common:
r = random.SystemRandom()
return "-".join(r.choice(wordlist) for _ in range(word_count))
+ def check_bridges_valid(self, bridges):
+ """
+ Does a regex check against a supplied list of bridges, to make sure they
+ are valid strings depending on the bridge type.
+ """
+ valid_bridges = []
+ self.log("Common", "check_bridges_valid", "Checking bridge syntax")
+ for bridge in bridges:
+ if bridge != "":
+ # Check the syntax of the custom bridge to make sure it looks legitimate
+ ipv4_pattern = re.compile(
+ "(obfs4\s+)?(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):([0-9]+)(\s+)([A-Z0-9]+)(.+)$"
+ )
+ ipv6_pattern = re.compile(
+ "(obfs4\s+)?\[(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\]:[0-9]+\s+[A-Z0-9]+(.+)$"
+ )
+ meek_lite_pattern = re.compile(
+ "(meek_lite)(\s)+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)(\s)+([0-9A-Z]+)(\s)+url=(.+)(\s)+front=(.+)"
+ )
+ snowflake_pattern = re.compile(
+ "(snowflake)(\s)+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)(\s)+([0-9A-Z]+)"
+ )
+ if (
+ ipv4_pattern.match(bridge)
+ or ipv6_pattern.match(bridge)
+ or meek_lite_pattern.match(bridge)
+ or snowflake_pattern.match(bridge)
+ ):
+ valid_bridges.append(bridge)
+ if valid_bridges:
+ return valid_bridges
+ else:
+ return False
+
def is_flatpak(self):
"""
Returns True if OnionShare is running in a Flatpak sandbox
@@ -479,6 +513,7 @@ class Common:
"""
return os.environ.get("SNAP_INSTANCE_NAME") == "onionshare"
+
@staticmethod
def random_string(num_bytes, output_len=None):
"""
diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py
index 6ef4af2c..6e1dad74 100644
--- a/cli/onionshare_cli/onion.py
+++ b/cli/onionshare_cli/onion.py
@@ -954,20 +954,6 @@ class Onion(object):
"update_builtin_bridges",
f"Obtained bridges: {builtin_bridges}",
)
- if builtin_bridges["meek"]:
- # Meek bridge needs to be defined as "meek_lite", not "meek",
- # for it to work with obfs4proxy.
- # We also refer to this bridge type as 'meek-azure' in our settings.
- # So first, rename the key in the dict
- builtin_bridges["meek-azure"] = builtin_bridges.pop("meek")
- new_meek_bridges = []
- # Now replace the values. They also need the url/front params appended
- for item in builtin_bridges["meek-azure"]:
- newline = item.replace("meek", "meek_lite")
- new_meek_bridges.append(
- f"{newline} url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com"
- )
- builtin_bridges["meek-azure"] = new_meek_bridges
# Save the new settings
self.settings.set("bridges_builtin", builtin_bridges)
self.settings.save()
diff --git a/cli/onionshare_cli/settings.py b/cli/onionshare_cli/settings.py
index 52e9c972..cab64681 100644
--- a/cli/onionshare_cli/settings.py
+++ b/cli/onionshare_cli/settings.py
@@ -103,6 +103,7 @@ class Settings(object):
"socket_file_path": "/var/run/tor/control",
"auth_type": "no_auth",
"auth_password": "",
+ "auto_connect": False,
"use_autoupdate": True,
"autoupdate_timestamp": None,
"bridges_enabled": False,
diff --git a/cli/onionshare_cli/web/send_base_mode.py b/cli/onionshare_cli/web/send_base_mode.py
index e608298b..d690c98d 100644
--- a/cli/onionshare_cli/web/send_base_mode.py
+++ b/cli/onionshare_cli/web/send_base_mode.py
@@ -44,8 +44,9 @@ class SendBaseModeWeb:
self.download_filesize = None
self.zip_writer = None
- # Store the tempfile objects here, so when they're garbage collected the files are deleted
- self.gzip_files = []
+ # Create a temporary dir to store gzip files in
+ self.gzip_tmp_dir = tempfile.TemporaryDirectory(dir=self.common.build_tmp_dir())
+ self.gzip_counter = 0
# If autostop_sharing, only allow one download at a time
self.download_in_progress = False
@@ -193,15 +194,12 @@ class SendBaseModeWeb:
# gzip compress the individual file, if it hasn't already been compressed
if use_gzip:
if filesystem_path not in self.gzip_individual_files:
- self.gzip_files.append(
- tempfile.NamedTemporaryFile("wb+", dir=self.common.build_tmp_dir())
+ gzip_filename = os.path.join(
+ self.gzip_tmp_dir.name, str(self.gzip_counter)
)
- gzip_file = self.gzip_files[-1]
- self._gzip_compress(filesystem_path, gzip_file.name, 6, None)
- self.gzip_individual_files[filesystem_path] = gzip_file.name
-
- # Cleanup this temp file
- self.web.cleanup_tempfiles.append(gzip_file)
+ self.gzip_counter += 1
+ self._gzip_compress(filesystem_path, gzip_filename, 6, None)
+ self.gzip_individual_files[filesystem_path] = gzip_filename
file_to_download = self.gzip_individual_files[filesystem_path]
filesize = os.path.getsize(self.gzip_individual_files[filesystem_path])
diff --git a/cli/onionshare_cli/web/web.py b/cli/onionshare_cli/web/web.py
index 64844b5c..fdbed567 100644
--- a/cli/onionshare_cli/web/web.py
+++ b/cli/onionshare_cli/web/web.py
@@ -171,7 +171,6 @@ class Web:
self.socketio.init_app(self.app)
self.chat_mode = ChatModeWeb(self.common, self)
- self.cleanup_tempfiles = []
self.cleanup_tempdirs = []
def get_mode(self):
@@ -405,13 +404,8 @@ class Web:
"""
self.common.log("Web", "cleanup")
- # Close all of the tempfile.NamedTemporaryFile
- for file in self.cleanup_tempfiles:
- file.close()
-
# Clean up the tempfile.NamedTemporaryDirectory objects
for dir in self.cleanup_tempdirs:
dir.cleanup()
- self.cleanup_tempfiles = []
self.cleanup_tempdirs = []
diff --git a/cli/tests/test_cli_settings.py b/cli/tests/test_cli_settings.py
index f370a674..ead4630b 100644
--- a/cli/tests/test_cli_settings.py
+++ b/cli/tests/test_cli_settings.py
@@ -37,6 +37,7 @@ class TestSettings:
"bridges_builtin": {},
"persistent_tabs": [],
"theme": 0,
+ "auto_connect": False,
}
for key in settings_obj._settings:
# Skip locale, it will not always default to the same thing
diff --git a/cli/tests/test_cli_web.py b/cli/tests/test_cli_web.py
index f6076ef9..335c3a1a 100644
--- a/cli/tests/test_cli_web.py
+++ b/cli/tests/test_cli_web.py
@@ -50,7 +50,6 @@ def web_obj(temp_dir, common_obj, mode, num_files=0):
web = Web(common_obj, False, mode_settings, mode)
web.running = True
- web.cleanup_tempfiles == []
web.cleanup_tempdirs == []
web.app.testing = True
@@ -308,17 +307,13 @@ class TestWeb:
def test_cleanup(self, common_obj, temp_dir_1024):
web = web_obj(temp_dir_1024, common_obj, "share", 3)
- temp_file = tempfile.NamedTemporaryFile()
temp_dir = tempfile.TemporaryDirectory()
- web.cleanup_tempfiles = [temp_file]
web.cleanup_tempdirs = [temp_dir]
web.cleanup()
- assert os.path.exists(temp_file.name) is False
assert os.path.exists(temp_dir.name) is False
- assert web.cleanup_tempfiles == []
assert web.cleanup_tempdirs == []
diff --git a/desktop/onionshare/connection_tab.py b/desktop/onionshare/connection_tab.py
new file mode 100644
index 00000000..1cf3c376
--- /dev/null
+++ b/desktop/onionshare/connection_tab.py
@@ -0,0 +1,681 @@
+# -*- coding: utf-8 -*-
+"""
+OnionShare | https://onionshare.org/
+
+Copyright (C) 2014-2021 Micah Lee, et al. <micah@micahflee.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import json
+import os
+from PySide2 import QtCore, QtWidgets, QtGui
+
+from onionshare_cli.censorship import (
+ CensorshipCircumvention,
+ CensorshipCircumventionError,
+)
+from onionshare_cli.meek import (
+ MeekNotRunning,
+ MeekNotFound,
+)
+from onionshare_cli.settings import Settings
+
+from . import strings
+from .gui_common import GuiCommon, ToggleCheckbox
+from .tor_connection import TorConnectionWidget
+from .update_checker import UpdateThread
+from .widgets import Alert
+
+
+class AutoConnectTab(QtWidgets.QWidget):
+ """
+ Initial Tab that appears in the very beginning to ask user if
+ should auto connect.
+ """
+
+ close_this_tab = QtCore.Signal()
+ tor_is_connected = QtCore.Signal()
+ tor_is_disconnected = QtCore.Signal()
+
+ def __init__(self, common, tab_id, status_bar, window, parent=None):
+ super(AutoConnectTab, self).__init__()
+ self.common = common
+ self.common.log("AutoConnectTab", "__init__")
+
+ self.status_bar = status_bar
+ self.tab_id = tab_id
+ self.window = window
+ self.parent = parent
+
+ # Was auto connected?
+ self.curr_settings = Settings(common)
+ self.curr_settings.load()
+ self.auto_connect_enabled = self.curr_settings.get("auto_connect")
+
+ # Rocket ship animation images
+ self.anim_stars = AnimStars(self, self.window)
+ self.anim_ship = AnimShip(self, self.window)
+ self.anim_smoke = AnimSmoke(self, self.window)
+
+ # Onionshare logo
+ self.image_label = QtWidgets.QLabel()
+ self.image_label.setPixmap(
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ GuiCommon.get_resource_path(
+ os.path.join(
+ "images", f"{common.gui.color_mode}_logo_text_bg.png"
+ )
+ )
+ )
+ )
+ )
+ self.image_label.setFixedSize(322, 65)
+ image_layout = QtWidgets.QVBoxLayout()
+ image_layout.addWidget(self.image_label)
+ self.image = QtWidgets.QWidget()
+ self.image.setLayout(image_layout)
+
+ # First launch widget
+ self.first_launch_widget = AutoConnectFirstLaunchWidget(
+ self.common, self.curr_settings
+ )
+ self.first_launch_widget.toggle_auto_connect.connect(self.toggle_auto_connect)
+ self.first_launch_widget.connect_clicked.connect(
+ self.first_launch_widget_connect_clicked
+ )
+ self.first_launch_widget.open_tor_settings.connect(self.open_tor_settings)
+ self.first_launch_widget.show()
+
+ # Use bridge widget
+ self.use_bridge_widget = AutoConnectUseBridgeWidget(self.common)
+ self.use_bridge_widget.connect_clicked.connect(self.use_bridge_connect_clicked)
+ self.use_bridge_widget.try_again_clicked.connect(
+ self.first_launch_widget_connect_clicked
+ )
+ self.use_bridge_widget.open_tor_settings.connect(self.open_tor_settings)
+ self.use_bridge_widget.hide()
+
+ # Tor connection widget
+ self.tor_con = TorConnectionWidget(self.common, self.status_bar)
+ self.tor_con.success.connect(self.tor_con_success)
+ self.tor_con.fail.connect(self.tor_con_fail)
+ self.tor_con.update_progress.connect(self.anim_stars.update)
+ self.tor_con.update_progress.connect(self.anim_ship.update)
+ self.tor_con.update_progress.connect(self.anim_smoke.update)
+ self.tor_con.hide()
+
+ # Layout
+ content_layout = QtWidgets.QVBoxLayout()
+ content_layout.addStretch()
+ content_layout.addWidget(self.image)
+ content_layout.addWidget(self.first_launch_widget)
+ content_layout.addWidget(self.use_bridge_widget)
+ content_layout.addWidget(self.tor_con)
+ content_layout.addStretch()
+ content_layout.setAlignment(QtCore.Qt.AlignCenter)
+ content_widget = QtWidgets.QWidget()
+ content_widget.setLayout(content_layout)
+
+ self.layout = QtWidgets.QHBoxLayout()
+ self.layout.addWidget(content_widget)
+ self.layout.addStretch()
+
+ self.setLayout(self.layout)
+
+ def check_autoconnect(self):
+ """
+ After rendering, check if autoconnect was clicked, then start connecting
+ """
+ self.common.log("AutoConnectTab", "autoconnect_checking")
+ if self.auto_connect_enabled:
+ self.first_launch_widget.enable_autoconnect_checkbox.setChecked(True)
+ self.first_launch_widget_connect_clicked()
+
+ def toggle_auto_connect(self):
+ """
+ Auto connect checkbox clicked
+ """
+ self.common.log("AutoConnectTab", "autoconnect_checkbox_clicked")
+ self.curr_settings.set(
+ "auto_connect",
+ self.first_launch_widget.enable_autoconnect_checkbox.isChecked(),
+ )
+ self.curr_settings.save()
+
+ def open_tor_settings(self):
+ self.parent.open_settings_tab(from_autoconnect=True, active_tab="tor")
+
+ def first_launch_widget_connect_clicked(self):
+ """
+ Connect button in first launch widget clicked. Try to connect to tor.
+ """
+ self.common.log("AutoConnectTab", "first_launch_widget_connect_clicked")
+ self.first_launch_widget.hide_buttons()
+
+ self.tor_con.show()
+ self.tor_con.start(self.curr_settings)
+
+ def _got_bridges(self):
+ self.use_bridge_widget.progress.hide()
+ self.use_bridge_widget.progress_label.hide()
+ # Try and connect again
+ self.common.log(
+ "AutoConnectTab",
+ "_got_bridges",
+ "Got bridges. Trying to reconnect to Tor",
+ )
+ self.tor_con.show()
+ self.tor_con.start(self.curr_settings)
+
+ def _got_no_bridges(self):
+ # If we got no bridges, try connecting again using built-in obfs4 bridges
+ self.curr_settings.set("bridges_type", "built-in")
+ self.curr_settings.set("bridges_builtin_pt", "obfs4")
+ self.curr_settings.set("bridges_enabled", True)
+ self.curr_settings.save()
+
+ self._got_bridges()
+
+ def _censorship_progress_update(self, progress, summary):
+ self.use_bridge_widget.progress.setValue(int(progress))
+ self.use_bridge_widget.progress_label.setText(
+ f"<strong>{strings._('gui_autoconnect_circumventing_censorship')}</strong><br>{summary}"
+ )
+
+ def network_connection_error(self):
+ """
+ Display an error if there simply seems no network connection.
+ """
+ self.use_bridge_widget.connection_status_label.setText(
+ strings._("gui_autoconnect_failed_to_connect_to_tor")
+ )
+ self.use_bridge_widget.progress.hide()
+ self.use_bridge_widget.progress_label.hide()
+ self.use_bridge_widget.error_label.show()
+ self.use_bridge_widget.country_combobox.setEnabled(True)
+ self.use_bridge_widget.show_buttons()
+ self.use_bridge_widget.show()
+
+ def use_bridge_connect_clicked(self):
+ """
+ Connect button in use bridge widget clicked.
+ """
+ self.common.log(
+ "AutoConnectTab",
+ "use_bridge_connect_clicked",
+ "Trying to automatically obtain bridges",
+ )
+ self.use_bridge_widget.hide_buttons()
+ self.use_bridge_widget.progress.show()
+ self.use_bridge_widget.progress_label.show()
+
+ if self.use_bridge_widget.detect_automatic_radio.isChecked():
+ country = False
+ else:
+ country = self.use_bridge_widget.country_combobox.currentData().lower()
+
+ self._censorship_progress_update(
+ 50, strings._("gui_autoconnect_circumventing_censorship_starting_meek")
+ )
+ try:
+ self.common.gui.meek.start()
+ self.censorship_circumvention = CensorshipCircumvention(
+ self.common, self.common.gui.meek
+ )
+ self._censorship_progress_update(
+ 75,
+ strings._(
+ "gui_autoconnect_circumventing_censorship_requesting_bridges"
+ ),
+ )
+ bridge_settings = self.censorship_circumvention.request_settings(
+ country=country
+ )
+ self.common.gui.meek.cleanup()
+
+ if bridge_settings and self.censorship_circumvention.save_settings(
+ self.curr_settings, bridge_settings
+ ):
+ self._censorship_progress_update(
+ 100,
+ strings._("gui_autoconnect_circumventing_censorship_got_bridges"),
+ )
+ self._got_bridges()
+ else:
+ self._got_no_bridges()
+ except (
+ MeekNotRunning,
+ MeekNotFound,
+ ) as e:
+ self._got_no_bridges()
+ except CensorshipCircumventionError as e:
+ self.common.log(
+ "AutoConnectTab",
+ "use_bridge_connect_clicked",
+ "Request to the Tor Censorship Circumvention API failed. No network connection?",
+ )
+ self.network_connection_error()
+
+ def check_for_updates(self):
+ """
+ Check for OnionShare updates in a new thread, if enabled.
+ """
+ if self.common.platform == "Windows" or self.common.platform == "Darwin":
+ if self.common.settings.get("use_autoupdate"):
+
+ def update_available(update_url, installed_version, latest_version):
+ Alert(
+ self.common,
+ strings._("update_available").format(
+ update_url, installed_version, latest_version
+ ),
+ )
+
+ self.update_thread = UpdateThread(self.common, self.common.gui.onion)
+ self.update_thread.update_available.connect(update_available)
+ self.update_thread.start()
+
+ def tor_con_success(self):
+ """
+ Finished testing tor connection.
+ """
+ self.tor_con.hide()
+ self.first_launch_widget.show_buttons()
+ self.use_bridge_widget.show_buttons()
+ self.use_bridge_widget.progress.hide()
+ self.use_bridge_widget.progress_label.hide()
+
+ if self.common.gui.onion.is_authenticated() and not self.tor_con.wasCanceled():
+ # Tell the tabs that Tor is connected
+ self.tor_is_connected.emit()
+ # After connecting to Tor, check for updates
+ self.check_for_updates()
+ # Close the tab
+ self.close_this_tab.emit()
+
+ def tor_con_fail(self, msg):
+ """
+ Finished testing tor connection.
+ """
+ self.tor_con.hide()
+
+ # If we're on first launch, switch to use bridge
+ if self.first_launch_widget.isVisible():
+ self.first_launch_widget.show_buttons()
+ self.first_launch_widget.hide()
+ self.use_bridge_widget.show()
+ else:
+ self.use_bridge_widget.show_buttons()
+
+ def reload_settings(self):
+ """
+ Reload the latest Tor settings, and reset to show the
+ first-launch widget if it had been hidden.
+ """
+ self.curr_settings.load()
+ self.auto_connect_enabled = self.curr_settings.get("auto_connect")
+ self.first_launch_widget.enable_autoconnect_checkbox.setChecked(
+ self.auto_connect_enabled
+ )
+ self.use_bridge_widget.hide()
+ self.first_launch_widget.show_buttons()
+ self.first_launch_widget.show()
+
+
+class Anim(QtWidgets.QLabel):
+ """
+ Rocket ship animation base class
+ """
+
+ force_update = QtCore.Signal(int)
+
+ def __init__(self, parent, window, w, h, filename):
+ super(Anim, self).__init__(parent=parent)
+
+ self.window = window
+ self.window.window_resized.connect(self.update_same_percent)
+
+ self.w = w
+ self.h = h
+ self.percent = 0
+ self.used_percentages = []
+
+ self.setPixmap(
+ QtGui.QPixmap.fromImage(
+ QtGui.QImage(
+ GuiCommon.get_resource_path(os.path.join("images", filename))
+ )
+ )
+ )
+ self.setFixedSize(self.w, self.h)
+ self.update(0)
+
+ self.force_update.connect(self.update)
+
+ def update_same_percent(self):
+ self.update(self.percent)
+
+ def update(self, percent):
+ self.percent = percent
+ self.move()
+ self.setGeometry(int(self.x), int(self.y), int(self.w), int(self.h))
+
+ def move(self):
+ # Implement in child
+ pass
+
+
+class AnimStars(Anim):
+ """
+ Rocket ship animation part: stars
+ """
+
+ def __init__(self, parent, window):
+ super(AnimStars, self).__init__(
+ parent, window, 740, 629, "tor-connect-stars.png"
+ )
+
+ def move(self):
+ self.x = self.window.width() - self.w
+ self.y = 0
+ # Stars don't move until 10%, then move down
+ if self.percent >= 10:
+ self.y += self.percent * 6.6
+
+
+class AnimShip(Anim):
+ """
+ Rocket ship animation part: ship
+ """
+
+ def __init__(self, parent, window):
+ super(AnimShip, self).__init__(parent, window, 239, 545, "tor-connect-ship.png")
+
+ def move(self):
+ self.x = self.window.width() - self.w - 150
+ self.y = self.window.height() - self.h - 40
+ # Ship moves up
+ self.y -= self.percent * 6.6
+
+
+class AnimSmoke(Anim):
+ """
+ Rocket ship animation part: smoke
+ """
+
+ def __init__(self, parent, window):
+ super(AnimSmoke, self).__init__(
+ parent, window, 522, 158, "tor-connect-smoke.png"
+ )
+
+ def move(self):
+ self.x = self.window.width() - self.w
+ self.y = self.window.height() - self.h + 50
+ # Smoke moves up until 50%, then moves down
+ self.y -= self.percent * 6.6
+ if self.percent >= 50:
+ self.y += self.percent * 6.7
+
+
+class AutoConnectFirstLaunchWidget(QtWidgets.QWidget):
+ """
+ When you first launch OnionShare, this is the widget that is displayed
+ """
+
+ toggle_auto_connect = QtCore.Signal()
+ connect_clicked = QtCore.Signal()
+ open_tor_settings = QtCore.Signal()
+
+ def __init__(self, common, settings):
+ super(AutoConnectFirstLaunchWidget, self).__init__()
+ self.common = common
+ self.common.log("AutoConnectFirstLaunchWidget", "__init__")
+
+ self.settings = settings
+
+ # Description and checkbox
+ description_label = QtWidgets.QLabel(strings._("gui_autoconnect_description"))
+ self.enable_autoconnect_checkbox = ToggleCheckbox(
+ strings._("gui_enable_autoconnect_checkbox")
+ )
+ self.enable_autoconnect_checkbox.setChecked(self.settings.get("auto_connect"))
+ self.enable_autoconnect_checkbox.clicked.connect(self._toggle_auto_connect)
+ self.enable_autoconnect_checkbox.setFixedWidth(400)
+ self.enable_autoconnect_checkbox.setStyleSheet(
+ common.gui.css["enable_autoconnect"]
+ )
+ description_layout = QtWidgets.QVBoxLayout()
+ description_layout.addWidget(description_label)
+ description_layout.addWidget(self.enable_autoconnect_checkbox)
+ description_widget = QtWidgets.QWidget()
+ description_widget.setLayout(description_layout)
+
+ # Buttons
+ self.connect_button = QtWidgets.QPushButton(strings._("gui_autoconnect_start"))
+ self.connect_button.clicked.connect(self._connect_clicked)
+ self.connect_button.setFixedWidth(150)
+ self.connect_button.setStyleSheet(common.gui.css["autoconnect_start_button"])
+ self.configure_button = QtWidgets.QPushButton(
+ strings._("gui_autoconnect_configure")
+ )
+ self.configure_button.clicked.connect(self._open_tor_settings)
+ self.configure_button.setFlat(True)
+ self.configure_button.setStyleSheet(
+ common.gui.css["autoconnect_configure_button"]
+ )
+ cta_layout = QtWidgets.QHBoxLayout()
+ cta_layout.addWidget(self.connect_button)
+ cta_layout.addWidget(self.configure_button)
+ cta_widget = QtWidgets.QWidget()
+ cta_widget.setLayout(cta_layout)
+
+ # Layout
+ layout = QtWidgets.QVBoxLayout()
+ layout.addWidget(description_widget)
+ layout.addWidget(cta_widget)
+ self.setLayout(layout)
+
+ def hide_buttons(self):
+ self.connect_button.hide()
+ self.configure_button.hide()
+
+ def show_buttons(self):
+ self.connect_button.show()
+ self.configure_button.show()
+
+ def _toggle_auto_connect(self):
+ self.toggle_auto_connect.emit()
+
+ def _connect_clicked(self):
+ self.connect_clicked.emit()
+
+ def _open_tor_settings(self):
+ self.open_tor_settings.emit()
+
+
+class AutoConnectUseBridgeWidget(QtWidgets.QWidget):
+ """
+ If connecting fails, this is the widget that helps the user bypass censorship
+ """
+
+ connect_clicked = QtCore.Signal()
+ try_again_clicked = QtCore.Signal()
+ open_tor_settings = QtCore.Signal()
+
+ def __init__(self, common):
+ super(AutoConnectUseBridgeWidget, self).__init__()
+ self.common = common
+ self.common.log("AutoConnectUseBridgeWidget", "__init__")
+
+ # Heading label when we fail to connect to Tor.
+ self.connection_status_label = QtWidgets.QLabel(
+ strings._("gui_autoconnect_failed_to_connect_to_tor")
+ )
+ self.connection_status_label.setTextFormat(QtCore.Qt.RichText)
+ self.connection_status_label.setStyleSheet(
+ common.gui.css["autoconnect_failed_to_connect_label"]
+ )
+
+ # Description
+ self.description_label = QtWidgets.QLabel(
+ strings._("gui_autoconnect_bridge_description")
+ )
+ self.description_label.setTextFormat(QtCore.Qt.RichText)
+ self.description_label.setWordWrap(True)
+
+ # Detection preference
+ self.detect_automatic_radio = QtWidgets.QRadioButton(
+ strings._("gui_autoconnect_bridge_detect_automatic")
+ )
+ self.detect_automatic_radio.toggled.connect(self._detect_automatic_toggled)
+ self.detect_manual_radio = QtWidgets.QRadioButton(
+ strings._("gui_autoconnect_bridge_detect_manual")
+ )
+ self.detect_manual_radio.toggled.connect(self._detect_manual_toggled)
+ detect_layout = QtWidgets.QVBoxLayout()
+ detect_layout.addWidget(self.detect_automatic_radio)
+ detect_layout.addWidget(self.detect_manual_radio)
+
+ # Country list
+ locale = self.common.settings.get("locale")
+ if not locale:
+ locale = "en"
+
+ with open(
+ GuiCommon.get_resource_path(os.path.join("countries", f"{locale}.json"))
+ ) as f:
+ countries = json.loads(f.read())
+
+ self.country_combobox = QtWidgets.QComboBox()
+ self.country_combobox.setStyleSheet(
+ common.gui.css["autoconnect_countries_combobox"]
+ )
+ for country_code in countries:
+ self.country_combobox.addItem(countries[country_code], country_code)
+
+ # Task label
+ self.task_label = QtWidgets.QLabel()
+ self.task_label.setStyleSheet(common.gui.css["autoconnect_task_label"])
+ self.task_label.setAlignment(QtCore.Qt.AlignCenter)
+ self.task_label.hide()
+
+ # Buttons
+ self.connect_button = QtWidgets.QPushButton(
+ strings._("gui_autoconnect_bridge_start")
+ )
+ self.connect_button.clicked.connect(self._connect_clicked)
+ self.connect_button.setFixedWidth(150)
+ self.connect_button.setStyleSheet(common.gui.css["autoconnect_start_button"])
+
+ self.try_again_button = QtWidgets.QPushButton(
+ strings._("gui_autoconnect_try_again_without_a_bridge")
+ )
+ self.try_again_button.clicked.connect(self._try_again_clicked)
+ self.try_again_button.setStyleSheet(common.gui.css["autoconnect_start_button"])
+
+ self.configure_button = QtWidgets.QPushButton(
+ strings._("gui_autoconnect_configure")
+ )
+ self.configure_button.clicked.connect(self._open_tor_settings)
+ self.configure_button.setFlat(True)
+ self.configure_button.setStyleSheet(
+ common.gui.css["autoconnect_configure_button"]
+ )
+
+ # Error label
+ self.error_label = QtWidgets.QLabel(
+ strings._("gui_autoconnect_could_not_connect_to_tor_api")
+ )
+ self.error_label.setStyleSheet(self.common.gui.css["tor_settings_error"])
+ self.error_label.setWordWrap(True)
+ self.error_label.hide()
+
+ self.progress = QtWidgets.QProgressBar()
+ self.progress.setRange(0, 100)
+ self.progress_label = QtWidgets.QLabel(
+ strings._("gui_autoconnect_circumventing_censorship")
+ )
+ self.progress_label.setAlignment(QtCore.Qt.AlignHCenter)
+ self.progress.hide()
+ self.progress_label.hide()
+
+ cta_layout = QtWidgets.QHBoxLayout()
+ cta_layout.addWidget(self.connect_button)
+ cta_layout.addWidget(self.try_again_button)
+ cta_layout.addWidget(self.configure_button)
+ cta_layout.addStretch()
+ cta_widget = QtWidgets.QWidget()
+ cta_widget.setLayout(cta_layout)
+
+ # Layout
+ layout = QtWidgets.QVBoxLayout()
+ layout.addWidget(self.connection_status_label)
+ layout.addWidget(self.description_label)
+ layout.addLayout(detect_layout)
+ layout.addWidget(self.country_combobox)
+ layout.addWidget(self.task_label)
+ layout.addWidget(cta_widget)
+ layout.addWidget(self.progress)
+ layout.addWidget(self.progress_label)
+ layout.addWidget(self.error_label)
+ self.setLayout(layout)
+
+ self.detect_automatic_radio.setChecked(True)
+
+ def hide_buttons(self):
+ self.connect_button.hide()
+ self.try_again_button.hide()
+ self.configure_button.hide()
+ self.description_label.hide()
+ self.error_label.hide()
+ self.detect_automatic_radio.hide()
+ self.detect_manual_radio.hide()
+
+ def show_buttons(self):
+ self.connect_button.show()
+ self.try_again_button.show()
+ self.description_label.show()
+ self.configure_button.show()
+ self.detect_automatic_radio.show()
+ self.detect_manual_radio.show()
+
+ def _detect_automatic_toggled(self):
+ self.country_combobox.setEnabled(False)
+ self.country_combobox.hide()
+
+ def _detect_manual_toggled(self):
+ self.country_combobox.setEnabled(True)
+ self.country_combobox.show()
+
+ def _connect_clicked(self):
+ self.country_combobox.setEnabled(False)
+ self.hide_buttons()
+ self.connection_status_label.setText(
+ strings._("gui_autoconnect_trying_to_connect_to_tor")
+ )
+ self.connect_clicked.emit()
+
+ def _try_again_clicked(self):
+ self.connection_status_label.setText(
+ strings._("gui_autoconnect_trying_to_connect_to_tor")
+ )
+ self.country_combobox.setEnabled(False)
+ self.country_combobox.hide()
+ self.hide_buttons()
+ self.try_again_clicked.emit()
+
+ def _open_tor_settings(self):
+ self.open_tor_settings.emit()
diff --git a/desktop/onionshare/gui_common.py b/desktop/onionshare/gui_common.py
index cda40c1e..c717fd22 100644
--- a/desktop/onionshare/gui_common.py
+++ b/desktop/onionshare/gui_common.py
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import shutil
from pkg_resources import resource_filename
+from PySide2 import QtCore, QtWidgets, QtGui
from . import strings
from onionshare_cli.onion import (
@@ -39,6 +40,7 @@ from onionshare_cli.onion import (
TorTooOldStealth,
PortNotAvailable,
)
+from onionshare_cli.meek import Meek
class GuiCommon:
@@ -77,6 +79,9 @@ class GuiCommon:
os.makedirs(self.events_dir, 0o700, True)
self.events_filename = os.path.join(self.events_dir, "events")
+ # Instantiate Meek, which is used to bypass censorship
+ self.meek = Meek(self.common, get_tor_paths=self.get_tor_paths)
+
self.css = self.get_css(qtapp.color_mode)
self.color_mode = qtapp.color_mode
@@ -116,6 +121,15 @@ class GuiCommon:
font-weight: bold;
font-size: 20px;
}""",
+ "settings_subtab_bar": """
+ QTabBar::tab {
+ background: transparent;
+ }
+ QTabBar::tab:selected {
+ border-bottom: 3px solid;
+ border-color: #4E064F;
+ padding: 3px
+ }""",
"mode_new_tab_button": """
QPushButton {
font-weight: bold;
@@ -149,6 +163,52 @@ class GuiCommon:
QStatusBar::item {
border: 0px;
}""",
+ "autoconnect_start_button": """
+ QPushButton {
+ background-color: #5fa416;
+ color: #ffffff;
+ padding: 10px;
+ border: 0;
+ border-radius: 5px;
+ }""",
+ "autoconnect_configure_button": """
+ QPushButton {
+ padding: 9px 29px;
+ color: #3f7fcf;
+ text-align: left;
+ }""",
+ "enable_autoconnect": """
+ QCheckBox {
+ margin-top: 30px;
+ background: #FCFCFC;
+ color: #000000;
+ border: 1px solid #DDDBDA;
+ border-radius: 8px;
+ padding: 24px 16px;
+ }
+ QCheckBox::indicator {
+ width: 0;
+ height: 0;
+ }""",
+ "autoconnect_countries_combobox": """
+ QComboBox {
+ padding: 10px;
+ font-size: 16px;
+ }
+ QComboBox:disabled {
+ color: #666666;
+ }
+ """,
+ "autoconnect_task_label": """
+ QLabel {
+ font-weight: bold;
+ }
+ """,
+ "autoconnect_failed_to_connect_label": """
+ QLabel {
+ font-size: 18px;
+ font-weight: bold;
+ }""",
# Common styles between modes and their child widgets
"mode_settings_toggle_advanced": """
QPushButton {
@@ -508,3 +568,50 @@ class GuiCommon:
elif type(e) is PortNotAvailable:
return strings._("error_port_not_available")
return None
+
+
+class ToggleCheckbox(QtWidgets.QCheckBox):
+ def __init__(self, text):
+ super(ToggleCheckbox, self).__init__(text)
+ # Set default parameters
+ self.setCursor(QtCore.Qt.PointingHandCursor)
+ self.w = 50
+ self.h = 24
+ self.bg_color = "#D4D4D4"
+ self.circle_color = "#BDBDBD"
+ self.active_color = "#4E0D4E"
+ self.inactive_color = ""
+
+ def hitButton(self, pos):
+ return self.toggleRect.contains(pos)
+
+ def paintEvent(self, e):
+ painter = QtGui.QPainter(self)
+ painter.setRenderHint(QtGui.QPainter.Antialiasing)
+ painter.setPen(QtCore.Qt.NoPen)
+ opt = QtWidgets.QStyleOptionButton()
+ opt.init(self)
+ self.initStyleOption(opt)
+ s = self.style()
+ s.drawControl(QtWidgets.QStyle.CE_CheckBox, opt, painter, self)
+
+ rect = QtCore.QRect(
+ s.subElementRect(QtWidgets.QStyle.SE_CheckBoxContents, opt, self)
+ )
+ x = (
+ rect.width() - rect.x() - self.w + 20
+ ) # 20 is the padding between text and toggle
+ y = self.height() / 2 - self.h / 2 + 16 # 16 is the padding top for the checkbox
+ self.toggleRect = QtCore.QRect(x, y, self.w, self.h)
+ painter.setBrush(QtGui.QColor(self.bg_color))
+ painter.drawRoundedRect(x, y, self.w, self.h, self.h / 2, self.h / 2)
+ if not self.isChecked():
+ painter.setBrush(QtGui.QColor(self.circle_color))
+ painter.drawEllipse(x, y - 3, self.h + 6, self.h + 6)
+ else:
+ painter.setBrush(QtGui.QColor(self.active_color))
+ painter.drawEllipse(
+ x + self.w - (self.h + 6), y - 3, self.h + 6, self.h + 6
+ )
+
+ painter.end()
diff --git a/desktop/onionshare/main_window.py b/desktop/onionshare/main_window.py
index 255cb405..d73f3370 100644
--- a/desktop/onionshare/main_window.py
+++ b/desktop/onionshare/main_window.py
@@ -23,10 +23,10 @@ import time
from PySide2 import QtCore, QtWidgets, QtGui
from . import strings
-from .tor_connection import TorConnectionDialog
from .widgets import Alert
-from .update_checker import UpdateThread
+from .connection_tab import AutoConnectTab
from .tab_widget import TabWidget
+from .settings_tab import SettingsTab
from .gui_common import GuiCommon
from .threads import OnionCleanupThread
@@ -36,6 +36,8 @@ class MainWindow(QtWidgets.QMainWindow):
MainWindow is the OnionShare main window, which contains the GUI elements, including all open tabs
"""
+ window_resized = QtCore.Signal()
+
def __init__(self, common, filenames):
super(MainWindow, self).__init__()
@@ -53,7 +55,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.settings_action = menu.addAction(strings._("gui_settings_window_title"))
self.settings_action.triggered.connect(self.open_settings)
self.help_action = menu.addAction(strings._("gui_settings_button_help"))
- self.help_action.triggered.connect(lambda: SettingsDialog.help_clicked(self))
+ self.help_action.triggered.connect(lambda: SettingsTab.open_help())
exit_action = menu.addAction(strings._("systray_menu_exit"))
exit_action.triggered.connect(self.close)
@@ -106,24 +108,6 @@ class MainWindow(QtWidgets.QMainWindow):
)
self.status_bar.addPermanentWidget(self.status_bar.server_status_indicator)
- # Tor settings button
- self.tor_settings_button = QtWidgets.QPushButton()
- self.tor_settings_button.setDefault(False)
- self.tor_settings_button.setFixedSize(40, 50)
- self.tor_settings_button.setIcon(
- QtGui.QIcon(
- GuiCommon.get_resource_path(
- "images/{}_tor_settings.png".format(self.common.gui.color_mode)
- )
- )
- )
- self.tor_settings_button.clicked.connect(self.open_tor_settings)
- self.tor_settings_button.setStyleSheet(self.common.gui.css["settings_button"])
- self.status_bar.addPermanentWidget(self.tor_settings_button)
-
- if os.environ.get("ONIONSHARE_HIDE_TOR_SETTINGS") == "1":
- self.tor_settings_button.hide()
-
# Settings button
self.settings_button = QtWidgets.QPushButton()
self.settings_button.setDefault(False)
@@ -140,13 +124,16 @@ class MainWindow(QtWidgets.QMainWindow):
self.status_bar.addPermanentWidget(self.settings_button)
# Tabs
- self.tabs = TabWidget(self.common, self.system_tray, self.status_bar)
+ self.tabs = TabWidget(self.common, self.system_tray, self.status_bar, self)
self.tabs.bring_to_front.connect(self.bring_to_front)
# If we have saved persistent tabs, try opening those
if len(self.common.settings.get("persistent_tabs")) > 0:
for mode_settings_id in self.common.settings.get("persistent_tabs"):
self.tabs.load_tab(mode_settings_id)
+ # If not connected to tor in beginning, show autoconnect tab
+ if not self.common.gui.onion.connected_to_tor:
+ self.tabs.new_tab_clicked()
else:
# Start with opening the first tab
self.tabs.new_tab_clicked()
@@ -160,18 +147,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.setCentralWidget(central_widget)
self.show()
- # Start the "Connecting to Tor" dialog, which calls onion.connect()
- tor_con = TorConnectionDialog(self.common)
- tor_con.canceled.connect(self.tor_connection_canceled)
- tor_con.success.connect(self.tabs.tor_is_connected)
- tor_con.open_tor_settings.connect(self.tor_connection_open_tor_settings)
- if not self.common.gui.local_only:
- tor_con.start()
- self.settings_have_changed()
-
- # After connecting to Tor, check for updates
- self.check_for_updates()
-
# Create the close warning dialog -- the dialog widget needs to be in the constructor
# in order to test it
self.close_dialog = QtWidgets.QMessageBox()
@@ -186,6 +161,9 @@ class MainWindow(QtWidgets.QMainWindow):
)
self.close_dialog.setDefaultButton(self.close_dialog.reject_button)
+ # Check for autoconnect
+ self.tabs.check_autoconnect_tab()
+
def tor_connection_canceled(self):
"""
If the user cancels before Tor finishes connecting, ask if they want to
@@ -246,15 +224,22 @@ class MainWindow(QtWidgets.QMainWindow):
"""
Open the TorSettingsTab
"""
- self.common.log("MainWindow", "open_tor_settings")
- self.tabs.open_tor_settings_tab()
+ self._open_settings(active_tab="tor")
def open_settings(self):
"""
- Open the SettingsTab
+ Open the general SettingsTab
"""
- self.common.log("MainWindow", "open_settings")
- self.tabs.open_settings_tab()
+ self._open_settings(active_tab="general")
+
+ def _open_settings(self, active_tab):
+ self.common.log("MainWindow", f"open settings with active tab: {active_tab}")
+ from_autoconnect = False
+ for tab_id in self.tabs.tabs:
+ if type(self.tabs.tabs[tab_id]) is AutoConnectTab:
+ from_autoconnect = True
+ break
+ self.tabs.open_settings_tab(from_autoconnect, active_tab=active_tab)
def settings_have_changed(self):
self.common.log("OnionShareGui", "settings_have_changed")
@@ -267,25 +252,6 @@ class MainWindow(QtWidgets.QMainWindow):
tab = self.tabs.widget(index)
tab.settings_have_changed()
- def check_for_updates(self):
- """
- Check for updates in a new thread, if enabled.
- """
- if self.common.platform == "Windows" or self.common.platform == "Darwin":
- if self.common.settings.get("use_autoupdate"):
-
- def update_available(update_url, installed_version, latest_version):
- Alert(
- self.common,
- strings._("update_available").format(
- update_url, installed_version, latest_version
- ),
- )
-
- self.update_thread = UpdateThread(self.common, self.common.gui.onion)
- self.update_thread.update_available.connect(update_available)
- self.update_thread.start()
-
def bring_to_front(self):
self.common.log("MainWindow", "bring_to_front")
self.raise_()
@@ -355,3 +321,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Wait 1 second for threads to close gracefully, so tests finally pass
time.sleep(1)
+
+ def resizeEvent(self, event):
+ self.window_resized.emit()
+ return super(MainWindow, self).resizeEvent(event) \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/ar.json b/desktop/onionshare/resources/countries/ar.json
new file mode 100644
index 00000000..d620cfc3
--- /dev/null
+++ b/desktop/onionshare/resources/countries/ar.json
@@ -0,0 +1 @@
+{"IS": "\u0622\u064a\u0633\u0644\u0646\u062f\u0627", "ET": "\u0625\u062b\u064a\u0648\u0628\u064a\u0627", "AZ": "\u0623\u0630\u0631\u0628\u064a\u062c\u0627\u0646", "AM": "\u0623\u0631\u0645\u064a\u0646\u064a\u0627", "AW": "\u0623\u0631\u0648\u0628\u0627", "ER": "\u0625\u0631\u064a\u062a\u0631\u064a\u0627", "ES": "\u0625\u0633\u0628\u0627\u0646\u064a\u0627", "AU": "\u0623\u0633\u062a\u0631\u0627\u0644\u064a\u0627", "EE": "\u0625\u0633\u062a\u0648\u0646\u064a\u0627", "IL": "\u0625\u0633\u0631\u0627\u0626\u064a\u0644", "SZ": "\u0625\u0633\u0648\u0627\u062a\u064a\u0646\u064a", "AF": "\u0623\u0641\u063a\u0627\u0646\u0633\u062a\u0627\u0646", "AR": "\u0627\u0644\u0623\u0631\u062c\u0646\u062a\u064a\u0646", "JO": "\u0627\u0644\u0623\u0631\u062f\u0646", "TF": "\u0627\u0644\u0623\u0642\u0627\u0644\u064a\u0645 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629 \u0627\u0644\u0641\u0631\u0646\u0633\u064a\u0629", "IO": "\u0627\u0644\u0625\u0642\u0644\u064a\u0645 \u0627\u0644\u0628\u0631\u064a\u0637\u0627\u0646\u064a \u0641\u064a \u0627\u0644\u0645\u062d\u064a\u0637 \u0627\u0644\u0647\u0646\u062f\u064a", "EC": "\u0627\u0644\u0625\u0643\u0648\u0627\u062f\u0648\u0631", "AE": "\u0627\u0644\u0625\u0645\u0627\u0631\u0627\u062a \u0627\u0644\u0639\u0631\u0628\u064a\u0629 \u0627\u0644\u0645\u062a\u062d\u062f\u0629", "AL": "\u0623\u0644\u0628\u0627\u0646\u064a\u0627", "BH": "\u0627\u0644\u0628\u062d\u0631\u064a\u0646", "BR": "\u0627\u0644\u0628\u0631\u0627\u0632\u064a\u0644", "PT": "\u0627\u0644\u0628\u0631\u062a\u063a\u0627\u0644", "BA": "\u0627\u0644\u0628\u0648\u0633\u0646\u0629 \u0648\u0627\u0644\u0647\u0631\u0633\u0643", "CZ": "\u0627\u0644\u062a\u0634\u064a\u0643", "ME": "\u0627\u0644\u062c\u0628\u0644 \u0627\u0644\u0623\u0633\u0648\u062f", "DZ": "\u0627\u0644\u062c\u0632\u0627\u0626\u0631", "DK": "\u0627\u0644\u062f\u0627\u0646\u0645\u0631\u0643", "CV": "\u0627\u0644\u0631\u0623\u0633 \u0627\u0644\u0623\u062e\u0636\u0631", "SV": "\u0627\u0644\u0633\u0644\u0641\u0627\u062f\u0648\u0631", "SN": "\u0627\u0644\u0633\u0646\u063a\u0627\u0644", "SD": "\u0627\u0644\u0633\u0648\u062f\u0627\u0646", "SE": "\u0627\u0644\u0633\u0648\u064a\u062f", "EH": "\u0627\u0644\u0635\u062d\u0631\u0627\u0621 \u0627\u0644\u063a\u0631\u0628\u064a\u0629", "SO": "\u0627\u0644\u0635\u0648\u0645\u0627\u0644", "CN": "\u0627\u0644\u0635\u064a\u0646", "IQ": "\u0627\u0644\u0639\u0631\u0627\u0642", "GA": "\u0627\u0644\u063a\u0627\u0628\u0648\u0646", "VA": "\u0627\u0644\u0641\u0627\u062a\u064a\u0643\u0627\u0646", "PH": "\u0627\u0644\u0641\u0644\u0628\u064a\u0646", "CM": "\u0627\u0644\u0643\u0627\u0645\u064a\u0631\u0648\u0646", "CG": "\u0627\u0644\u0643\u0648\u0646\u063a\u0648 - \u0628\u0631\u0627\u0632\u0627\u0641\u064a\u0644", "CD": "\u0627\u0644\u0643\u0648\u0646\u063a\u0648 - \u0643\u064a\u0646\u0634\u0627\u0633\u0627", "KW": "\u0627\u0644\u0643\u0648\u064a\u062a", "DE": "\u0623\u0644\u0645\u0627\u0646\u064a\u0627", "MA": "\u0627\u0644\u0645\u063a\u0631\u0628", "MX": "\u0627\u0644\u0645\u0643\u0633\u064a\u0643", "SA": "\u0627\u0644\u0645\u0645\u0644\u0643\u0629 \u0627\u0644\u0639\u0631\u0628\u064a\u0629 \u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629", "GB": "\u0627\u0644\u0645\u0645\u0644\u0643\u0629 \u0627\u0644\u0645\u062a\u062d\u062f\u0629", "NO": "\u0627\u0644\u0646\u0631\u0648\u064a\u062c", "AT": "\u0627\u0644\u0646\u0645\u0633\u0627", "NE": "\u0627\u0644\u0646\u064a\u062c\u0631", "IN": "\u0627\u0644\u0647\u0646\u062f", "US": "\u0627\u0644\u0648\u0644\u0627\u064a\u0627\u062a \u0627\u0644\u0645\u062a\u062d\u062f\u0629", "JP": "\u0627\u0644\u064a\u0627\u0628\u0627\u0646", "YE": "\u0627\u0644\u064a\u0645\u0646", "GR": "\u0627\u0644\u064a\u0648\u0646\u0627\u0646", "AQ": "\u0623\u0646\u062a\u0627\u0631\u0643\u062a\u064a\u0643\u0627", "AG": "\u0623\u0646\u062a\u064a\u063a\u0648\u0627 \u0648\u0628\u0631\u0628\u0648\u062f\u0627", "AD": "\u0623\u0646\u062f\u0648\u0631\u0627", "ID": "\u0625\u0646\u062f\u0648\u0646\u064a\u0633\u064a\u0627", "AO": "\u0623\u0646\u063a\u0648\u0644\u0627", "AI": "\u0623\u0646\u063a\u0648\u064a\u0644\u0627", "UY": "\u0623\u0648\u0631\u063a\u0648\u0627\u064a", "UZ": "\u0623\u0648\u0632\u0628\u0643\u0633\u062a\u0627\u0646", "UG": "\u0623\u0648\u063a\u0646\u062f\u0627", "UA": "\u0623\u0648\u0643\u0631\u0627\u0646\u064a\u0627", "IR": "\u0625\u064a\u0631\u0627\u0646", "IE": "\u0623\u064a\u0631\u0644\u0646\u062f\u0627", "IT": "\u0625\u064a\u0637\u0627\u0644\u064a\u0627", "PG": "\u0628\u0627\u0628\u0648\u0627 \u063a\u064a\u0646\u064a\u0627 \u0627\u0644\u062c\u062f\u064a\u062f\u0629", "PY": "\u0628\u0627\u0631\u0627\u063a\u0648\u0627\u064a", "PK": "\u0628\u0627\u0643\u0633\u062a\u0627\u0646", "PW": "\u0628\u0627\u0644\u0627\u0648", "BB": "\u0628\u0631\u0628\u0627\u062f\u0648\u0633", "BM": "\u0628\u0631\u0645\u0648\u062f\u0627", "BN": "\u0628\u0631\u0648\u0646\u0627\u064a", "BE": "\u0628\u0644\u062c\u064a\u0643\u0627", "BG": "\u0628\u0644\u063a\u0627\u0631\u064a\u0627", "BZ": "\u0628\u0644\u064a\u0632", "BD": "\u0628\u0646\u063a\u0644\u0627\u062f\u064a\u0634", "PA": "\u0628\u0646\u0645\u0627", "BJ": "\u0628\u0646\u064a\u0646", "BT": "\u0628\u0648\u062a\u0627\u0646", "BW": "\u0628\u0648\u062a\u0633\u0648\u0627\u0646\u0627", "PR": "\u0628\u0648\u0631\u062a\u0648\u0631\u064a\u0643\u0648", "BF": "\u0628\u0648\u0631\u0643\u064a\u0646\u0627 \u0641\u0627\u0633\u0648", "BI": "\u0628\u0648\u0631\u0648\u0646\u062f\u064a", "PL": "\u0628\u0648\u0644\u0646\u062f\u0627", "BO": "\u0628\u0648\u0644\u064a\u0641\u064a\u0627", "PF": "\u0628\u0648\u0644\u064a\u0646\u064a\u0632\u064a\u0627 \u0627\u0644\u0641\u0631\u0646\u0633\u064a\u0629", "PE": "\u0628\u064a\u0631\u0648", "BY": "\u0628\u064a\u0644\u0627\u0631\u0648\u0633", "TH": "\u062a\u0627\u064a\u0644\u0627\u0646\u062f", "TW": "\u062a\u0627\u064a\u0648\u0627\u0646", "TM": "\u062a\u0631\u0643\u0645\u0627\u0646\u0633\u062a\u0627\u0646", "TR": "\u062a\u0631\u0643\u064a\u0627", "TT": "\u062a\u0631\u064a\u0646\u064a\u062f\u0627\u062f \u0648\u062a\u0648\u0628\u0627\u063a\u0648", "TD": "\u062a\u0634\u0627\u062f", "CL": "\u062a\u0634\u064a\u0644\u064a", "TZ": "\u062a\u0646\u0632\u0627\u0646\u064a\u0627", "TG": "\u062a\u0648\u063a\u0648", "TK": "\u062a\u0648\u0643\u064a\u0644\u0648", "TN": "\u062a\u0648\u0646\u0633", "TO": "\u062a\u0648\u0646\u063a\u0627", "TL": "\u062a\u064a\u0645\u0648\u0631 - \u0644\u064a\u0634\u062a\u064a", "JM": "\u062c\u0627\u0645\u0627\u064a\u0643\u0627", "GI": "\u062c\u0628\u0644 \u0637\u0627\u0631\u0642", "AX": "\u062c\u0632\u0631 \u0622\u0644\u0627\u0646\u062f", "BS": "\u062c\u0632\u0631 \u0627\u0644\u0628\u0647\u0627\u0645\u0627", "KM": "\u062c\u0632\u0631 \u0627\u0644\u0642\u0645\u0631", "MQ": "\u062c\u0632\u0631 \u0627\u0644\u0645\u0627\u0631\u062a\u064a\u0646\u064a\u0643", "MV": "\u062c\u0632\u0631 \u0627\u0644\u0645\u0627\u0644\u062f\u064a\u0641", "PN": "\u062c\u0632\u0631 \u0628\u064a\u062a\u0643\u064a\u0631\u0646", "TC": "\u062c\u0632\u0631 \u062a\u0648\u0631\u0643\u0633 \u0648\u0643\u0627\u064a\u0643\u0648\u0633", "SB": "\u062c\u0632\u0631 \u0633\u0644\u064a\u0645\u0627\u0646", "FO": "\u062c\u0632\u0631 \u0641\u0627\u0631\u0648", "FK": "\u062c\u0632\u0631 \u0641\u0648\u0643\u0644\u0627\u0646\u062f", "VG": "\u062c\u0632\u0631 \u0641\u064a\u0631\u062c\u0646 \u0627\u0644\u0628\u0631\u064a\u0637\u0627\u0646\u064a\u0629", "VI": "\u062c\u0632\u0631 \u0641\u064a\u0631\u062c\u0646 \u0627\u0644\u062a\u0627\u0628\u0639\u0629 \u0644\u0644\u0648\u0644\u0627\u064a\u0627\u062a \u0627\u0644\u0645\u062a\u062d\u062f\u0629", "KY": "\u062c\u0632\u0631 \u0643\u0627\u064a\u0645\u0627\u0646", "CK": "\u062c\u0632\u0631 \u0643\u0648\u0643", "CC": "\u062c\u0632\u0631 \u0643\u0648\u0643\u0648\u0633 (\u0643\u064a\u0644\u064a\u0646\u063a)", "WF": "\u062c\u0632\u0631 \u0648\u0627\u0644\u0633 \u0648\u0641\u0648\u062a\u0648\u0646\u0627", "BV": "\u062c\u0632\u064a\u0631\u0629 \u0628\u0648\u0641\u064a\u0647", "CX": "\u062c\u0632\u064a\u0631\u0629 \u0643\u0631\u064a\u0633\u0645\u0627\u0633", "IM": "\u062c\u0632\u064a\u0631\u0629 \u0645\u0627\u0646", "NF": "\u062c\u0632\u064a\u0631\u0629 \u0646\u0648\u0631\u0641\u0648\u0644\u0643", "HM": "\u062c\u0632\u064a\u0631\u0629 \u0647\u064a\u0631\u062f \u0648\u062c\u0632\u0631 \u0645\u0627\u0643\u062f\u0648\u0646\u0627\u0644\u062f", "CF": "\u062c\u0645\u0647\u0648\u0631\u064a\u0629 \u0623\u0641\u0631\u064a\u0642\u064a\u0627 \u0627\u0644\u0648\u0633\u0637\u0649", "DO": "\u062c\u0645\u0647\u0648\u0631\u064a\u0629 \u0627\u0644\u062f\u0648\u0645\u064a\u0646\u064a\u0643\u0627\u0646", "ZA": "\u062c\u0646\u0648\u0628 \u0623\u0641\u0631\u064a\u0642\u064a\u0627", "SS": "\u062c\u0646\u0648\u0628 \u0627\u0644\u0633\u0648\u062f\u0627\u0646", "GE": "\u062c\u0648\u0631\u062c\u064a\u0627", "GS": "\u062c\u0648\u0631\u062c\u064a\u0627 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629 \u0648\u062c\u0632\u0631 \u0633\u0627\u0646\u062f\u0648\u064a\u062a\u0634 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629", "DJ": "\u062c\u064a\u0628\u0648\u062a\u064a", "DM": "\u062f\u0648\u0645\u064a\u0646\u064a\u0643\u0627", "RW": "\u0631\u0648\u0627\u0646\u062f\u0627", "RU": "\u0631\u0648\u0633\u064a\u0627", "RO": "\u0631\u0648\u0645\u0627\u0646\u064a\u0627", "RE": "\u0631\u0648\u064a\u0646\u064a\u0648\u0646", "ZM": "\u0632\u0627\u0645\u0628\u064a\u0627", "ZW": "\u0632\u064a\u0645\u0628\u0627\u0628\u0648\u064a", "CI": "\u0633\u0627\u062d\u0644 \u0627\u0644\u0639\u0627\u062c", "WS": "\u0633\u0627\u0645\u0648\u0627", "AS": "\u0633\u0627\u0645\u0648\u0627 \u0627\u0644\u0623\u0645\u0631\u064a\u0643\u064a\u0629", "BL": "\u0633\u0627\u0646 \u0628\u0627\u0631\u062a\u0644\u064a\u0645\u064a", "PM": "\u0633\u0627\u0646 \u0628\u064a\u064a\u0631 \u0648\u0645\u0643\u0648\u064a\u0644\u0648\u0646", "MF": "\u0633\u0627\u0646 \u0645\u0627\u0631\u062a\u0646", "SM": "\u0633\u0627\u0646 \u0645\u0627\u0631\u064a\u0646\u0648", "VC": "\u0633\u0627\u0646\u062a \u0641\u0646\u0633\u0646\u062a \u0648\u062c\u0632\u0631 \u063a\u0631\u064a\u0646\u0627\u062f\u064a\u0646", "KN": "\u0633\u0627\u0646\u062a \u0643\u064a\u062a\u0633 \u0648\u0646\u064a\u0641\u064a\u0633", "LC": "\u0633\u0627\u0646\u062a \u0644\u0648\u0633\u064a\u0627", "SX": "\u0633\u0627\u0646\u062a \u0645\u0627\u0631\u062a\u0646", "SH": "\u0633\u0627\u0646\u062a \u0647\u064a\u0644\u064a\u0646\u0627", "ST": "\u0633\u0627\u0648 \u062a\u0648\u0645\u064a \u0648\u0628\u0631\u064a\u0646\u0633\u064a\u0628\u064a", "LK": "\u0633\u0631\u064a\u0644\u0627\u0646\u0643\u0627", "SJ": "\u0633\u0641\u0627\u0644\u0628\u0627\u0631\u062f \u0648\u062c\u0627\u0646 \u0645\u0627\u064a\u0646", "SK": "\u0633\u0644\u0648\u0641\u0627\u0643\u064a\u0627", "SI": "\u0633\u0644\u0648\u0641\u064a\u0646\u064a\u0627", "SG": "\u0633\u0646\u063a\u0627\u0641\u0648\u0631\u0629", "SY": "\u0633\u0648\u0631\u064a\u0627", "SR": "\u0633\u0648\u0631\u064a\u0646\u0627\u0645", "CH": "\u0633\u0648\u064a\u0633\u0631\u0627", "SL": "\u0633\u064a\u0631\u0627\u0644\u064a\u0648\u0646", "SC": "\u0633\u064a\u0634\u0644", "RS": "\u0635\u0631\u0628\u064a\u0627", "TJ": "\u0637\u0627\u062c\u064a\u0643\u0633\u062a\u0627\u0646", "OM": "\u0639\u064f\u0645\u0627\u0646", "GM": "\u063a\u0627\u0645\u0628\u064a\u0627", "GH": "\u063a\u0627\u0646\u0627", "GD": "\u063a\u0631\u064a\u0646\u0627\u062f\u0627", "GL": "\u063a\u0631\u064a\u0646\u0644\u0627\u0646\u062f", "GT": "\u063a\u0648\u0627\u062a\u064a\u0645\u0627\u0644\u0627", "GP": "\u063a\u0648\u0627\u062f\u0644\u0648\u0628", "GU": "\u063a\u0648\u0627\u0645", "GF": "\u063a\u0648\u064a\u0627\u0646\u0627 \u0627\u0644\u0641\u0631\u0646\u0633\u064a\u0629", "GY": "\u063a\u064a\u0627\u0646\u0627", "GG": "\u063a\u064a\u0631\u0646\u0632\u064a", "GN": "\u063a\u064a\u0646\u064a\u0627", "GQ": "\u063a\u064a\u0646\u064a\u0627 \u0627\u0644\u0627\u0633\u062a\u0648\u0627\u0626\u064a\u0629", "GW": "\u063a\u064a\u0646\u064a\u0627 \u0628\u064a\u0633\u0627\u0648", "VU": "\u0641\u0627\u0646\u0648\u0627\u062a\u0648", "FR": "\u0641\u0631\u0646\u0633\u0627", "VE": "\u0641\u0646\u0632\u0648\u064a\u0644\u0627", "FI": "\u0641\u0646\u0644\u0646\u062f\u0627", "VN": "\u0641\u064a\u062a\u0646\u0627\u0645", "FJ": "\u0641\u064a\u062c\u064a", "CY": "\u0642\u0628\u0631\u0635", "QA": "\u0642\u0637\u0631", "KG": "\u0642\u064a\u0631\u063a\u064a\u0632\u0633\u062a\u0627\u0646", "KZ": "\u0643\u0627\u0632\u0627\u062e\u0633\u062a\u0627\u0646", "NC": "\u0643\u0627\u0644\u064a\u062f\u0648\u0646\u064a\u0627 \u0627\u0644\u062c\u062f\u064a\u062f\u0629", "HR": "\u0643\u0631\u0648\u0627\u062a\u064a\u0627", "KH": "\u0643\u0645\u0628\u0648\u062f\u064a\u0627", "CA": "\u0643\u0646\u062f\u0627", "CU": "\u0643\u0648\u0628\u0627", "CW": "\u0643\u0648\u0631\u0627\u0633\u0627\u0648", "KR": "\u0643\u0648\u0631\u064a\u0627 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629", "KP": "\u0643\u0648\u0631\u064a\u0627 \u0627\u0644\u0634\u0645\u0627\u0644\u064a\u0629", "CR": "\u0643\u0648\u0633\u062a\u0627\u0631\u064a\u0643\u0627", "CO": "\u0643\u0648\u0644\u0648\u0645\u0628\u064a\u0627", "KI": "\u0643\u064a\u0631\u064a\u0628\u0627\u062a\u064a", "KE": "\u0643\u064a\u0646\u064a\u0627", "LV": "\u0644\u0627\u062a\u0641\u064a\u0627", "LA": "\u0644\u0627\u0648\u0633", "LB": "\u0644\u0628\u0646\u0627\u0646", "LU": "\u0644\u0648\u0643\u0633\u0645\u0628\u0648\u0631\u063a", "LY": "\u0644\u064a\u0628\u064a\u0627", "LR": "\u0644\u064a\u0628\u064a\u0631\u064a\u0627", "LT": "\u0644\u064a\u062a\u0648\u0627\u0646\u064a\u0627", "LI": "\u0644\u064a\u062e\u062a\u0646\u0634\u062a\u0627\u064a\u0646", "LS": "\u0644\u064a\u0633\u0648\u062a\u0648", "MT": "\u0645\u0627\u0644\u0637\u0627", "ML": "\u0645\u0627\u0644\u064a", "MY": "\u0645\u0627\u0644\u064a\u0632\u064a\u0627", "YT": "\u0645\u0627\u064a\u0648\u062a", "MG": "\u0645\u062f\u063a\u0634\u0642\u0631", "EG": "\u0645\u0635\u0631", "MK": "\u0645\u0642\u062f\u0648\u0646\u064a\u0627 \u0627\u0644\u0634\u0645\u0627\u0644\u064a\u0629", "MW": "\u0645\u0644\u0627\u0648\u064a", "MO": "\u0645\u0646\u0637\u0642\u0629 \u0645\u0627\u0643\u0627\u0648 \u0627\u0644\u0625\u062f\u0627\u0631\u064a\u0629 \u0627\u0644\u062e\u0627\u0635\u0629", "MN": "\u0645\u0646\u063a\u0648\u0644\u064a\u0627", "MR": "\u0645\u0648\u0631\u064a\u062a\u0627\u0646\u064a\u0627", "MU": "\u0645\u0648\u0631\u064a\u0634\u064a\u0648\u0633", "MZ": "\u0645\u0648\u0632\u0645\u0628\u064a\u0642", "MD": "\u0645\u0648\u0644\u062f\u0648\u0641\u0627", "MC": "\u0645\u0648\u0646\u0627\u0643\u0648", "MS": "\u0645\u0648\u0646\u062a\u0633\u0631\u0627\u062a", "MM": "\u0645\u064a\u0627\u0646\u0645\u0627\u0631 (\u0628\u0648\u0631\u0645\u0627)", "NA": "\u0646\u0627\u0645\u064a\u0628\u064a\u0627", "NR": "\u0646\u0627\u0648\u0631\u0648", "NP": "\u0646\u064a\u0628\u0627\u0644", "NG": "\u0646\u064a\u062c\u064a\u0631\u064a\u0627", "NI": "\u0646\u064a\u0643\u0627\u0631\u0627\u063a\u0648\u0627", "NZ": "\u0646\u064a\u0648\u0632\u064a\u0644\u0646\u062f\u0627", "NU": "\u0646\u064a\u0648\u064a", "HT": "\u0647\u0627\u064a\u062a\u064a", "HN": "\u0647\u0646\u062f\u0648\u0631\u0627\u0633", "HU": "\u0647\u0646\u063a\u0627\u0631\u064a\u0627", "NL": "\u0647\u0648\u0644\u0646\u062f\u0627", "BQ": "\u0647\u0648\u0644\u0646\u062f\u0627 \u0627\u0644\u0643\u0627\u0631\u064a\u0628\u064a\u0629", "HK": "\u0647\u0648\u0646\u063a \u0643\u0648\u0646\u063a \u0627\u0644\u0635\u064a\u0646\u064a\u0629 (\u0645\u0646\u0637\u0642\u0629 \u0625\u062f\u0627\u0631\u064a\u0629 \u062e\u0627\u0635\u0629)"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/bn.json b/desktop/onionshare/resources/countries/bn.json
new file mode 100644
index 00000000..c9aa81f0
--- /dev/null
+++ b/desktop/onionshare/resources/countries/bn.json
@@ -0,0 +1 @@
+{"AT": "\u0985\u09b8\u09cd\u099f\u09cd\u09b0\u09bf\u09af\u09bc\u09be", "AU": "\u0985\u09b8\u09cd\u099f\u09cd\u09b0\u09c7\u09b2\u09bf\u09af\u09bc\u09be", "AO": "\u0985\u09cd\u09af\u09be\u0999\u09cd\u0997\u09cb\u09b2\u09be", "AQ": "\u0985\u09cd\u09af\u09be\u09a8\u09cd\u099f\u09be\u09b0\u09cd\u0995\u099f\u09bf\u0995\u09be", "AG": "\u0985\u09cd\u09af\u09be\u09a8\u09cd\u099f\u09bf\u0997\u09c1\u09af\u09bc\u09be \u0993 \u09ac\u09be\u09b0\u09ac\u09c1\u09a1\u09be", "IM": "\u0986\u0987\u09b2 \u0985\u09ab \u09ae\u09cd\u09af\u09be\u09a8", "IS": "\u0986\u0987\u09b8\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "AZ": "\u0986\u099c\u09be\u09b0\u09ac\u09be\u0987\u099c\u09be\u09a8", "AD": "\u0986\u09a8\u09cd\u09a1\u09cb\u09b0\u09be", "AF": "\u0986\u09ab\u0997\u09be\u09a8\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "AS": "\u0986\u09ae\u09c7\u09b0\u09bf\u0995\u09be\u09a8 \u09b8\u09be\u09ae\u09cb\u09af\u09bc\u09be", "IE": "\u0986\u09af\u09bc\u09be\u09b0\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "AW": "\u0986\u09b0\u09c1\u09ac\u09be", "AR": "\u0986\u09b0\u09cd\u099c\u09c7\u09a8\u09cd\u099f\u09bf\u09a8\u09be", "AM": "\u0986\u09b0\u09cd\u09ae\u09c7\u09a8\u09bf\u09af\u09bc\u09be", "DZ": "\u0986\u09b2\u099c\u09c7\u09b0\u09bf\u09af\u09bc\u09be", "AL": "\u0986\u09b2\u09ac\u09c7\u09a8\u09bf\u09af\u09bc\u09be", "AX": "\u0986\u09b2\u09be\u09a8\u09cd\u09a1 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "UA": "\u0987\u0989\u0995\u09cd\u09b0\u09c7\u09a8", "EC": "\u0987\u0995\u09c1\u09af\u09bc\u09c7\u09a1\u09b0", "IL": "\u0987\u099c\u09b0\u09be\u09af\u09bc\u09c7\u09b2", "IT": "\u0987\u09a4\u09be\u09b2\u09bf", "ET": "\u0987\u09a5\u09bf\u0993\u09aa\u09bf\u09af\u09bc\u09be", "ID": "\u0987\u09a8\u09cd\u09a6\u09cb\u09a8\u09c7\u09b6\u09bf\u09af\u09bc\u09be", "YE": "\u0987\u09af\u09bc\u09c7\u09ae\u09c7\u09a8", "IQ": "\u0987\u09b0\u09be\u0995", "IR": "\u0987\u09b0\u09be\u09a8", "ER": "\u0987\u09b0\u09bf\u09a4\u09cd\u09b0\u09bf\u09af\u09bc\u09be", "SZ": "\u0987\u09b8\u0993\u09af\u09bc\u09be\u09a4\u09bf\u09a8\u09bf", "UG": "\u0989\u0997\u09be\u09a8\u09cd\u09a1\u09be", "UZ": "\u0989\u099c\u09ac\u09c7\u0995\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "KP": "\u0989\u09a4\u09cd\u09a4\u09b0 \u0995\u09cb\u09b0\u09bf\u09af\u09bc\u09be", "MK": "\u0989\u09a4\u09cd\u09a4\u09b0 \u09ae\u09cd\u09af\u09be\u09b8\u09c7\u09a1\u09cb\u09a8\u09bf\u09af\u09bc\u09be", "UY": "\u0989\u09b0\u09c1\u0997\u09c1\u09af\u09bc\u09c7", "SV": "\u098f\u09b2 \u09b8\u09be\u09b2\u09ad\u09c7\u09a6\u09b0", "EE": "\u098f\u09b8\u09cd\u09a4\u09cb\u09a8\u09bf\u09af\u09bc\u09be", "AI": "\u098f\u09cd\u09af\u09be\u0999\u09cd\u0997\u09c1\u0987\u09b2\u09be", "OM": "\u0993\u09ae\u09be\u09a8", "WF": "\u0993\u09af\u09bc\u09be\u09b2\u09bf\u09b8 \u0993 \u09ab\u09c1\u099f\u09c1\u09a8\u09be", "CG": "\u0995\u0999\u09cd\u0997\u09cb - \u09ac\u09cd\u09b0\u09be\u099c\u09be\u09ad\u09bf\u09b2", "CD": "\u0995\u0999\u09cd\u0997\u09cb-\u0995\u09bf\u09a8\u09b6\u09be\u09b8\u09be", "KM": "\u0995\u09ae\u09cb\u09b0\u09cb\u09b8", "KH": "\u0995\u09ae\u09cd\u09ac\u09cb\u09a1\u09bf\u09af\u09bc\u09be", "CO": "\u0995\u09b2\u09ae\u09cd\u09ac\u09bf\u09af\u09bc\u09be", "KZ": "\u0995\u09be\u099c\u09be\u0996\u09b8\u09cd\u09a4\u09be\u09a8", "QA": "\u0995\u09be\u09a4\u09be\u09b0", "CA": "\u0995\u09be\u09a8\u09be\u09a1\u09be", "CU": "\u0995\u09bf\u0989\u09ac\u09be", "KG": "\u0995\u09bf\u09b0\u0997\u09bf\u099c\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "KI": "\u0995\u09bf\u09b0\u09bf\u09ac\u09be\u09a4\u09bf", "CK": "\u0995\u09c1\u0995 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "KW": "\u0995\u09c1\u09af\u09bc\u09c7\u09a4", "CW": "\u0995\u09c1\u09b0\u09be\u09b8\u09be\u0993", "KE": "\u0995\u09c7\u09a8\u09bf\u09af\u09bc\u09be", "CV": "\u0995\u09c7\u09aa\u09ad\u09be\u09b0\u09cd\u09a6\u09c7", "KY": "\u0995\u09c7\u09ae\u09cd\u09af\u09be\u09a8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "CC": "\u0995\u09cb\u0995\u09cb\u09b8 (\u0995\u09bf\u09b2\u09bf\u0982) \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "CI": "\u0995\u09cb\u09a4 \u09a6\u09bf\u09ad\u09cb\u09af\u09bc\u09be\u09b0", "CR": "\u0995\u09cb\u09b8\u09cd\u099f\u09be\u09b0\u09bf\u0995\u09be", "CM": "\u0995\u09cd\u09af\u09be\u09ae\u09c7\u09b0\u09c1\u09a8", "BQ": "\u0995\u09cd\u09af\u09be\u09b0\u09bf\u09ac\u09bf\u09af\u09bc\u09be\u09a8 \u09a8\u09c7\u09a6\u09be\u09b0\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1\u09b8", "CX": "\u0995\u09cd\u09b0\u09bf\u09b8\u09ae\u09be\u09b8 \u09a6\u09cd\u09ac\u09c0\u09aa", "HR": "\u0995\u09cd\u09b0\u09cb\u09af\u09bc\u09c7\u09b6\u09bf\u09af\u09bc\u09be", "GM": "\u0997\u09be\u09ae\u09cd\u09ac\u09bf\u09af\u09bc\u09be", "GN": "\u0997\u09bf\u09a8\u09bf", "GW": "\u0997\u09bf\u09a8\u09bf-\u09ac\u09bf\u09b8\u09be\u0989", "GY": "\u0997\u09bf\u09af\u09bc\u09be\u09a8\u09be", "GT": "\u0997\u09c1\u09af\u09bc\u09be\u09a4\u09c7\u09ae\u09be\u09b2\u09be", "GP": "\u0997\u09c1\u09af\u09bc\u09be\u09a6\u09c7\u09b2\u09cc\u09aa", "GU": "\u0997\u09c1\u09af\u09bc\u09be\u09ae", "GG": "\u0997\u09c1\u09af\u09bc\u09be\u09b0\u09cd\u09a8\u09b8\u09bf", "GA": "\u0997\u09cd\u09af\u09be\u09ac\u09a8", "GL": "\u0997\u09cd\u09b0\u09c0\u09a8\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "GR": "\u0997\u09cd\u09b0\u09c0\u09b8", "GD": "\u0997\u09cd\u09b0\u09c7\u09a8\u09be\u09a1\u09be", "GH": "\u0998\u09be\u09a8\u09be", "TD": "\u099a\u09be\u09a6", "CL": "\u099a\u09bf\u09b2\u09bf", "CN": "\u099a\u09c0\u09a8", "CZ": "\u099a\u09c7\u099a\u09bf\u09af\u09bc\u09be", "GE": "\u099c\u09b0\u09cd\u099c\u09bf\u09af\u09bc\u09be", "JO": "\u099c\u09b0\u09cd\u09a1\u09a8", "JP": "\u099c\u09be\u09aa\u09be\u09a8", "JM": "\u099c\u09be\u09ae\u09be\u0987\u0995\u09be", "ZM": "\u099c\u09be\u09ae\u09cd\u09ac\u09bf\u09af\u09bc\u09be", "DE": "\u099c\u09be\u09b0\u09cd\u09ae\u09be\u09a8\u09bf", "DJ": "\u099c\u09bf\u09ac\u09c1\u09a4\u09bf", "GI": "\u099c\u09bf\u09ac\u09cd\u09b0\u09be\u09b2\u09cd\u099f\u09be\u09b0", "ZW": "\u099c\u09bf\u09ae\u09cd\u09ac\u09be\u09ac\u09cb\u09af\u09bc\u09c7", "TK": "\u099f\u09cb\u0995\u09c7\u09b2\u09be\u0989", "TG": "\u099f\u09cb\u0997\u09cb", "TO": "\u099f\u09cb\u0999\u09cd\u0997\u09be", "DK": "\u09a1\u09c7\u09a8\u09ae\u09be\u09b0\u09cd\u0995", "DM": "\u09a1\u09cb\u09ae\u09bf\u09a8\u09bf\u0995\u09be", "DO": "\u09a1\u09cb\u09ae\u09c7\u09a8\u09bf\u0995\u09be\u09a8 \u09aa\u09cd\u09b0\u099c\u09be\u09a4\u09a8\u09cd\u09a4\u09cd\u09b0", "TW": "\u09a4\u09be\u0987\u0993\u09af\u09bc\u09be\u09a8", "TJ": "\u09a4\u09be\u099c\u09bf\u0995\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "TZ": "\u09a4\u09be\u099e\u09cd\u099c\u09be\u09a8\u09bf\u09af\u09bc\u09be", "TN": "\u09a4\u09bf\u0989\u09a8\u09bf\u09b8\u09bf\u09af\u09bc\u09be", "TL": "\u09a4\u09bf\u09ae\u09c1\u09b0-\u09b2\u09c7\u09b8\u09cd\u09a4\u09c7", "TR": "\u09a4\u09c1\u09b0\u09b8\u09cd\u0995", "TM": "\u09a4\u09c1\u09b0\u09cd\u0995\u09ae\u09c7\u09a8\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "TC": "\u09a4\u09c1\u09b0\u09cd\u0995\u09b8 \u0993 \u0995\u09be\u0987\u0995\u09cb\u09b8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "TT": "\u09a4\u09cd\u09b0\u09bf\u09a8\u09bf\u09a8\u09be\u09a6 \u0993 \u099f\u09cb\u09ac\u09cd\u09af\u09be\u0997\u09cb", "TH": "\u09a5\u09be\u0987\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "ZA": "\u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u0986\u09ab\u09cd\u09b0\u09bf\u0995\u09be", "KR": "\u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u0995\u09cb\u09b0\u09bf\u09af\u09bc\u09be", "GS": "\u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u099c\u09b0\u09cd\u099c\u09bf\u09af\u09bc\u09be \u0993 \u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u09b8\u09cd\u09af\u09be\u09a8\u09cd\u09a1\u0989\u0987\u099a \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "SS": "\u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u09b8\u09c1\u09a6\u09be\u09a8", "NO": "\u09a8\u09b0\u0993\u09af\u09bc\u09c7", "NF": "\u09a8\u09b0\u09ab\u09cb\u0995 \u09a6\u09cd\u09ac\u09c0\u09aa", "NE": "\u09a8\u09be\u0987\u099c\u09be\u09b0", "NG": "\u09a8\u09be\u0987\u099c\u09c7\u09b0\u09bf\u09af\u09bc\u09be", "NR": "\u09a8\u09be\u0989\u09b0\u09c1", "NA": "\u09a8\u09be\u09ae\u09bf\u09ac\u09bf\u09af\u09bc\u09be", "NC": "\u09a8\u09bf\u0989 \u0995\u09cd\u09af\u09be\u09b2\u09c7\u09a1\u09cb\u09a8\u09bf\u09af\u09bc\u09be", "NZ": "\u09a8\u09bf\u0989\u099c\u09bf\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "NU": "\u09a8\u09bf\u0989\u09af\u09bc\u09c7", "NI": "\u09a8\u09bf\u0995\u09be\u09b0\u09be\u0997\u09c1\u09af\u09bc\u09be", "GQ": "\u09a8\u09bf\u09b0\u0995\u09cd\u09b7\u09c0\u09af\u09bc \u0997\u09bf\u09a8\u09bf", "NL": "\u09a8\u09c7\u09a6\u09be\u09b0\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1\u09b8", "NP": "\u09a8\u09c7\u09aa\u09be\u09b2", "PT": "\u09aa\u09b0\u09cd\u09a4\u09c1\u0997\u09be\u09b2", "EH": "\u09aa\u09b6\u09cd\u099a\u09bf\u09ae \u09b8\u09be\u09b9\u09be\u09b0\u09be", "PK": "\u09aa\u09be\u0995\u09bf\u09b8\u09cd\u09a4\u09be\u09a8", "PA": "\u09aa\u09be\u09a8\u09be\u09ae\u09be", "PG": "\u09aa\u09be\u09aa\u09c1\u09af\u09bc\u09be \u09a8\u09bf\u0989 \u0997\u09bf\u09a8\u09bf", "PW": "\u09aa\u09be\u09b2\u09be\u0989", "PN": "\u09aa\u09bf\u099f\u0995\u09c7\u09af\u09bc\u09be\u09b0\u09cd\u09a8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "PR": "\u09aa\u09c1\u09af\u09bc\u09c7\u09b0\u09cd\u09a4\u09cb \u09b0\u09bf\u0995\u09cb", "PE": "\u09aa\u09c7\u09b0\u09c1", "PL": "\u09aa\u09cb\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "PY": "\u09aa\u09cd\u09af\u09be\u09b0\u09be\u0997\u09c1\u09af\u09bc\u09c7", "FK": "\u09ab\u0995\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "GF": "\u09ab\u09b0\u09be\u09b8\u09c0 \u0997\u09be\u09af\u09bc\u09be\u09a8\u09be", "TF": "\u09ab\u09b0\u09be\u09b8\u09c0 \u09a6\u0995\u09cd\u09b7\u09bf\u09a3\u09be\u099e\u09cd\u099a\u09b2", "PF": "\u09ab\u09b0\u09be\u09b8\u09c0 \u09aa\u09b2\u09bf\u09a8\u09c7\u09b6\u09bf\u09af\u09bc\u09be", "FJ": "\u09ab\u09bf\u099c\u09bf", "FI": "\u09ab\u09bf\u09a8\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "PH": "\u09ab\u09bf\u09b2\u09bf\u09aa\u09be\u0987\u09a8", "FO": "\u09ab\u09cd\u09af\u09be\u09b0\u0993 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "FR": "\u09ab\u09cd\u09b0\u09be\u09a8\u09cd\u09b8", "BW": "\u09ac\u09a4\u09b8\u09cb\u09af\u09bc\u09be\u09a8\u09be", "BO": "\u09ac\u09b2\u09bf\u09ad\u09bf\u09af\u09bc\u09be", "BA": "\u09ac\u09b8\u09a8\u09bf\u09af\u09bc\u09be \u0993 \u09b9\u09be\u09b0\u09cd\u099c\u09c7\u0997\u09cb\u09ad\u09bf\u09a8\u09be", "BD": "\u09ac\u09be\u0982\u09b2\u09be\u09a6\u09c7\u09b6", "BB": "\u09ac\u09be\u09b0\u09ac\u09be\u09a6\u09cb\u09b8", "BM": "\u09ac\u09be\u09b0\u09ae\u09c1\u09a1\u09be", "BH": "\u09ac\u09be\u09b9\u09b0\u09be\u0987\u09a8", "BS": "\u09ac\u09be\u09b9\u09be\u09ae\u09be \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "BF": "\u09ac\u09c1\u09b0\u0995\u09bf\u09a8\u09be \u09ab\u09be\u09b8\u09cb", "BI": "\u09ac\u09c1\u09b0\u09c1\u09a8\u09cd\u09a1\u09bf", "BG": "\u09ac\u09c1\u09b2\u0997\u09c7\u09b0\u09bf\u09af\u09bc\u09be", "BJ": "\u09ac\u09c7\u09a8\u09bf\u09a8", "BE": "\u09ac\u09c7\u09b2\u099c\u09bf\u09af\u09bc\u09be\u09ae", "BY": "\u09ac\u09c7\u09b2\u09be\u09b0\u09c1\u09b6", "BZ": "\u09ac\u09c7\u09b2\u09bf\u099c", "BV": "\u09ac\u09cb\u09ad\u09c7\u099f \u09a6\u09cd\u09ac\u09c0\u09aa", "BR": "\u09ac\u09cd\u09b0\u09be\u099c\u09bf\u09b2", "IO": "\u09ac\u09cd\u09b0\u09bf\u099f\u09bf\u09b6 \u09ad\u09be\u09b0\u09a4 \u09ae\u09b9\u09be\u09b8\u09be\u0997\u09b0\u09c0\u09af\u09bc \u0985\u099e\u09cd\u099a\u09b2", "VG": "\u09ac\u09cd\u09b0\u09bf\u099f\u09bf\u09b6 \u09ad\u09be\u09b0\u09cd\u099c\u09bf\u09a8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "BN": "\u09ac\u09cd\u09b0\u09c1\u09a8\u09c7\u0987", "VU": "\u09ad\u09be\u09a8\u09c1\u09af\u09bc\u09be\u099f\u09c1", "IN": "\u09ad\u09be\u09b0\u09a4", "VN": "\u09ad\u09bf\u09af\u09bc\u09c7\u09a4\u09a8\u09be\u09ae", "BT": "\u09ad\u09c1\u099f\u09be\u09a8", "VE": "\u09ad\u09c7\u09a8\u09c7\u099c\u09c1\u09af\u09bc\u09c7\u09b2\u09be", "VA": "\u09ad\u09cd\u09af\u09be\u099f\u09bf\u0995\u09be\u09a8 \u09b8\u09bf\u099f\u09bf", "MN": "\u09ae\u0999\u09cd\u0997\u09cb\u09b2\u09bf\u09af\u09bc\u09be", "CF": "\u09ae\u09a7\u09cd\u09af \u0986\u09ab\u09cd\u09b0\u09bf\u0995\u09be\u09b0 \u09aa\u09cd\u09b0\u099c\u09be\u09a4\u09a8\u09cd\u09a4\u09cd\u09b0", "MS": "\u09ae\u09a8\u09cd\u099f\u09b8\u09c7\u09b0\u09be\u099f", "ME": "\u09ae\u09a8\u09cd\u099f\u09bf\u09a8\u09bf\u0997\u09cd\u09b0\u09cb", "MR": "\u09ae\u09b0\u09bf\u09a4\u09be\u09a8\u09bf\u09af\u09bc\u09be", "MU": "\u09ae\u09b0\u09bf\u09b6\u09be\u09b8", "MD": "\u09ae\u09b2\u09a1\u09cb\u09ad\u09be", "MG": "\u09ae\u09be\u09a6\u09be\u0997\u09be\u09b8\u09cd\u0995\u09be\u09b0", "MM": "\u09ae\u09be\u09af\u09bc\u09be\u09a8\u09ae\u09be\u09b0 (\u09ac\u09be\u09b0\u09cd\u09ae\u09be)", "YT": "\u09ae\u09be\u09af\u09bc\u09cb\u09a4\u09cd\u09a4\u09c7", "US": "\u09ae\u09be\u09b0\u09cd\u0995\u09bf\u09a8 \u09af\u09c1\u0995\u09cd\u09a4\u09b0\u09be\u09b7\u09cd\u099f\u09cd\u09b0", "VI": "\u09ae\u09be\u09b0\u09cd\u0995\u09bf\u09a8 \u09af\u09c1\u0995\u09cd\u09a4\u09b0\u09be\u09b7\u09cd\u099f\u09cd\u09b0\u09c7\u09b0 \u09ad\u09be\u09b0\u09cd\u099c\u09bf\u09a8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "MQ": "\u09ae\u09be\u09b0\u09cd\u099f\u09bf\u09a8\u09bf\u0995", "MV": "\u09ae\u09be\u09b2\u09a6\u09cd\u09ac\u09c0\u09aa", "MY": "\u09ae\u09be\u09b2\u09af\u09bc\u09c7\u09b6\u09bf\u09af\u09bc\u09be", "MW": "\u09ae\u09be\u09b2\u09be\u0989\u0987", "ML": "\u09ae\u09be\u09b2\u09bf", "MT": "\u09ae\u09be\u09b2\u09cd\u099f\u09be", "EG": "\u09ae\u09bf\u09b6\u09b0", "MX": "\u09ae\u09c7\u0995\u09cd\u09b8\u09bf\u0995\u09cb", "MZ": "\u09ae\u09cb\u099c\u09be\u09ae\u09cd\u09ac\u09bf\u0995", "MC": "\u09ae\u09cb\u09a8\u09be\u0995\u09cb", "MA": "\u09ae\u09cb\u09b0\u0995\u09cd\u0995\u09cb", "MO": "\u09ae\u09cd\u09af\u09be\u0995\u09be\u0993 \u098f\u09b8\u098f\u0986\u09b0 \u099a\u09c0\u09a8\u09be", "GB": "\u09af\u09c1\u0995\u09cd\u09a4\u09b0\u09be\u099c\u09cd\u09af", "RU": "\u09b0\u09be\u09b6\u09bf\u09af\u09bc\u09be", "RE": "\u09b0\u09bf\u0987\u0989\u09a8\u09bf\u09af\u09bc\u09a8", "RW": "\u09b0\u09c1\u09af\u09bc\u09be\u09a8\u09cd\u09a1\u09be", "RO": "\u09b0\u09cb\u09ae\u09be\u09a8\u09bf\u09af\u09bc\u09be", "LR": "\u09b2\u09be\u0987\u09ac\u09c7\u09b0\u09bf\u09af\u09bc\u09be", "LA": "\u09b2\u09be\u0993\u09b8", "LU": "\u09b2\u09be\u0995\u09cd\u09b8\u09c7\u09ae\u09ac\u09be\u09b0\u09cd\u0997", "LV": "\u09b2\u09be\u09a4\u09cd\u09ad\u09bf\u09af\u09bc\u09be", "LI": "\u09b2\u09bf\u099a\u09c7\u09a8\u09b8\u09cd\u099f\u09c7\u0987\u09a8", "LT": "\u09b2\u09bf\u09a5\u09c1\u09af\u09bc\u09be\u09a8\u09bf\u09af\u09bc\u09be", "LY": "\u09b2\u09bf\u09ac\u09bf\u09af\u09bc\u09be", "LB": "\u09b2\u09c7\u09ac\u09be\u09a8\u09a8", "LS": "\u09b2\u09c7\u09b8\u09cb\u09a5\u09cb", "LK": "\u09b6\u09cd\u09b0\u09c0\u09b2\u0999\u09cd\u0995\u09be", "AE": "\u09b8\u0982\u09af\u09c1\u0995\u09cd\u09a4 \u0986\u09b0\u09ac \u0986\u09ae\u09bf\u09b0\u09be\u09a4", "SB": "\u09b8\u09b2\u09cb\u09ae\u09a8 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c", "CY": "\u09b8\u09be\u0987\u09aa\u09cd\u09b0\u09be\u09b8", "ST": "\u09b8\u09be\u0993\u099f\u09cb\u09ae\u09be \u0993 \u09aa\u09cd\u09b0\u09bf\u09a8\u09cd\u09b8\u09bf\u09aa\u09bf", "SM": "\u09b8\u09be\u09a8 \u09ae\u09be\u09b0\u09bf\u09a8\u09cb", "WS": "\u09b8\u09be\u09ae\u09cb\u09af\u09bc\u09be", "RS": "\u09b8\u09be\u09b0\u09cd\u09ac\u09bf\u09af\u09bc\u09be", "SG": "\u09b8\u09bf\u0999\u09cd\u0997\u09be\u09aa\u09c1\u09b0", "SX": "\u09b8\u09bf\u09a8\u09cd\u099f \u09ae\u09be\u09b0\u09cd\u099f\u09c7\u09a8", "SL": "\u09b8\u09bf\u09af\u09bc\u09c7\u09b0\u09be \u09b2\u09bf\u0993\u09a8", "SY": "\u09b8\u09bf\u09b0\u09bf\u09af\u09bc\u09be", "SC": "\u09b8\u09bf\u09b8\u09bf\u09b2\u09bf", "CH": "\u09b8\u09c1\u0987\u099c\u09be\u09b0\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "SE": "\u09b8\u09c1\u0987\u09a1\u09c7\u09a8", "SD": "\u09b8\u09c1\u09a6\u09be\u09a8", "SR": "\u09b8\u09c1\u09b0\u09bf\u09a8\u09be\u09ae", "SN": "\u09b8\u09c7\u09a8\u09c7\u0997\u09be\u09b2", "KN": "\u09b8\u09c7\u09a8\u09cd\u099f \u0995\u09bf\u099f\u09b8 \u0993 \u09a8\u09c7\u09ad\u09bf\u09b8", "PM": "\u09b8\u09c7\u09a8\u09cd\u099f \u09aa\u09bf\u09af\u09bc\u09c7\u09b0 \u0993 \u09ae\u09bf\u0995\u09c1\u09af\u09bc\u09c7\u09b2\u09a8", "BL": "\u09b8\u09c7\u09a8\u09cd\u099f \u09ac\u09be\u09b0\u09a5\u09c7\u09b2\u09bf\u09ae\u09bf", "VC": "\u09b8\u09c7\u09a8\u09cd\u099f \u09ad\u09bf\u09a8\u09b8\u09c7\u09a8\u09cd\u099f \u0993 \u0997\u09cd\u09b0\u09c7\u09a8\u09be\u09a1\u09bf\u09a8\u09b8", "MF": "\u09b8\u09c7\u09a8\u09cd\u099f \u09ae\u09be\u09b0\u09cd\u099f\u09bf\u09a8", "LC": "\u09b8\u09c7\u09a8\u09cd\u099f \u09b2\u09c1\u09b8\u09bf\u09af\u09bc\u09be", "SH": "\u09b8\u09c7\u09a8\u09cd\u099f \u09b9\u09c7\u09b2\u09c7\u09a8\u09be", "SO": "\u09b8\u09cb\u09ae\u09be\u09b2\u09bf\u09af\u09bc\u09be", "SA": "\u09b8\u09cc\u09a6\u09bf \u0986\u09b0\u09ac", "ES": "\u09b8\u09cd\u09aa\u09c7\u09a8", "SJ": "\u09b8\u09cd\u09ac\u09be\u09b2\u09ac\u09be\u09b0\u09cd\u09a1 \u0993 \u099c\u09be\u09a8 \u09ae\u09c7\u09af\u09bc\u09c7\u09a8", "SK": "\u09b8\u09cd\u09b2\u09cb\u09ad\u09be\u0995\u09bf\u09af\u09bc\u09be", "SI": "\u09b8\u09cd\u09b2\u09cb\u09ad\u09be\u09a8\u09bf\u09af\u09bc\u09be", "HK": "\u09b9\u0982\u0995\u0982 \u098f\u09b8\u098f\u0986\u09b0 \u099a\u09c0\u09a8\u09be", "HN": "\u09b9\u09a8\u09cd\u09a1\u09c1\u09b0\u09be\u09b8", "HT": "\u09b9\u09be\u0987\u09a4\u09bf", "HU": "\u09b9\u09be\u0999\u09cd\u0997\u09c7\u09b0\u09bf", "HM": "\u09b9\u09be\u09b0\u09cd\u09a1 \u098f\u09ac\u0982 \u09ae\u09cd\u09af\u09be\u0995\u09a1\u09cb\u09a8\u09be\u09b2\u09cd\u09a1 \u09a6\u09cd\u09ac\u09c0\u09aa\u09aa\u09c1\u099e\u09cd\u099c"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/de.json b/desktop/onionshare/resources/countries/de.json
new file mode 100644
index 00000000..33f21aed
--- /dev/null
+++ b/desktop/onionshare/resources/countries/de.json
@@ -0,0 +1 @@
+{"AF": "Afghanistan", "EG": "\u00c4gypten", "AX": "\u00c5landinseln", "AL": "Albanien", "DZ": "Algerien", "AS": "Amerikanisch-Samoa", "VI": "Amerikanische Jungferninseln", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktis", "AG": "Antigua und Barbuda", "GQ": "\u00c4quatorialguinea", "AR": "Argentinien", "AM": "Armenien", "AW": "Aruba", "AZ": "Aserbaidschan", "ET": "\u00c4thiopien", "AU": "Australien", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesch", "BB": "Barbados", "BY": "Belarus", "BE": "Belgien", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivien", "BQ": "Bonaire, Sint Eustatius und Saba", "BA": "Bosnien und Herzegowina", "BW": "Botsuana", "BV": "Bouvetinsel", "BR": "Brasilien", "VG": "Britische Jungferninseln", "IO": "Britisches Territorium im Indischen Ozean", "BN": "Brunei Darussalam", "BG": "Bulgarien", "BF": "Burkina Faso", "BI": "Burundi", "CV": "Cabo Verde", "CL": "Chile", "CN": "China", "CK": "Cookinseln", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire", "CW": "Cura\u00e7ao", "DK": "D\u00e4nemark", "DE": "Deutschland", "DM": "Dominica", "DO": "Dominikanische Republik", "DJ": "Dschibuti", "EC": "Ecuador", "SV": "El Salvador", "ER": "Eritrea", "EE": "Estland", "SZ": "Eswatini", "FK": "Falklandinseln", "FO": "F\u00e4r\u00f6er", "FJ": "Fidschi", "FI": "Finnland", "FR": "Frankreich", "GF": "Franz\u00f6sisch-Guayana", "PF": "Franz\u00f6sisch-Polynesien", "TF": "Franz\u00f6sische S\u00fcd- und Antarktisgebiete", "GA": "Gabun", "GM": "Gambia", "GE": "Georgien", "GH": "Ghana", "GI": "Gibraltar", "GD": "Grenada", "GR": "Griechenland", "GL": "Gr\u00f6nland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard und McDonaldinseln", "HN": "Honduras", "IN": "Indien", "ID": "Indonesien", "IQ": "Irak", "IR": "Iran", "IE": "Irland", "IS": "Island", "IM": "Isle of Man", "IL": "Israel", "IT": "Italien", "JM": "Jamaika", "JP": "Japan", "YE": "Jemen", "JO": "Jordanien", "KY": "Kaimaninseln", "KH": "Kambodscha", "CM": "Kamerun", "CA": "Kanada", "KZ": "Kasachstan", "QA": "Katar", "KE": "Kenia", "KG": "Kirgisistan", "KI": "Kiribati", "CC": "Kokosinseln", "CO": "Kolumbien", "KM": "Komoren", "CG": "Kongo-Brazzaville", "CD": "Kongo-Kinshasa", "HR": "Kroatien", "CU": "Kuba", "KW": "Kuwait", "LA": "Laos", "LS": "Lesotho", "LV": "Lettland", "LB": "Libanon", "LR": "Liberia", "LY": "Libyen", "LI": "Liechtenstein", "LT": "Litauen", "LU": "Luxemburg", "MG": "Madagaskar", "MW": "Malawi", "MY": "Malaysia", "MV": "Malediven", "ML": "Mali", "MT": "Malta", "MA": "Marokko", "MQ": "Martinique", "MR": "Mauretanien", "MU": "Mauritius", "YT": "Mayotte", "MX": "Mexiko", "MC": "Monaco", "MN": "Mongolei", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mosambik", "MM": "Myanmar", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NC": "Neukaledonien", "NZ": "Neuseeland", "NI": "Nicaragua", "NL": "Niederlande", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "KP": "Nordkorea", "MK": "Nordmazedonien", "NF": "Norfolkinsel", "NO": "Norwegen", "OM": "Oman", "AT": "\u00d6sterreich", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua-Neuguinea", "PY": "Paraguay", "PE": "Peru", "PH": "Philippinen", "PN": "Pitcairninseln", "PL": "Polen", "PT": "Portugal", "PR": "Puerto Rico", "MD": "Republik Moldau", "RE": "R\u00e9union", "RW": "Ruanda", "RO": "Rum\u00e4nien", "RU": "Russland", "SB": "Salomonen", "ZM": "Sambia", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 und Pr\u00edncipe", "SA": "Saudi-Arabien", "SE": "Schweden", "CH": "Schweiz", "SN": "Senegal", "RS": "Serbien", "SC": "Seychellen", "SL": "Sierra Leone", "ZW": "Simbabwe", "SG": "Singapur", "SX": "Sint Maarten", "SK": "Slowakei", "SI": "Slowenien", "SO": "Somalia", "HK": "Sonderverwaltungsregion Hongkong", "MO": "Sonderverwaltungsregion Macau", "ES": "Spanien", "SJ": "Spitzbergen und Jan Mayen", "LK": "Sri Lanka", "BL": "St. Barth\u00e9lemy", "SH": "St. Helena", "KN": "St. Kitts und Nevis", "LC": "St. Lucia", "MF": "St. Martin", "PM": "St. Pierre und Miquelon", "VC": "St. Vincent und die Grenadinen", "ZA": "S\u00fcdafrika", "SD": "Sudan", "GS": "S\u00fcdgeorgien und die S\u00fcdlichen Sandwichinseln", "KR": "S\u00fcdkorea", "SS": "S\u00fcdsudan", "SR": "Suriname", "SY": "Syrien", "TJ": "Tadschikistan", "TW": "Taiwan", "TZ": "Tansania", "TH": "Thailand", "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad und Tobago", "TD": "Tschad", "CZ": "Tschechien", "TN": "Tunesien", "TR": "T\u00fcrkei", "TM": "Turkmenistan", "TC": "Turks- und Caicosinseln", "UG": "Uganda", "UA": "Ukraine", "HU": "Ungarn", "UY": "Uruguay", "UZ": "Usbekistan", "VU": "Vanuatu", "VA": "Vatikanstadt", "VE": "Venezuela", "AE": "Vereinigte Arabische Emirate", "US": "Vereinigte Staaten", "GB": "Vereinigtes K\u00f6nigreich", "VN": "Vietnam", "WF": "Wallis und Futuna", "CX": "Weihnachtsinsel", "EH": "Westsahara", "CF": "Zentralafrikanische Republik", "CY": "Zypern"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/el.json b/desktop/onionshare/resources/countries/el.json
new file mode 100644
index 00000000..2be69778
--- /dev/null
+++ b/desktop/onionshare/resources/countries/el.json
@@ -0,0 +1 @@
+{"SH": "\u0391\u03b3\u03af\u03b1 \u0395\u03bb\u03ad\u03bd\u03b7", "LC": "\u0391\u03b3\u03af\u03b1 \u039b\u03bf\u03c5\u03ba\u03af\u03b1", "BL": "\u0386\u03b3\u03b9\u03bf\u03c2 \u0392\u03b1\u03c1\u03b8\u03bf\u03bb\u03bf\u03bc\u03b1\u03af\u03bf\u03c2", "VC": "\u0386\u03b3\u03b9\u03bf\u03c2 \u0392\u03b9\u03ba\u03ad\u03bd\u03c4\u03b9\u03bf\u03c2 \u03ba\u03b1\u03b9 \u0393\u03c1\u03b5\u03bd\u03b1\u03b4\u03af\u03bd\u03b5\u03c2", "SM": "\u0386\u03b3\u03b9\u03bf\u03c2 \u039c\u03b1\u03c1\u03af\u03bd\u03bf\u03c2", "MF": "\u0386\u03b3\u03b9\u03bf\u03c2 \u039c\u03b1\u03c1\u03c4\u03af\u03bd\u03bf\u03c2 (\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03cc \u03c4\u03bc\u03ae\u03bc\u03b1)", "SX": "\u0386\u03b3\u03b9\u03bf\u03c2 \u039c\u03b1\u03c1\u03c4\u03af\u03bd\u03bf\u03c2 (\u039f\u03bb\u03bb\u03b1\u03bd\u03b4\u03b9\u03ba\u03cc \u03c4\u03bc\u03ae\u03bc\u03b1)", "AO": "\u0391\u03b3\u03ba\u03cc\u03bb\u03b1", "AZ": "\u0391\u03b6\u03b5\u03c1\u03bc\u03c0\u03b1\u03ca\u03c4\u03b6\u03ac\u03bd", "EG": "\u0391\u03af\u03b3\u03c5\u03c0\u03c4\u03bf\u03c2", "ET": "\u0391\u03b9\u03b8\u03b9\u03bf\u03c0\u03af\u03b1", "HT": "\u0391\u03ca\u03c4\u03ae", "CI": "\u0391\u03ba\u03c4\u03ae \u0395\u03bb\u03b5\u03c6\u03b1\u03bd\u03c4\u03bf\u03c3\u03c4\u03bf\u03cd", "AL": "\u0391\u03bb\u03b2\u03b1\u03bd\u03af\u03b1", "DZ": "\u0391\u03bb\u03b3\u03b5\u03c1\u03af\u03b1", "VI": "\u0391\u03bc\u03b5\u03c1\u03b9\u03ba\u03b1\u03bd\u03b9\u03ba\u03ad\u03c2 \u03a0\u03b1\u03c1\u03b8\u03ad\u03bd\u03b5\u03c2 \u039d\u03ae\u03c3\u03bf\u03b9", "AS": "\u0391\u03bc\u03b5\u03c1\u03b9\u03ba\u03b1\u03bd\u03b9\u03ba\u03ae \u03a3\u03b1\u03bc\u03cc\u03b1", "AI": "\u0391\u03bd\u03b3\u03ba\u03bf\u03c5\u03af\u03bb\u03b1", "AD": "\u0391\u03bd\u03b4\u03cc\u03c1\u03b1", "AQ": "\u0391\u03bd\u03c4\u03b1\u03c1\u03ba\u03c4\u03b9\u03ba\u03ae", "AG": "\u0391\u03bd\u03c4\u03af\u03b3\u03ba\u03bf\u03c5\u03b1 \u03ba\u03b1\u03b9 \u039c\u03c0\u03b1\u03c1\u03bc\u03c0\u03bf\u03cd\u03bd\u03c4\u03b1", "AR": "\u0391\u03c1\u03b3\u03b5\u03bd\u03c4\u03b9\u03bd\u03ae", "AM": "\u0391\u03c1\u03bc\u03b5\u03bd\u03af\u03b1", "AW": "\u0391\u03c1\u03bf\u03cd\u03bc\u03c0\u03b1", "AU": "\u0391\u03c5\u03c3\u03c4\u03c1\u03b1\u03bb\u03af\u03b1", "AT": "\u0391\u03c5\u03c3\u03c4\u03c1\u03af\u03b1", "AF": "\u0391\u03c6\u03b3\u03b1\u03bd\u03b9\u03c3\u03c4\u03ac\u03bd", "VU": "\u0392\u03b1\u03bd\u03bf\u03c5\u03ac\u03c4\u03bf\u03c5", "VA": "\u0392\u03b1\u03c4\u03b9\u03ba\u03b1\u03bd\u03cc", "BE": "\u0392\u03ad\u03bb\u03b3\u03b9\u03bf", "VE": "\u0392\u03b5\u03bd\u03b5\u03b6\u03bf\u03c5\u03ad\u03bb\u03b1", "BM": "\u0392\u03b5\u03c1\u03bc\u03bf\u03cd\u03b4\u03b5\u03c2", "VN": "\u0392\u03b9\u03b5\u03c4\u03bd\u03ac\u03bc", "BO": "\u0392\u03bf\u03bb\u03b9\u03b2\u03af\u03b1", "KP": "\u0392\u03cc\u03c1\u03b5\u03b9\u03b1 \u039a\u03bf\u03c1\u03ad\u03b1", "MK": "\u0392\u03cc\u03c1\u03b5\u03b9\u03b1 \u039c\u03b1\u03ba\u03b5\u03b4\u03bf\u03bd\u03af\u03b1", "BA": "\u0392\u03bf\u03c3\u03bd\u03af\u03b1 - \u0395\u03c1\u03b6\u03b5\u03b3\u03bf\u03b2\u03af\u03bd\u03b7", "BG": "\u0392\u03bf\u03c5\u03bb\u03b3\u03b1\u03c1\u03af\u03b1", "BR": "\u0392\u03c1\u03b1\u03b6\u03b9\u03bb\u03af\u03b1", "IO": "\u0392\u03c1\u03b5\u03c4\u03b1\u03bd\u03b9\u03ba\u03ac \u0395\u03b4\u03ac\u03c6\u03b7 \u0399\u03bd\u03b4\u03b9\u03ba\u03bf\u03cd \u03a9\u03ba\u03b5\u03b1\u03bd\u03bf\u03cd", "VG": "\u0392\u03c1\u03b5\u03c4\u03b1\u03bd\u03b9\u03ba\u03ad\u03c2 \u03a0\u03b1\u03c1\u03b8\u03ad\u03bd\u03b5\u03c2 \u039d\u03ae\u03c3\u03bf\u03b9", "FR": "\u0393\u03b1\u03bb\u03bb\u03af\u03b1", "TF": "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ac \u039d\u03cc\u03c4\u03b9\u03b1 \u0395\u03b4\u03ac\u03c6\u03b7", "GF": "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ae \u0393\u03bf\u03c5\u03b9\u03ac\u03bd\u03b1", "PF": "\u0393\u03b1\u03bb\u03bb\u03b9\u03ba\u03ae \u03a0\u03bf\u03bb\u03c5\u03bd\u03b7\u03c3\u03af\u03b1", "DE": "\u0393\u03b5\u03c1\u03bc\u03b1\u03bd\u03af\u03b1", "GE": "\u0393\u03b5\u03c9\u03c1\u03b3\u03af\u03b1", "GI": "\u0393\u03b9\u03b2\u03c1\u03b1\u03bb\u03c4\u03ac\u03c1", "GM": "\u0393\u03ba\u03ac\u03bc\u03c0\u03b9\u03b1", "GA": "\u0393\u03ba\u03b1\u03bc\u03c0\u03cc\u03bd", "GH": "\u0393\u03ba\u03ac\u03bd\u03b1", "GG": "\u0393\u03ba\u03ad\u03c1\u03bd\u03b6\u03b9", "GU": "\u0393\u03ba\u03bf\u03c5\u03ac\u03bc", "GP": "\u0393\u03bf\u03c5\u03b1\u03b4\u03b5\u03bb\u03bf\u03cd\u03c0\u03b7", "WF": "\u0393\u03bf\u03c5\u03ac\u03bb\u03b9\u03c2 \u03ba\u03b1\u03b9 \u03a6\u03bf\u03c5\u03c4\u03bf\u03cd\u03bd\u03b1", "GT": "\u0393\u03bf\u03c5\u03b1\u03c4\u03b5\u03bc\u03ac\u03bb\u03b1", "GY": "\u0393\u03bf\u03c5\u03b9\u03ac\u03bd\u03b1", "GN": "\u0393\u03bf\u03c5\u03b9\u03bd\u03ad\u03b1", "GW": "\u0393\u03bf\u03c5\u03b9\u03bd\u03ad\u03b1 \u039c\u03c0\u03b9\u03c3\u03ac\u03bf\u03c5", "GD": "\u0393\u03c1\u03b5\u03bd\u03ac\u03b4\u03b1", "GL": "\u0393\u03c1\u03bf\u03b9\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "DK": "\u0394\u03b1\u03bd\u03af\u03b1", "DO": "\u0394\u03bf\u03bc\u03b9\u03bd\u03b9\u03ba\u03b1\u03bd\u03ae \u0394\u03b7\u03bc\u03bf\u03ba\u03c1\u03b1\u03c4\u03af\u03b1", "EH": "\u0394\u03c5\u03c4\u03b9\u03ba\u03ae \u03a3\u03b1\u03c7\u03ac\u03c1\u03b1", "SV": "\u0395\u03bb \u03a3\u03b1\u03bb\u03b2\u03b1\u03b4\u03cc\u03c1", "CH": "\u0395\u03bb\u03b2\u03b5\u03c4\u03af\u03b1", "GR": "\u0395\u03bb\u03bb\u03ac\u03b4\u03b1", "ER": "\u0395\u03c1\u03c5\u03b8\u03c1\u03b1\u03af\u03b1", "EE": "\u0395\u03c3\u03b8\u03bf\u03bd\u03af\u03b1", "ZM": "\u0396\u03ac\u03bc\u03c0\u03b9\u03b1", "ZW": "\u0396\u03b9\u03bc\u03c0\u03ac\u03bc\u03c0\u03bf\u03c5\u03b5", "AE": "\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b1 \u0391\u03c1\u03b1\u03b2\u03b9\u03ba\u03ac \u0395\u03bc\u03b9\u03c1\u03ac\u03c4\u03b1", "US": "\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a0\u03bf\u03bb\u03b9\u03c4\u03b5\u03af\u03b5\u03c2", "GB": "\u0397\u03bd\u03c9\u03bc\u03ad\u03bd\u03bf \u0392\u03b1\u03c3\u03af\u03bb\u03b5\u03b9\u03bf", "JP": "\u0399\u03b1\u03c0\u03c9\u03bd\u03af\u03b1", "IN": "\u0399\u03bd\u03b4\u03af\u03b1", "ID": "\u0399\u03bd\u03b4\u03bf\u03bd\u03b7\u03c3\u03af\u03b1", "JO": "\u0399\u03bf\u03c1\u03b4\u03b1\u03bd\u03af\u03b1", "IQ": "\u0399\u03c1\u03ac\u03ba", "IR": "\u0399\u03c1\u03ac\u03bd", "IE": "\u0399\u03c1\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "GQ": "\u0399\u03c3\u03b7\u03bc\u03b5\u03c1\u03b9\u03bd\u03ae \u0393\u03bf\u03c5\u03b9\u03bd\u03ad\u03b1", "EC": "\u0399\u03c3\u03b7\u03bc\u03b5\u03c1\u03b9\u03bd\u03cc\u03c2", "IS": "\u0399\u03c3\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "ES": "\u0399\u03c3\u03c0\u03b1\u03bd\u03af\u03b1", "IL": "\u0399\u03c3\u03c1\u03b1\u03ae\u03bb", "IT": "\u0399\u03c4\u03b1\u03bb\u03af\u03b1", "KZ": "\u039a\u03b1\u03b6\u03b1\u03ba\u03c3\u03c4\u03ac\u03bd", "CM": "\u039a\u03b1\u03bc\u03b5\u03c1\u03bf\u03cd\u03bd", "KH": "\u039a\u03b1\u03bc\u03c0\u03cc\u03c4\u03b6\u03b7", "CA": "\u039a\u03b1\u03bd\u03b1\u03b4\u03ac\u03c2", "QA": "\u039a\u03b1\u03c4\u03ac\u03c1", "CF": "\u039a\u03b5\u03bd\u03c4\u03c1\u03bf\u03b1\u03c6\u03c1\u03b9\u03ba\u03b1\u03bd\u03b9\u03ba\u03ae \u0394\u03b7\u03bc\u03bf\u03ba\u03c1\u03b1\u03c4\u03af\u03b1", "KE": "\u039a\u03ad\u03bd\u03c5\u03b1", "CN": "\u039a\u03af\u03bd\u03b1", "KG": "\u039a\u03b9\u03c1\u03b3\u03b9\u03c3\u03c4\u03ac\u03bd", "KI": "\u039a\u03b9\u03c1\u03b9\u03bc\u03c0\u03ac\u03c4\u03b9", "CO": "\u039a\u03bf\u03bb\u03bf\u03bc\u03b2\u03af\u03b1", "KM": "\u039a\u03bf\u03bc\u03cc\u03c1\u03b5\u03c2", "CD": "\u039a\u03bf\u03bd\u03b3\u03ba\u03cc - \u039a\u03b9\u03bd\u03c3\u03ac\u03c3\u03b1", "CG": "\u039a\u03bf\u03bd\u03b3\u03ba\u03cc - \u039c\u03c0\u03c1\u03b1\u03b6\u03b1\u03b2\u03af\u03bb", "CR": "\u039a\u03cc\u03c3\u03c4\u03b1 \u03a1\u03af\u03ba\u03b1", "CU": "\u039a\u03bf\u03cd\u03b2\u03b1", "KW": "\u039a\u03bf\u03c5\u03b2\u03ad\u03b9\u03c4", "CW": "\u039a\u03bf\u03c5\u03c1\u03b1\u03c3\u03ac\u03bf", "HR": "\u039a\u03c1\u03bf\u03b1\u03c4\u03af\u03b1", "CY": "\u039a\u03cd\u03c0\u03c1\u03bf\u03c2", "LA": "\u039b\u03ac\u03bf\u03c2", "LS": "\u039b\u03b5\u03c3\u03cc\u03c4\u03bf", "LV": "\u039b\u03b5\u03c4\u03bf\u03bd\u03af\u03b1", "BY": "\u039b\u03b5\u03c5\u03ba\u03bf\u03c1\u03c9\u03c3\u03af\u03b1", "LB": "\u039b\u03af\u03b2\u03b1\u03bd\u03bf\u03c2", "LR": "\u039b\u03b9\u03b2\u03b5\u03c1\u03af\u03b1", "LY": "\u039b\u03b9\u03b2\u03cd\u03b7", "LT": "\u039b\u03b9\u03b8\u03bf\u03c5\u03b1\u03bd\u03af\u03b1", "LI": "\u039b\u03b9\u03c7\u03c4\u03b5\u03bd\u03c3\u03c4\u03ac\u03b9\u03bd", "LU": "\u039b\u03bf\u03c5\u03be\u03b5\u03bc\u03b2\u03bf\u03cd\u03c1\u03b3\u03bf", "YT": "\u039c\u03b1\u03b3\u03b9\u03cc\u03c4", "MG": "\u039c\u03b1\u03b4\u03b1\u03b3\u03b1\u03c3\u03ba\u03ac\u03c1\u03b7", "MO": "\u039c\u03b1\u03ba\u03ac\u03bf \u0395\u0394\u03a0 \u039a\u03af\u03bd\u03b1\u03c2", "MY": "\u039c\u03b1\u03bb\u03b1\u03b9\u03c3\u03af\u03b1", "MW": "\u039c\u03b1\u03bb\u03ac\u03bf\u03c5\u03b9", "MV": "\u039c\u03b1\u03bb\u03b4\u03af\u03b2\u03b5\u03c2", "ML": "\u039c\u03ac\u03bb\u03b9", "MT": "\u039c\u03ac\u03bb\u03c4\u03b1", "MA": "\u039c\u03b1\u03c1\u03cc\u03ba\u03bf", "MQ": "\u039c\u03b1\u03c1\u03c4\u03b9\u03bd\u03af\u03ba\u03b1", "MU": "\u039c\u03b1\u03c5\u03c1\u03af\u03ba\u03b9\u03bf\u03c2", "MR": "\u039c\u03b1\u03c5\u03c1\u03b9\u03c4\u03b1\u03bd\u03af\u03b1", "ME": "\u039c\u03b1\u03c5\u03c1\u03bf\u03b2\u03bf\u03cd\u03bd\u03b9\u03bf", "MX": "\u039c\u03b5\u03be\u03b9\u03ba\u03cc", "MM": "\u039c\u03b9\u03b1\u03bd\u03bc\u03ac\u03c1 (\u0392\u03b9\u03c1\u03bc\u03b1\u03bd\u03af\u03b1)", "MN": "\u039c\u03bf\u03b3\u03b3\u03bf\u03bb\u03af\u03b1", "MZ": "\u039c\u03bf\u03b6\u03b1\u03bc\u03b2\u03af\u03ba\u03b7", "MD": "\u039c\u03bf\u03bb\u03b4\u03b1\u03b2\u03af\u03b1", "MC": "\u039c\u03bf\u03bd\u03b1\u03ba\u03cc", "MS": "\u039c\u03bf\u03bd\u03c3\u03b5\u03c1\u03ac\u03c4", "BD": "\u039c\u03c0\u03b1\u03bd\u03b3\u03ba\u03bb\u03b1\u03bd\u03c4\u03ad\u03c2", "BB": "\u039c\u03c0\u03b1\u03c1\u03bc\u03c0\u03ad\u03b9\u03bd\u03c4\u03bf\u03c2", "BS": "\u039c\u03c0\u03b1\u03c7\u03ac\u03bc\u03b5\u03c2", "BH": "\u039c\u03c0\u03b1\u03c7\u03c1\u03ad\u03b9\u03bd", "BZ": "\u039c\u03c0\u03b5\u03bb\u03af\u03b6", "BJ": "\u039c\u03c0\u03b5\u03bd\u03af\u03bd", "BW": "\u039c\u03c0\u03bf\u03c4\u03c3\u03bf\u03c5\u03ac\u03bd\u03b1", "BF": "\u039c\u03c0\u03bf\u03c5\u03c1\u03ba\u03af\u03bd\u03b1 \u03a6\u03ac\u03c3\u03bf", "BI": "\u039c\u03c0\u03bf\u03c5\u03c1\u03bf\u03cd\u03bd\u03c4\u03b9", "BT": "\u039c\u03c0\u03bf\u03c5\u03c4\u03ac\u03bd", "BN": "\u039c\u03c0\u03c1\u03bf\u03c5\u03bd\u03ad\u03b9", "NA": "\u039d\u03b1\u03bc\u03af\u03bc\u03c0\u03b9\u03b1", "NR": "\u039d\u03b1\u03bf\u03c5\u03c1\u03bf\u03cd", "NZ": "\u039d\u03ad\u03b1 \u0396\u03b7\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "NC": "\u039d\u03ad\u03b1 \u039a\u03b1\u03bb\u03b7\u03b4\u03bf\u03bd\u03af\u03b1", "NP": "\u039d\u03b5\u03c0\u03ac\u03bb", "KY": "\u039d\u03ae\u03c3\u03bf\u03b9 \u039a\u03ad\u03b9\u03bc\u03b1\u03bd", "CC": "\u039d\u03ae\u03c3\u03bf\u03b9 \u039a\u03cc\u03ba\u03bf\u03c2 (\u039a\u03af\u03bb\u03b9\u03bd\u03b3\u03ba)", "CK": "\u039d\u03ae\u03c3\u03bf\u03b9 \u039a\u03bf\u03c5\u03ba", "GS": "\u039d\u03ae\u03c3\u03bf\u03b9 \u039d\u03cc\u03c4\u03b9\u03b1 \u0393\u03b5\u03c9\u03c1\u03b3\u03af\u03b1 \u03ba\u03b1\u03b9 \u039d\u03cc\u03c4\u03b9\u03b5\u03c2 \u03a3\u03ac\u03bd\u03c4\u03bf\u03c5\u03b9\u03c4\u03c2", "AX": "\u039d\u03ae\u03c3\u03bf\u03b9 \u038c\u03bb\u03b1\u03bd\u03c4", "PN": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a0\u03af\u03c4\u03ba\u03b5\u03c1\u03bd", "SB": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a3\u03bf\u03bb\u03bf\u03bc\u03ce\u03bd\u03c4\u03bf\u03c2", "TC": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a4\u03b5\u03c1\u03ba\u03c2 \u03ba\u03b1\u03b9 \u039a\u03ac\u03b9\u03ba\u03bf\u03c2", "FO": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a6\u03b5\u03c1\u03cc\u03b5\u03c2", "FK": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a6\u03cc\u03ba\u03bb\u03b1\u03bd\u03c4", "HM": "\u039d\u03ae\u03c3\u03bf\u03b9 \u03a7\u03b5\u03c1\u03bd\u03c4 \u03ba\u03b1\u03b9 \u039c\u03b1\u03ba\u03bd\u03c4\u03cc\u03bd\u03b1\u03bb\u03bd\u03c4", "BV": "\u039d\u03ae\u03c3\u03bf\u03c2 \u039c\u03c0\u03bf\u03c5\u03b2\u03ad", "NF": "\u039d\u03ae\u03c3\u03bf\u03c2 \u039d\u03cc\u03c1\u03c6\u03bf\u03bb\u03ba", "IM": "\u039d\u03ae\u03c3\u03bf\u03c2 \u03c4\u03bf\u03c5 \u039c\u03b1\u03bd", "CX": "\u039d\u03ae\u03c3\u03bf\u03c2 \u03c4\u03c9\u03bd \u03a7\u03c1\u03b9\u03c3\u03c4\u03bf\u03c5\u03b3\u03ad\u03bd\u03bd\u03c9\u03bd", "NE": "\u039d\u03af\u03b3\u03b7\u03c1\u03b1\u03c2", "NG": "\u039d\u03b9\u03b3\u03b7\u03c1\u03af\u03b1", "NI": "\u039d\u03b9\u03ba\u03b1\u03c1\u03ac\u03b3\u03bf\u03c5\u03b1", "NU": "\u039d\u03b9\u03bf\u03cd\u03b5", "NO": "\u039d\u03bf\u03c1\u03b2\u03b7\u03b3\u03af\u03b1", "ZA": "\u039d\u03cc\u03c4\u03b9\u03b1 \u0391\u03c6\u03c1\u03b9\u03ba\u03ae", "KR": "\u039d\u03cc\u03c4\u03b9\u03b1 \u039a\u03bf\u03c1\u03ad\u03b1", "SS": "\u039d\u03cc\u03c4\u03b9\u03bf \u03a3\u03bf\u03c5\u03b4\u03ac\u03bd", "DM": "\u039d\u03c4\u03bf\u03bc\u03af\u03bd\u03b9\u03ba\u03b1", "NL": "\u039f\u03bb\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "BQ": "\u039f\u03bb\u03bb\u03b1\u03bd\u03b4\u03af\u03b1 \u039a\u03b1\u03c1\u03b1\u03ca\u03b2\u03b9\u03ba\u03ae\u03c2", "OM": "\u039f\u03bc\u03ac\u03bd", "HN": "\u039f\u03bd\u03b4\u03bf\u03cd\u03c1\u03b1", "HU": "\u039f\u03c5\u03b3\u03b3\u03b1\u03c1\u03af\u03b1", "UG": "\u039f\u03c5\u03b3\u03ba\u03ac\u03bd\u03c4\u03b1", "UZ": "\u039f\u03c5\u03b6\u03bc\u03c0\u03b5\u03ba\u03b9\u03c3\u03c4\u03ac\u03bd", "UA": "\u039f\u03c5\u03ba\u03c1\u03b1\u03bd\u03af\u03b1", "UY": "\u039f\u03c5\u03c1\u03bf\u03c5\u03b3\u03bf\u03c5\u03ac\u03b7", "PK": "\u03a0\u03b1\u03ba\u03b9\u03c3\u03c4\u03ac\u03bd", "PW": "\u03a0\u03b1\u03bb\u03ac\u03bf\u03c5", "PA": "\u03a0\u03b1\u03bd\u03b1\u03bc\u03ac\u03c2", "PG": "\u03a0\u03b1\u03c0\u03bf\u03cd\u03b1 \u039d\u03ad\u03b1 \u0393\u03bf\u03c5\u03b9\u03bd\u03ad\u03b1", "PY": "\u03a0\u03b1\u03c1\u03b1\u03b3\u03bf\u03c5\u03ac\u03b7", "PE": "\u03a0\u03b5\u03c1\u03bf\u03cd", "PL": "\u03a0\u03bf\u03bb\u03c9\u03bd\u03af\u03b1", "PT": "\u03a0\u03bf\u03c1\u03c4\u03bf\u03b3\u03b1\u03bb\u03af\u03b1", "PR": "\u03a0\u03bf\u03c5\u03ad\u03c1\u03c4\u03bf \u03a1\u03af\u03ba\u03bf", "CV": "\u03a0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf \u0391\u03ba\u03c1\u03c9\u03c4\u03ae\u03c1\u03b9\u03bf", "RE": "\u03a1\u03b5\u03ca\u03bd\u03b9\u03cc\u03bd", "RW": "\u03a1\u03bf\u03c5\u03ac\u03bd\u03c4\u03b1", "RO": "\u03a1\u03bf\u03c5\u03bc\u03b1\u03bd\u03af\u03b1", "RU": "\u03a1\u03c9\u03c3\u03af\u03b1", "WS": "\u03a3\u03b1\u03bc\u03cc\u03b1", "ST": "\u03a3\u03ac\u03bf \u03a4\u03bf\u03bc\u03ad \u03ba\u03b1\u03b9 \u03a0\u03c1\u03af\u03bd\u03c3\u03b9\u03c0\u03b5", "SA": "\u03a3\u03b1\u03bf\u03c5\u03b4\u03b9\u03ba\u03ae \u0391\u03c1\u03b1\u03b2\u03af\u03b1", "SJ": "\u03a3\u03b2\u03ac\u03bb\u03bc\u03c0\u03b1\u03c1\u03bd\u03c4 \u03ba\u03b1\u03b9 \u0393\u03b9\u03b1\u03bd \u039c\u03b1\u03b3\u03b9\u03ad\u03bd", "KN": "\u03a3\u03b5\u03bd \u039a\u03b9\u03c4\u03c2 \u03ba\u03b1\u03b9 \u039d\u03ad\u03b2\u03b9\u03c2", "PM": "\u03a3\u03b5\u03bd \u03a0\u03b9\u03b5\u03c1 \u03ba\u03b1\u03b9 \u039c\u03b9\u03ba\u03b5\u03bb\u03cc\u03bd", "SN": "\u03a3\u03b5\u03bd\u03b5\u03b3\u03ac\u03bb\u03b7", "RS": "\u03a3\u03b5\u03c1\u03b2\u03af\u03b1", "SC": "\u03a3\u03b5\u03cb\u03c7\u03ad\u03bb\u03bb\u03b5\u03c2", "SG": "\u03a3\u03b9\u03b3\u03ba\u03b1\u03c0\u03bf\u03cd\u03c1\u03b7", "SL": "\u03a3\u03b9\u03ad\u03c1\u03b1 \u039b\u03b5\u03cc\u03bd\u03b5", "SK": "\u03a3\u03bb\u03bf\u03b2\u03b1\u03ba\u03af\u03b1", "SI": "\u03a3\u03bb\u03bf\u03b2\u03b5\u03bd\u03af\u03b1", "SO": "\u03a3\u03bf\u03bc\u03b1\u03bb\u03af\u03b1", "SZ": "\u03a3\u03bf\u03c5\u03b1\u03b6\u03b9\u03bb\u03ac\u03bd\u03b4\u03b7", "SD": "\u03a3\u03bf\u03c5\u03b4\u03ac\u03bd", "SE": "\u03a3\u03bf\u03c5\u03b7\u03b4\u03af\u03b1", "SR": "\u03a3\u03bf\u03c5\u03c1\u03b9\u03bd\u03ac\u03bc", "LK": "\u03a3\u03c1\u03b9 \u039b\u03ac\u03bd\u03ba\u03b1", "SY": "\u03a3\u03c5\u03c1\u03af\u03b1", "TW": "\u03a4\u03b1\u03ca\u03b2\u03ac\u03bd", "TH": "\u03a4\u03b1\u03ca\u03bb\u03ac\u03bd\u03b4\u03b7", "TZ": "\u03a4\u03b1\u03bd\u03b6\u03b1\u03bd\u03af\u03b1", "TJ": "\u03a4\u03b1\u03c4\u03b6\u03b9\u03ba\u03b9\u03c3\u03c4\u03ac\u03bd", "JM": "\u03a4\u03b6\u03b1\u03bc\u03ac\u03b9\u03ba\u03b1", "DJ": "\u03a4\u03b6\u03b9\u03bc\u03c0\u03bf\u03c5\u03c4\u03af", "TL": "\u03a4\u03b9\u03bc\u03cc\u03c1-\u039b\u03ad\u03c3\u03c4\u03b5", "TG": "\u03a4\u03cc\u03b3\u03ba\u03bf", "TK": "\u03a4\u03bf\u03ba\u03b5\u03bb\u03ac\u03bf\u03c5", "TO": "\u03a4\u03cc\u03bd\u03b3\u03ba\u03b1", "TR": "\u03a4\u03bf\u03c5\u03c1\u03ba\u03af\u03b1", "TM": "\u03a4\u03bf\u03c5\u03c1\u03ba\u03bc\u03b5\u03bd\u03b9\u03c3\u03c4\u03ac\u03bd", "TT": "\u03a4\u03c1\u03b9\u03bd\u03b9\u03bd\u03c4\u03ac\u03bd\u03c4 \u03ba\u03b1\u03b9 \u03a4\u03bf\u03bc\u03c0\u03ac\u03b3\u03ba\u03bf", "TD": "\u03a4\u03c3\u03b1\u03bd\u03c4", "CZ": "\u03a4\u03c3\u03b5\u03c7\u03af\u03b1", "TN": "\u03a4\u03c5\u03bd\u03b7\u03c3\u03af\u03b1", "YE": "\u03a5\u03b5\u03bc\u03ad\u03bd\u03b7", "PH": "\u03a6\u03b9\u03bb\u03b9\u03c0\u03c0\u03af\u03bd\u03b5\u03c2", "FI": "\u03a6\u03b9\u03bd\u03bb\u03b1\u03bd\u03b4\u03af\u03b1", "FJ": "\u03a6\u03af\u03c4\u03b6\u03b9", "CL": "\u03a7\u03b9\u03bb\u03ae", "HK": "\u03a7\u03bf\u03bd\u03b3\u03ba \u039a\u03bf\u03bd\u03b3\u03ba \u0395\u0394\u03a0 \u039a\u03af\u03bd\u03b1\u03c2"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/en.json b/desktop/onionshare/resources/countries/en.json
new file mode 100644
index 00000000..e2a664e8
--- /dev/null
+++ b/desktop/onionshare/resources/countries/en.json
@@ -0,0 +1 @@
+{"AF": "Afghanistan", "AX": "\u00c5land Islands", "AL": "Albania", "DZ": "Algeria", "AS": "American Samoa", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarctica", "AG": "Antigua & Barbuda", "AR": "Argentina", "AM": "Armenia", "AW": "Aruba", "AU": "Australia", "AT": "Austria", "AZ": "Azerbaijan", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BY": "Belarus", "BE": "Belgium", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivia", "BA": "Bosnia & Herzegovina", "BW": "Botswana", "BV": "Bouvet Island", "BR": "Brazil", "IO": "British Indian Ocean Territory", "VG": "British Virgin Islands", "BN": "Brunei", "BG": "Bulgaria", "BF": "Burkina Faso", "BI": "Burundi", "KH": "Cambodia", "CM": "Cameroon", "CA": "Canada", "CV": "Cape Verde", "BQ": "Caribbean Netherlands", "KY": "Cayman Islands", "CF": "Central African Republic", "TD": "Chad", "CL": "Chile", "CN": "China", "CX": "Christmas Island", "CC": "Cocos (Keeling) Islands", "CO": "Colombia", "KM": "Comoros", "CG": "Congo - Brazzaville", "CD": "Congo - Kinshasa", "CK": "Cook Islands", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire", "HR": "Croatia", "CU": "Cuba", "CW": "Cura\u00e7ao", "CY": "Cyprus", "CZ": "Czechia", "DK": "Denmark", "DJ": "Djibouti", "DM": "Dominica", "DO": "Dominican Republic", "EC": "Ecuador", "EG": "Egypt", "SV": "El Salvador", "GQ": "Equatorial Guinea", "ER": "Eritrea", "EE": "Estonia", "SZ": "Eswatini", "ET": "Ethiopia", "FK": "Falkland Islands", "FO": "Faroe Islands", "FJ": "Fiji", "FI": "Finland", "FR": "France", "GF": "French Guiana", "PF": "French Polynesia", "TF": "French Southern Territories", "GA": "Gabon", "GM": "Gambia", "GE": "Georgia", "DE": "Germany", "GH": "Ghana", "GI": "Gibraltar", "GR": "Greece", "GL": "Greenland", "GD": "Grenada", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard & McDonald Islands", "HN": "Honduras", "HK": "Hong Kong SAR China", "HU": "Hungary", "IS": "Iceland", "IN": "India", "ID": "Indonesia", "IR": "Iran", "IQ": "Iraq", "IE": "Ireland", "IM": "Isle of Man", "IL": "Israel", "IT": "Italy", "JM": "Jamaica", "JP": "Japan", "JO": "Jordan", "KZ": "Kazakhstan", "KE": "Kenya", "KI": "Kiribati", "KW": "Kuwait", "KG": "Kyrgyzstan", "LA": "Laos", "LV": "Latvia", "LB": "Lebanon", "LS": "Lesotho", "LR": "Liberia", "LY": "Libya", "LI": "Liechtenstein", "LT": "Lithuania", "LU": "Luxembourg", "MO": "Macao SAR China", "MG": "Madagascar", "MW": "Malawi", "MY": "Malaysia", "MV": "Maldives", "ML": "Mali", "MT": "Malta", "MQ": "Martinique", "MR": "Mauritania", "MU": "Mauritius", "YT": "Mayotte", "MX": "Mexico", "MD": "Moldova", "MC": "Monaco", "MN": "Mongolia", "ME": "Montenegro", "MS": "Montserrat", "MA": "Morocco", "MZ": "Mozambique", "MM": "Myanmar (Burma)", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NL": "Netherlands", "NC": "New Caledonia", "NZ": "New Zealand", "NI": "Nicaragua", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "NF": "Norfolk Island", "KP": "North Korea", "MK": "North Macedonia", "NO": "Norway", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua New Guinea", "PY": "Paraguay", "PE": "Peru", "PH": "Philippines", "PN": "Pitcairn Islands", "PL": "Poland", "PT": "Portugal", "PR": "Puerto Rico", "QA": "Qatar", "RE": "R\u00e9union", "RO": "Romania", "RU": "Russia", "RW": "Rwanda", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 & Pr\u00edncipe", "SA": "Saudi Arabia", "SN": "Senegal", "RS": "Serbia", "SC": "Seychelles", "SL": "Sierra Leone", "SG": "Singapore", "SX": "Sint Maarten", "SK": "Slovakia", "SI": "Slovenia", "SB": "Solomon Islands", "SO": "Somalia", "ZA": "South Africa", "GS": "South Georgia & South Sandwich Islands", "KR": "South Korea", "SS": "South Sudan", "ES": "Spain", "LK": "Sri Lanka", "BL": "St. Barth\u00e9lemy", "SH": "St. Helena", "KN": "St. Kitts & Nevis", "LC": "St. Lucia", "MF": "St. Martin", "PM": "St. Pierre & Miquelon", "VC": "St. Vincent & Grenadines", "SD": "Sudan", "SR": "Suriname", "SJ": "Svalbard & Jan Mayen", "SE": "Sweden", "CH": "Switzerland", "SY": "Syria", "TW": "Taiwan", "TJ": "Tajikistan", "TZ": "Tanzania", "TH": "Thailand", "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad & Tobago", "TN": "Tunisia", "TR": "Turkey", "TM": "Turkmenistan", "TC": "Turks & Caicos Islands", "VI": "U.S. Virgin Islands", "UG": "Uganda", "UA": "Ukraine", "AE": "United Arab Emirates", "GB": "United Kingdom", "US": "United States", "UY": "Uruguay", "UZ": "Uzbekistan", "VU": "Vanuatu", "VA": "Vatican City", "VE": "Venezuela", "VN": "Vietnam", "WF": "Wallis & Futuna", "EH": "Western Sahara", "YE": "Yemen", "ZM": "Zambia", "ZW": "Zimbabwe"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/es.json b/desktop/onionshare/resources/countries/es.json
new file mode 100644
index 00000000..87b466dd
--- /dev/null
+++ b/desktop/onionshare/resources/countries/es.json
@@ -0,0 +1 @@
+{"AF": "Afganist\u00e1n", "AL": "Albania", "DE": "Alemania", "AD": "Andorra", "AO": "Angola", "AI": "Anguila", "AQ": "Ant\u00e1rtida", "AG": "Antigua y Barbuda", "SA": "Arabia Saud\u00ed", "DZ": "Argelia", "AR": "Argentina", "AM": "Armenia", "AW": "Aruba", "AU": "Australia", "AT": "Austria", "AZ": "Azerbaiy\u00e1n", "BS": "Bahamas", "BD": "Banglad\u00e9s", "BB": "Barbados", "BH": "Bar\u00e9in", "BE": "B\u00e9lgica", "BZ": "Belice", "BJ": "Ben\u00edn", "BM": "Bermudas", "BY": "Bielorrusia", "BO": "Bolivia", "BA": "Bosnia y Herzegovina", "BW": "Botsuana", "BR": "Brasil", "BN": "Brun\u00e9i", "BG": "Bulgaria", "BF": "Burkina Faso", "BI": "Burundi", "BT": "But\u00e1n", "CV": "Cabo Verde", "KH": "Camboya", "CM": "Camer\u00fan", "CA": "Canad\u00e1", "BQ": "Caribe neerland\u00e9s", "QA": "Catar", "TD": "Chad", "CZ": "Chequia", "CL": "Chile", "CN": "China", "CY": "Chipre", "VA": "Ciudad del Vaticano", "CO": "Colombia", "KM": "Comoras", "CG": "Congo", "KP": "Corea del Norte", "KR": "Corea del Sur", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire", "HR": "Croacia", "CU": "Cuba", "CW": "Curazao", "DK": "Dinamarca", "DM": "Dominica", "EC": "Ecuador", "EG": "Egipto", "SV": "El Salvador", "AE": "Emiratos \u00c1rabes Unidos", "ER": "Eritrea", "SK": "Eslovaquia", "SI": "Eslovenia", "ES": "Espa\u00f1a", "US": "Estados Unidos", "EE": "Estonia", "SZ": "Esuatini", "ET": "Etiop\u00eda", "PH": "Filipinas", "FI": "Finlandia", "FJ": "Fiyi", "FR": "Francia", "GA": "Gab\u00f3n", "GM": "Gambia", "GE": "Georgia", "GH": "Ghana", "GI": "Gibraltar", "GD": "Granada", "GR": "Grecia", "GL": "Groenlandia", "GP": "Guadalupe", "GU": "Guam", "GT": "Guatemala", "GF": "Guayana Francesa", "GG": "Guernsey", "GN": "Guinea", "GQ": "Guinea Ecuatorial", "GW": "Guinea-Bis\u00e1u", "GY": "Guyana", "HT": "Hait\u00ed", "HN": "Honduras", "HU": "Hungr\u00eda", "IN": "India", "ID": "Indonesia", "IQ": "Irak", "IR": "Ir\u00e1n", "IE": "Irlanda", "BV": "Isla Bouvet", "IM": "Isla de Man", "CX": "Isla de Navidad", "NF": "Isla Norfolk", "IS": "Islandia", "AX": "Islas \u00c5land", "KY": "Islas Caim\u00e1n", "CC": "Islas Cocos", "CK": "Islas Cook", "FO": "Islas Feroe", "GS": "Islas Georgia del Sur y Sandwich del Sur", "HM": "Islas Heard y McDonald", "FK": "Islas Malvinas", "PN": "Islas Pitcairn", "SB": "Islas Salom\u00f3n", "TC": "Islas Turcas y Caicos", "VG": "Islas V\u00edrgenes Brit\u00e1nicas", "VI": "Islas V\u00edrgenes de EE. UU.", "IL": "Israel", "IT": "Italia", "JM": "Jamaica", "JP": "Jap\u00f3n", "JO": "Jordania", "KZ": "Kazajist\u00e1n", "KE": "Kenia", "KG": "Kirguist\u00e1n", "KI": "Kiribati", "KW": "Kuwait", "LA": "Laos", "LS": "Lesoto", "LV": "Letonia", "LB": "L\u00edbano", "LR": "Liberia", "LY": "Libia", "LI": "Liechtenstein", "LT": "Lituania", "LU": "Luxemburgo", "MK": "Macedonia del Norte", "MG": "Madagascar", "MY": "Malasia", "MW": "Malaui", "MV": "Maldivas", "ML": "Mali", "MT": "Malta", "MA": "Marruecos", "MQ": "Martinica", "MU": "Mauricio", "MR": "Mauritania", "YT": "Mayotte", "MX": "M\u00e9xico", "MD": "Moldavia", "MC": "M\u00f3naco", "MN": "Mongolia", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mozambique", "MM": "Myanmar (Birmania)", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NI": "Nicaragua", "NE": "N\u00edger", "NG": "Nigeria", "NU": "Niue", "NO": "Noruega", "NC": "Nueva Caledonia", "NZ": "Nueva Zelanda", "OM": "Om\u00e1n", "NL": "Pa\u00edses Bajos", "PK": "Pakist\u00e1n", "PW": "Palaos", "PA": "Panam\u00e1", "PG": "Pap\u00faa Nueva Guinea", "PY": "Paraguay", "PE": "Per\u00fa", "PF": "Polinesia Francesa", "PL": "Polonia", "PT": "Portugal", "PR": "Puerto Rico", "HK": "RAE de Hong Kong (China)", "MO": "RAE de Macao (China)", "GB": "Reino Unido", "CF": "Rep\u00fablica Centroafricana", "CD": "Rep\u00fablica Democr\u00e1tica del Congo", "DO": "Rep\u00fablica Dominicana", "RE": "Reuni\u00f3n", "RW": "Ruanda", "RO": "Ruman\u00eda", "RU": "Rusia", "EH": "S\u00e1hara Occidental", "WS": "Samoa", "AS": "Samoa Americana", "BL": "San Bartolom\u00e9", "KN": "San Crist\u00f3bal y Nieves", "SM": "San Marino", "MF": "San Mart\u00edn", "PM": "San Pedro y Miquel\u00f3n", "VC": "San Vicente y las Granadinas", "SH": "Santa Elena", "LC": "Santa Luc\u00eda", "ST": "Santo Tom\u00e9 y Pr\u00edncipe", "SN": "Senegal", "RS": "Serbia", "SC": "Seychelles", "SL": "Sierra Leona", "SG": "Singapur", "SX": "Sint Maarten", "SY": "Siria", "SO": "Somalia", "LK": "Sri Lanka", "ZA": "Sud\u00e1frica", "SD": "Sud\u00e1n", "SS": "Sud\u00e1n del Sur", "SE": "Suecia", "CH": "Suiza", "SR": "Surinam", "SJ": "Svalbard y Jan Mayen", "TH": "Tailandia", "TW": "Taiw\u00e1n", "TZ": "Tanzania", "TJ": "Tayikist\u00e1n", "IO": "Territorio Brit\u00e1nico del Oc\u00e9ano \u00cdndico", "TF": "Territorios Australes Franceses", "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad y Tobago", "TN": "T\u00fanez", "TM": "Turkmenist\u00e1n", "TR": "Turqu\u00eda", "UA": "Ucrania", "UG": "Uganda", "UY": "Uruguay", "UZ": "Uzbekist\u00e1n", "VU": "Vanuatu", "VE": "Venezuela", "VN": "Vietnam", "WF": "Wallis y Futuna", "YE": "Yemen", "DJ": "Yibuti", "ZM": "Zambia", "ZW": "Zimbabue"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/fi.json b/desktop/onionshare/resources/countries/fi.json
new file mode 100644
index 00000000..4f921984
--- /dev/null
+++ b/desktop/onionshare/resources/countries/fi.json
@@ -0,0 +1 @@
+{"AF": "Afganistan", "AX": "Ahvenanmaa", "NL": "Alankomaat", "AL": "Albania", "DZ": "Algeria", "AS": "Amerikan Samoa", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktis", "AG": "Antigua ja Barbuda", "AE": "Arabiemiirikunnat", "AR": "Argentiina", "AM": "Armenia", "AW": "Aruba", "AU": "Australia", "AZ": "Azerbaid\u017ean", "BS": "Bahama", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BE": "Belgia", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivia", "BA": "Bosnia ja Hertsegovina", "BW": "Botswana", "BV": "Bouvet\u2019nsaari", "BR": "Brasilia", "IO": "Brittil\u00e4inen Intian valtameren alue", "VG": "Brittil\u00e4iset Neitsytsaaret", "BN": "Brunei", "BG": "Bulgaria", "BF": "Burkina Faso", "BI": "Burundi", "KY": "Caymansaaret", "CL": "Chile", "CK": "Cookinsaaret", "CR": "Costa Rica", "CW": "Cura\u00e7ao", "DJ": "Djibouti", "DM": "Dominica", "DO": "Dominikaaninen tasavalta", "EC": "Ecuador", "EG": "Egypti", "SV": "El Salvador", "ER": "Eritrea", "ES": "Espanja", "ZA": "Etel\u00e4-Afrikka", "GS": "Etel\u00e4-Georgia ja Etel\u00e4iset Sandwichsaaret", "KR": "Etel\u00e4-Korea", "SS": "Etel\u00e4-Sudan", "ET": "Etiopia", "FK": "Falklandinsaaret", "FJ": "Fid\u017ei", "PH": "Filippiinit", "FO": "F\u00e4rsaaret", "GA": "Gabon", "GM": "Gambia", "GE": "Georgia", "GH": "Ghana", "GI": "Gibraltar", "GD": "Grenada", "GL": "Gr\u00f6nlanti", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard ja McDonaldinsaaret", "HN": "Honduras", "HK": "Hongkong \u2013 Kiinan e.h.a.", "SJ": "Huippuvuoret ja Jan Mayen", "ID": "Indonesia", "IN": "Intia", "IQ": "Irak", "IR": "Iran", "IE": "Irlanti", "IS": "Islanti", "GB": "Iso-Britannia", "IL": "Israel", "IT": "Italia", "TL": "It\u00e4-Timor", "AT": "It\u00e4valta", "JM": "Jamaika", "JP": "Japani", "YE": "Jemen", "JO": "Jordania", "CX": "Joulusaari", "KH": "Kambod\u017ea", "CM": "Kamerun", "CA": "Kanada", "CV": "Kap Verde", "BQ": "Karibian Alankomaat", "KZ": "Kazakstan", "KE": "Kenia", "CF": "Keski-Afrikan tasavalta", "CN": "Kiina", "KG": "Kirgisia", "KI": "Kiribati", "CO": "Kolumbia", "KM": "Komorit", "CD": "Kongon demokraattinen tasavalta", "CG": "Kongon tasavalta", "CC": "Kookossaaret (Keelingsaaret)", "GR": "Kreikka", "HR": "Kroatia", "CU": "Kuuba", "KW": "Kuwait", "CY": "Kypros", "LA": "Laos", "LV": "Latvia", "LS": "Lesotho", "LB": "Libanon", "LR": "Liberia", "LY": "Libya", "LI": "Liechtenstein", "LT": "Liettua", "LU": "Luxemburg", "EH": "L\u00e4nsi-Sahara", "MO": "Macao \u2013 Kiinan e.h.a.", "MG": "Madagaskar", "MW": "Malawi", "MV": "Malediivit", "MY": "Malesia", "ML": "Mali", "MT": "Malta", "IM": "Mansaari", "MA": "Marokko", "MQ": "Martinique", "MR": "Mauritania", "MU": "Mauritius", "YT": "Mayotte", "MX": "Meksiko", "MD": "Moldova", "MC": "Monaco", "MN": "Mongolia", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mosambik", "MM": "Myanmar (Burma)", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NI": "Nicaragua", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "NF": "Norfolkinsaari", "NO": "Norja", "CI": "Norsunluurannikko", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua-Uusi-Guinea", "PY": "Paraguay", "PE": "Peru", "PN": "Pitcairn", "KP": "Pohjois-Korea", "MK": "Pohjois-Makedonia", "PT": "Portugali", "PR": "Puerto Rico", "PL": "Puola", "GQ": "P\u00e4iv\u00e4ntasaajan Guinea", "QA": "Qatar", "FR": "Ranska", "TF": "Ranskan etel\u00e4iset alueet", "GF": "Ranskan Guayana", "PF": "Ranskan Polynesia", "RE": "R\u00e9union", "RO": "Romania", "RW": "Ruanda", "SE": "Ruotsi", "SH": "Saint Helena", "KN": "Saint Kitts ja Nevis", "LC": "Saint Lucia", "VC": "Saint Vincent ja Grenadiinit", "BL": "Saint-Barth\u00e9lemy", "MF": "Saint-Martin", "PM": "Saint-Pierre ja Miquelon", "DE": "Saksa", "SB": "Salomonsaaret", "ZM": "Sambia", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 ja Pr\u00edncipe", "SA": "Saudi-Arabia", "SN": "Senegal", "RS": "Serbia", "SC": "Seychellit", "SL": "Sierra Leone", "SG": "Singapore", "SX": "Sint Maarten", "SK": "Slovakia", "SI": "Slovenia", "SO": "Somalia", "LK": "Sri Lanka", "SD": "Sudan", "FI": "Suomi", "SR": "Suriname", "CH": "Sveitsi", "SZ": "Swazimaa", "SY": "Syyria", "TJ": "Tad\u017eikistan", "TW": "Taiwan", "TZ": "Tansania", "DK": "Tanska", "TH": "Thaimaa", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad ja Tobago", "TD": "T\u0161ad", "CZ": "T\u0161ekki", "TN": "Tunisia", "TR": "Turkki", "TM": "Turkmenistan", "TC": "Turks- ja Caicossaaret", "UG": "Uganda", "UA": "Ukraina", "HU": "Unkari", "UY": "Uruguay", "NC": "Uusi-Kaledonia", "NZ": "Uusi-Seelanti", "UZ": "Uzbekistan", "BY": "Valko-Ven\u00e4j\u00e4", "VU": "Vanuatu", "VA": "Vatikaani", "VE": "Venezuela", "RU": "Ven\u00e4j\u00e4", "VN": "Vietnam", "EE": "Viro", "WF": "Wallis ja Futuna", "US": "Yhdysvallat", "VI": "Yhdysvaltain Neitsytsaaret", "ZW": "Zimbabwe"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/fr.json b/desktop/onionshare/resources/countries/fr.json
new file mode 100644
index 00000000..5bb9a530
--- /dev/null
+++ b/desktop/onionshare/resources/countries/fr.json
@@ -0,0 +1 @@
+{"AF": "Afghanistan", "ZA": "Afrique du Sud", "AL": "Albanie", "DZ": "Alg\u00e9rie", "DE": "Allemagne", "AD": "Andorre", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarctique", "AG": "Antigua-et-Barbuda", "SA": "Arabie saoudite", "AR": "Argentine", "AM": "Arm\u00e9nie", "AW": "Aruba", "AU": "Australie", "AT": "Autriche", "AZ": "Azerba\u00efdjan", "BS": "Bahamas", "BH": "Bahre\u00efn", "BD": "Bangladesh", "BB": "Barbade", "BE": "Belgique", "BZ": "Belize", "BJ": "B\u00e9nin", "BM": "Bermudes", "BT": "Bhoutan", "BY": "Bi\u00e9lorussie", "BO": "Bolivie", "BA": "Bosnie-Herz\u00e9govine", "BW": "Botswana", "BR": "Br\u00e9sil", "BN": "Brun\u00e9i Darussalam", "BG": "Bulgarie", "BF": "Burkina Faso", "BI": "Burundi", "KH": "Cambodge", "CM": "Cameroun", "CA": "Canada", "CV": "Cap-Vert", "CL": "Chili", "CN": "Chine", "CY": "Chypre", "CO": "Colombie", "KM": "Comores", "CG": "Congo-Brazzaville", "CD": "Congo-Kinshasa", "KP": "Cor\u00e9e du Nord", "KR": "Cor\u00e9e du Sud", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire", "HR": "Croatie", "CU": "Cuba", "CW": "Cura\u00e7ao", "DK": "Danemark", "DJ": "Djibouti", "DM": "Dominique", "EG": "\u00c9gypte", "AE": "\u00c9mirats arabes unis", "EC": "\u00c9quateur", "ER": "\u00c9rythr\u00e9e", "ES": "Espagne", "EE": "Estonie", "SZ": "Eswatini", "VA": "\u00c9tat de la Cit\u00e9 du Vatican", "US": "\u00c9tats-Unis", "ET": "\u00c9thiopie", "FJ": "Fidji", "FI": "Finlande", "FR": "France", "GA": "Gabon", "GM": "Gambie", "GE": "G\u00e9orgie", "GS": "G\u00e9orgie du Sud et \u00eeles Sandwich du Sud", "GH": "Ghana", "GI": "Gibraltar", "GR": "Gr\u00e8ce", "GD": "Grenade", "GL": "Groenland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernesey", "GN": "Guin\u00e9e", "GQ": "Guin\u00e9e \u00e9quatoriale", "GW": "Guin\u00e9e-Bissau", "GY": "Guyana", "GF": "Guyane fran\u00e7aise", "HT": "Ha\u00efti", "HN": "Honduras", "HU": "Hongrie", "BV": "\u00cele Bouvet", "CX": "\u00cele Christmas", "IM": "\u00cele de Man", "NF": "\u00cele Norfolk", "AX": "\u00celes \u00c5land", "KY": "\u00celes Ca\u00efmans", "CC": "\u00celes Cocos", "CK": "\u00celes Cook", "FO": "\u00celes F\u00e9ro\u00e9", "HM": "\u00celes Heard et McDonald", "FK": "\u00celes Malouines", "PN": "\u00celes Pitcairn", "SB": "\u00celes Salomon", "TC": "\u00celes Turques-et-Ca\u00efques", "VG": "\u00celes Vierges britanniques", "VI": "\u00celes Vierges des \u00c9tats-Unis", "IN": "Inde", "ID": "Indon\u00e9sie", "IQ": "Irak", "IR": "Iran", "IE": "Irlande", "IS": "Islande", "IL": "Isra\u00ebl", "IT": "Italie", "JM": "Jama\u00efque", "JP": "Japon", "JO": "Jordanie", "KZ": "Kazakhstan", "KE": "Kenya", "KG": "Kirghizistan", "KI": "Kiribati", "KW": "Kowe\u00eft", "RE": "La R\u00e9union", "LA": "Laos", "LS": "Lesotho", "LV": "Lettonie", "LB": "Liban", "LR": "Lib\u00e9ria", "LY": "Libye", "LI": "Liechtenstein", "LT": "Lituanie", "LU": "Luxembourg", "MK": "Mac\u00e9doine du Nord", "MG": "Madagascar", "MY": "Malaisie", "MW": "Malawi", "MV": "Maldives", "ML": "Mali", "MT": "Malte", "MA": "Maroc", "MQ": "Martinique", "MU": "Maurice", "MR": "Mauritanie", "YT": "Mayotte", "MX": "Mexique", "MD": "Moldavie", "MC": "Monaco", "MN": "Mongolie", "ME": "Mont\u00e9n\u00e9gro", "MS": "Montserrat", "MZ": "Mozambique", "MM": "Myanmar (Birmanie)", "NA": "Namibie", "NR": "Nauru", "NP": "N\u00e9pal", "NI": "Nicaragua", "NE": "Niger", "NG": "Nig\u00e9ria", "NU": "Niue", "NO": "Norv\u00e8ge", "NC": "Nouvelle-Cal\u00e9donie", "NZ": "Nouvelle-Z\u00e9lande", "OM": "Oman", "UG": "Ouganda", "UZ": "Ouzb\u00e9kistan", "PK": "Pakistan", "PW": "Palaos", "PA": "Panama", "PG": "Papouasie-Nouvelle-Guin\u00e9e", "PY": "Paraguay", "NL": "Pays-Bas", "BQ": "Pays-Bas carib\u00e9ens", "PE": "P\u00e9rou", "PH": "Philippines", "PL": "Pologne", "PF": "Polyn\u00e9sie fran\u00e7aise", "PR": "Porto Rico", "PT": "Portugal", "QA": "Qatar", "HK": "R.A.S. chinoise de Hong Kong", "MO": "R.A.S. chinoise de Macao", "CF": "R\u00e9publique centrafricaine", "DO": "R\u00e9publique dominicaine", "RO": "Roumanie", "GB": "Royaume-Uni", "RU": "Russie", "RW": "Rwanda", "EH": "Sahara occidental", "BL": "Saint-Barth\u00e9lemy", "KN": "Saint-Christophe-et-Ni\u00e9v\u00e8s", "SM": "Saint-Marin", "MF": "Saint-Martin", "SX": "Saint-Martin (partie n\u00e9erlandaise)", "PM": "Saint-Pierre-et-Miquelon", "VC": "Saint-Vincent-et-les-Grenadines", "SH": "Sainte-H\u00e9l\u00e8ne", "LC": "Sainte-Lucie", "SV": "Salvador", "WS": "Samoa", "AS": "Samoa am\u00e9ricaines", "ST": "Sao Tom\u00e9-et-Principe", "SN": "S\u00e9n\u00e9gal", "RS": "Serbie", "SC": "Seychelles", "SL": "Sierra Leone", "SG": "Singapour", "SK": "Slovaquie", "SI": "Slov\u00e9nie", "SO": "Somalie", "SD": "Soudan", "SS": "Soudan du Sud", "LK": "Sri Lanka", "SE": "Su\u00e8de", "CH": "Suisse", "SR": "Suriname", "SJ": "Svalbard et Jan Mayen", "SY": "Syrie", "TJ": "Tadjikistan", "TW": "Ta\u00efwan", "TZ": "Tanzanie", "TD": "Tchad", "CZ": "Tch\u00e9quie", "TF": "Terres australes fran\u00e7aises", "IO": "Territoire britannique de l\u2019oc\u00e9an Indien", "TH": "Tha\u00eflande", "TL": "Timor oriental", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinit\u00e9-et-Tobago", "TN": "Tunisie", "TM": "Turkm\u00e9nistan", "TR": "Turquie", "UA": "Ukraine", "UY": "Uruguay", "VU": "Vanuatu", "VE": "Venezuela", "VN": "Vietnam", "WF": "Wallis-et-Futuna", "YE": "Y\u00e9men", "ZM": "Zambie", "ZW": "Zimbabwe"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/gl.json b/desktop/onionshare/resources/countries/gl.json
new file mode 100644
index 00000000..44652965
--- /dev/null
+++ b/desktop/onionshare/resources/countries/gl.json
@@ -0,0 +1 @@
+{"AQ": "A Ant\u00e1rtida", "AR": "A Arxentina", "CN": "A China", "GW": "A Guinea Bissau", "IN": "A India", "PF": "A Polinesia Francesa", "AZ": "Acerbaix\u00e1n", "AF": "Afganist\u00e1n", "AL": "Albania", "DE": "Alema\u00f1a", "DZ": "Alxeria", "AD": "Andorra", "AO": "Angola", "AI": "Anguila", "AG": "Antigua e Barbuda", "SA": "Arabia Saudita", "AM": "Armenia", "AW": "Aruba", "AU": "Australia", "AT": "Austria", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BY": "Belar\u00fas", "BZ": "Belize", "BE": "B\u00e9lxica", "BJ": "Ben\u00edn", "BO": "Bolivia", "BA": "Bosnia e Hercegovina", "BW": "Botswana", "BN": "Brunei", "BG": "Bulgaria", "BF": "Burkina Faso", "BI": "Burundi", "BT": "But\u00e1n", "CV": "Cabo Verde", "KH": "Camboxa", "CM": "Camer\u00fan", "BQ": "Caribe Neerland\u00e9s", "TD": "Chad", "CZ": "Chequia", "CL": "Chile", "CY": "Chipre", "VA": "Cidade do Vaticano", "CO": "Colombia", "KM": "Comores", "KP": "Corea do Norte", "KR": "Corea do Sur", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire", "HR": "Croacia", "CU": "Cuba", "CW": "Cura\u00e7ao", "DK": "Dinamarca", "DJ": "Djibuti", "DM": "Dominica", "EC": "Ecuador", "ER": "Eritrea", "SK": "Eslovaquia", "SI": "Eslovenia", "ES": "Espa\u00f1a", "EE": "Estonia", "SZ": "Eswatini", "ET": "Etiop\u00eda", "EG": "Exipto", "PH": "Filipinas", "FI": "Finlandia", "FJ": "Fixi", "FR": "Francia", "GA": "Gab\u00f3n", "GM": "Gambia", "GH": "Ghana", "GD": "Granada", "GR": "Grecia", "GL": "Groenlandia", "GP": "Guadalupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GY": "G\u00fciana", "GF": "G\u00fciana Francesa", "GN": "Guinea", "GQ": "Guinea Ecuatorial", "HT": "Hait\u00ed", "HN": "Honduras", "HK": "Hong Kong RAE da China", "HU": "Hungr\u00eda", "BV": "Illa Bouvet", "CX": "Illa Christmas", "IM": "Illa de Man", "HM": "Illa Heard e Illas McDonald", "NF": "Illa Norfolk", "AX": "Illas \u00c5land", "BM": "Illas Bermudas", "KY": "Illas Caim\u00e1n", "CC": "Illas Cocos (Keeling)", "CK": "Illas Cook", "FO": "Illas Feroe", "FK": "Illas Malvinas", "PN": "Illas Pitcairn", "SB": "Illas Salom\u00f3n", "TC": "Illas Turks e Caicos", "VG": "Illas Virxes Brit\u00e1nicas", "VI": "Illas Virxes Estadounidenses", "GS": "Illas Xeorxia do Sur e Sandwich do Sur", "ID": "Indonesia", "IR": "Ir\u00e1n", "IQ": "Iraq", "IE": "Irlanda", "IS": "Islandia", "IL": "Israel", "IT": "Italia", "KZ": "Kazakist\u00e1n", "KE": "Kenya", "KG": "Kirguizist\u00e1n", "KI": "Kiribati", "KW": "Kuwait", "LA": "Laos", "LS": "Lesotho", "LV": "Letonia", "LR": "Liberia", "LY": "Libia", "LI": "Liechtenstein", "LT": "Lituania", "LU": "Luxemburgo", "MO": "Macau RAE da China", "MK": "Macedonia do Norte", "MG": "Madagascar", "MY": "Malaisia", "MW": "Malawi", "MV": "Maldivas", "ML": "Mal\u00ed", "MT": "Malta", "MA": "Marrocos", "MQ": "Martinica", "MU": "Mauricio", "MR": "Mauritania", "YT": "Mayotte", "MX": "M\u00e9xico", "MD": "Moldavia", "MC": "M\u00f3naco", "MN": "Mongolia", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mozambique", "MM": "Myanmar (Birmania)", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "NI": "Nicaragua", "NU": "Niue", "NE": "N\u00edxer", "NG": "Nixeria", "NO": "Noruega", "NC": "Nova Caledonia", "NZ": "Nova Zelandia", "BR": "O Brasil", "CA": "O Canad\u00e1", "YE": "O Iemen", "LB": "O L\u00edbano", "PY": "O Paraguai", "PE": "O Per\u00fa", "GB": "O Reino Unido", "EH": "O S\u00e1hara Occidental", "SV": "O Salvador", "SD": "O Sud\u00e1n", "SS": "O Sud\u00e1n do Sur", "UY": "O Uruguai", "JP": "O Xap\u00f3n", "OM": "Om\u00e1n", "AE": "Os Emiratos \u00c1rabes Unidos", "US": "Os Estados Unidos", "NL": "Pa\u00edses Baixos", "PW": "Palau", "PA": "Panam\u00e1", "PG": "Pap\u00faa-Nova Guinea", "PK": "Paquist\u00e1n", "PL": "Polonia", "PR": "Porto Rico", "PT": "Portugal", "QA": "Qatar", "CF": "Rep\u00fablica Centroafricana", "CD": "Rep\u00fablica Democr\u00e1tica do Congo", "CG": "Rep\u00fablica do Congo", "DO": "Rep\u00fablica Dominicana", "RE": "Reuni\u00f3n", "RO": "Roman\u00eda", "RW": "Ruanda", "RU": "Rusia", "BL": "Saint Barth\u00e9lemy", "KN": "Saint Kitts e Nevis", "MF": "Saint Martin", "PM": "Saint Pierre et Miquelon", "WS": "Samoa", "AS": "Samoa Americana", "SM": "San Marino", "ST": "San Tom\u00e9 e Pr\u00edncipe", "VC": "San Vicente e As Granadinas", "SH": "Santa Helena", "LC": "Santa Luc\u00eda", "SN": "Senegal", "RS": "Serbia", "SL": "Serra Leoa", "SC": "Seychelles", "SG": "Singapur", "SX": "Sint Maarten", "SY": "Siria", "SO": "Somalia", "LK": "Sri Lanka", "SE": "Suecia", "CH": "Su\u00edza", "ZA": "Sur\u00e1frica", "SR": "Suriname", "SJ": "Svalbard e Jan Mayen", "TH": "Tailandia", "TW": "Taiw\u00e1n", "TZ": "Tanzania", "TJ": "Taxiquist\u00e1n", "IO": "Territorio Brit\u00e1nico do Oc\u00e9ano \u00cdndico", "TF": "Territorios Austrais Franceses", "TL": "Timor Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad e Tobago", "TN": "Tunisia", "TM": "Turkmenist\u00e1n", "TR": "Turqu\u00eda", "UA": "Ucra\u00edna", "UG": "Uganda", "UZ": "Uzbekist\u00e1n", "VU": "Vanuatu", "VE": "Venezuela", "VN": "Vietnam", "WF": "Wallis e Futuna", "JM": "Xamaica", "GE": "Xeorxia", "GI": "Xibraltar", "JO": "Xordania", "ZM": "Zambia", "ZW": "Zimbabwe"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/is.json b/desktop/onionshare/resources/countries/is.json
new file mode 100644
index 00000000..5ba082a7
--- /dev/null
+++ b/desktop/onionshare/resources/countries/is.json
@@ -0,0 +1 @@
+{"AF": "Afganistan", "AL": "Alban\u00eda", "DZ": "Als\u00edr", "AD": "Andorra", "AO": "Ang\u00f3la", "AI": "Angvilla", "AG": "Ant\u00edgva og Barb\u00fada", "AR": "Argent\u00edna", "AM": "Armen\u00eda", "AW": "Ar\u00faba", "AZ": "Aserba\u00eddsjan", "AT": "Austurr\u00edki", "AX": "\u00c1landseyjar", "AU": "\u00c1stral\u00eda", "BS": "Bahamaeyjar", "US": "Bandar\u00edkin", "AS": "Bandar\u00edska Sam\u00f3a", "VI": "Bandar\u00edsku J\u00f3mfr\u00faaeyjar", "BD": "Bangladess", "BB": "Barbados", "BH": "Barein", "BE": "Belg\u00eda", "BZ": "Bel\u00eds", "BJ": "Ben\u00edn", "BM": "Berm\u00fadaeyjar", "BA": "Bosn\u00eda og Herseg\u00f3v\u00edna", "BW": "Botsvana", "BV": "Bouveteyja", "BO": "B\u00f3liv\u00eda", "BR": "Brasil\u00eda", "IO": "Bresku Indlandshafseyjar", "VG": "Bresku J\u00f3mfr\u00faaeyjar", "GB": "Bretland", "BN": "Br\u00fanei", "BG": "B\u00falgar\u00eda", "BF": "B\u00fark\u00edna Fas\u00f3", "BI": "B\u00far\u00fand\u00ed", "BT": "B\u00fatan", "KY": "Caymaneyjar", "CK": "Cooks-eyjar", "CW": "Curacao", "DK": "Danm\u00f6rk", "DJ": "Dj\u00edb\u00fat\u00ed", "DM": "D\u00f3min\u00edka", "DO": "D\u00f3min\u00edska l\u00fd\u00f0veldi\u00f0", "EG": "Egyptaland", "EE": "Eistland", "EC": "Ekvador", "SV": "El Salvador", "ER": "Er\u00edtrea", "ET": "E\u00fe\u00ed\u00f3p\u00eda", "FK": "Falklandseyjar", "PH": "Filippseyjar", "FI": "Finnland", "FJ": "F\u00eddj\u00edeyjar", "CI": "F\u00edlabeinsstr\u00f6ndin", "FR": "Frakkland", "GF": "Franska Gv\u00e6jana", "PF": "Franska P\u00f3l\u00fdnes\u00eda", "TF": "Fr\u00f6nsku su\u00f0l\u00e6gu landsv\u00e6\u00f0in", "FO": "F\u00e6reyjar", "GA": "Gabon", "GM": "Gamb\u00eda", "GH": "Gana", "GE": "Georg\u00eda", "GI": "G\u00edbraltar", "GN": "G\u00ednea", "GW": "G\u00ednea-Biss\u00e1", "GD": "Grenada", "GR": "Grikkland", "CV": "Gr\u00e6nh\u00f6f\u00f0aeyjar", "GL": "Gr\u00e6nland", "GG": "Guernsey", "GP": "Gvadel\u00fapeyjar", "GU": "Gvam", "GT": "Gvatemala", "GY": "Gv\u00e6jana", "HT": "Ha\u00edt\u00ed", "HM": "Heard og McDonaldseyjar", "NL": "Holland", "HN": "Hond\u00faras", "BY": "Hv\u00edta-R\u00fassland", "IN": "Indland", "ID": "Ind\u00f3nes\u00eda", "IQ": "\u00cdrak", "IR": "\u00cdran", "IE": "\u00cdrland", "IS": "\u00cdsland", "IL": "\u00cdsrael", "IT": "\u00cdtal\u00eda", "JM": "Jama\u00edka", "JP": "Japan", "YE": "Jemen", "CX": "J\u00f3laey", "JO": "J\u00f3rdan\u00eda", "KH": "Kamb\u00f3d\u00eda", "CM": "Kamer\u00fan", "CA": "Kanada", "BQ": "Kar\u00edbahafshluti Hollands", "KZ": "Kasakstan", "QA": "Katar", "KE": "Ken\u00eda", "KG": "Kirgistan", "CN": "K\u00edna", "KI": "K\u00edribat\u00ed", "CG": "Kong\u00f3-Brazzaville", "CD": "Kong\u00f3-Kinshasa", "CR": "Kostar\u00edka", "CC": "K\u00f3koseyjar (Keeling)", "CO": "K\u00f3lumb\u00eda", "KM": "K\u00f3moreyjar", "HR": "Kr\u00f3at\u00eda", "CU": "K\u00faba", "KW": "K\u00faveit", "CY": "K\u00fdpur", "LA": "Laos", "LS": "Les\u00f3t\u00f3", "LV": "Lettland", "LI": "Liechtenstein", "LT": "Lith\u00e1en", "LB": "L\u00edbanon", "LR": "L\u00edber\u00eda", "LY": "L\u00edb\u00eda", "LU": "L\u00faxemborg", "MG": "Madagaskar", "MY": "Malas\u00eda", "MW": "Malav\u00ed", "MV": "Mald\u00edveyjar", "ML": "Mal\u00ed", "MT": "Malta", "MA": "Marokk\u00f3", "MQ": "Martin\u00edk", "YT": "Mayotte", "MR": "M\u00e1ritan\u00eda", "MU": "M\u00e1rit\u00edus", "MX": "Mex\u00edk\u00f3", "CF": "Mi\u00f0-Afr\u00edkul\u00fd\u00f0veldi\u00f0", "GQ": "Mi\u00f0baugs-G\u00ednea", "MM": "Mjanmar (B\u00farma)", "MD": "Mold\u00f3va", "MN": "Mong\u00f3l\u00eda", "MS": "Montserrat", "MC": "M\u00f3nak\u00f3", "MZ": "M\u00f3samb\u00edk", "IM": "M\u00f6n", "NA": "Namib\u00eda", "NR": "N\u00e1r\u00fa", "NP": "Nepal", "NU": "Niue", "NE": "N\u00edger", "NG": "N\u00edger\u00eda", "NI": "N\u00edkaragva", "KP": "Nor\u00f0ur-K\u00f3rea", "MK": "Nor\u00f0ur-Maked\u00f3n\u00eda", "NO": "Noregur", "NF": "Norfolkeyja", "NC": "N\u00fdja-Kaled\u00f3n\u00eda", "NZ": "N\u00fdja-Sj\u00e1land", "OM": "\u00d3man", "PK": "Pakistan", "PW": "Pal\u00e1", "PA": "Panama", "PG": "Pap\u00faa N\u00fdja-G\u00ednea", "PY": "Paragv\u00e6", "PE": "Per\u00fa", "PN": "Pitcairn-eyjar", "PT": "Port\u00fagal", "PL": "P\u00f3lland", "PR": "P\u00faert\u00f3 R\u00edk\u00f3", "RE": "R\u00e9union", "RW": "R\u00faanda", "RO": "R\u00famen\u00eda", "RU": "R\u00fassland", "MF": "Saint-Martin", "SB": "Sal\u00f3monseyjar", "ZM": "Samb\u00eda", "AE": "Sameinu\u00f0u arab\u00edsku furstad\u00e6min", "WS": "Sam\u00f3a", "SM": "San Mar\u00edn\u00f3", "BL": "Sankti Bart\u00f3l\u00f3meusareyjar", "SH": "Sankti Helena", "KN": "Sankti Kitts og Nevis", "LC": "Sankti L\u00fas\u00eda", "SX": "Sankti Martin", "PM": "Sankti Pierre og Miquelon", "VC": "Sankti Vinsent og Grenad\u00edneyjar", "ST": "Sa\u00f3 T\u00f3me og Prins\u00edpe", "SA": "S\u00e1di-Arab\u00eda", "SN": "Senegal", "RS": "Serb\u00eda", "SC": "Seychelles-eyjar", "HK": "s\u00e9rstj\u00f3rnarsv\u00e6\u00f0i\u00f0 Hong Kong", "MO": "s\u00e9rstj\u00f3rnarsv\u00e6\u00f0i\u00f0 Maka\u00f3", "ZW": "Simbabve", "SG": "Singap\u00far", "SL": "S\u00ederra Le\u00f3ne", "CL": "S\u00edle", "SK": "Sl\u00f3vak\u00eda", "SI": "Sl\u00f3ven\u00eda", "SO": "S\u00f3mal\u00eda", "ES": "Sp\u00e1nn", "LK": "Sr\u00ed Lanka", "ZA": "Su\u00f0ur-Afr\u00edka", "GS": "Su\u00f0ur-Georg\u00eda og Su\u00f0ur-Sandv\u00edkureyjar", "KR": "Su\u00f0ur-K\u00f3rea", "SS": "Su\u00f0ur-S\u00fadan", "AQ": "Su\u00f0urskautslandi\u00f0", "SD": "S\u00fadan", "SR": "S\u00far\u00ednam", "SJ": "Svalbar\u00f0i og Jan Mayen", "ME": "Svartfjallaland", "SZ": "Svas\u00edland", "CH": "Sviss", "SE": "Sv\u00ed\u00fej\u00f3\u00f0", "SY": "S\u00fdrland", "TJ": "Tadsjikistan", "TH": "Ta\u00edland", "TW": "Ta\u00edvan", "TZ": "Tansan\u00eda", "CZ": "T\u00e9kkland", "TL": "T\u00edmor-Leste", "TO": "Tonga", "TG": "T\u00f3g\u00f3", "TK": "T\u00f3kel\u00e1", "TT": "Tr\u00ednidad og T\u00f3bag\u00f3", "TD": "Tsjad", "TC": "Turks- og Caicoseyjar", "TN": "T\u00fanis", "TM": "T\u00farkmenistan", "TR": "Tyrkland", "HU": "Ungverjaland", "UG": "\u00daganda", "UA": "\u00dakra\u00edna", "UY": "\u00dar\u00fagv\u00e6", "UZ": "\u00dasbekistan", "VU": "Van\u00faat\u00fa", "VA": "Vat\u00edkani\u00f0", "VE": "Venes\u00faela", "EH": "Vestur-Sahara", "VN": "V\u00edetnam", "WF": "Wallis- og F\u00fat\u00fanaeyjar", "DE": "\u00de\u00fdskaland"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/ja.json b/desktop/onionshare/resources/countries/ja.json
new file mode 100644
index 00000000..22e4054a
--- /dev/null
+++ b/desktop/onionshare/resources/countries/ja.json
@@ -0,0 +1 @@
+{"IS": "\u30a2\u30a4\u30b9\u30e9\u30f3\u30c9", "IE": "\u30a2\u30a4\u30eb\u30e9\u30f3\u30c9", "AZ": "\u30a2\u30bc\u30eb\u30d0\u30a4\u30b8\u30e3\u30f3", "AF": "\u30a2\u30d5\u30ac\u30cb\u30b9\u30bf\u30f3", "US": "\u30a2\u30e1\u30ea\u30ab\u5408\u8846\u56fd", "AE": "\u30a2\u30e9\u30d6\u9996\u9577\u56fd\u9023\u90a6", "DZ": "\u30a2\u30eb\u30b8\u30a7\u30ea\u30a2", "AR": "\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3", "AW": "\u30a2\u30eb\u30d0", "AL": "\u30a2\u30eb\u30d0\u30cb\u30a2", "AM": "\u30a2\u30eb\u30e1\u30cb\u30a2", "AI": "\u30a2\u30f3\u30ae\u30e9", "AO": "\u30a2\u30f3\u30b4\u30e9", "AG": "\u30a2\u30f3\u30c6\u30a3\u30b0\u30a2\u30fb\u30d0\u30fc\u30d6\u30fc\u30c0", "AD": "\u30a2\u30f3\u30c9\u30e9", "YE": "\u30a4\u30a8\u30e1\u30f3", "GB": "\u30a4\u30ae\u30ea\u30b9", "IL": "\u30a4\u30b9\u30e9\u30a8\u30eb", "IT": "\u30a4\u30bf\u30ea\u30a2", "IQ": "\u30a4\u30e9\u30af", "IR": "\u30a4\u30e9\u30f3", "IN": "\u30a4\u30f3\u30c9", "ID": "\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2", "WF": "\u30a6\u30a9\u30ea\u30b9\u30fb\u30d5\u30c4\u30ca", "UG": "\u30a6\u30ac\u30f3\u30c0", "UA": "\u30a6\u30af\u30e9\u30a4\u30ca", "UZ": "\u30a6\u30ba\u30d9\u30ad\u30b9\u30bf\u30f3", "UY": "\u30a6\u30eb\u30b0\u30a2\u30a4", "EC": "\u30a8\u30af\u30a2\u30c9\u30eb", "EG": "\u30a8\u30b8\u30d7\u30c8", "EE": "\u30a8\u30b9\u30c8\u30cb\u30a2", "SZ": "\u30a8\u30b9\u30ef\u30c6\u30a3\u30cb", "ET": "\u30a8\u30c1\u30aa\u30d4\u30a2", "ER": "\u30a8\u30ea\u30c8\u30ea\u30a2", "SV": "\u30a8\u30eb\u30b5\u30eb\u30d0\u30c9\u30eb", "AU": "\u30aa\u30fc\u30b9\u30c8\u30e9\u30ea\u30a2", "AT": "\u30aa\u30fc\u30b9\u30c8\u30ea\u30a2", "AX": "\u30aa\u30fc\u30e9\u30f3\u30c9\u8af8\u5cf6", "OM": "\u30aa\u30de\u30fc\u30f3", "NL": "\u30aa\u30e9\u30f3\u30c0", "BQ": "\u30aa\u30e9\u30f3\u30c0\u9818\u30ab\u30ea\u30d6", "GH": "\u30ac\u30fc\u30ca", "CV": "\u30ab\u30fc\u30dc\u30d9\u30eb\u30c7", "GG": "\u30ac\u30fc\u30f3\u30b8\u30fc", "GY": "\u30ac\u30a4\u30a2\u30ca", "KZ": "\u30ab\u30b6\u30d5\u30b9\u30bf\u30f3", "QA": "\u30ab\u30bf\u30fc\u30eb", "CA": "\u30ab\u30ca\u30c0", "GA": "\u30ac\u30dc\u30f3", "CM": "\u30ab\u30e1\u30eb\u30fc\u30f3", "GM": "\u30ac\u30f3\u30d3\u30a2", "KH": "\u30ab\u30f3\u30dc\u30b8\u30a2", "GN": "\u30ae\u30cb\u30a2", "GW": "\u30ae\u30cb\u30a2\u30d3\u30b5\u30a6", "CY": "\u30ad\u30d7\u30ed\u30b9", "CU": "\u30ad\u30e5\u30fc\u30d0", "CW": "\u30ad\u30e5\u30e9\u30bd\u30fc", "GR": "\u30ae\u30ea\u30b7\u30e3", "KI": "\u30ad\u30ea\u30d0\u30b9", "KG": "\u30ad\u30eb\u30ae\u30b9", "GT": "\u30b0\u30a2\u30c6\u30de\u30e9", "GP": "\u30b0\u30a2\u30c9\u30eb\u30fc\u30d7", "GU": "\u30b0\u30a2\u30e0", "KW": "\u30af\u30a6\u30a7\u30fc\u30c8", "CK": "\u30af\u30c3\u30af\u8af8\u5cf6", "GL": "\u30b0\u30ea\u30fc\u30f3\u30e9\u30f3\u30c9", "CX": "\u30af\u30ea\u30b9\u30de\u30b9\u5cf6", "GD": "\u30b0\u30ec\u30ca\u30c0", "HR": "\u30af\u30ed\u30a2\u30c1\u30a2", "KY": "\u30b1\u30a4\u30de\u30f3\u8af8\u5cf6", "KE": "\u30b1\u30cb\u30a2", "CI": "\u30b3\u30fc\u30c8\u30b8\u30dc\u30ef\u30fc\u30eb", "CC": "\u30b3\u30b3\u30b9(\u30ad\u30fc\u30ea\u30f3\u30b0)\u8af8\u5cf6", "CR": "\u30b3\u30b9\u30bf\u30ea\u30ab", "KM": "\u30b3\u30e2\u30ed", "CO": "\u30b3\u30ed\u30f3\u30d3\u30a2", "CG": "\u30b3\u30f3\u30b4\u5171\u548c\u56fd(\u30d6\u30e9\u30b6\u30d3\u30eb)", "CD": "\u30b3\u30f3\u30b4\u6c11\u4e3b\u5171\u548c\u56fd(\u30ad\u30f3\u30b7\u30e3\u30b5)", "SA": "\u30b5\u30a6\u30b8\u30a2\u30e9\u30d3\u30a2", "GS": "\u30b5\u30a6\u30b9\u30b8\u30e7\u30fc\u30b8\u30a2\u30fb\u30b5\u30a6\u30b9\u30b5\u30f3\u30c9\u30a6\u30a3\u30c3\u30c1\u8af8\u5cf6", "WS": "\u30b5\u30e2\u30a2", "BL": "\u30b5\u30f3\u30fb\u30d0\u30eb\u30c6\u30eb\u30df\u30fc", "MF": "\u30b5\u30f3\u30fb\u30de\u30eb\u30bf\u30f3", "ST": "\u30b5\u30f3\u30c8\u30e1\u30fb\u30d7\u30ea\u30f3\u30b7\u30da", "ZM": "\u30b6\u30f3\u30d3\u30a2", "PM": "\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u5cf6\u30fb\u30df\u30af\u30ed\u30f3\u5cf6", "SM": "\u30b5\u30f3\u30de\u30ea\u30ce", "SL": "\u30b7\u30a8\u30e9\u30ec\u30aa\u30cd", "DJ": "\u30b8\u30d6\u30c1", "GI": "\u30b8\u30d6\u30e9\u30eb\u30bf\u30eb", "JM": "\u30b8\u30e3\u30de\u30a4\u30ab", "GE": "\u30b8\u30e7\u30fc\u30b8\u30a2", "SY": "\u30b7\u30ea\u30a2", "SG": "\u30b7\u30f3\u30ac\u30dd\u30fc\u30eb", "SX": "\u30b7\u30f3\u30c8\u30fb\u30de\u30fc\u30eb\u30c6\u30f3", "ZW": "\u30b8\u30f3\u30d0\u30d6\u30a8", "CH": "\u30b9\u30a4\u30b9", "SE": "\u30b9\u30a6\u30a7\u30fc\u30c7\u30f3", "SD": "\u30b9\u30fc\u30c0\u30f3", "SJ": "\u30b9\u30d0\u30fc\u30eb\u30d0\u30eb\u8af8\u5cf6\u30fb\u30e4\u30f3\u30de\u30a4\u30a8\u30f3\u5cf6", "ES": "\u30b9\u30da\u30a4\u30f3", "SR": "\u30b9\u30ea\u30ca\u30e0", "LK": "\u30b9\u30ea\u30e9\u30f3\u30ab", "SK": "\u30b9\u30ed\u30d0\u30ad\u30a2", "SI": "\u30b9\u30ed\u30d9\u30cb\u30a2", "SC": "\u30bb\u30fc\u30b7\u30a7\u30eb", "SN": "\u30bb\u30cd\u30ac\u30eb", "RS": "\u30bb\u30eb\u30d3\u30a2", "KN": "\u30bb\u30f3\u30c8\u30af\u30ea\u30b9\u30c8\u30d5\u30a1\u30fc\u30fb\u30cd\u30fc\u30f4\u30a3\u30b9", "VC": "\u30bb\u30f3\u30c8\u30d3\u30f3\u30bb\u30f3\u30c8\u53ca\u3073\u30b0\u30ec\u30ca\u30c7\u30a3\u30fc\u30f3\u8af8\u5cf6", "SH": "\u30bb\u30f3\u30c8\u30d8\u30ec\u30ca", "LC": "\u30bb\u30f3\u30c8\u30eb\u30b7\u30a2", "SO": "\u30bd\u30de\u30ea\u30a2", "SB": "\u30bd\u30ed\u30e2\u30f3\u8af8\u5cf6", "TC": "\u30bf\u30fc\u30af\u30b9\u30fb\u30ab\u30a4\u30b3\u30b9\u8af8\u5cf6", "TH": "\u30bf\u30a4", "TJ": "\u30bf\u30b8\u30ad\u30b9\u30bf\u30f3", "TZ": "\u30bf\u30f3\u30b6\u30cb\u30a2", "CZ": "\u30c1\u30a7\u30b3", "TD": "\u30c1\u30e3\u30c9", "TN": "\u30c1\u30e5\u30cb\u30b8\u30a2", "CL": "\u30c1\u30ea", "DK": "\u30c7\u30f3\u30de\u30fc\u30af", "DE": "\u30c9\u30a4\u30c4", "TG": "\u30c8\u30fc\u30b4", "TK": "\u30c8\u30b1\u30e9\u30a6", "DO": "\u30c9\u30df\u30cb\u30ab\u5171\u548c\u56fd", "DM": "\u30c9\u30df\u30cb\u30ab\u56fd", "TT": "\u30c8\u30ea\u30cb\u30c0\u30fc\u30c9\u30fb\u30c8\u30d0\u30b4", "TM": "\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3", "TR": "\u30c8\u30eb\u30b3", "TO": "\u30c8\u30f3\u30ac", "NG": "\u30ca\u30a4\u30b8\u30a7\u30ea\u30a2", "NR": "\u30ca\u30a6\u30eb", "NA": "\u30ca\u30df\u30d3\u30a2", "NU": "\u30cb\u30a6\u30a8", "NI": "\u30cb\u30ab\u30e9\u30b0\u30a2", "NE": "\u30cb\u30b8\u30a7\u30fc\u30eb", "NC": "\u30cb\u30e5\u30fc\u30ab\u30ec\u30c9\u30cb\u30a2", "NZ": "\u30cb\u30e5\u30fc\u30b8\u30fc\u30e9\u30f3\u30c9", "NP": "\u30cd\u30d1\u30fc\u30eb", "NF": "\u30ce\u30fc\u30d5\u30a9\u30fc\u30af\u5cf6", "NO": "\u30ce\u30eb\u30a6\u30a7\u30fc", "HM": "\u30cf\u30fc\u30c9\u5cf6\u30fb\u30de\u30af\u30c9\u30ca\u30eb\u30c9\u8af8\u5cf6", "BH": "\u30d0\u30fc\u30ec\u30fc\u30f3", "HT": "\u30cf\u30a4\u30c1", "PK": "\u30d1\u30ad\u30b9\u30bf\u30f3", "VA": "\u30d0\u30c1\u30ab\u30f3\u5e02\u56fd", "PA": "\u30d1\u30ca\u30de", "VU": "\u30d0\u30cc\u30a2\u30c4", "BS": "\u30d0\u30cf\u30de", "PG": "\u30d1\u30d7\u30a2\u30cb\u30e5\u30fc\u30ae\u30cb\u30a2", "BM": "\u30d0\u30df\u30e5\u30fc\u30c0", "PW": "\u30d1\u30e9\u30aa", "PY": "\u30d1\u30e9\u30b0\u30a2\u30a4", "BB": "\u30d0\u30eb\u30d0\u30c9\u30b9", "HU": "\u30cf\u30f3\u30ac\u30ea\u30fc", "BD": "\u30d0\u30f3\u30b0\u30e9\u30c7\u30b7\u30e5", "PN": "\u30d4\u30c8\u30b1\u30a2\u30f3\u8af8\u5cf6", "FJ": "\u30d5\u30a3\u30b8\u30fc", "PH": "\u30d5\u30a3\u30ea\u30d4\u30f3", "FI": "\u30d5\u30a3\u30f3\u30e9\u30f3\u30c9", "BT": "\u30d6\u30fc\u30bf\u30f3", "BV": "\u30d6\u30fc\u30d9\u5cf6", "PR": "\u30d7\u30a8\u30eb\u30c8\u30ea\u30b3", "FO": "\u30d5\u30a7\u30ed\u30fc\u8af8\u5cf6", "FK": "\u30d5\u30a9\u30fc\u30af\u30e9\u30f3\u30c9\u8af8\u5cf6", "BR": "\u30d6\u30e9\u30b8\u30eb", "FR": "\u30d5\u30e9\u30f3\u30b9", "BG": "\u30d6\u30eb\u30ac\u30ea\u30a2", "BF": "\u30d6\u30eb\u30ad\u30ca\u30d5\u30a1\u30bd", "BN": "\u30d6\u30eb\u30cd\u30a4", "BI": "\u30d6\u30eb\u30f3\u30b8", "VN": "\u30d9\u30c8\u30ca\u30e0", "BJ": "\u30d9\u30ca\u30f3", "VE": "\u30d9\u30cd\u30ba\u30a8\u30e9", "BY": "\u30d9\u30e9\u30eb\u30fc\u30b7", "BZ": "\u30d9\u30ea\u30fc\u30ba", "PE": "\u30da\u30eb\u30fc", "BE": "\u30d9\u30eb\u30ae\u30fc", "PL": "\u30dd\u30fc\u30e9\u30f3\u30c9", "BA": "\u30dc\u30b9\u30cb\u30a2\u30fb\u30d8\u30eb\u30c4\u30a7\u30b4\u30d3\u30ca", "BW": "\u30dc\u30c4\u30ef\u30ca", "BO": "\u30dc\u30ea\u30d3\u30a2", "PT": "\u30dd\u30eb\u30c8\u30ac\u30eb", "HN": "\u30db\u30f3\u30b8\u30e5\u30e9\u30b9", "MG": "\u30de\u30c0\u30ac\u30b9\u30ab\u30eb", "YT": "\u30de\u30e8\u30c3\u30c8", "MW": "\u30de\u30e9\u30a6\u30a4", "ML": "\u30de\u30ea", "MT": "\u30de\u30eb\u30bf", "MQ": "\u30de\u30eb\u30c6\u30a3\u30cb\u30fc\u30af", "MY": "\u30de\u30ec\u30fc\u30b7\u30a2", "IM": "\u30de\u30f3\u5cf6", "MM": "\u30df\u30e3\u30f3\u30de\u30fc (\u30d3\u30eb\u30de)", "MX": "\u30e1\u30ad\u30b7\u30b3", "MU": "\u30e2\u30fc\u30ea\u30b7\u30e3\u30b9", "MR": "\u30e2\u30fc\u30ea\u30bf\u30cb\u30a2", "MZ": "\u30e2\u30b6\u30f3\u30d3\u30fc\u30af", "MC": "\u30e2\u30ca\u30b3", "MV": "\u30e2\u30eb\u30c7\u30a3\u30d6", "MD": "\u30e2\u30eb\u30c9\u30d0", "MA": "\u30e2\u30ed\u30c3\u30b3", "MN": "\u30e2\u30f3\u30b4\u30eb", "ME": "\u30e2\u30f3\u30c6\u30cd\u30b0\u30ed", "MS": "\u30e2\u30f3\u30c8\u30bb\u30e9\u30c8", "JO": "\u30e8\u30eb\u30c0\u30f3", "LA": "\u30e9\u30aa\u30b9", "LV": "\u30e9\u30c8\u30d3\u30a2", "LT": "\u30ea\u30c8\u30a2\u30cb\u30a2", "LY": "\u30ea\u30d3\u30a2", "LI": "\u30ea\u30d2\u30c6\u30f3\u30b7\u30e5\u30bf\u30a4\u30f3", "LR": "\u30ea\u30d9\u30ea\u30a2", "RO": "\u30eb\u30fc\u30de\u30cb\u30a2", "LU": "\u30eb\u30af\u30bb\u30f3\u30d6\u30eb\u30af", "RW": "\u30eb\u30ef\u30f3\u30c0", "LS": "\u30ec\u30bd\u30c8", "LB": "\u30ec\u30d0\u30ce\u30f3", "RE": "\u30ec\u30e6\u30cb\u30aa\u30f3", "RU": "\u30ed\u30b7\u30a2", "IO": "\u82f1\u9818\u30a4\u30f3\u30c9\u6d0b\u5730\u57df", "VG": "\u82f1\u9818\u30f4\u30a1\u30fc\u30b8\u30f3\u8af8\u5cf6", "KR": "\u97d3\u56fd", "EH": "\u897f\u30b5\u30cf\u30e9", "GQ": "\u8d64\u9053\u30ae\u30cb\u30a2", "TW": "\u53f0\u6e7e", "CF": "\u4e2d\u592e\u30a2\u30d5\u30ea\u30ab\u5171\u548c\u56fd", "MO": "\u4e2d\u83ef\u4eba\u6c11\u5171\u548c\u56fd\u30de\u30ab\u30aa\u7279\u5225\u884c\u653f\u533a", "HK": "\u4e2d\u83ef\u4eba\u6c11\u5171\u548c\u56fd\u9999\u6e2f\u7279\u5225\u884c\u653f\u533a", "CN": "\u4e2d\u56fd", "TL": "\u6771\u30c6\u30a3\u30e2\u30fc\u30eb", "ZA": "\u5357\u30a2\u30d5\u30ea\u30ab", "SS": "\u5357\u30b9\u30fc\u30c0\u30f3", "AQ": "\u5357\u6975", "JP": "\u65e5\u672c", "GF": "\u4ecf\u9818\u30ae\u30a2\u30ca", "PF": "\u4ecf\u9818\u30dd\u30ea\u30cd\u30b7\u30a2", "TF": "\u4ecf\u9818\u6975\u5357\u8af8\u5cf6", "VI": "\u7c73\u9818\u30f4\u30a1\u30fc\u30b8\u30f3\u8af8\u5cf6", "AS": "\u7c73\u9818\u30b5\u30e2\u30a2", "MK": "\u5317\u30de\u30b1\u30c9\u30cb\u30a2", "KP": "\u5317\u671d\u9bae"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/lt.json b/desktop/onionshare/resources/countries/lt.json
new file mode 100644
index 00000000..51afdefa
--- /dev/null
+++ b/desktop/onionshare/resources/countries/lt.json
@@ -0,0 +1 @@
+{"AF": "Afganistanas", "IE": "Airija", "AX": "Aland\u0173 Salos", "AL": "Albanija", "DZ": "Al\u017eyras", "AS": "Amerikos Samoa", "AD": "Andora", "AI": "Angilija", "AO": "Angola", "AQ": "Antarktida", "AG": "Antigva ir Barbuda", "AR": "Argentina", "AM": "Arm\u0117nija", "AW": "Aruba", "AU": "Australija", "AT": "Austrija", "AZ": "Azerbaid\u017eanas", "BS": "Bahamos", "BH": "Bahreinas", "BY": "Baltarusija", "BD": "Banglade\u0161as", "BB": "Barbadosas", "BE": "Belgija", "BZ": "Belizas", "BJ": "Beninas", "BM": "Bermuda", "GW": "Bisau Gvin\u0117ja", "BO": "Bolivija", "BA": "Bosnija ir Hercegovina", "BW": "Botsvana", "BR": "Brazilija", "BN": "Brun\u0117jus", "BG": "Bulgarija", "BF": "Burkina Fasas", "BI": "Burundis", "BT": "Butanas", "BV": "Buv\u0117 Sala", "CF": "Centrin\u0117s Afrikos Respublika", "TD": "\u010cadas", "CZ": "\u010cekija", "CL": "\u010cil\u0117", "DK": "Danija", "VG": "Did\u017eiosios Britanijos Mergeli\u0173 Salos", "DM": "Dominika", "DO": "Dominikos Respublika", "CI": "Dramblio Kaulo Krantas", "DJ": "D\u017eibutis", "EG": "Egiptas", "EC": "Ekvadoras", "ER": "Eritr\u0117ja", "EE": "Estija", "ET": "Etiopija", "FO": "Farer\u0173 Salos", "FJ": "Fid\u017eis", "PH": "Filipinai", "FK": "Folklando Salos", "GA": "Gabonas", "GY": "Gajana", "GM": "Gambija", "GH": "Gana", "GG": "Gernsis", "GI": "Gibraltaras", "GR": "Graikija", "GD": "Grenada", "GL": "Grenlandija", "GE": "Gruzija", "GU": "Guamas", "GP": "Gvadelupa", "GT": "Gvatemala", "GN": "Gvin\u0117ja", "HT": "Haitis", "HM": "Herdo ir Makdonaldo Salos", "HN": "Hond\u016bras", "IN": "Indija", "IO": "Indijos Vandenyno Brit\u0173 Sritis", "ID": "Indonezija", "HK": "Ypatingasis Administracinis Kinijos Regionas Honkongas", "MO": "Ypatingasis Administracinis Kinijos Regionas Makao", "IQ": "Irakas", "IR": "Iranas", "IS": "Islandija", "ES": "Ispanija", "IT": "Italija", "IL": "Izraelis", "JM": "Jamaika", "JP": "Japonija", "YE": "Jemenas", "JO": "Jordanija", "GB": "Jungtin\u0117 Karalyst\u0117", "US": "Jungtin\u0117s Valstijos", "AE": "Jungtiniai Arab\u0173 Emyratai", "VI": "Jungtini\u0173 Valstij\u0173 Mergeli\u0173 Salos", "ME": "Juodkalnija", "KY": "Kaiman\u0173 Salos", "CX": "Kal\u0117d\u0173 Sala", "KH": "Kambod\u017ea", "CM": "Kamer\u016bnas", "CA": "Kanada", "BQ": "Karib\u0173 Nyderlandai", "QA": "Kataras", "KZ": "Kazachstanas", "KE": "Kenija", "CN": "Kinija", "CY": "Kipras", "KG": "Kirgizija", "KI": "Kiribatis", "CW": "Kiurasao", "CC": "Kokos\u0173 (Kilingo) Salos", "CO": "Kolumbija", "KM": "Komorai", "CG": "Kongas-Brazavilis", "CD": "Kongas-Kin\u0161asa", "CR": "Kosta Rika", "HR": "Kroatija", "CU": "Kuba", "CK": "Kuko Salos", "KW": "Kuveitas", "LA": "Laosas", "LV": "Latvija", "PL": "Lenkija", "LS": "Lesotas", "LB": "Libanas", "LR": "Liberija", "LY": "Libija", "LI": "Lichten\u0161teinas", "LT": "Lietuva", "LU": "Liuksemburgas", "MG": "Madagaskaras", "YT": "Majotas", "MY": "Malaizija", "MW": "Malavis", "MV": "Maldyvai", "ML": "Malis", "MT": "Malta", "MA": "Marokas", "MQ": "Martinika", "MU": "Mauricijus", "MR": "Mauritanija", "MX": "Meksika", "IM": "Meno Sala", "MM": "Mianmaras (Birma)", "MD": "Moldova", "MC": "Monakas", "MN": "Mongolija", "MS": "Montseratas", "MZ": "Mozambikas", "NA": "Namibija", "NC": "Naujoji Kaledonija", "NZ": "Naujoji Zelandija", "NR": "Nauru", "NP": "Nepalas", "NL": "Nyderlandai", "NG": "Nigerija", "NE": "Nigeris", "NI": "Nikaragva", "NU": "Niuj\u0117", "NF": "Norfolko sala", "NO": "Norvegija", "OM": "Omanas", "PK": "Pakistanas", "PW": "Palau", "PA": "Panama", "PG": "Papua Naujoji Gvin\u0117ja", "PY": "Paragvajus", "PE": "Peru", "ZA": "Piet\u0173 Afrika", "GS": "Piet\u0173 D\u017eord\u017eija ir Piet\u0173 Sandvi\u010do salos", "KR": "Piet\u0173 Kor\u0117ja", "SS": "Piet\u0173 Sudanas", "PN": "Pitkerno salos", "PT": "Portugalija", "FR": "Pranc\u016bzija", "GF": "Pranc\u016bzijos Gviana", "TF": "Pranc\u016bzijos Piet\u0173 sritys", "PF": "Pranc\u016bzijos Polinezija", "PR": "Puerto Rikas", "GQ": "Pusiaujo Gvin\u0117ja", "RE": "Reunjonas", "TL": "Ryt\u0173 Timoras", "RW": "Ruanda", "RO": "Rumunija", "RU": "Rusija", "SB": "Saliamono Salos", "SV": "Salvadoras", "WS": "Samoa", "SM": "San Marinas", "ST": "San Tom\u0117 ir Prinsip\u0117", "SA": "Saudo Arabija", "SC": "Sei\u0161eliai", "BL": "Sen Bartelemi", "MF": "Sen Martenas", "PM": "Sen Pjeras ir Mikelonas", "SN": "Senegalas", "KN": "Sent Kitsas ir Nevis", "LC": "Sent Lusija", "RS": "Serbija", "SL": "Siera Leon\u0117", "SG": "Singap\u016bras", "SX": "Sint Martenas", "SY": "Sirija", "SK": "Slovakija", "SI": "Slov\u0117nija", "SO": "Somalis", "SD": "Sudanas", "FI": "Suomija", "SR": "Surinamas", "SJ": "Svalbardas ir Janas Majenas", "SZ": "Svazilandas", "KP": "\u0160iaur\u0117s Kor\u0117ja", "MK": "\u0160iaur\u0117s Makedonija", "LK": "\u0160ri Lanka", "SH": "\u0160v. Elenos Sala", "SE": "\u0160vedija", "CH": "\u0160veicarija", "VC": "\u0160ventasis Vincentas ir Grenadinai", "TJ": "Tad\u017eikija", "TH": "Tailandas", "TW": "Taivanas", "TZ": "Tanzanija", "TC": "Terkso ir Kaikoso Salos", "TG": "Togas", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidadas ir Tobagas", "TN": "Tunisas", "TR": "Turkija", "TM": "Turkm\u0117nistanas", "UG": "Uganda", "UA": "Ukraina", "UY": "Urugvajus", "UZ": "Uzbekistanas", "EH": "Vakar\u0173 Sachara", "VU": "Vanuatu", "VA": "Vatikano Miesto Valstyb\u0117", "VE": "Venesuela", "HU": "Vengrija", "VN": "Vietnamas", "DE": "Vokietija", "WF": "Volisas ir Fut\u016bna", "ZM": "Zambija", "ZW": "Zimbabv\u0117", "CV": "\u017daliasis Ky\u0161ulys"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/nb_NO.json b/desktop/onionshare/resources/countries/nb_NO.json
new file mode 100644
index 00000000..2134d702
--- /dev/null
+++ b/desktop/onionshare/resources/countries/nb_NO.json
@@ -0,0 +1 @@
+{"AF": "Afghanistan", "AL": "Albania", "DZ": "Algerie", "AS": "Amerikansk Samoa", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktis", "AG": "Antigua og Barbuda", "AR": "Argentina", "AM": "Armenia", "AW": "Aruba", "AZ": "Aserbajdsjan", "AU": "Australia", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BE": "Belgia", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivia", "BA": "Bosnia-Hercegovina", "BW": "Botswana", "BV": "Bouvet\u00f8ya", "BR": "Brasil", "BN": "Brunei", "BG": "Bulgaria", "BF": "Burkina Faso", "BI": "Burundi", "CA": "Canada", "KY": "Cayman\u00f8yene", "CL": "Chile", "CX": "Christmas\u00f8ya", "CO": "Colombia", "CK": "Cook\u00f8yene", "CR": "Costa Rica", "CU": "Cuba", "CW": "Cura\u00e7ao", "DK": "Danmark", "VI": "De amerikanske jomfru\u00f8yene", "VG": "De britiske jomfru\u00f8yene", "AE": "De forente arabiske emirater", "TF": "De franske s\u00f8rterritorier", "DO": "Den dominikanske republikk", "CF": "Den sentralafrikanske republikk", "IO": "Det britiske territoriet i Indiahavet", "DJ": "Djibouti", "DM": "Dominica", "EC": "Ecuador", "EG": "Egypt", "GQ": "Ekvatorial-Guinea", "SV": "El Salvador", "CI": "Elfenbenskysten", "ER": "Eritrea", "EE": "Estland", "SZ": "Eswatini", "ET": "Etiopia", "FK": "Falklands\u00f8yene", "FJ": "Fiji", "PH": "Filippinene", "FI": "Finland", "FR": "Frankrike", "GF": "Fransk Guyana", "PF": "Fransk Polynesia", "FO": "F\u00e6r\u00f8yene", "GA": "Gabon", "GM": "Gambia", "GE": "Georgia", "GH": "Ghana", "GI": "Gibraltar", "GD": "Grenada", "GL": "Gr\u00f8nland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard- og McDonald\u00f8yene", "GR": "Hellas", "HN": "Honduras", "HK": "Hongkong S.A.R. Kina", "BY": "Hviterussland", "IN": "India", "ID": "Indonesia", "IQ": "Irak", "IR": "Iran", "IE": "Irland", "IS": "Island", "IL": "Israel", "IT": "Italia", "JM": "Jamaica", "JP": "Japan", "YE": "Jemen", "JO": "Jordan", "KH": "Kambodsja", "CM": "Kamerun", "CV": "Kapp Verde", "BQ": "Karibisk Nederland", "KZ": "Kasakhstan", "KE": "Kenya", "CN": "Kina", "KG": "Kirgisistan", "KI": "Kiribati", "CC": "Kokos\u00f8yene", "KM": "Komorene", "CG": "Kongo-Brazzaville", "CD": "Kongo-Kinshasa", "HR": "Kroatia", "KW": "Kuwait", "CY": "Kypros", "LA": "Laos", "LV": "Latvia", "LS": "Lesotho", "LB": "Libanon", "LR": "Liberia", "LY": "Libya", "LI": "Liechtenstein", "LT": "Litauen", "LU": "Luxemburg", "MO": "Macao S.A.R. Kina", "MG": "Madagaskar", "MW": "Malawi", "MY": "Malaysia", "MV": "Maldivene", "ML": "Mali", "MT": "Malta", "IM": "Man", "MA": "Marokko", "MQ": "Martinique", "MR": "Mauritania", "MU": "Mauritius", "YT": "Mayotte", "MX": "Mexico", "MD": "Moldova", "MC": "Monaco", "MN": "Mongolia", "ME": "Montenegro", "MS": "Montserrat", "MZ": "Mosambik", "MM": "Myanmar (Burma)", "NA": "Namibia", "NR": "Nauru", "NL": "Nederland", "NP": "Nepal", "NZ": "New Zealand", "NI": "Nicaragua", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "KP": "Nord-Korea", "MK": "Nord-Makedonia", "NF": "Norfolk\u00f8ya", "NO": "Norge", "NC": "Ny-Caledonia", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua Ny-Guinea", "PY": "Paraguay", "PE": "Peru", "PN": "Pitcairn\u00f8yene", "PL": "Polen", "PT": "Portugal", "PR": "Puerto Rico", "QA": "Qatar", "RE": "R\u00e9union", "RO": "Romania", "RU": "Russland", "RW": "Rwanda", "KN": "Saint Kitts og Nevis", "BL": "Saint-Barth\u00e9lemy", "MF": "Saint-Martin", "PM": "Saint-Pierre-et-Miquelon", "SB": "Salomon\u00f8yene", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 og Pr\u00edncipe", "SA": "Saudi-Arabia", "SN": "Senegal", "RS": "Serbia", "SC": "Seychellene", "SL": "Sierra Leone", "SG": "Singapore", "SX": "Sint Maarten", "SK": "Slovakia", "SI": "Slovenia", "SO": "Somalia", "ES": "Spania", "LK": "Sri Lanka", "SH": "St. Helena", "LC": "St. Lucia", "VC": "St. Vincent og Grenadinene", "GB": "Storbritannia", "SD": "Sudan", "SR": "Surinam", "SJ": "Svalbard og Jan Mayen", "CH": "Sveits", "SE": "Sverige", "SY": "Syria", "ZA": "S\u00f8r-Afrika", "GS": "S\u00f8r-Georgia og S\u00f8r-Sandwich\u00f8yene", "KR": "S\u00f8r-Korea", "SS": "S\u00f8r-Sudan", "TJ": "Tadsjikistan", "TW": "Taiwan", "TZ": "Tanzania", "TH": "Thailand", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad og Tobago", "TD": "Tsjad", "CZ": "Tsjekkia", "TN": "Tunisia", "TM": "Turkmenistan", "TC": "Turks- og Caicos\u00f8yene", "TR": "Tyrkia", "DE": "Tyskland", "UG": "Uganda", "UA": "Ukraina", "HU": "Ungarn", "UY": "Uruguay", "US": "USA", "UZ": "Usbekistan", "VU": "Vanuatu", "VA": "Vatikanstaten", "VE": "Venezuela", "EH": "Vest-Sahara", "VN": "Vietnam", "WF": "Wallis og Futuna", "ZM": "Zambia", "ZW": "Zimbabwe", "TL": "\u00d8st-Timor", "AT": "\u00d8sterrike", "AX": "\u00c5land"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/pl.json b/desktop/onionshare/resources/countries/pl.json
new file mode 100644
index 00000000..8d102e77
--- /dev/null
+++ b/desktop/onionshare/resources/countries/pl.json
@@ -0,0 +1 @@
+{"AF": "Afganistan", "AL": "Albania", "DZ": "Algieria", "AD": "Andora", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktyda", "AG": "Antigua i Barbuda", "SA": "Arabia Saudyjska", "AR": "Argentyna", "AM": "Armenia", "AW": "Aruba", "AU": "Australia", "AT": "Austria", "AZ": "Azerbejd\u017can", "BS": "Bahamy", "BH": "Bahrajn", "BD": "Bangladesz", "BB": "Barbados", "BE": "Belgia", "BZ": "Belize", "BJ": "Benin", "BM": "Bermudy", "BT": "Bhutan", "BY": "Bia\u0142oru\u015b", "BO": "Boliwia", "BA": "Bo\u015bnia i Hercegowina", "BW": "Botswana", "BR": "Brazylia", "BN": "Brunei", "IO": "Brytyjskie Terytorium Oceanu Indyjskiego", "VG": "Brytyjskie Wyspy Dziewicze", "BG": "Bu\u0142garia", "BF": "Burkina Faso", "BI": "Burundi", "CL": "Chile", "CN": "Chiny", "HR": "Chorwacja", "CI": "C\u00f4te d\u2019Ivoire", "CW": "Cura\u00e7ao", "CY": "Cypr", "TD": "Czad", "ME": "Czarnog\u00f3ra", "CZ": "Czechy", "DK": "Dania", "CD": "Demokratyczna Republika Konga", "DM": "Dominika", "DO": "Dominikana", "DJ": "D\u017cibuti", "EG": "Egipt", "EC": "Ekwador", "ER": "Erytrea", "EE": "Estonia", "SZ": "Eswatini", "ET": "Etiopia", "FK": "Falklandy", "FJ": "Fid\u017ci", "PH": "Filipiny", "FI": "Finlandia", "FR": "Francja", "TF": "Francuskie Terytoria Po\u0142udniowe i Antarktyczne", "GA": "Gabon", "GM": "Gambia", "GS": "Georgia Po\u0142udniowa i Sandwich Po\u0142udniowy", "GH": "Ghana", "GI": "Gibraltar", "GR": "Grecja", "GD": "Grenada", "GL": "Grenlandia", "GE": "Gruzja", "GU": "Guam", "GG": "Guernsey", "GY": "Gujana", "GF": "Gujana Francuska", "GP": "Gwadelupa", "GT": "Gwatemala", "GN": "Gwinea", "GW": "Gwinea Bissau", "GQ": "Gwinea R\u00f3wnikowa", "HT": "Haiti", "ES": "Hiszpania", "NL": "Holandia", "HN": "Honduras", "IN": "Indie", "ID": "Indonezja", "IQ": "Irak", "IR": "Iran", "IE": "Irlandia", "IS": "Islandia", "IL": "Izrael", "JM": "Jamajka", "JP": "Japonia", "YE": "Jemen", "JO": "Jordania", "KY": "Kajmany", "KH": "Kambod\u017ca", "CM": "Kamerun", "CA": "Kanada", "QA": "Katar", "KZ": "Kazachstan", "KE": "Kenia", "KG": "Kirgistan", "KI": "Kiribati", "CO": "Kolumbia", "KM": "Komory", "CG": "Kongo", "KR": "Korea Po\u0142udniowa", "KP": "Korea P\u00f3\u0142nocna", "CR": "Kostaryka", "CU": "Kuba", "KW": "Kuwejt", "LA": "Laos", "LS": "Lesotho", "LB": "Liban", "LR": "Liberia", "LY": "Libia", "LI": "Liechtenstein", "LT": "Litwa", "LU": "Luksemburg", "LV": "\u0141otwa", "MK": "Macedonia P\u00f3\u0142nocna", "MG": "Madagaskar", "YT": "Majotta", "MW": "Malawi", "MV": "Malediwy", "MY": "Malezja", "ML": "Mali", "MT": "Malta", "MA": "Maroko", "MQ": "Martynika", "MR": "Mauretania", "MU": "Mauritius", "MX": "Meksyk", "MM": "Mjanma (Birma)", "MD": "Mo\u0142dawia", "MC": "Monako", "MN": "Mongolia", "MS": "Montserrat", "MZ": "Mozambik", "NA": "Namibia", "NR": "Nauru", "NP": "Nepal", "BQ": "Niderlandy Karaibskie", "DE": "Niemcy", "NE": "Niger", "NG": "Nigeria", "NI": "Nikaragua", "NU": "Niue", "NF": "Norfolk", "NO": "Norwegia", "NC": "Nowa Kaledonia", "NZ": "Nowa Zelandia", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua-Nowa Gwinea", "PY": "Paragwaj", "PE": "Peru", "PN": "Pitcairn", "PF": "Polinezja Francuska", "PL": "Polska", "PR": "Portoryko", "PT": "Portugalia", "ZA": "Republika Po\u0142udniowej Afryki", "CF": "Republika \u015arodkowoafryka\u0144ska", "CV": "Republika Zielonego Przyl\u0105dka", "RE": "Reunion", "RU": "Rosja", "RO": "Rumunia", "RW": "Rwanda", "EH": "Sahara Zachodnia", "KN": "Saint Kitts i Nevis", "LC": "Saint Lucia", "VC": "Saint Vincent i Grenadyny", "BL": "Saint-Barth\u00e9lemy", "MF": "Saint-Martin", "PM": "Saint-Pierre i Miquelon", "SV": "Salwador", "WS": "Samoa", "AS": "Samoa Ameryka\u0144skie", "SM": "San Marino", "SN": "Senegal", "RS": "Serbia", "SC": "Seszele", "SL": "Sierra Leone", "SG": "Singapur", "SX": "Sint Maarten", "SK": "S\u0142owacja", "SI": "S\u0142owenia", "SO": "Somalia", "HK": "SRA Hongkong (Chiny)", "MO": "SRA Makau (Chiny)", "LK": "Sri Lanka", "US": "Stany Zjednoczone", "SD": "Sudan", "SS": "Sudan Po\u0142udniowy", "SR": "Surinam", "SJ": "Svalbard i Jan Mayen", "SY": "Syria", "CH": "Szwajcaria", "SE": "Szwecja", "TJ": "Tad\u017cykistan", "TH": "Tajlandia", "TW": "Tajwan", "TZ": "Tanzania", "TL": "Timor Wschodni", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trynidad i Tobago", "TN": "Tunezja", "TR": "Turcja", "TM": "Turkmenistan", "TC": "Turks i Caicos", "UG": "Uganda", "UA": "Ukraina", "UY": "Urugwaj", "UZ": "Uzbekistan", "VU": "Vanuatu", "WF": "Wallis i Futuna", "VA": "Watykan", "VE": "Wenezuela", "HU": "W\u0119gry", "GB": "Wielka Brytania", "VN": "Wietnam", "IT": "W\u0142ochy", "BV": "Wyspa Bouveta", "CX": "Wyspa Bo\u017cego Narodzenia", "IM": "Wyspa Man", "SH": "Wyspa \u015awi\u0119tej Heleny", "AX": "Wyspy Alandzkie", "CK": "Wyspy Cooka", "VI": "Wyspy Dziewicze Stan\u00f3w Zjednoczonych", "HM": "Wyspy Heard i McDonalda", "CC": "Wyspy Kokosowe", "FO": "Wyspy Owcze", "SB": "Wyspy Salomona", "ST": "Wyspy \u015awi\u0119tego Tomasza i Ksi\u0105\u017c\u0119ca", "ZM": "Zambia", "ZW": "Zimbabwe", "AE": "Zjednoczone Emiraty Arabskie"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/pt_BR.json b/desktop/onionshare/resources/countries/pt_BR.json
new file mode 100644
index 00000000..3745df4d
--- /dev/null
+++ b/desktop/onionshare/resources/countries/pt_BR.json
@@ -0,0 +1 @@
+{"AF": "Afeganist\u00e3o", "ZA": "\u00c1frica do Sul", "AL": "Alb\u00e2nia", "DE": "Alemanha", "AD": "Andorra", "AO": "Angola", "AI": "Anguila", "AQ": "Ant\u00e1rtida", "AG": "Ant\u00edgua e Barbuda", "SA": "Ar\u00e1bia Saudita", "DZ": "Arg\u00e9lia", "AR": "Argentina", "AM": "Arm\u00eania", "AW": "Aruba", "AU": "Austr\u00e1lia", "AT": "\u00c1ustria", "AZ": "Azerbaij\u00e3o", "BS": "Bahamas", "BH": "Bahrein", "BD": "Bangladesh", "BB": "Barbados", "BE": "B\u00e9lgica", "BZ": "Belize", "BJ": "Benin", "BM": "Bermudas", "BY": "Bielorr\u00fassia", "BO": "Bol\u00edvia", "BA": "B\u00f3snia e Herzegovina", "BW": "Botsuana", "BR": "Brasil", "BN": "Brunei", "BG": "Bulg\u00e1ria", "BF": "Burquina Faso", "BI": "Burundi", "BT": "But\u00e3o", "CV": "Cabo Verde", "CM": "Camar\u00f5es", "KH": "Camboja", "CA": "Canad\u00e1", "QA": "Catar", "KZ": "Cazaquist\u00e3o", "TD": "Chade", "CL": "Chile", "CN": "China", "CY": "Chipre", "VA": "Cidade do Vaticano", "CO": "Col\u00f4mbia", "KM": "Comores", "CD": "Congo - Kinshasa", "KP": "Coreia do Norte", "KR": "Coreia do Sul", "CI": "Costa do Marfim", "CR": "Costa Rica", "HR": "Cro\u00e1cia", "CU": "Cuba", "CW": "Cura\u00e7ao", "DK": "Dinamarca", "DJ": "Djibuti", "DM": "Dominica", "EG": "Egito", "SV": "El Salvador", "AE": "Emirados \u00c1rabes Unidos", "EC": "Equador", "ER": "Eritreia", "SK": "Eslov\u00e1quia", "SI": "Eslov\u00eania", "ES": "Espanha", "SZ": "Essuat\u00edni", "US": "Estados Unidos", "EE": "Est\u00f4nia", "ET": "Eti\u00f3pia", "FJ": "Fiji", "PH": "Filipinas", "FI": "Finl\u00e2ndia", "FR": "Fran\u00e7a", "GA": "Gab\u00e3o", "GM": "G\u00e2mbia", "GH": "Gana", "GE": "Ge\u00f3rgia", "GI": "Gibraltar", "GD": "Granada", "GR": "Gr\u00e9cia", "GL": "Groenl\u00e2ndia", "GP": "Guadalupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GY": "Guiana", "GF": "Guiana Francesa", "GN": "Guin\u00e9", "GQ": "Guin\u00e9 Equatorial", "GW": "Guin\u00e9-Bissau", "HT": "Haiti", "HN": "Honduras", "HK": "Hong Kong, RAE da China", "HU": "Hungria", "YE": "I\u00eamen", "BV": "Ilha Bouvet", "CX": "Ilha Christmas", "IM": "Ilha de Man", "NF": "Ilha Norfolk", "AX": "Ilhas Aland", "KY": "Ilhas Cayman", "CC": "Ilhas Cocos (Keeling)", "CK": "Ilhas Cook", "FO": "Ilhas Faroe", "GS": "Ilhas Ge\u00f3rgia do Sul e Sandwich do Sul", "HM": "Ilhas Heard e McDonald", "FK": "Ilhas Malvinas", "PN": "Ilhas Pitcairn", "SB": "Ilhas Salom\u00e3o", "TC": "Ilhas Turcas e Caicos", "VI": "Ilhas Virgens Americanas", "VG": "Ilhas Virgens Brit\u00e2nicas", "IN": "\u00cdndia", "ID": "Indon\u00e9sia", "IR": "Ir\u00e3", "IQ": "Iraque", "IE": "Irlanda", "IS": "Isl\u00e2ndia", "IL": "Israel", "IT": "It\u00e1lia", "JM": "Jamaica", "JP": "Jap\u00e3o", "JO": "Jord\u00e2nia", "KW": "Kuwait", "LA": "Laos", "LS": "Lesoto", "LV": "Let\u00f4nia", "LB": "L\u00edbano", "LR": "Lib\u00e9ria", "LY": "L\u00edbia", "LI": "Liechtenstein", "LT": "Litu\u00e2nia", "LU": "Luxemburgo", "MO": "Macau, RAE da China", "MK": "Maced\u00f4nia do Norte", "MG": "Madagascar", "MY": "Mal\u00e1sia", "MW": "Malaui", "MV": "Maldivas", "ML": "Mali", "MT": "Malta", "MA": "Marrocos", "MQ": "Martinica", "MU": "Maur\u00edcio", "MR": "Maurit\u00e2nia", "YT": "Mayotte", "MX": "M\u00e9xico", "MM": "Mianmar (Birm\u00e2nia)", "MZ": "Mo\u00e7ambique", "MD": "Moldova", "MC": "M\u00f4naco", "MN": "Mong\u00f3lia", "ME": "Montenegro", "MS": "Montserrat", "NA": "Nam\u00edbia", "NR": "Nauru", "NP": "Nepal", "NI": "Nicar\u00e1gua", "NE": "N\u00edger", "NG": "Nig\u00e9ria", "NU": "Niue", "NO": "Noruega", "NC": "Nova Caled\u00f4nia", "NZ": "Nova Zel\u00e2ndia", "OM": "Om\u00e3", "NL": "Pa\u00edses Baixos", "BQ": "Pa\u00edses Baixos Caribenhos", "PW": "Palau", "PA": "Panam\u00e1", "PG": "Papua-Nova Guin\u00e9", "PK": "Paquist\u00e3o", "PY": "Paraguai", "PE": "Peru", "PF": "Polin\u00e9sia Francesa", "PL": "Pol\u00f4nia", "PR": "Porto Rico", "PT": "Portugal", "KE": "Qu\u00eania", "KG": "Quirguist\u00e3o", "KI": "Quiribati", "GB": "Reino Unido", "CF": "Rep\u00fablica Centro-Africana", "CG": "Rep\u00fablica do Congo", "DO": "Rep\u00fablica Dominicana", "RE": "Reuni\u00e3o", "RO": "Rom\u00eania", "RW": "Ruanda", "RU": "R\u00fassia", "EH": "Saara Ocidental", "WS": "Samoa", "AS": "Samoa Americana", "SM": "San Marino", "SH": "Santa Helena", "LC": "Santa L\u00facia", "BL": "S\u00e3o Bartolomeu", "KN": "S\u00e3o Crist\u00f3v\u00e3o e N\u00e9vis", "MF": "S\u00e3o Martinho", "PM": "S\u00e3o Pedro e Miquel\u00e3o", "ST": "S\u00e3o Tom\u00e9 e Pr\u00edncipe", "VC": "S\u00e3o Vicente e Granadinas", "SC": "Seicheles", "SN": "Senegal", "SL": "Serra Leoa", "RS": "S\u00e9rvia", "SG": "Singapura", "SX": "Sint Maarten", "SY": "S\u00edria", "SO": "Som\u00e1lia", "LK": "Sri Lanka", "SD": "Sud\u00e3o", "SS": "Sud\u00e3o do Sul", "SE": "Su\u00e9cia", "CH": "Su\u00ed\u00e7a", "SR": "Suriname", "SJ": "Svalbard e Jan Mayen", "TJ": "Tadjiquist\u00e3o", "TH": "Tail\u00e2ndia", "TW": "Taiwan", "TZ": "Tanz\u00e2nia", "CZ": "Tch\u00e9quia", "IO": "Territ\u00f3rio Brit\u00e2nico do Oceano \u00cdndico", "TF": "Territ\u00f3rios Franceses do Sul", "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad e Tobago", "TN": "Tun\u00edsia", "TM": "Turcomenist\u00e3o", "TR": "Turquia", "UA": "Ucr\u00e2nia", "UG": "Uganda", "UY": "Uruguai", "UZ": "Uzbequist\u00e3o", "VU": "Vanuatu", "VE": "Venezuela", "VN": "Vietn\u00e3", "WF": "Wallis e Futuna", "ZM": "Z\u00e2mbia", "ZW": "Zimb\u00e1bue"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/pt_PT.json b/desktop/onionshare/resources/countries/pt_PT.json
new file mode 100644
index 00000000..580bc314
--- /dev/null
+++ b/desktop/onionshare/resources/countries/pt_PT.json
@@ -0,0 +1 @@
+{"AF": "Afeganist\u00e3o", "ZA": "\u00c1frica do Sul", "AX": "Alanda", "AL": "Alb\u00e2nia", "DE": "Alemanha", "AD": "Andorra", "AO": "Angola", "AI": "Anguila", "AQ": "Ant\u00e1rtida", "AG": "Ant\u00edgua e Barbuda", "SA": "Ar\u00e1bia Saudita", "DZ": "Arg\u00e9lia", "AR": "Argentina", "AM": "Arm\u00e9nia", "AW": "Aruba", "AU": "Austr\u00e1lia", "AT": "\u00c1ustria", "AZ": "Azerbaij\u00e3o", "BS": "Baamas", "BD": "Bangladeche", "BB": "Barbados", "BH": "Bar\u00e9m", "BE": "B\u00e9lgica", "BZ": "Belize", "BJ": "Benim", "BM": "Bermudas", "BY": "Bielorr\u00fassia", "BO": "Bol\u00edvia", "BA": "B\u00f3snia e Herzegovina", "BW": "Botsuana", "BR": "Brasil", "BN": "Brunei", "BG": "Bulg\u00e1ria", "BF": "Burquina Faso", "BI": "Burundi", "BT": "But\u00e3o", "CV": "Cabo Verde", "CM": "Camar\u00f5es", "KH": "Camboja", "CA": "Canad\u00e1", "QA": "Catar", "KZ": "Cazaquist\u00e3o", "TD": "Chade", "CZ": "Ch\u00e9quia", "CL": "Chile", "CN": "China", "CY": "Chipre", "VA": "Cidade do Vaticano", "CO": "Col\u00f4mbia", "KM": "Comores", "CG": "Congo-Brazzaville", "CD": "Congo-Kinshasa", "KP": "Coreia do Norte", "KR": "Coreia do Sul", "CR": "Costa Rica", "CI": "C\u00f4te d\u2019Ivoire (Costa do Marfim)", "HR": "Cro\u00e1cia", "CU": "Cuba", "CW": "Cura\u00e7au", "DK": "Dinamarca", "DM": "Dom\u00ednica", "EG": "Egito", "AE": "Emirados \u00c1rabes Unidos", "EC": "Equador", "ER": "Eritreia", "SK": "Eslov\u00e1quia", "SI": "Eslov\u00e9nia", "ES": "Espanha", "SZ": "Essuat\u00edni", "US": "Estados Unidos", "EE": "Est\u00f3nia", "ET": "Eti\u00f3pia", "FJ": "Fiji", "PH": "Filipinas", "FI": "Finl\u00e2ndia", "FR": "Fran\u00e7a", "GA": "Gab\u00e3o", "GM": "G\u00e2mbia", "GH": "Gana", "GE": "Ge\u00f3rgia", "GI": "Gibraltar", "GD": "Granada", "GR": "Gr\u00e9cia", "GL": "Gronel\u00e2ndia", "GP": "Guadalupe", "GU": "Guame", "GT": "Guatemala", "GG": "Guernesey", "GY": "Guiana", "GF": "Guiana Francesa", "GN": "Guin\u00e9", "GQ": "Guin\u00e9 Equatorial", "GW": "Guin\u00e9-Bissau", "HT": "Haiti", "HN": "Honduras", "HK": "Hong Kong, RAE da China", "HU": "Hungria", "YE": "I\u00e9men", "BV": "Ilha Bouvet", "IM": "Ilha de Man", "CX": "Ilha do Natal", "NF": "Ilha Norfolk", "KY": "Ilhas Caim\u00e3o", "CK": "Ilhas Cook", "CC": "Ilhas dos Cocos (Keeling)", "FO": "Ilhas Faro\u00e9", "GS": "Ilhas Ge\u00f3rgia do Sul e Sandwich do Sul", "HM": "Ilhas Heard e McDonald", "FK": "Ilhas Malvinas (Falkland)", "PN": "Ilhas Pitcairn", "SB": "Ilhas Salom\u00e3o", "TC": "Ilhas Turcas e Caicos", "VG": "Ilhas Virgens Brit\u00e2nicas", "VI": "Ilhas Virgens dos EUA", "IN": "\u00cdndia", "ID": "Indon\u00e9sia", "IR": "Ir\u00e3o", "IQ": "Iraque", "IE": "Irlanda", "IS": "Isl\u00e2ndia", "IL": "Israel", "IT": "It\u00e1lia", "JM": "Jamaica", "JP": "Jap\u00e3o", "DJ": "Jibuti", "JO": "Jord\u00e2nia", "KW": "Koweit", "LA": "Laos", "LS": "Lesoto", "LV": "Let\u00f3nia", "LB": "L\u00edbano", "LR": "Lib\u00e9ria", "LY": "L\u00edbia", "LI": "Listenstaine", "LT": "Litu\u00e2nia", "LU": "Luxemburgo", "MO": "Macau, RAE da China", "MK": "Maced\u00f3nia do Norte", "MG": "Madag\u00e1scar", "YT": "Maiote", "MY": "Mal\u00e1sia", "MW": "Mal\u00e1ui", "MV": "Maldivas", "ML": "Mali", "MT": "Malta", "MA": "Marrocos", "MQ": "Martinica", "MU": "Maur\u00edcia", "MR": "Maurit\u00e2nia", "MX": "M\u00e9xico", "MM": "Mianmar (Birm\u00e2nia)", "MZ": "Mo\u00e7ambique", "MD": "Mold\u00e1via", "MC": "M\u00f3naco", "MN": "Mong\u00f3lia", "MS": "Monserrate", "ME": "Montenegro", "NA": "Nam\u00edbia", "NR": "Nauru", "NP": "Nepal", "NI": "Nicar\u00e1gua", "NE": "N\u00edger", "NG": "Nig\u00e9ria", "NU": "Niu\u00ea", "NO": "Noruega", "NC": "Nova Caled\u00f3nia", "NZ": "Nova Zel\u00e2ndia", "OM": "Om\u00e3", "NL": "Pa\u00edses Baixos", "BQ": "Pa\u00edses Baixos Caribenhos", "PW": "Palau", "PA": "Panam\u00e1", "PG": "Papua-Nova Guin\u00e9", "PK": "Paquist\u00e3o", "PY": "Paraguai", "PE": "Peru", "PF": "Polin\u00e9sia Francesa", "PL": "Pol\u00f3nia", "PR": "Porto Rico", "PT": "Portugal", "KE": "Qu\u00e9nia", "KG": "Quirguist\u00e3o", "KI": "Quirib\u00e1ti", "GB": "Reino Unido", "CF": "Rep\u00fablica Centro-Africana", "DO": "Rep\u00fablica Dominicana", "RE": "Reuni\u00e3o", "RO": "Rom\u00e9nia", "RW": "Ruanda", "RU": "R\u00fassia", "SV": "Salvador", "WS": "Samoa", "AS": "Samoa Americana", "SH": "Santa Helena", "LC": "Santa L\u00facia", "BL": "S\u00e3o Bartolomeu", "KN": "S\u00e3o Crist\u00f3v\u00e3o e Neves", "SM": "S\u00e3o Marinho", "MF": "S\u00e3o Martinho", "SX": "S\u00e3o Martinho (Sint Maarten)", "PM": "S\u00e3o Pedro e Miquel\u00e3o", "ST": "S\u00e3o Tom\u00e9 e Pr\u00edncipe", "VC": "S\u00e3o Vicente e Granadinas", "EH": "Sara Ocidental", "SC": "Seicheles", "SN": "Senegal", "SL": "Serra Leoa", "RS": "S\u00e9rvia", "SG": "Singapura", "SY": "S\u00edria", "SO": "Som\u00e1lia", "LK": "Sri Lanca", "SD": "Sud\u00e3o", "SS": "Sud\u00e3o do Sul", "SE": "Su\u00e9cia", "CH": "Su\u00ed\u00e7a", "SR": "Suriname", "SJ": "Svalbard e Jan Mayen", "TH": "Tail\u00e2ndia", "TW": "Taiwan", "TJ": "Tajiquist\u00e3o", "TZ": "Tanz\u00e2nia", "IO": "Territ\u00f3rio Brit\u00e2nico do Oceano \u00cdndico", "TF": "Territ\u00f3rios Austrais Franceses", "TL": "Timor-Leste", "TG": "Togo", "TO": "Tonga", "TK": "Toquelau", "TT": "Trindade e Tobago", "TN": "Tun\u00edsia", "TM": "Turquemenist\u00e3o", "TR": "Turquia", "UA": "Ucr\u00e2nia", "UG": "Uganda", "UY": "Uruguai", "UZ": "Usbequist\u00e3o", "VU": "Vanuatu", "VE": "Venezuela", "VN": "Vietname", "WF": "Wallis e Futuna", "ZM": "Z\u00e2mbia", "ZW": "Zimbabu\u00e9"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/ru.json b/desktop/onionshare/resources/countries/ru.json
new file mode 100644
index 00000000..ffbc3ef9
--- /dev/null
+++ b/desktop/onionshare/resources/countries/ru.json
@@ -0,0 +1 @@
+{"AU": "\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0438\u044f", "AT": "\u0410\u0432\u0441\u0442\u0440\u0438\u044f", "AZ": "\u0410\u0437\u0435\u0440\u0431\u0430\u0439\u0434\u0436\u0430\u043d", "AX": "\u0410\u043b\u0430\u043d\u0434\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430", "AL": "\u0410\u043b\u0431\u0430\u043d\u0438\u044f", "DZ": "\u0410\u043b\u0436\u0438\u0440", "AS": "\u0410\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u043e\u0435 \u0421\u0430\u043c\u043e\u0430", "AI": "\u0410\u043d\u0433\u0438\u043b\u044c\u044f", "AO": "\u0410\u043d\u0433\u043e\u043b\u0430", "AD": "\u0410\u043d\u0434\u043e\u0440\u0440\u0430", "AQ": "\u0410\u043d\u0442\u0430\u0440\u043a\u0442\u0438\u0434\u0430", "AG": "\u0410\u043d\u0442\u0438\u0433\u0443\u0430 \u0438 \u0411\u0430\u0440\u0431\u0443\u0434\u0430", "AR": "\u0410\u0440\u0433\u0435\u043d\u0442\u0438\u043d\u0430", "AM": "\u0410\u0440\u043c\u0435\u043d\u0438\u044f", "AW": "\u0410\u0440\u0443\u0431\u0430", "AF": "\u0410\u0444\u0433\u0430\u043d\u0438\u0441\u0442\u0430\u043d", "BS": "\u0411\u0430\u0433\u0430\u043c\u044b", "BD": "\u0411\u0430\u043d\u0433\u043b\u0430\u0434\u0435\u0448", "BB": "\u0411\u0430\u0440\u0431\u0430\u0434\u043e\u0441", "BH": "\u0411\u0430\u0445\u0440\u0435\u0439\u043d", "BY": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u044c", "BZ": "\u0411\u0435\u043b\u0438\u0437", "BE": "\u0411\u0435\u043b\u044c\u0433\u0438\u044f", "BJ": "\u0411\u0435\u043d\u0438\u043d", "BM": "\u0411\u0435\u0440\u043c\u0443\u0434\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430", "BG": "\u0411\u043e\u043b\u0433\u0430\u0440\u0438\u044f", "BO": "\u0411\u043e\u043b\u0438\u0432\u0438\u044f", "BQ": "\u0411\u043e\u043d\u044d\u0439\u0440, \u0421\u0438\u043d\u0442-\u042d\u0441\u0442\u0430\u0442\u0438\u0443\u0441 \u0438 \u0421\u0430\u0431\u0430", "BA": "\u0411\u043e\u0441\u043d\u0438\u044f \u0438 \u0413\u0435\u0440\u0446\u0435\u0433\u043e\u0432\u0438\u043d\u0430", "BW": "\u0411\u043e\u0442\u0441\u0432\u0430\u043d\u0430", "BR": "\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u044f", "IO": "\u0411\u0440\u0438\u0442\u0430\u043d\u0441\u043a\u0430\u044f \u0442\u0435\u0440\u0440\u0438\u0442\u043e\u0440\u0438\u044f \u0432 \u0418\u043d\u0434\u0438\u0439\u0441\u043a\u043e\u043c \u043e\u043a\u0435\u0430\u043d\u0435", "BN": "\u0411\u0440\u0443\u043d\u0435\u0439-\u0414\u0430\u0440\u0443\u0441\u0441\u0430\u043b\u0430\u043c", "BF": "\u0411\u0443\u0440\u043a\u0438\u043d\u0430-\u0424\u0430\u0441\u043e", "BI": "\u0411\u0443\u0440\u0443\u043d\u0434\u0438", "BT": "\u0411\u0443\u0442\u0430\u043d", "VU": "\u0412\u0430\u043d\u0443\u0430\u0442\u0443", "VA": "\u0412\u0430\u0442\u0438\u043a\u0430\u043d", "GB": "\u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u044f", "HU": "\u0412\u0435\u043d\u0433\u0440\u0438\u044f", "VE": "\u0412\u0435\u043d\u0435\u0441\u0443\u044d\u043b\u0430", "VG": "\u0412\u0438\u0440\u0433\u0438\u043d\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430 (\u0412\u0435\u043b\u0438\u043a\u043e\u0431\u0440\u0438\u0442\u0430\u043d\u0438\u044f)", "VI": "\u0412\u0438\u0440\u0433\u0438\u043d\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430 (\u0421\u0428\u0410)", "TL": "\u0412\u043e\u0441\u0442\u043e\u0447\u043d\u044b\u0439 \u0422\u0438\u043c\u043e\u0440", "VN": "\u0412\u044c\u0435\u0442\u043d\u0430\u043c", "GA": "\u0413\u0430\u0431\u043e\u043d", "HT": "\u0413\u0430\u0438\u0442\u0438", "GY": "\u0413\u0430\u0439\u0430\u043d\u0430", "GM": "\u0413\u0430\u043c\u0431\u0438\u044f", "GH": "\u0413\u0430\u043d\u0430", "GP": "\u0413\u0432\u0430\u0434\u0435\u043b\u0443\u043f\u0430", "GT": "\u0413\u0432\u0430\u0442\u0435\u043c\u0430\u043b\u0430", "GN": "\u0413\u0432\u0438\u043d\u0435\u044f", "GW": "\u0413\u0432\u0438\u043d\u0435\u044f-\u0411\u0438\u0441\u0430\u0443", "DE": "\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u044f", "GG": "\u0413\u0435\u0440\u043d\u0441\u0438", "GI": "\u0413\u0438\u0431\u0440\u0430\u043b\u0442\u0430\u0440", "HN": "\u0413\u043e\u043d\u0434\u0443\u0440\u0430\u0441", "HK": "\u0413\u043e\u043d\u043a\u043e\u043d\u0433 (\u0421\u0410\u0420)", "GD": "\u0413\u0440\u0435\u043d\u0430\u0434\u0430", "GL": "\u0413\u0440\u0435\u043d\u043b\u0430\u043d\u0434\u0438\u044f", "GR": "\u0413\u0440\u0435\u0446\u0438\u044f", "GE": "\u0413\u0440\u0443\u0437\u0438\u044f", "GU": "\u0413\u0443\u0430\u043c", "DK": "\u0414\u0430\u043d\u0438\u044f", "DJ": "\u0414\u0436\u0438\u0431\u0443\u0442\u0438", "DM": "\u0414\u043e\u043c\u0438\u043d\u0438\u043a\u0430", "DO": "\u0414\u043e\u043c\u0438\u043d\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430", "EG": "\u0415\u0433\u0438\u043f\u0435\u0442", "ZM": "\u0417\u0430\u043c\u0431\u0438\u044f", "EH": "\u0417\u0430\u043f\u0430\u0434\u043d\u0430\u044f \u0421\u0430\u0445\u0430\u0440\u0430", "ZW": "\u0417\u0438\u043c\u0431\u0430\u0431\u0432\u0435", "IL": "\u0418\u0437\u0440\u0430\u0438\u043b\u044c", "IN": "\u0418\u043d\u0434\u0438\u044f", "ID": "\u0418\u043d\u0434\u043e\u043d\u0435\u0437\u0438\u044f", "JO": "\u0418\u043e\u0440\u0434\u0430\u043d\u0438\u044f", "IQ": "\u0418\u0440\u0430\u043a", "IR": "\u0418\u0440\u0430\u043d", "IE": "\u0418\u0440\u043b\u0430\u043d\u0434\u0438\u044f", "IS": "\u0418\u0441\u043b\u0430\u043d\u0434\u0438\u044f", "ES": "\u0418\u0441\u043f\u0430\u043d\u0438\u044f", "IT": "\u0418\u0442\u0430\u043b\u0438\u044f", "YE": "\u0419\u0435\u043c\u0435\u043d", "CV": "\u041a\u0430\u0431\u043e-\u0412\u0435\u0440\u0434\u0435", "KZ": "\u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d", "KH": "\u041a\u0430\u043c\u0431\u043e\u0434\u0436\u0430", "CM": "\u041a\u0430\u043c\u0435\u0440\u0443\u043d", "CA": "\u041a\u0430\u043d\u0430\u0434\u0430", "QA": "\u041a\u0430\u0442\u0430\u0440", "KE": "\u041a\u0435\u043d\u0438\u044f", "CY": "\u041a\u0438\u043f\u0440", "KG": "\u041a\u0438\u0440\u0433\u0438\u0437\u0438\u044f", "KI": "\u041a\u0438\u0440\u0438\u0431\u0430\u0442\u0438", "CN": "\u041a\u0438\u0442\u0430\u0439", "KP": "\u041a\u041d\u0414\u0420", "CC": "\u041a\u043e\u043a\u043e\u0441\u043e\u0432\u044b\u0435 \u043e-\u0432\u0430", "CO": "\u041a\u043e\u043b\u0443\u043c\u0431\u0438\u044f", "KM": "\u041a\u043e\u043c\u043e\u0440\u044b", "CG": "\u041a\u043e\u043d\u0433\u043e - \u0411\u0440\u0430\u0437\u0437\u0430\u0432\u0438\u043b\u044c", "CD": "\u041a\u043e\u043d\u0433\u043e - \u041a\u0438\u043d\u0448\u0430\u0441\u0430", "CR": "\u041a\u043e\u0441\u0442\u0430-\u0420\u0438\u043a\u0430", "CI": "\u041a\u043e\u0442-\u0434\u2019\u0418\u0432\u0443\u0430\u0440", "CU": "\u041a\u0443\u0431\u0430", "KW": "\u041a\u0443\u0432\u0435\u0439\u0442", "CW": "\u041a\u044e\u0440\u0430\u0441\u0430\u043e", "LA": "\u041b\u0430\u043e\u0441", "LV": "\u041b\u0430\u0442\u0432\u0438\u044f", "LS": "\u041b\u0435\u0441\u043e\u0442\u043e", "LR": "\u041b\u0438\u0431\u0435\u0440\u0438\u044f", "LB": "\u041b\u0438\u0432\u0430\u043d", "LY": "\u041b\u0438\u0432\u0438\u044f", "LT": "\u041b\u0438\u0442\u0432\u0430", "LI": "\u041b\u0438\u0445\u0442\u0435\u043d\u0448\u0442\u0435\u0439\u043d", "LU": "\u041b\u044e\u043a\u0441\u0435\u043c\u0431\u0443\u0440\u0433", "MU": "\u041c\u0430\u0432\u0440\u0438\u043a\u0438\u0439", "MR": "\u041c\u0430\u0432\u0440\u0438\u0442\u0430\u043d\u0438\u044f", "MG": "\u041c\u0430\u0434\u0430\u0433\u0430\u0441\u043a\u0430\u0440", "YT": "\u041c\u0430\u0439\u043e\u0442\u0442\u0430", "MO": "\u041c\u0430\u043a\u0430\u043e (\u0421\u0410\u0420)", "MW": "\u041c\u0430\u043b\u0430\u0432\u0438", "MY": "\u041c\u0430\u043b\u0430\u0439\u0437\u0438\u044f", "ML": "\u041c\u0430\u043b\u0438", "MV": "\u041c\u0430\u043b\u044c\u0434\u0438\u0432\u044b", "MT": "\u041c\u0430\u043b\u044c\u0442\u0430", "MA": "\u041c\u0430\u0440\u043e\u043a\u043a\u043e", "MQ": "\u041c\u0430\u0440\u0442\u0438\u043d\u0438\u043a\u0430", "MX": "\u041c\u0435\u043a\u0441\u0438\u043a\u0430", "MZ": "\u041c\u043e\u0437\u0430\u043c\u0431\u0438\u043a", "MD": "\u041c\u043e\u043b\u0434\u043e\u0432\u0430", "MC": "\u041c\u043e\u043d\u0430\u043a\u043e", "MN": "\u041c\u043e\u043d\u0433\u043e\u043b\u0438\u044f", "MS": "\u041c\u043e\u043d\u0442\u0441\u0435\u0440\u0440\u0430\u0442", "MM": "\u041c\u044c\u044f\u043d\u043c\u0430 (\u0411\u0438\u0440\u043c\u0430)", "NA": "\u041d\u0430\u043c\u0438\u0431\u0438\u044f", "NR": "\u041d\u0430\u0443\u0440\u0443", "NP": "\u041d\u0435\u043f\u0430\u043b", "NE": "\u041d\u0438\u0433\u0435\u0440", "NG": "\u041d\u0438\u0433\u0435\u0440\u0438\u044f", "NL": "\u041d\u0438\u0434\u0435\u0440\u043b\u0430\u043d\u0434\u044b", "NI": "\u041d\u0438\u043a\u0430\u0440\u0430\u0433\u0443\u0430", "NU": "\u041d\u0438\u0443\u044d", "NZ": "\u041d\u043e\u0432\u0430\u044f \u0417\u0435\u043b\u0430\u043d\u0434\u0438\u044f", "NC": "\u041d\u043e\u0432\u0430\u044f \u041a\u0430\u043b\u0435\u0434\u043e\u043d\u0438\u044f", "NO": "\u041d\u043e\u0440\u0432\u0435\u0433\u0438\u044f", "BV": "\u043e-\u0432 \u0411\u0443\u0432\u0435", "IM": "\u043e-\u0432 \u041c\u044d\u043d", "NF": "\u043e-\u0432 \u041d\u043e\u0440\u0444\u043e\u043b\u043a", "CX": "\u043e-\u0432 \u0420\u043e\u0436\u0434\u0435\u0441\u0442\u0432\u0430", "SH": "\u043e-\u0432 \u0421\u0432. \u0415\u043b\u0435\u043d\u044b", "PN": "\u043e-\u0432\u0430 \u041f\u0438\u0442\u043a\u044d\u0440\u043d", "TC": "\u043e-\u0432\u0430 \u0422\u0451\u0440\u043a\u0441 \u0438 \u041a\u0430\u0439\u043a\u043e\u0441", "HM": "\u043e-\u0432\u0430 \u0425\u0435\u0440\u0434 \u0438 \u041c\u0430\u043a\u0434\u043e\u043d\u0430\u043b\u044c\u0434", "AE": "\u041e\u0410\u042d", "OM": "\u041e\u043c\u0430\u043d", "KY": "\u041e\u0441\u0442\u0440\u043e\u0432\u0430 \u041a\u0430\u0439\u043c\u0430\u043d", "CK": "\u041e\u0441\u0442\u0440\u043e\u0432\u0430 \u041a\u0443\u043a\u0430", "PK": "\u041f\u0430\u043a\u0438\u0441\u0442\u0430\u043d", "PW": "\u041f\u0430\u043b\u0430\u0443", "PA": "\u041f\u0430\u043d\u0430\u043c\u0430", "PG": "\u041f\u0430\u043f\u0443\u0430 \u2014 \u041d\u043e\u0432\u0430\u044f \u0413\u0432\u0438\u043d\u0435\u044f", "PY": "\u041f\u0430\u0440\u0430\u0433\u0432\u0430\u0439", "PE": "\u041f\u0435\u0440\u0443", "PL": "\u041f\u043e\u043b\u044c\u0448\u0430", "PT": "\u041f\u043e\u0440\u0442\u0443\u0433\u0430\u043b\u0438\u044f", "PR": "\u041f\u0443\u044d\u0440\u0442\u043e-\u0420\u0438\u043a\u043e", "KR": "\u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430 \u041a\u043e\u0440\u0435\u044f", "RE": "\u0420\u0435\u044e\u043d\u044c\u043e\u043d", "RU": "\u0420\u043e\u0441\u0441\u0438\u044f", "RW": "\u0420\u0443\u0430\u043d\u0434\u0430", "RO": "\u0420\u0443\u043c\u044b\u043d\u0438\u044f", "SV": "\u0421\u0430\u043b\u044c\u0432\u0430\u0434\u043e\u0440", "WS": "\u0421\u0430\u043c\u043e\u0430", "SM": "\u0421\u0430\u043d-\u041c\u0430\u0440\u0438\u043d\u043e", "ST": "\u0421\u0430\u043d-\u0422\u043e\u043c\u0435 \u0438 \u041f\u0440\u0438\u043d\u0441\u0438\u043f\u0438", "SA": "\u0421\u0430\u0443\u0434\u043e\u0432\u0441\u043a\u0430\u044f \u0410\u0440\u0430\u0432\u0438\u044f", "MK": "\u0421\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0438\u044f", "SC": "\u0421\u0435\u0439\u0448\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u041e\u0441\u0442\u0440\u043e\u0432\u0430", "BL": "\u0421\u0435\u043d-\u0411\u0430\u0440\u0442\u0435\u043b\u0435\u043c\u0438", "MF": "\u0421\u0435\u043d-\u041c\u0430\u0440\u0442\u0435\u043d", "PM": "\u0421\u0435\u043d-\u041f\u044c\u0435\u0440 \u0438 \u041c\u0438\u043a\u0435\u043b\u043e\u043d", "SN": "\u0421\u0435\u043d\u0435\u0433\u0430\u043b", "VC": "\u0421\u0435\u043d\u0442-\u0412\u0438\u043d\u0441\u0435\u043d\u0442 \u0438 \u0413\u0440\u0435\u043d\u0430\u0434\u0438\u043d\u044b", "KN": "\u0421\u0435\u043d\u0442-\u041a\u0438\u0442\u0441 \u0438 \u041d\u0435\u0432\u0438\u0441", "LC": "\u0421\u0435\u043d\u0442-\u041b\u044e\u0441\u0438\u044f", "RS": "\u0421\u0435\u0440\u0431\u0438\u044f", "SG": "\u0421\u0438\u043d\u0433\u0430\u043f\u0443\u0440", "SX": "\u0421\u0438\u043d\u0442-\u041c\u0430\u0440\u0442\u0435\u043d", "SY": "\u0421\u0438\u0440\u0438\u044f", "SK": "\u0421\u043b\u043e\u0432\u0430\u043a\u0438\u044f", "SI": "\u0421\u043b\u043e\u0432\u0435\u043d\u0438\u044f", "US": "\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0435 \u0428\u0442\u0430\u0442\u044b", "SB": "\u0421\u043e\u043b\u043e\u043c\u043e\u043d\u043e\u0432\u044b \u041e\u0441\u0442\u0440\u043e\u0432\u0430", "SO": "\u0421\u043e\u043c\u0430\u043b\u0438", "SD": "\u0421\u0443\u0434\u0430\u043d", "SR": "\u0421\u0443\u0440\u0438\u043d\u0430\u043c", "SL": "\u0421\u044c\u0435\u0440\u0440\u0430-\u041b\u0435\u043e\u043d\u0435", "TJ": "\u0422\u0430\u0434\u0436\u0438\u043a\u0438\u0441\u0442\u0430\u043d", "TH": "\u0422\u0430\u0438\u043b\u0430\u043d\u0434", "TW": "\u0422\u0430\u0439\u0432\u0430\u043d\u044c", "TZ": "\u0422\u0430\u043d\u0437\u0430\u043d\u0438\u044f", "TG": "\u0422\u043e\u0433\u043e", "TK": "\u0422\u043e\u043a\u0435\u043b\u0430\u0443", "TO": "\u0422\u043e\u043d\u0433\u0430", "TT": "\u0422\u0440\u0438\u043d\u0438\u0434\u0430\u0434 \u0438 \u0422\u043e\u0431\u0430\u0433\u043e", "TN": "\u0422\u0443\u043d\u0438\u0441", "TM": "\u0422\u0443\u0440\u043a\u043c\u0435\u043d\u0438\u0441\u0442\u0430\u043d", "TR": "\u0422\u0443\u0440\u0446\u0438\u044f", "UG": "\u0423\u0433\u0430\u043d\u0434\u0430", "UZ": "\u0423\u0437\u0431\u0435\u043a\u0438\u0441\u0442\u0430\u043d", "UA": "\u0423\u043a\u0440\u0430\u0438\u043d\u0430", "WF": "\u0423\u043e\u043b\u043b\u0438\u0441 \u0438 \u0424\u0443\u0442\u0443\u043d\u0430", "UY": "\u0423\u0440\u0443\u0433\u0432\u0430\u0439", "FO": "\u0424\u0430\u0440\u0435\u0440\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430", "FJ": "\u0424\u0438\u0434\u0436\u0438", "PH": "\u0424\u0438\u043b\u0438\u043f\u043f\u0438\u043d\u044b", "FI": "\u0424\u0438\u043d\u043b\u044f\u043d\u0434\u0438\u044f", "FK": "\u0424\u043e\u043b\u043a\u043b\u0435\u043d\u0434\u0441\u043a\u0438\u0435 \u043e-\u0432\u0430", "FR": "\u0424\u0440\u0430\u043d\u0446\u0438\u044f", "GF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0430\u044f \u0413\u0432\u0438\u0430\u043d\u0430", "PF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0430\u044f \u041f\u043e\u043b\u0438\u043d\u0435\u0437\u0438\u044f", "TF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0438\u0435 \u042e\u0436\u043d\u044b\u0435 \u0442\u0435\u0440\u0440\u0438\u0442\u043e\u0440\u0438\u0438", "HR": "\u0425\u043e\u0440\u0432\u0430\u0442\u0438\u044f", "CF": "\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e-\u0410\u0444\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430", "TD": "\u0427\u0430\u0434", "ME": "\u0427\u0435\u0440\u043d\u043e\u0433\u043e\u0440\u0438\u044f", "CZ": "\u0427\u0435\u0445\u0438\u044f", "CL": "\u0427\u0438\u043b\u0438", "CH": "\u0428\u0432\u0435\u0439\u0446\u0430\u0440\u0438\u044f", "SE": "\u0428\u0432\u0435\u0446\u0438\u044f", "SJ": "\u0428\u043f\u0438\u0446\u0431\u0435\u0440\u0433\u0435\u043d \u0438 \u042f\u043d-\u041c\u0430\u0439\u0435\u043d", "LK": "\u0428\u0440\u0438-\u041b\u0430\u043d\u043a\u0430", "EC": "\u042d\u043a\u0432\u0430\u0434\u043e\u0440", "GQ": "\u042d\u043a\u0432\u0430\u0442\u043e\u0440\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0413\u0432\u0438\u043d\u0435\u044f", "ER": "\u042d\u0440\u0438\u0442\u0440\u0435\u044f", "SZ": "\u042d\u0441\u0432\u0430\u0442\u0438\u043d\u0438", "EE": "\u042d\u0441\u0442\u043e\u043d\u0438\u044f", "ET": "\u042d\u0444\u0438\u043e\u043f\u0438\u044f", "GS": "\u042e\u0436\u043d\u0430\u044f \u0413\u0435\u043e\u0440\u0433\u0438\u044f \u0438 \u042e\u0436\u043d\u044b\u0435 \u0421\u0430\u043d\u0434\u0432\u0438\u0447\u0435\u0432\u044b \u043e-\u0432\u0430", "ZA": "\u042e\u0436\u043d\u043e-\u0410\u0444\u0440\u0438\u043a\u0430\u043d\u0441\u043a\u0430\u044f \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0438\u043a\u0430", "SS": "\u042e\u0436\u043d\u044b\u0439 \u0421\u0443\u0434\u0430\u043d", "JM": "\u042f\u043c\u0430\u0439\u043a\u0430", "JP": "\u042f\u043f\u043e\u043d\u0438\u044f"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/sv.json b/desktop/onionshare/resources/countries/sv.json
new file mode 100644
index 00000000..77b65a55
--- /dev/null
+++ b/desktop/onionshare/resources/countries/sv.json
@@ -0,0 +1 @@
+{"AF": "Afghanistan", "AL": "Albanien", "DZ": "Algeriet", "VI": "Amerikanska Jungfru\u00f6arna", "AS": "Amerikanska Samoa", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktis", "AG": "Antigua och Barbuda", "AR": "Argentina", "AM": "Armenien", "AW": "Aruba", "AU": "Australien", "AZ": "Azerbajdzjan", "BS": "Bahamas", "BH": "Bahrain", "BD": "Bangladesh", "BB": "Barbados", "BE": "Belgien", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "BT": "Bhutan", "BO": "Bolivia", "BA": "Bosnien och Hercegovina", "BW": "Botswana", "BV": "Bouvet\u00f6n", "BR": "Brasilien", "VG": "Brittiska Jungfru\u00f6arna", "IO": "Brittiska territoriet i Indiska oceanen", "BN": "Brunei", "BG": "Bulgarien", "BF": "Burkina Faso", "BI": "Burundi", "KY": "Cayman\u00f6arna", "CF": "Centralafrikanska republiken", "CL": "Chile", "CO": "Colombia", "CK": "Cook\u00f6arna", "CR": "Costa Rica", "CW": "Cura\u00e7ao", "CY": "Cypern", "CI": "C\u00f4te d\u2019Ivoire", "DK": "Danmark", "DJ": "Djibouti", "DM": "Dominica", "DO": "Dominikanska republiken", "EC": "Ecuador", "EG": "Egypten", "GQ": "Ekvatorialguinea", "SV": "El Salvador", "ER": "Eritrea", "EE": "Estland", "ET": "Etiopien", "FK": "Falklands\u00f6arna", "FJ": "Fiji", "PH": "Filippinerna", "FI": "Finland", "FR": "Frankrike", "GF": "Franska Guyana", "PF": "Franska Polynesien", "TF": "Franska sydterritorierna", "FO": "F\u00e4r\u00f6arna", "AE": "F\u00f6renade Arabemiraten", "GA": "Gabon", "GM": "Gambia", "GE": "Georgien", "GH": "Ghana", "GI": "Gibraltar", "GR": "Grekland", "GD": "Grenada", "GL": "Gr\u00f6nland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GN": "Guinea", "GW": "Guinea-Bissau", "GY": "Guyana", "HT": "Haiti", "HM": "Heard\u00f6n och McDonald\u00f6arna", "HN": "Honduras", "HK": "Hongkong", "IN": "Indien", "ID": "Indonesien", "IQ": "Irak", "IR": "Iran", "IE": "Irland", "IS": "Island", "IM": "Isle of Man", "IL": "Israel", "IT": "Italien", "JM": "Jamaica", "JP": "Japan", "YE": "Jemen", "JO": "Jordanien", "CX": "Jul\u00f6n", "KH": "Kambodja", "CM": "Kamerun", "CA": "Kanada", "CV": "Kap Verde", "BQ": "Karibiska Nederl\u00e4nderna", "KZ": "Kazakstan", "KE": "Kenya", "CN": "Kina", "KG": "Kirgizistan", "KI": "Kiribati", "CC": "Kokos\u00f6arna", "KM": "Komorerna", "CG": "Kongo-Brazzaville", "CD": "Kongo-Kinshasa", "HR": "Kroatien", "CU": "Kuba", "KW": "Kuwait", "LA": "Laos", "LS": "Lesotho", "LV": "Lettland", "LB": "Libanon", "LR": "Liberia", "LY": "Libyen", "LI": "Liechtenstein", "LT": "Litauen", "LU": "Luxemburg", "MO": "Macao", "MG": "Madagaskar", "MW": "Malawi", "MY": "Malaysia", "MV": "Maldiverna", "ML": "Mali", "MT": "Malta", "MA": "Marocko", "MQ": "Martinique", "MR": "Mauretanien", "MU": "Mauritius", "YT": "Mayotte", "MX": "Mexiko", "MZ": "Mo\u00e7ambique", "MD": "Moldavien", "MC": "Monaco", "MN": "Mongoliet", "ME": "Montenegro", "MS": "Montserrat", "MM": "Myanmar (Burma)", "NA": "Namibia", "NR": "Nauru", "NL": "Nederl\u00e4nderna", "NP": "Nepal", "NI": "Nicaragua", "NE": "Niger", "NG": "Nigeria", "NU": "Niue", "KP": "Nordkorea", "MK": "Nordmakedonien", "NF": "Norfolk\u00f6n", "NO": "Norge", "NC": "Nya Kaledonien", "NZ": "Nya Zeeland", "OM": "Oman", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua Nya Guinea", "PY": "Paraguay", "PE": "Peru", "PN": "Pitcairn\u00f6arna", "PL": "Polen", "PT": "Portugal", "PR": "Puerto Rico", "QA": "Qatar", "RE": "R\u00e9union", "RO": "Rum\u00e4nien", "RW": "Rwanda", "RU": "Ryssland", "BL": "S:t Barth\u00e9lemy", "SH": "S:t Helena", "KN": "S:t Kitts och Nevis", "LC": "S:t Lucia", "PM": "S:t Pierre och Miquelon", "VC": "S:t Vincent och Grenadinerna", "MF": "Saint-Martin", "SB": "Salomon\u00f6arna", "WS": "Samoa", "SM": "San Marino", "ST": "S\u00e3o Tom\u00e9 och Pr\u00edncipe", "SA": "Saudiarabien", "CH": "Schweiz", "SN": "Senegal", "RS": "Serbien", "SC": "Seychellerna", "SL": "Sierra Leone", "SG": "Singapore", "SX": "Sint Maarten", "SK": "Slovakien", "SI": "Slovenien", "SO": "Somalia", "ES": "Spanien", "LK": "Sri Lanka", "GB": "Storbritannien", "SD": "Sudan", "SR": "Surinam", "SJ": "Svalbard och Jan Mayen", "SE": "Sverige", "SZ": "Swaziland", "ZA": "Sydafrika", "GS": "Sydgeorgien och Sydsandwich\u00f6arna", "KR": "Sydkorea", "SS": "Sydsudan", "SY": "Syrien", "TJ": "Tadzjikistan", "TW": "Taiwan", "TZ": "Tanzania", "TD": "Tchad", "TH": "Thailand", "CZ": "Tjeckien", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad och Tobago", "TN": "Tunisien", "TR": "Turkiet", "TM": "Turkmenistan", "TC": "Turks- och Caicos\u00f6arna", "DE": "Tyskland", "UG": "Uganda", "UA": "Ukraina", "HU": "Ungern", "UY": "Uruguay", "US": "USA", "UZ": "Uzbekistan", "VU": "Vanuatu", "VA": "Vatikanstaten", "VE": "Venezuela", "VN": "Vietnam", "BY": "Vitryssland", "EH": "V\u00e4stsahara", "WF": "Wallis- och Futuna\u00f6arna", "ZM": "Zambia", "ZW": "Zimbabwe", "AX": "\u00c5land", "AT": "\u00d6sterrike", "TL": "\u00d6sttimor"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/tr.json b/desktop/onionshare/resources/countries/tr.json
new file mode 100644
index 00000000..c6da9370
--- /dev/null
+++ b/desktop/onionshare/resources/countries/tr.json
@@ -0,0 +1 @@
+{"VI": "ABD Virjin Adalar\u0131", "AF": "Afganistan", "AX": "\u00c5land Adalar\u0131", "DE": "Almanya", "US": "Amerika Birle\u015fik Devletleri", "AS": "Amerikan Samoas\u0131", "AD": "Andorra", "AO": "Angola", "AI": "Anguilla", "AQ": "Antarktika", "AG": "Antigua ve Barbuda", "AR": "Arjantin", "AL": "Arnavutluk", "AW": "Aruba", "AU": "Avustralya", "AT": "Avusturya", "AZ": "Azerbaycan", "BS": "Bahamalar", "BH": "Bahreyn", "BD": "Banglade\u015f", "BB": "Barbados", "EH": "Bat\u0131 Sahra", "BY": "Belarus", "BE": "Bel\u00e7ika", "BZ": "Belize", "BJ": "Benin", "BM": "Bermuda", "AE": "Birle\u015fik Arap Emirlikleri", "GB": "Birle\u015fik Krall\u0131k", "BO": "Bolivya", "BA": "Bosna-Hersek", "BW": "Botsvana", "BV": "Bouvet Adas\u0131", "BR": "Brezilya", "IO": "Britanya Hint Okyanusu Topraklar\u0131", "VG": "Britanya Virjin Adalar\u0131", "BN": "Brunei", "BG": "Bulgaristan", "BF": "Burkina Faso", "BI": "Burundi", "BT": "Butan", "CV": "Cape Verde", "KY": "Cayman Adalar\u0131", "GI": "Cebelitar\u0131k", "DZ": "Cezayir", "CX": "Christmas Adas\u0131", "DJ": "Cibuti", "CC": "Cocos (Keeling) Adalar\u0131", "CK": "Cook Adalar\u0131", "CI": "C\u00f4te d\u2019Ivoire", "CW": "Cura\u00e7ao", "TD": "\u00c7ad", "CZ": "\u00c7ekya", "CN": "\u00c7in", "HK": "\u00c7in Hong Kong \u00d6\u0130B", "MO": "\u00c7in Makao \u00d6\u0130B", "DK": "Danimarka", "DO": "Dominik Cumhuriyeti", "DM": "Dominika", "EC": "Ekvador", "GQ": "Ekvator Ginesi", "SV": "El Salvador", "ID": "Endonezya", "ER": "Eritre", "AM": "Ermenistan", "EE": "Estonya", "SZ": "Esvatini", "ET": "Etiyopya", "FK": "Falkland Adalar\u0131", "FO": "Faroe Adalar\u0131", "MA": "Fas", "FJ": "Fiji", "PH": "Filipinler", "FI": "Finlandiya", "FR": "Fransa", "GF": "Frans\u0131z Guyanas\u0131", "TF": "Frans\u0131z G\u00fcney Topraklar\u0131", "PF": "Frans\u0131z Polinezyas\u0131", "GA": "Gabon", "GM": "Gambiya", "GH": "Gana", "GN": "Gine", "GW": "Gine-Bissau", "GD": "Grenada", "GL": "Gr\u00f6nland", "GP": "Guadeloupe", "GU": "Guam", "GT": "Guatemala", "GG": "Guernsey", "GY": "Guyana", "ZA": "G\u00fcney Afrika", "GS": "G\u00fcney Georgia ve G\u00fcney Sandwich Adalar\u0131", "KR": "G\u00fcney Kore", "SS": "G\u00fcney Sudan", "GE": "G\u00fcrcistan", "HT": "Haiti", "HM": "Heard Adas\u0131 ve McDonald Adalar\u0131", "HR": "H\u0131rvatistan", "IN": "Hindistan", "NL": "Hollanda", "HN": "Honduras", "IQ": "Irak", "IR": "\u0130ran", "IE": "\u0130rlanda", "ES": "\u0130spanya", "IL": "\u0130srail", "SE": "\u0130sve\u00e7", "CH": "\u0130svi\u00e7re", "IT": "\u0130talya", "IS": "\u0130zlanda", "JM": "Jamaika", "JP": "Japonya", "KH": "Kambo\u00e7ya", "CM": "Kamerun", "CA": "Kanada", "ME": "Karada\u011f", "BQ": "Karayip Hollandas\u0131", "QA": "Katar", "KZ": "Kazakistan", "KE": "Kenya", "CY": "K\u0131br\u0131s", "KG": "K\u0131rg\u0131zistan", "KI": "Kiribati", "CO": "Kolombiya", "KM": "Komorlar", "CG": "Kongo - Brazavil", "CD": "Kongo - Kin\u015fasa", "CR": "Kosta Rika", "KW": "Kuveyt", "KP": "Kuzey Kore", "MK": "Kuzey Makedonya", "CU": "K\u00fcba", "LA": "Laos", "LS": "Lesotho", "LV": "Letonya", "LR": "Liberya", "LY": "Libya", "LI": "Liechtenstein", "LT": "Litvanya", "LB": "L\u00fcbnan", "LU": "L\u00fcksemburg", "HU": "Macaristan", "MG": "Madagaskar", "MW": "Malavi", "MV": "Maldivler", "MY": "Malezya", "ML": "Mali", "MT": "Malta", "IM": "Man Adas\u0131", "MQ": "Martinik", "MU": "Mauritius", "YT": "Mayotte", "MX": "Meksika", "EG": "M\u0131s\u0131r", "MN": "Mo\u011folistan", "MD": "Moldova", "MC": "Monako", "MS": "Montserrat", "MR": "Moritanya", "MZ": "Mozambik", "MM": "Myanmar (Burma)", "NA": "Namibya", "NR": "Nauru", "NP": "Nepal", "NE": "Nijer", "NG": "Nijerya", "NI": "Nikaragua", "NU": "Niue", "NF": "Norfolk Adas\u0131", "NO": "Norve\u00e7", "CF": "Orta Afrika Cumhuriyeti", "UZ": "\u00d6zbekistan", "PK": "Pakistan", "PW": "Palau", "PA": "Panama", "PG": "Papua Yeni Gine", "PY": "Paraguay", "PE": "Peru", "PN": "Pitcairn Adalar\u0131", "PL": "Polonya", "PT": "Portekiz", "PR": "Porto Riko", "RE": "Reunion", "RO": "Romanya", "RW": "Ruanda", "RU": "Rusya", "BL": "Saint Barthelemy", "SH": "Saint Helena", "KN": "Saint Kitts ve Nevis", "LC": "Saint Lucia", "MF": "Saint Martin", "PM": "Saint Pierre ve Miquelon", "VC": "Saint Vincent ve Grenadinler", "WS": "Samoa", "SM": "San Marino", "ST": "Sao Tome ve Principe", "SN": "Senegal", "SC": "Sey\u015feller", "RS": "S\u0131rbistan", "SL": "Sierra Leone", "SG": "Singapur", "SX": "Sint Maarten", "SK": "Slovakya", "SI": "Slovenya", "SB": "Solomon Adalar\u0131", "SO": "Somali", "LK": "Sri Lanka", "SD": "Sudan", "SR": "Surinam", "SY": "Suriye", "SA": "Suudi Arabistan", "SJ": "Svalbard ve Jan Mayen", "CL": "\u015eili", "TJ": "Tacikistan", "TZ": "Tanzanya", "TH": "Tayland", "TW": "Tayvan", "TL": "Timor-Leste", "TG": "Togo", "TK": "Tokelau", "TO": "Tonga", "TT": "Trinidad ve Tobago", "TN": "Tunus", "TC": "Turks ve Caicos Adalar\u0131", "TR": "T\u00fcrkiye", "TM": "T\u00fcrkmenistan", "UG": "Uganda", "UA": "Ukrayna", "OM": "Umman", "UY": "Uruguay", "JO": "\u00dcrd\u00fcn", "VU": "Vanuatu", "VA": "Vatikan", "VE": "Venezuela", "VN": "Vietnam", "WF": "Wallis ve Futuna", "YE": "Yemen", "NC": "Yeni Kaledonya", "NZ": "Yeni Zelanda", "GR": "Yunanistan", "ZM": "Zambiya", "ZW": "Zimbabve"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/uk.json b/desktop/onionshare/resources/countries/uk.json
new file mode 100644
index 00000000..009893c4
--- /dev/null
+++ b/desktop/onionshare/resources/countries/uk.json
@@ -0,0 +1 @@
+{"AU": "\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0456\u044f", "AT": "\u0410\u0432\u0441\u0442\u0440\u0456\u044f", "AZ": "\u0410\u0437\u0435\u0440\u0431\u0430\u0439\u0434\u0436\u0430\u043d", "AX": "\u0410\u043b\u0430\u043d\u0434\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "AL": "\u0410\u043b\u0431\u0430\u043d\u0456\u044f", "DZ": "\u0410\u043b\u0436\u0438\u0440", "AS": "\u0410\u043c\u0435\u0440\u0438\u043a\u0430\u043d\u0441\u044c\u043a\u0435 \u0421\u0430\u043c\u043e\u0430", "AO": "\u0410\u043d\u0433\u043e\u043b\u0430", "AI": "\u0410\u043d\u0491\u0456\u043b\u044c\u044f", "AD": "\u0410\u043d\u0434\u043e\u0440\u0440\u0430", "AQ": "\u0410\u043d\u0442\u0430\u0440\u043a\u0442\u0438\u043a\u0430", "AG": "\u0410\u043d\u0442\u0438\u0491\u0443\u0430 \u0456 \u0411\u0430\u0440\u0431\u0443\u0434\u0430", "AR": "\u0410\u0440\u0433\u0435\u043d\u0442\u0438\u043d\u0430", "AW": "\u0410\u0440\u0443\u0431\u0430", "AF": "\u0410\u0444\u0433\u0430\u043d\u0456\u0441\u0442\u0430\u043d", "BS": "\u0411\u0430\u0433\u0430\u043c\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "BD": "\u0411\u0430\u043d\u0433\u043b\u0430\u0434\u0435\u0448", "BB": "\u0411\u0430\u0440\u0431\u0430\u0434\u043e\u0441", "BH": "\u0411\u0430\u0445\u0440\u0435\u0439\u043d", "BZ": "\u0411\u0435\u043b\u0456\u0437", "BE": "\u0411\u0435\u043b\u044c\u0491\u0456\u044f", "BJ": "\u0411\u0435\u043d\u0456\u043d", "BM": "\u0411\u0435\u0440\u043c\u0443\u0434\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "BY": "\u0411\u0456\u043b\u043e\u0440\u0443\u0441\u044c", "BG": "\u0411\u043e\u043b\u0433\u0430\u0440\u0456\u044f", "BO": "\u0411\u043e\u043b\u0456\u0432\u0456\u044f", "BA": "\u0411\u043e\u0441\u043d\u0456\u044f \u0456 \u0413\u0435\u0440\u0446\u0435\u0491\u043e\u0432\u0438\u043d\u0430", "BW": "\u0411\u043e\u0442\u0441\u0432\u0430\u043d\u0430", "BR": "\u0411\u0440\u0430\u0437\u0456\u043b\u0456\u044f", "IO": "\u0411\u0440\u0438\u0442\u0430\u043d\u0441\u044c\u043a\u0430 \u0442\u0435\u0440\u0438\u0442\u043e\u0440\u0456\u044f \u0432 \u0406\u043d\u0434\u0456\u0439\u0441\u044c\u043a\u043e\u043c\u0443 \u041e\u043a\u0435\u0430\u043d\u0456", "VG": "\u0411\u0440\u0438\u0442\u0430\u043d\u0441\u044c\u043a\u0456 \u0412\u0456\u0440\u0433\u0456\u043d\u0441\u044c\u043a\u0456 \u043e\u0441\u0442\u0440\u043e\u0432\u0438", "BN": "\u0411\u0440\u0443\u043d\u0435\u0439", "BF": "\u0411\u0443\u0440\u043a\u0456\u043d\u0430-\u0424\u0430\u0441\u043e", "BI": "\u0411\u0443\u0440\u0443\u043d\u0434\u0456", "BT": "\u0411\u0443\u0442\u0430\u043d", "VU": "\u0412\u0430\u043d\u0443\u0430\u0442\u0443", "VA": "\u0412\u0430\u0442\u0438\u043a\u0430\u043d", "GB": "\u0412\u0435\u043b\u0438\u043a\u0430 \u0411\u0440\u0438\u0442\u0430\u043d\u0456\u044f", "VE": "\u0412\u0435\u043d\u0435\u0441\u0443\u0435\u043b\u0430", "VI": "\u0412\u0456\u0440\u0433\u0456\u043d\u0441\u044c\u043a\u0456 \u043e\u0441\u0442\u0440\u043e\u0432\u0438, \u0421\u0428\u0410", "AM": "\u0412\u0456\u0440\u043c\u0435\u043d\u0456\u044f", "VN": "\u0412\u02bc\u0454\u0442\u043d\u0430\u043c", "GA": "\u0413\u0430\u0431\u043e\u043d", "HT": "\u0413\u0430\u0457\u0442\u0456", "GM": "\u0413\u0430\u043c\u0431\u0456\u044f", "GH": "\u0413\u0430\u043d\u0430", "GN": "\u0413\u0432\u0456\u043d\u0435\u044f", "GW": "\u0413\u0432\u0456\u043d\u0435\u044f-\u0411\u0456\u0441\u0430\u0443", "HN": "\u0413\u043e\u043d\u0434\u0443\u0440\u0430\u0441", "HK": "\u0413\u043e\u043d\u043a\u043e\u043d\u0433, \u041e.\u0410.\u0420. \u041a\u0438\u0442\u0430\u044e", "GR": "\u0413\u0440\u0435\u0446\u0456\u044f", "GE": "\u0413\u0440\u0443\u0437\u0456\u044f", "GY": "\u0490\u0430\u0439\u0430\u043d\u0430", "GP": "\u0490\u0432\u0430\u0434\u0435\u043b\u0443\u043f\u0430", "GT": "\u0490\u0432\u0430\u0442\u0435\u043c\u0430\u043b\u0430", "GG": "\u0490\u0435\u0440\u043d\u0441\u0456", "GI": "\u0490\u0456\u0431\u0440\u0430\u043b\u0442\u0430\u0440", "GD": "\u0490\u0440\u0435\u043d\u0430\u0434\u0430", "GL": "\u0490\u0440\u0435\u043d\u043b\u0430\u043d\u0434\u0456\u044f", "GU": "\u0490\u0443\u0430\u043c", "DK": "\u0414\u0430\u043d\u0456\u044f", "DJ": "\u0414\u0436\u0438\u0431\u0443\u0442\u0456", "DM": "\u0414\u043e\u043c\u0456\u043d\u0456\u043a\u0430", "DO": "\u0414\u043e\u043c\u0456\u043d\u0456\u043a\u0430\u043d\u0441\u044c\u043a\u0430 \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0456\u043a\u0430", "EC": "\u0415\u043a\u0432\u0430\u0434\u043e\u0440", "GQ": "\u0415\u043a\u0432\u0430\u0442\u043e\u0440\u0456\u0430\u043b\u044c\u043d\u0430 \u0413\u0432\u0456\u043d\u0435\u044f", "ER": "\u0415\u0440\u0438\u0442\u0440\u0435\u044f", "SZ": "\u0415\u0441\u0432\u0430\u0442\u0456\u043d\u0456", "EE": "\u0415\u0441\u0442\u043e\u043d\u0456\u044f", "ET": "\u0415\u0444\u0456\u043e\u043f\u0456\u044f", "EG": "\u0404\u0433\u0438\u043f\u0435\u0442", "YE": "\u0404\u043c\u0435\u043d", "ZM": "\u0417\u0430\u043c\u0431\u0456\u044f", "EH": "\u0417\u0430\u0445\u0456\u0434\u043d\u0430 \u0421\u0430\u0445\u0430\u0440\u0430", "ZW": "\u0417\u0456\u043c\u0431\u0430\u0431\u0432\u0435", "IL": "\u0406\u0437\u0440\u0430\u0457\u043b\u044c", "IN": "\u0406\u043d\u0434\u0456\u044f", "ID": "\u0406\u043d\u0434\u043e\u043d\u0435\u0437\u0456\u044f", "IQ": "\u0406\u0440\u0430\u043a", "IR": "\u0406\u0440\u0430\u043d", "IE": "\u0406\u0440\u043b\u0430\u043d\u0434\u0456\u044f", "IS": "\u0406\u0441\u043b\u0430\u043d\u0434\u0456\u044f", "ES": "\u0406\u0441\u043f\u0430\u043d\u0456\u044f", "IT": "\u0406\u0442\u0430\u043b\u0456\u044f", "JO": "\u0419\u043e\u0440\u0434\u0430\u043d\u0456\u044f", "CV": "\u041a\u0430\u0431\u043e-\u0412\u0435\u0440\u0434\u0435", "KZ": "\u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d", "KY": "\u041a\u0430\u0439\u043c\u0430\u043d\u043e\u0432\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "KH": "\u041a\u0430\u043c\u0431\u043e\u0434\u0436\u0430", "CM": "\u041a\u0430\u043c\u0435\u0440\u0443\u043d", "CA": "\u041a\u0430\u043d\u0430\u0434\u0430", "QA": "\u041a\u0430\u0442\u0430\u0440", "KE": "\u041a\u0435\u043d\u0456\u044f", "KG": "\u041a\u0438\u0440\u0433\u0438\u0437\u0441\u0442\u0430\u043d", "CN": "\u041a\u0438\u0442\u0430\u0439", "CY": "\u041a\u0456\u043f\u0440", "KI": "\u041a\u0456\u0440\u0456\u0431\u0430\u0442\u0456", "CC": "\u041a\u043e\u043a\u043e\u0441\u043e\u0432\u0456 (\u041a\u0456\u043b\u0456\u043d\u0491) \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "CO": "\u041a\u043e\u043b\u0443\u043c\u0431\u0456\u044f", "KM": "\u041a\u043e\u043c\u043e\u0440\u0438", "CG": "\u041a\u043e\u043d\u0433\u043e \u2013 \u0411\u0440\u0430\u0437\u0437\u0430\u0432\u0456\u043b\u044c", "CD": "\u041a\u043e\u043d\u0433\u043e \u2013 \u041a\u0456\u043d\u0448\u0430\u0441\u0430", "CR": "\u041a\u043e\u0441\u0442\u0430-\u0420\u0456\u043a\u0430", "CI": "\u041a\u043e\u0442-\u0434\u02bc\u0406\u0432\u0443\u0430\u0440", "CU": "\u041a\u0443\u0431\u0430", "KW": "\u041a\u0443\u0432\u0435\u0439\u0442", "CW": "\u041a\u044e\u0440\u0430\u0441\u0430\u043e", "LA": "\u041b\u0430\u043e\u0441", "LV": "\u041b\u0430\u0442\u0432\u0456\u044f", "LS": "\u041b\u0435\u0441\u043e\u0442\u043e", "LT": "\u041b\u0438\u0442\u0432\u0430", "LR": "\u041b\u0456\u0431\u0435\u0440\u0456\u044f", "LB": "\u041b\u0456\u0432\u0430\u043d", "LY": "\u041b\u0456\u0432\u0456\u044f", "LI": "\u041b\u0456\u0445\u0442\u0435\u043d\u0448\u0442\u0435\u0439\u043d", "LU": "\u041b\u044e\u043a\u0441\u0435\u043c\u0431\u0443\u0440\u0491", "MR": "\u041c\u0430\u0432\u0440\u0438\u0442\u0430\u043d\u0456\u044f", "MU": "\u041c\u0430\u0432\u0440\u0456\u043a\u0456\u0439", "MG": "\u041c\u0430\u0434\u0430\u0433\u0430\u0441\u043a\u0430\u0440", "YT": "\u041c\u0430\u0439\u043e\u0442\u0442\u0430", "MO": "\u041c\u0430\u043a\u0430\u043e, \u041e.\u0410.\u0420 \u041a\u0438\u0442\u0430\u044e", "MW": "\u041c\u0430\u043b\u0430\u0432\u0456", "MY": "\u041c\u0430\u043b\u0430\u0439\u0437\u0456\u044f", "ML": "\u041c\u0430\u043b\u0456", "MV": "\u041c\u0430\u043b\u044c\u0434\u0456\u0432\u0438", "MT": "\u041c\u0430\u043b\u044c\u0442\u0430", "MA": "\u041c\u0430\u0440\u043e\u043a\u043a\u043e", "MQ": "\u041c\u0430\u0440\u0442\u0456\u043d\u0456\u043a\u0430", "MX": "\u041c\u0435\u043a\u0441\u0438\u043a\u0430", "MZ": "\u041c\u043e\u0437\u0430\u043c\u0431\u0456\u043a", "MD": "\u041c\u043e\u043b\u0434\u043e\u0432\u0430", "MC": "\u041c\u043e\u043d\u0430\u043a\u043e", "MN": "\u041c\u043e\u043d\u0433\u043e\u043b\u0456\u044f", "MS": "\u041c\u043e\u043d\u0442\u0441\u0435\u0440\u0440\u0430\u0442", "MM": "\u041c\u02bc\u044f\u043d\u043c\u0430 (\u0411\u0456\u0440\u043c\u0430)", "NA": "\u041d\u0430\u043c\u0456\u0431\u0456\u044f", "NR": "\u041d\u0430\u0443\u0440\u0443", "NP": "\u041d\u0435\u043f\u0430\u043b", "NE": "\u041d\u0456\u0433\u0435\u0440", "NG": "\u041d\u0456\u0433\u0435\u0440\u0456\u044f", "NL": "\u041d\u0456\u0434\u0435\u0440\u043b\u0430\u043d\u0434\u0438", "BQ": "\u041d\u0456\u0434\u0435\u0440\u043b\u0430\u043d\u0434\u0441\u044c\u043a\u0456 \u041a\u0430\u0440\u0438\u0431\u0441\u044c\u043a\u0456 \u043e\u0441\u0442\u0440\u043e\u0432\u0438", "NI": "\u041d\u0456\u043a\u0430\u0440\u0430\u0491\u0443\u0430", "DE": "\u041d\u0456\u043c\u0435\u0447\u0447\u0438\u043d\u0430", "NU": "\u041d\u0456\u0443\u0435", "NZ": "\u041d\u043e\u0432\u0430 \u0417\u0435\u043b\u0430\u043d\u0434\u0456\u044f", "NC": "\u041d\u043e\u0432\u0430 \u041a\u0430\u043b\u0435\u0434\u043e\u043d\u0456\u044f", "NO": "\u041d\u043e\u0440\u0432\u0435\u0491\u0456\u044f", "AE": "\u041e\u0431\u02bc\u0454\u0434\u043d\u0430\u043d\u0456 \u0410\u0440\u0430\u0431\u0441\u044c\u043a\u0456 \u0415\u043c\u0456\u0440\u0430\u0442\u0438", "OM": "\u041e\u043c\u0430\u043d", "BV": "\u041e\u0441\u0442\u0440\u0456\u0432 \u0411\u0443\u0432\u0435", "IM": "\u041e\u0441\u0442\u0440\u0456\u0432 \u041c\u0435\u043d", "NF": "\u041e\u0441\u0442\u0440\u0456\u0432 \u041d\u043e\u0440\u0444\u043e\u043b\u043a", "CX": "\u041e\u0441\u0442\u0440\u0456\u0432 \u0420\u0456\u0437\u0434\u0432\u0430", "SH": "\u041e\u0441\u0442\u0440\u0456\u0432 \u0421\u0432\u044f\u0442\u043e\u0457 \u0404\u043b\u0435\u043d\u0438", "HM": "\u041e\u0441\u0442\u0440\u043e\u0432\u0438 \u0413\u0435\u0440\u0434 \u0456 \u041c\u0430\u043a\u0434\u043e\u043d\u0430\u043b\u0434", "CK": "\u041e\u0441\u0442\u0440\u043e\u0432\u0438 \u041a\u0443\u043a\u0430", "PN": "\u041e\u0441\u0442\u0440\u043e\u0432\u0438 \u041f\u0456\u0442\u043a\u0435\u0440\u043d", "TC": "\u041e\u0441\u0442\u0440\u043e\u0432\u0438 \u0422\u0435\u0440\u043a\u0441 \u0456 \u041a\u0430\u0439\u043a\u043e\u0441", "PK": "\u041f\u0430\u043a\u0438\u0441\u0442\u0430\u043d", "PW": "\u041f\u0430\u043b\u0430\u0443", "PA": "\u041f\u0430\u043d\u0430\u043c\u0430", "PG": "\u041f\u0430\u043f\u0443\u0430-\u041d\u043e\u0432\u0430 \u0490\u0432\u0456\u043d\u0435\u044f", "PY": "\u041f\u0430\u0440\u0430\u0491\u0432\u0430\u0439", "PE": "\u041f\u0435\u0440\u0443", "GS": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0430 \u0414\u0436\u043e\u0440\u0434\u0436\u0456\u044f \u0442\u0430 \u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0456 \u0421\u0430\u043d\u0434\u0432\u0456\u0447\u0435\u0432\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "KR": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0430 \u041a\u043e\u0440\u0435\u044f", "SS": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0438\u0439 \u0421\u0443\u0434\u0430\u043d", "ZA": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u043e-\u0410\u0444\u0440\u0438\u043a\u0430\u043d\u0441\u044c\u043a\u0430 \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0456\u043a\u0430", "KP": "\u041f\u0456\u0432\u043d\u0456\u0447\u043d\u0430 \u041a\u043e\u0440\u0435\u044f", "MK": "\u041f\u0456\u0432\u043d\u0456\u0447\u043d\u0430 \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0456\u044f", "PL": "\u041f\u043e\u043b\u044c\u0449\u0430", "PT": "\u041f\u043e\u0440\u0442\u0443\u0491\u0430\u043b\u0456\u044f", "PR": "\u041f\u0443\u0435\u0440\u0442\u043e-\u0420\u0456\u043a\u043e", "RE": "\u0420\u0435\u044e\u043d\u044c\u0439\u043e\u043d", "RU": "\u0420\u043e\u0441\u0456\u044f", "RW": "\u0420\u0443\u0430\u043d\u0434\u0430", "RO": "\u0420\u0443\u043c\u0443\u043d\u0456\u044f", "SV": "\u0421\u0430\u043b\u044c\u0432\u0430\u0434\u043e\u0440", "WS": "\u0421\u0430\u043c\u043e\u0430", "SM": "\u0421\u0430\u043d-\u041c\u0430\u0440\u0456\u043d\u043e", "ST": "\u0421\u0430\u043d-\u0422\u043e\u043c\u0435 \u0456 \u041f\u0440\u0456\u043d\u0441\u0456\u043f\u0456", "SA": "\u0421\u0430\u0443\u0434\u0456\u0432\u0441\u044c\u043a\u0430 \u0410\u0440\u0430\u0432\u0456\u044f", "SC": "\u0421\u0435\u0439\u0448\u0435\u043b\u044c\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "BL": "\u0421\u0435\u043d-\u0411\u0430\u0440\u0442\u0435\u043b\u044c\u043c\u0456", "MF": "\u0421\u0435\u043d-\u041c\u0430\u0440\u0442\u0435\u043d", "PM": "\u0421\u0435\u043d-\u041f\u02bc\u0454\u0440 \u0456 \u041c\u0456\u043a\u0435\u043b\u043e\u043d", "SN": "\u0421\u0435\u043d\u0435\u0433\u0430\u043b", "VC": "\u0421\u0435\u043d\u0442-\u0412\u0456\u043d\u0441\u0435\u043d\u0442 \u0456 \u0490\u0440\u0435\u043d\u0430\u0434\u0456\u043d\u0438", "KN": "\u0421\u0435\u043d\u0442-\u041a\u0456\u0442\u0441 \u0456 \u041d\u0435\u0432\u0456\u0441", "LC": "\u0421\u0435\u043d\u0442-\u041b\u044e\u0441\u0456\u044f", "RS": "\u0421\u0435\u0440\u0431\u0456\u044f", "SY": "\u0421\u0438\u0440\u0456\u044f", "SG": "\u0421\u0456\u043d\u0433\u0430\u043f\u0443\u0440", "SX": "\u0421\u0456\u043d\u0442-\u041c\u0430\u0440\u0442\u0435\u043d", "SK": "\u0421\u043b\u043e\u0432\u0430\u0447\u0447\u0438\u043d\u0430", "SI": "\u0421\u043b\u043e\u0432\u0435\u043d\u0456\u044f", "SB": "\u0421\u043e\u043b\u043e\u043c\u043e\u043d\u043e\u0432\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "SO": "\u0421\u043e\u043c\u0430\u043b\u0456", "US": "\u0421\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0456 \u0428\u0442\u0430\u0442\u0438", "SD": "\u0421\u0443\u0434\u0430\u043d", "SR": "\u0421\u0443\u0440\u0456\u043d\u0430\u043c", "SL": "\u0421\u044c\u0454\u0440\u0440\u0430-\u041b\u0435\u043e\u043d\u0435", "TJ": "\u0422\u0430\u0434\u0436\u0438\u043a\u0438\u0441\u0442\u0430\u043d", "TH": "\u0422\u0430\u0457\u043b\u0430\u043d\u0434", "TW": "\u0422\u0430\u0439\u0432\u0430\u043d\u044c", "TZ": "\u0422\u0430\u043d\u0437\u0430\u043d\u0456\u044f", "TL": "\u0422\u0456\u043c\u043e\u0440-\u041b\u0435\u0448\u0442\u0456", "TG": "\u0422\u043e\u0433\u043e", "TK": "\u0422\u043e\u043a\u0435\u043b\u0430\u0443", "TO": "\u0422\u043e\u043d\u0491\u0430", "TT": "\u0422\u0440\u0456\u043d\u0456\u0434\u0430\u0434 \u0456 \u0422\u043e\u0431\u0430\u0491\u043e", "TN": "\u0422\u0443\u043d\u0456\u0441", "TR": "\u0422\u0443\u0440\u0435\u0447\u0447\u0438\u043d\u0430", "TM": "\u0422\u0443\u0440\u043a\u043c\u0435\u043d\u0456\u0441\u0442\u0430\u043d", "UG": "\u0423\u0433\u0430\u043d\u0434\u0430", "HU": "\u0423\u0433\u043e\u0440\u0449\u0438\u043d\u0430", "UZ": "\u0423\u0437\u0431\u0435\u043a\u0438\u0441\u0442\u0430\u043d", "UA": "\u0423\u043a\u0440\u0430\u0457\u043d\u0430", "WF": "\u0423\u043e\u043b\u043b\u0456\u0441 \u0456 \u0424\u0443\u0442\u0443\u043d\u0430", "UY": "\u0423\u0440\u0443\u0491\u0432\u0430\u0439", "FO": "\u0424\u0430\u0440\u0435\u0440\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "FJ": "\u0424\u0456\u0434\u0436\u0456", "PH": "\u0424\u0456\u043b\u0456\u043f\u043f\u0456\u043d\u0438", "FI": "\u0424\u0456\u043d\u043b\u044f\u043d\u0434\u0456\u044f", "FK": "\u0424\u043e\u043b\u043a\u043b\u0435\u043d\u0434\u0441\u044c\u043a\u0456 \u041e\u0441\u0442\u0440\u043e\u0432\u0438", "FR": "\u0424\u0440\u0430\u043d\u0446\u0456\u044f", "GF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u044c\u043a\u0430 \u0490\u0432\u0456\u0430\u043d\u0430", "PF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u044c\u043a\u0430 \u041f\u043e\u043b\u0456\u043d\u0435\u0437\u0456\u044f", "TF": "\u0424\u0440\u0430\u043d\u0446\u0443\u0437\u044c\u043a\u0456 \u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0456 \u0422\u0435\u0440\u0438\u0442\u043e\u0440\u0456\u0457", "HR": "\u0425\u043e\u0440\u0432\u0430\u0442\u0456\u044f", "CF": "\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0430\u0444\u0440\u0438\u043a\u0430\u043d\u0441\u044c\u043a\u0430 \u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0456\u043a\u0430", "TD": "\u0427\u0430\u0434", "CZ": "\u0427\u0435\u0445\u0456\u044f", "CL": "\u0427\u0456\u043b\u0456", "ME": "\u0427\u043e\u0440\u043d\u043e\u0433\u043e\u0440\u0456\u044f", "CH": "\u0428\u0432\u0435\u0439\u0446\u0430\u0440\u0456\u044f", "SE": "\u0428\u0432\u0435\u0446\u0456\u044f", "SJ": "\u0428\u043f\u0456\u0446\u0431\u0435\u0440\u0433\u0435\u043d \u0442\u0430 \u042f\u043d-\u041c\u0430\u0454\u043d", "LK": "\u0428\u0440\u0456-\u041b\u0430\u043d\u043a\u0430", "JM": "\u042f\u043c\u0430\u0439\u043a\u0430", "JP": "\u042f\u043f\u043e\u043d\u0456\u044f"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/countries/zh_Hans.json b/desktop/onionshare/resources/countries/zh_Hans.json
new file mode 100644
index 00000000..88aa0997
--- /dev/null
+++ b/desktop/onionshare/resources/countries/zh_Hans.json
@@ -0,0 +1 @@
+{"AL": "\u963f\u5c14\u5df4\u5c3c\u4e9a", "DZ": "\u963f\u5c14\u53ca\u5229\u4e9a", "AF": "\u963f\u5bcc\u6c57", "AR": "\u963f\u6839\u5ef7", "AE": "\u963f\u62c9\u4f2f\u8054\u5408\u914b\u957f\u56fd", "AW": "\u963f\u9c81\u5df4", "OM": "\u963f\u66fc", "AZ": "\u963f\u585e\u62dc\u7586", "EG": "\u57c3\u53ca", "ET": "\u57c3\u585e\u4fc4\u6bd4\u4e9a", "IE": "\u7231\u5c14\u5170", "EE": "\u7231\u6c99\u5c3c\u4e9a", "AD": "\u5b89\u9053\u5c14", "AO": "\u5b89\u54e5\u62c9", "AI": "\u5b89\u572d\u62c9", "AG": "\u5b89\u63d0\u74dc\u548c\u5df4\u5e03\u8fbe", "AT": "\u5965\u5730\u5229", "AX": "\u5965\u5170\u7fa4\u5c9b", "AU": "\u6fb3\u5927\u5229\u4e9a", "BB": "\u5df4\u5df4\u591a\u65af", "PG": "\u5df4\u5e03\u4e9a\u65b0\u51e0\u5185\u4e9a", "BS": "\u5df4\u54c8\u9a6c", "PK": "\u5df4\u57fa\u65af\u5766", "PY": "\u5df4\u62c9\u572d", "BH": "\u5df4\u6797", "PA": "\u5df4\u62ff\u9a6c", "BR": "\u5df4\u897f", "BY": "\u767d\u4fc4\u7f57\u65af", "BM": "\u767e\u6155\u5927", "BG": "\u4fdd\u52a0\u5229\u4e9a", "MK": "\u5317\u9a6c\u5176\u987f", "BJ": "\u8d1d\u5b81", "BE": "\u6bd4\u5229\u65f6", "IS": "\u51b0\u5c9b", "PR": "\u6ce2\u591a\u9ece\u5404", "PL": "\u6ce2\u5170", "BA": "\u6ce2\u65af\u5c3c\u4e9a\u548c\u9ed1\u585e\u54e5\u7ef4\u90a3", "BO": "\u73bb\u5229\u7ef4\u4e9a", "BZ": "\u4f2f\u5229\u5179", "BW": "\u535a\u8328\u74e6\u7eb3", "BT": "\u4e0d\u4e39", "BF": "\u5e03\u57fa\u7eb3\u6cd5\u7d22", "BI": "\u5e03\u9686\u8fea", "BV": "\u5e03\u97e6\u5c9b", "KP": "\u671d\u9c9c", "GQ": "\u8d64\u9053\u51e0\u5185\u4e9a", "DK": "\u4e39\u9ea6", "DE": "\u5fb7\u56fd", "TL": "\u4e1c\u5e1d\u6c76", "TG": "\u591a\u54e5", "DO": "\u591a\u7c73\u5c3c\u52a0\u5171\u548c\u56fd", "DM": "\u591a\u7c73\u5c3c\u514b", "RU": "\u4fc4\u7f57\u65af", "EC": "\u5384\u74dc\u591a\u5c14", "ER": "\u5384\u7acb\u7279\u91cc\u4e9a", "FR": "\u6cd5\u56fd", "FO": "\u6cd5\u7f57\u7fa4\u5c9b", "PF": "\u6cd5\u5c5e\u6ce2\u5229\u5c3c\u897f\u4e9a", "GF": "\u6cd5\u5c5e\u572d\u4e9a\u90a3", "TF": "\u6cd5\u5c5e\u5357\u90e8\u9886\u5730", "MF": "\u6cd5\u5c5e\u5723\u9a6c\u4e01", "VA": "\u68b5\u8482\u5188", "PH": "\u83f2\u5f8b\u5bbe", "FJ": "\u6590\u6d4e", "FI": "\u82ac\u5170", "CV": "\u4f5b\u5f97\u89d2", "FK": "\u798f\u514b\u5170\u7fa4\u5c9b", "GM": "\u5188\u6bd4\u4e9a", "CG": "\u521a\u679c\uff08\u5e03\uff09", "CD": "\u521a\u679c\uff08\u91d1\uff09", "CO": "\u54e5\u4f26\u6bd4\u4e9a", "CR": "\u54e5\u65af\u8fbe\u9ece\u52a0", "GD": "\u683c\u6797\u7eb3\u8fbe", "GL": "\u683c\u9675\u5170", "GE": "\u683c\u9c81\u5409\u4e9a", "GG": "\u6839\u897f\u5c9b", "CU": "\u53e4\u5df4", "GP": "\u74dc\u5fb7\u7f57\u666e", "GU": "\u5173\u5c9b", "GY": "\u572d\u4e9a\u90a3", "KZ": "\u54c8\u8428\u514b\u65af\u5766", "HT": "\u6d77\u5730", "KR": "\u97e9\u56fd", "NL": "\u8377\u5170", "BQ": "\u8377\u5c5e\u52a0\u52d2\u6bd4\u533a", "SX": "\u8377\u5c5e\u5723\u9a6c\u4e01", "HM": "\u8d6b\u5fb7\u5c9b\u548c\u9ea6\u514b\u5510\u7eb3\u7fa4\u5c9b", "ME": "\u9ed1\u5c71", "HN": "\u6d2a\u90fd\u62c9\u65af", "KI": "\u57fa\u91cc\u5df4\u65af", "DJ": "\u5409\u5e03\u63d0", "KG": "\u5409\u5c14\u5409\u65af\u65af\u5766", "GN": "\u51e0\u5185\u4e9a", "GW": "\u51e0\u5185\u4e9a\u6bd4\u7ecd", "CA": "\u52a0\u62ff\u5927", "GH": "\u52a0\u7eb3", "GA": "\u52a0\u84ec", "KH": "\u67ec\u57d4\u5be8", "CZ": "\u6377\u514b", "ZW": "\u6d25\u5df4\u5e03\u97e6", "CM": "\u5580\u9ea6\u9686", "QA": "\u5361\u5854\u5c14", "KY": "\u5f00\u66fc\u7fa4\u5c9b", "CC": "\u79d1\u79d1\u65af\uff08\u57fa\u6797\uff09\u7fa4\u5c9b", "KM": "\u79d1\u6469\u7f57", "CI": "\u79d1\u7279\u8fea\u74e6", "KW": "\u79d1\u5a01\u7279", "HR": "\u514b\u7f57\u5730\u4e9a", "KE": "\u80af\u5c3c\u4e9a", "CK": "\u5e93\u514b\u7fa4\u5c9b", "CW": "\u5e93\u62c9\u7d22", "LV": "\u62c9\u8131\u7ef4\u4e9a", "LS": "\u83b1\u7d22\u6258", "LA": "\u8001\u631d", "LB": "\u9ece\u5df4\u5ae9", "LT": "\u7acb\u9676\u5b9b", "LR": "\u5229\u6bd4\u91cc\u4e9a", "LY": "\u5229\u6bd4\u4e9a", "LI": "\u5217\u652f\u6566\u58eb\u767b", "RE": "\u7559\u5c3c\u6c6a", "LU": "\u5362\u68ee\u5821", "RW": "\u5362\u65fa\u8fbe", "RO": "\u7f57\u9a6c\u5c3c\u4e9a", "MG": "\u9a6c\u8fbe\u52a0\u65af\u52a0", "IM": "\u9a6c\u6069\u5c9b", "MV": "\u9a6c\u5c14\u4ee3\u592b", "MT": "\u9a6c\u8033\u4ed6", "MW": "\u9a6c\u62c9\u7ef4", "MY": "\u9a6c\u6765\u897f\u4e9a", "ML": "\u9a6c\u91cc", "MQ": "\u9a6c\u63d0\u5c3c\u514b", "YT": "\u9a6c\u7ea6\u7279", "MU": "\u6bdb\u91cc\u6c42\u65af", "MR": "\u6bdb\u91cc\u5854\u5c3c\u4e9a", "US": "\u7f8e\u56fd", "AS": "\u7f8e\u5c5e\u8428\u6469\u4e9a", "VI": "\u7f8e\u5c5e\u7ef4\u5c14\u4eac\u7fa4\u5c9b", "MN": "\u8499\u53e4", "MS": "\u8499\u7279\u585e\u62c9\u7279", "BD": "\u5b5f\u52a0\u62c9\u56fd", "PE": "\u79d8\u9c81", "MM": "\u7f05\u7538", "MD": "\u6469\u5c14\u591a\u74e6", "MA": "\u6469\u6d1b\u54e5", "MC": "\u6469\u7eb3\u54e5", "MZ": "\u83ab\u6851\u6bd4\u514b", "MX": "\u58a8\u897f\u54e5", "NA": "\u7eb3\u7c73\u6bd4\u4e9a", "ZA": "\u5357\u975e", "AQ": "\u5357\u6781\u6d32", "GS": "\u5357\u4e54\u6cbb\u4e9a\u548c\u5357\u6851\u5a01\u5947\u7fa4\u5c9b", "SS": "\u5357\u82cf\u4e39", "NR": "\u7459\u9c81", "NI": "\u5c3c\u52a0\u62c9\u74dc", "NP": "\u5c3c\u6cca\u5c14", "NE": "\u5c3c\u65e5\u5c14", "NG": "\u5c3c\u65e5\u5229\u4e9a", "NU": "\u7ebd\u57c3", "NO": "\u632a\u5a01", "NF": "\u8bfa\u798f\u514b\u5c9b", "PW": "\u5e15\u52b3", "PN": "\u76ae\u7279\u51ef\u6069\u7fa4\u5c9b", "PT": "\u8461\u8404\u7259", "JP": "\u65e5\u672c", "SE": "\u745e\u5178", "CH": "\u745e\u58eb", "SV": "\u8428\u5c14\u74e6\u591a", "WS": "\u8428\u6469\u4e9a", "RS": "\u585e\u5c14\u7ef4\u4e9a", "SL": "\u585e\u62c9\u5229\u6602", "SN": "\u585e\u5185\u52a0\u5c14", "CY": "\u585e\u6d66\u8def\u65af", "SC": "\u585e\u820c\u5c14", "SA": "\u6c99\u7279\u963f\u62c9\u4f2f", "BL": "\u5723\u5df4\u6cf0\u52d2\u7c73", "CX": "\u5723\u8bde\u5c9b", "ST": "\u5723\u591a\u7f8e\u548c\u666e\u6797\u897f\u6bd4", "SH": "\u5723\u8d6b\u52d2\u62ff", "KN": "\u5723\u57fa\u8328\u548c\u5c3c\u7ef4\u65af", "LC": "\u5723\u5362\u897f\u4e9a", "SM": "\u5723\u9a6c\u529b\u8bfa", "PM": "\u5723\u76ae\u57c3\u5c14\u548c\u5bc6\u514b\u9686\u7fa4\u5c9b", "VC": "\u5723\u6587\u68ee\u7279\u548c\u683c\u6797\u7eb3\u4e01\u65af", "LK": "\u65af\u91cc\u5170\u5361", "SK": "\u65af\u6d1b\u4f10\u514b", "SI": "\u65af\u6d1b\u6587\u5c3c\u4e9a", "SJ": "\u65af\u74e6\u5c14\u5df4\u548c\u626c\u9a6c\u5ef6", "SZ": "\u65af\u5a01\u58eb\u5170", "SD": "\u82cf\u4e39", "SR": "\u82cf\u91cc\u5357", "SB": "\u6240\u7f57\u95e8\u7fa4\u5c9b", "SO": "\u7d22\u9a6c\u91cc", "TJ": "\u5854\u5409\u514b\u65af\u5766", "TW": "\u53f0\u6e7e", "TH": "\u6cf0\u56fd", "TZ": "\u5766\u6851\u5c3c\u4e9a", "TO": "\u6c64\u52a0", "TC": "\u7279\u514b\u65af\u548c\u51ef\u79d1\u65af\u7fa4\u5c9b", "TT": "\u7279\u7acb\u5c3c\u8fbe\u548c\u591a\u5df4\u54e5", "TN": "\u7a81\u5c3c\u65af", "TR": "\u571f\u8033\u5176", "TM": "\u571f\u5e93\u66fc\u65af\u5766", "TK": "\u6258\u514b\u52b3", "WF": "\u74e6\u5229\u65af\u548c\u5bcc\u56fe\u7eb3", "VU": "\u74e6\u52aa\u963f\u56fe", "GT": "\u5371\u5730\u9a6c\u62c9", "VE": "\u59d4\u5185\u745e\u62c9", "BN": "\u6587\u83b1", "UG": "\u4e4c\u5e72\u8fbe", "UA": "\u4e4c\u514b\u5170", "UY": "\u4e4c\u62c9\u572d", "UZ": "\u4e4c\u5179\u522b\u514b\u65af\u5766", "ES": "\u897f\u73ed\u7259", "EH": "\u897f\u6492\u54c8\u62c9", "GR": "\u5e0c\u814a", "SG": "\u65b0\u52a0\u5761", "NC": "\u65b0\u5580\u91cc\u591a\u5c3c\u4e9a", "NZ": "\u65b0\u897f\u5170", "HU": "\u5308\u7259\u5229", "SY": "\u53d9\u5229\u4e9a", "JM": "\u7259\u4e70\u52a0", "AM": "\u4e9a\u7f8e\u5c3c\u4e9a", "YE": "\u4e5f\u95e8", "IQ": "\u4f0a\u62c9\u514b", "IR": "\u4f0a\u6717", "IL": "\u4ee5\u8272\u5217", "IT": "\u610f\u5927\u5229", "IN": "\u5370\u5ea6", "ID": "\u5370\u5ea6\u5c3c\u897f\u4e9a", "GB": "\u82f1\u56fd", "VG": "\u82f1\u5c5e\u7ef4\u5c14\u4eac\u7fa4\u5c9b", "IO": "\u82f1\u5c5e\u5370\u5ea6\u6d0b\u9886\u5730", "JO": "\u7ea6\u65e6", "VN": "\u8d8a\u5357", "ZM": "\u8d5e\u6bd4\u4e9a", "TD": "\u4e4d\u5f97", "GI": "\u76f4\u5e03\u7f57\u9640", "CL": "\u667a\u5229", "CF": "\u4e2d\u975e\u5171\u548c\u56fd", "CN": "\u4e2d\u56fd", "MO": "\u4e2d\u56fd\u6fb3\u95e8\u7279\u522b\u884c\u653f\u533a", "HK": "\u4e2d\u56fd\u9999\u6e2f\u7279\u522b\u884c\u653f\u533a"} \ No newline at end of file
diff --git a/desktop/onionshare/resources/images/dark_logo_text_bg.png b/desktop/onionshare/resources/images/dark_logo_text_bg.png
new file mode 100644
index 00000000..065443b2
--- /dev/null
+++ b/desktop/onionshare/resources/images/dark_logo_text_bg.png
Binary files differ
diff --git a/desktop/onionshare/resources/images/light_logo_text_bg.png b/desktop/onionshare/resources/images/light_logo_text_bg.png
new file mode 100644
index 00000000..72156b50
--- /dev/null
+++ b/desktop/onionshare/resources/images/light_logo_text_bg.png
Binary files differ
diff --git a/desktop/onionshare/resources/images/tor-connect-ship.png b/desktop/onionshare/resources/images/tor-connect-ship.png
new file mode 100644
index 00000000..9dfeddb1
--- /dev/null
+++ b/desktop/onionshare/resources/images/tor-connect-ship.png
Binary files differ
diff --git a/desktop/onionshare/resources/images/tor-connect-smoke.png b/desktop/onionshare/resources/images/tor-connect-smoke.png
new file mode 100644
index 00000000..c0cab360
--- /dev/null
+++ b/desktop/onionshare/resources/images/tor-connect-smoke.png
Binary files differ
diff --git a/desktop/onionshare/resources/images/tor-connect-stars.png b/desktop/onionshare/resources/images/tor-connect-stars.png
new file mode 100644
index 00000000..c5c82cb7
--- /dev/null
+++ b/desktop/onionshare/resources/images/tor-connect-stars.png
Binary files differ
diff --git a/desktop/onionshare/resources/locale/en.json b/desktop/onionshare/resources/locale/en.json
index f8c4cd2b..e90547f7 100644
--- a/desktop/onionshare/resources/locale/en.json
+++ b/desktop/onionshare/resources/locale/en.json
@@ -10,7 +10,7 @@
"gui_add_files": "Add Files",
"gui_add_folder": "Add Folder",
"gui_remove": "Remove",
- "gui_dragdrop_sandbox_flatpak": "To make the Flatpak sandbox more secure, drag and drop is not supported. Use the Add Files and Add Folder buttons to browse for files instead.",
+ "gui_dragdrop_sandbox_flatpak": "To make the Flatpak sandbox more secure, drag and drop is not supported. Use the \"Add Files\" and \"Add Folder\" buttons to select files instead.",
"gui_file_selection_remove_all": "Remove All",
"gui_choose_items": "Choose",
"gui_share_start_server": "Start sharing",
@@ -27,9 +27,9 @@
"gui_copy_url": "Copy Address",
"gui_copy_client_auth": "Copy Private Key",
"gui_canceled": "Canceled",
- "gui_copied_url_title": "Copied OnionShare Address",
+ "gui_copied_url_title": "OnionShare Address Copied",
"gui_copied_url": "OnionShare address copied to clipboard",
- "gui_copied_client_auth_title": "Copied Private Key",
+ "gui_copied_client_auth_title": "Private Key Copied",
"gui_copied_client_auth": "Private Key copied to clipboard",
"gui_show_qr_code": "Show QR Code",
"gui_qr_code_dialog_title": "OnionShare QR Code",
@@ -42,7 +42,25 @@
"gui_please_wait": "Starting… Click to cancel.",
"zip_progress_bar_format": "Compressing: %p%",
"gui_tor_settings_window_title": "Tor Settings",
+ "gui_autoconnect_description": "OnionShare relies on the Tor Network, run by thousands of volunteers around the world.",
+ "gui_enable_autoconnect_checkbox": "Connect to Tor automatically",
+ "gui_autoconnect_failed_to_connect_to_tor": "Failed to Connect to Tor",
+ "gui_autoconnect_trying_to_connect_to_tor": "Trying to Connect to Tor...",
+ "gui_autoconnect_bridge_description": "Are you connected to the internet?<br><br>It's also possible that your internet is being censored. You might be able to bypass this using a bridge.",
+ "gui_autoconnect_bridge_detect_automatic": "Automatically determine my country from my IP address",
+ "gui_autoconnect_bridge_detect_manual": "Manually select my country",
+ "gui_autoconnect_start": "Connect to Tor",
+ "gui_autoconnect_configure": "Network Settings",
+ "gui_autoconnect_bridge_start": "Use a Bridge",
+ "gui_autoconnect_try_again_without_a_bridge": "Try again without a Bridge",
+ "gui_autoconnect_circumventing_censorship": "Trying to resolve connectivity issues",
+ "gui_autoconnect_circumventing_censorship_starting_circumvention": "Starting censorship circumvention process",
+ "gui_autoconnect_circumventing_censorship_starting_meek": "Starting Meek for domain-fronting",
+ "gui_autoconnect_circumventing_censorship_requesting_bridges": "Requesting bridges from the Tor Censorship Circumvention API",
+ "gui_autoconnect_circumventing_censorship_got_bridges": "Got bridges! Trying to reconnect to Tor",
+ "gui_autoconnect_could_not_connect_to_tor_api": "Could not connect to the Tor API. Make sure you are connected to the internet before trying again.",
"gui_settings_window_title": "Settings",
+ "gui_general_settings_window_title": "General",
"gui_settings_autoupdate_label": "Check for new version",
"gui_settings_autoupdate_option": "Notify me when a new version is available",
"gui_settings_autoupdate_timestamp": "Last checked: {}",
@@ -62,7 +80,7 @@
"gui_settings_authenticate_password_option": "Password",
"gui_settings_password_label": "Password",
"gui_settings_tor_bridges": "Connect using a Tor bridge?",
- "gui_settings_tor_bridges_label": "Bridges help you access the Tor Network in places where Tor is blocked. Depending on where you are, one bridge may work better than another.",
+ "gui_settings_tor_bridges_label": "Bridges helps your traffic enter the Tor Network where Tor access is blocked. Depending on where you are, one bridge may work better than another.",
"gui_settings_bridge_use_checkbox": "Use a bridge",
"gui_settings_bridge_radio_builtin": "Select a built-in bridge",
"gui_settings_bridge_none_radio_option": "Don't use a bridge",
@@ -131,14 +149,14 @@
"history_requests_tooltip": "{} web requests",
"error_cannot_create_data_dir": "Could not create OnionShare data folder: {}",
"gui_receive_mode_warning": "Receive mode lets people upload files to your computer.<br><br><b>Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing.</b>",
- "gui_open_folder_error": "Failed to open folder with xdg-open. The file is here: {}",
+ "gui_open_folder_error": "Could not open the folder with xdg-open. The file is here: {}",
"gui_settings_language_label": "Language",
"gui_settings_theme_label": "Theme",
"gui_settings_theme_auto": "Auto",
"gui_settings_theme_light": "Light",
"gui_settings_theme_dark": "Dark",
- "gui_settings_language_changed_notice": "Restart OnionShare for the new language to be applied.",
- "gui_color_mode_changed_notice": "Restart OnionShare for the new color mode to be applied.",
+ "gui_settings_language_changed_notice": "Restart OnionShare to change to the new language.",
+ "gui_color_mode_changed_notice": "Restart OnionShare to see the new colors.",
"systray_menu_exit": "Quit",
"systray_page_loaded_title": "Page Loaded",
"systray_page_loaded_message": "OnionShare address loaded",
@@ -157,10 +175,10 @@
"gui_all_modes_progress_starting": "{0:s}, %p% (calculating)",
"gui_all_modes_progress_eta": "{0:s}, ETA: {1:s}, %p%",
"gui_share_mode_no_files": "No Files Sent Yet",
- "gui_share_mode_autostop_timer_waiting": "Waiting to finish sending",
+ "gui_share_mode_autostop_timer_waiting": "Finishing sending…",
"gui_website_mode_no_files": "No Website Shared Yet",
"gui_receive_mode_no_files": "No Files Received Yet",
- "gui_receive_mode_autostop_timer_waiting": "Waiting to finish receiving",
+ "gui_receive_mode_autostop_timer_waiting": "Finishing receiving…",
"days_first_letter": "d",
"hours_first_letter": "h",
"minutes_first_letter": "m",
@@ -180,14 +198,14 @@
"gui_tab_name_website": "Website",
"gui_tab_name_chat": "Chat",
"gui_close_tab_warning_title": "Are you sure?",
- "gui_close_tab_warning_persistent_description": "This tab is persistent. If you close it you'll lose the onion address that it's using. Are you sure you want to close it?",
- "gui_close_tab_warning_share_description": "You're in the process of sending files. Are you sure you want to close this tab?",
- "gui_close_tab_warning_receive_description": "You're in the process of receiving files. Are you sure you want to close this tab?",
- "gui_close_tab_warning_website_description": "You're actively hosting a website. Are you sure you want to close this tab?",
+ "gui_close_tab_warning_persistent_description": "Close persistent tab and lose the onion address it is using?",
+ "gui_close_tab_warning_share_description": "Close tab that is sending files?",
+ "gui_close_tab_warning_receive_description": "Close tab that is receiving files?",
+ "gui_close_tab_warning_website_description": "Close tab that is hosting a website?",
"gui_close_tab_warning_close": "Close",
"gui_close_tab_warning_cancel": "Cancel",
"gui_quit_warning_title": "Are you sure?",
- "gui_quit_warning_description": "Sharing is active in some of your tabs. If you quit, all of your tabs will close. Are you sure you want to quit?",
+ "gui_quit_warning_description": "Quit and close all tabs, even though sharing is active in some of them?",
"gui_quit_warning_quit": "Quit",
"gui_quit_warning_cancel": "Cancel",
"mode_settings_advanced_toggle_show": "Show advanced settings",
@@ -219,18 +237,18 @@
"settings_error_bundled_tor_not_supported": "Using the Tor version that comes with OnionShare does not work in developer mode on Windows or macOS.",
"settings_error_bundled_tor_timeout": "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?",
"settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}",
- "gui_rendezvous_cleanup": "Waiting for Tor circuits to close to be sure your files have successfully transferred.\n\nThis might take a few minutes.",
+ "gui_rendezvous_cleanup": "Waiting for Tor circuits to close to be sure your files have transferred.\n\nThis might take a few minutes.",
"gui_rendezvous_cleanup_quit_early": "Quit Early",
"error_port_not_available": "OnionShare port not available",
"history_receive_read_message_button": "Read Message",
"error_tor_protocol_error": "There was an error with Tor: {}",
- "moat_contact_label": "Contacting BridgeDB...",
+ "moat_contact_label": "Contacting BridgeDB…",
"moat_captcha_label": "Solve the CAPTCHA to request a bridge.",
"moat_captcha_placeholder": "Enter the characters from the image",
"moat_captcha_submit": "Submit",
"moat_captcha_reload": "Reload",
- "moat_bridgedb_error": "Error contacting BridgeDB.",
- "moat_captcha_error": "The solution is not correct. Please try again.",
- "moat_solution_empty_error": "You must enter the characters from the image",
+ "moat_bridgedb_error": "Could not contact BridgeDB.",
+ "moat_captcha_error": "Incorrect solution. Please try again.",
+ "moat_solution_empty_error": "Enter the characters from the image",
"mode_tor_not_connected_label": "OnionShare is not connected to the Tor network"
-}
+} \ No newline at end of file
diff --git a/desktop/onionshare/settings_parent_tab.py b/desktop/onionshare/settings_parent_tab.py
new file mode 100644
index 00000000..2ade0e05
--- /dev/null
+++ b/desktop/onionshare/settings_parent_tab.py
@@ -0,0 +1,72 @@
+from PySide2 import QtCore, QtWidgets, QtGui
+
+from onionshare_cli.mode_settings import ModeSettings
+
+from . import strings
+from .tab import Tab
+from .threads import EventHandlerThread
+from .gui_common import GuiCommon
+from .tor_settings_tab import TorSettingsTab
+from .settings_tab import SettingsTab
+from .connection_tab import AutoConnectTab
+
+
+class SettingsParentTab(QtWidgets.QTabWidget):
+ """
+ The settings tab widget containing the tor settings
+ and app settings subtabs
+ """
+
+ bring_to_front = QtCore.Signal()
+ close_this_tab = QtCore.Signal()
+
+ def __init__(
+ self, common, tab_id, parent=None, active_tab="general", from_autoconnect=False
+ ):
+ super(SettingsParentTab, self).__init__()
+ self.parent = parent
+ self.common = common
+ self.common.log("SettingsParentTab", "__init__")
+
+ # Keep track of tabs in a dictionary that maps tab_id to tab.
+ # Each tab has a unique, auto-incremented id (tab_id). This is different than the
+ # tab's index, which changes as tabs are re-arranged.
+ self.tabs = {
+ "general": 0,
+ "tor": 1,
+ }
+ self.tab_id = tab_id
+ self.current_tab_id = self.tabs[active_tab]
+
+ # Use a custom tab bar
+ tab_bar = TabBar(self.common)
+ self.setTabBar(tab_bar)
+ settings_tab = SettingsTab(self.common, self.tabs["general"], parent=self)
+ self.tor_settings_tab = TorSettingsTab(
+ self.common,
+ self.tabs["tor"],
+ self.parent.are_tabs_active(),
+ self.parent.status_bar,
+ parent=self,
+ from_autoconnect=from_autoconnect,
+ )
+ self.addTab(settings_tab, strings._("gui_general_settings_window_title"))
+ self.addTab(self.tor_settings_tab, strings._("gui_tor_settings_window_title"))
+
+ # Set up the tab widget
+ self.setMovable(False)
+ self.setTabsClosable(False)
+ self.setUsesScrollButtons(False)
+ self.setCurrentIndex(self.current_tab_id)
+
+
+class TabBar(QtWidgets.QTabBar):
+ """
+ A custom tab bar
+ """
+
+ move_new_tab_button = QtCore.Signal()
+
+ def __init__(self, common):
+ super(TabBar, self).__init__()
+ self.setStyleSheet(common.gui.css["settings_subtab_bar"])
diff --git a/desktop/onionshare/settings_tab.py b/desktop/onionshare/settings_tab.py
index 58843a0d..cf2261b6 100644
--- a/desktop/onionshare/settings_tab.py
+++ b/desktop/onionshare/settings_tab.py
@@ -33,9 +33,7 @@ class SettingsTab(QtWidgets.QWidget):
Settings dialog.
"""
- close_this_tab = QtCore.Signal()
-
- def __init__(self, common, tab_id):
+ def __init__(self, common, tab_id, parent=None):
super(SettingsTab, self).__init__()
self.common = common
@@ -43,6 +41,7 @@ class SettingsTab(QtWidgets.QWidget):
self.system = platform.system()
self.tab_id = tab_id
+ self.parent = parent
# Automatic updates options
@@ -283,7 +282,7 @@ class SettingsTab(QtWidgets.QWidget):
# Save the new settings
settings.save()
- self.close_this_tab.emit()
+ self.parent.close_this_tab.emit()
def help_clicked(self):
"""
diff --git a/desktop/onionshare/tab_widget.py b/desktop/onionshare/tab_widget.py
index 773dbdd5..3c1a1703 100644
--- a/desktop/onionshare/tab_widget.py
+++ b/desktop/onionshare/tab_widget.py
@@ -26,8 +26,8 @@ from . import strings
from .tab import Tab
from .threads import EventHandlerThread
from .gui_common import GuiCommon
-from .tor_settings_tab import TorSettingsTab
-from .settings_tab import SettingsTab
+from .settings_parent_tab import SettingsParentTab
+from .connection_tab import AutoConnectTab
class TabWidget(QtWidgets.QTabWidget):
@@ -37,13 +37,14 @@ class TabWidget(QtWidgets.QTabWidget):
bring_to_front = QtCore.Signal()
- def __init__(self, common, system_tray, status_bar):
+ def __init__(self, common, system_tray, status_bar, window):
super(TabWidget, self).__init__()
self.common = common
self.common.log("TabWidget", "__init__")
self.system_tray = system_tray
self.status_bar = status_bar
+ self.window = window
# Keep track of tabs in a dictionary that maps tab_id to tab.
# Each tab has a unique, auto-incremented id (tab_id). This is different than the
@@ -96,8 +97,8 @@ class TabWidget(QtWidgets.QTabWidget):
# Clean up each tab
for tab_id in self.tabs:
if not (
- type(self.tabs[tab_id]) is SettingsTab
- or type(self.tabs[tab_id]) is TorSettingsTab
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
):
self.tabs[tab_id].cleanup()
@@ -136,8 +137,8 @@ class TabWidget(QtWidgets.QTabWidget):
# If it's Settings or Tor Settings, ignore
if (
- type(self.tabs[tab_id]) is SettingsTab
- or type(self.tabs[tab_id]) is TorSettingsTab
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
):
# Blank the server status indicator
self.status_bar.server_status_image_label.clear()
@@ -159,8 +160,16 @@ class TabWidget(QtWidgets.QTabWidget):
pass
def new_tab_clicked(self):
- # Create a new tab
- self.add_tab()
+ # if already connected to tor or local only, create a new tab
+ # Else open the initial connection tab
+ if self.common.gui.local_only or self.common.gui.onion.is_authenticated():
+ self.add_tab()
+ else:
+ self.open_connection_tab()
+
+ def check_autoconnect_tab(self):
+ if type(self.tabs[0]) is AutoConnectTab:
+ self.tabs[0].check_autoconnect()
def load_tab(self, mode_settings_id):
# Load the tab's mode settings
@@ -198,42 +207,49 @@ class TabWidget(QtWidgets.QTabWidget):
# Bring the window to front, in case this is being added by an event
self.bring_to_front.emit()
- def open_settings_tab(self):
- self.common.log("TabWidget", "open_settings_tab")
+ def open_connection_tab(self):
+ self.common.log("TabWidget", "open_connection_tab")
- # See if a settings tab is already open, and if so switch to it
+ # See if a connection tab is already open, and if so switch to it
for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is SettingsTab:
+ if type(self.tabs[tab_id]) is AutoConnectTab:
self.setCurrentIndex(self.indexOf(self.tabs[tab_id]))
return
- settings_tab = SettingsTab(self.common, self.current_tab_id)
- settings_tab.close_this_tab.connect(self.close_settings_tab)
- self.tabs[self.current_tab_id] = settings_tab
+ connection_tab = AutoConnectTab(
+ self.common, self.current_tab_id, self.status_bar, self.window, parent=self
+ )
+ connection_tab.close_this_tab.connect(self.close_connection_tab)
+ connection_tab.tor_is_connected.connect(self.tor_is_connected)
+ connection_tab.tor_is_disconnected.connect(self.tor_is_disconnected)
+ self.tabs[self.current_tab_id] = connection_tab
self.current_tab_id += 1
- index = self.addTab(settings_tab, strings._("gui_settings_window_title"))
+ index = self.addTab(connection_tab, strings._("gui_autoconnect_start"))
self.setCurrentIndex(index)
- def open_tor_settings_tab(self):
- self.common.log("TabWidget", "open_tor_settings_tab")
+ def open_settings_tab(self, from_autoconnect=False, active_tab="general"):
+ self.common.log("TabWidget", "open_settings_tab")
# See if a settings tab is already open, and if so switch to it
for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is TorSettingsTab:
+ if type(self.tabs[tab_id]) is SettingsParentTab:
self.setCurrentIndex(self.indexOf(self.tabs[tab_id]))
return
- self.tor_settings_tab = TorSettingsTab(
- self.common, self.current_tab_id, self.are_tabs_active(), self.status_bar
+ settings_tab = SettingsParentTab(
+ self.common,
+ self.current_tab_id,
+ active_tab=active_tab,
+ parent=self,
+ from_autoconnect=from_autoconnect,
)
- self.tor_settings_tab.close_this_tab.connect(self.close_tor_settings_tab)
+ settings_tab.close_this_tab.connect(self.close_settings_tab)
+ self.tor_settings_tab = settings_tab.tor_settings_tab
self.tor_settings_tab.tor_is_connected.connect(self.tor_is_connected)
self.tor_settings_tab.tor_is_disconnected.connect(self.tor_is_disconnected)
- self.tabs[self.current_tab_id] = self.tor_settings_tab
+ self.tabs[self.current_tab_id] = settings_tab
self.current_tab_id += 1
- index = self.addTab(
- self.tor_settings_tab, strings._("gui_tor_settings_window_title")
- )
+ index = self.addTab(settings_tab, strings._("gui_settings_window_title"))
self.setCurrentIndex(index)
def change_title(self, tab_id, title):
@@ -279,8 +295,8 @@ class TabWidget(QtWidgets.QTabWidget):
persistent_tabs = []
for tab_id in self.tabs:
if not (
- type(self.tabs[tab_id]) is SettingsTab
- or type(self.tabs[tab_id]) is TorSettingsTab
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
):
tab = self.widget(self.indexOf(self.tabs[tab_id]))
if tab.settings.get("persistent", "enabled"):
@@ -296,12 +312,12 @@ class TabWidget(QtWidgets.QTabWidget):
tab_id = tab.tab_id
if (
- type(self.tabs[tab_id]) is SettingsTab
- or type(self.tabs[tab_id]) is TorSettingsTab
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
):
self.common.log("TabWidget", "closing a settings tab")
- if type(self.tabs[tab_id]) is TorSettingsTab:
+ if type(self.tabs[tab_id]) is SettingsParentTab:
self.tor_settings_tab = None
# Remove the tab
@@ -334,18 +350,41 @@ class TabWidget(QtWidgets.QTabWidget):
else:
self.common.log("TabWidget", "user does not want to close the tab")
- def close_settings_tab(self):
- self.common.log("TabWidget", "close_settings_tab")
+ def close_connection_tab(self):
+ self.common.log("TabWidget", "close_connection_tab")
for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is SettingsTab:
+ if type(self.tabs[tab_id]) is AutoConnectTab:
index = self.indexOf(self.tabs[tab_id])
self.close_tab(index)
return
- def close_tor_settings_tab(self):
- self.common.log("TabWidget", "close_tor_settings_tab")
- for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is TorSettingsTab:
+ def close_settings_tab(self):
+ self.common.log("TabWidget", "close_settings_tab")
+ for tab_id in list(self.tabs):
+ if type(self.tabs[tab_id]) is AutoConnectTab:
+ # If we are being returned to the AutoConnectTab, but
+ # the user has fixed their Tor settings in the TorSettings
+ # tab, *and* they have enabled autoconnect, then
+ # we should close the AutoConnect Tab.
+ if self.common.gui.onion.is_authenticated():
+ self.common.log(
+ "TabWidget",
+ "close_settings_tab",
+ "Tor is connected and we can auto-connect, so closing the tab",
+ )
+ index = self.indexOf(self.tabs[tab_id])
+ self.close_tab(index)
+ else:
+ self.tabs[tab_id].reload_settings()
+ self.common.log(
+ "TabWidget",
+ "close_settings_tab",
+ "Reloading settings in case they changed in the TorSettingsTab. Not auto-connecting",
+ )
+ break
+ # List of indices may have changed due to the above, so we loop over it again as another copy
+ for tab_id in list(self.tabs):
+ if type(self.tabs[tab_id]) is SettingsParentTab:
index = self.indexOf(self.tabs[tab_id])
self.close_tab(index)
return
@@ -356,8 +395,8 @@ class TabWidget(QtWidgets.QTabWidget):
"""
for tab_id in self.tabs:
if not (
- type(self.tabs[tab_id]) is SettingsTab
- or type(self.tabs[tab_id]) is TorSettingsTab
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
):
mode = self.tabs[tab_id].get_mode()
if mode:
@@ -379,23 +418,23 @@ class TabWidget(QtWidgets.QTabWidget):
def tor_is_connected(self):
for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is SettingsTab:
- self.tabs[tab_id].tor_is_connected()
- else:
- if not type(self.tabs[tab_id]) is TorSettingsTab:
- mode = self.tabs[tab_id].get_mode()
- if mode:
- mode.tor_connection_started()
+ if not (
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
+ ):
+ mode = self.tabs[tab_id].get_mode()
+ if mode:
+ mode.tor_connection_started()
def tor_is_disconnected(self):
for tab_id in self.tabs:
- if type(self.tabs[tab_id]) is SettingsTab:
- self.tabs[tab_id].tor_is_disconnected()
- else:
- if not type(self.tabs[tab_id]) is TorSettingsTab:
- mode = self.tabs[tab_id].get_mode()
- if mode:
- mode.tor_connection_stopped()
+ if not (
+ type(self.tabs[tab_id]) is SettingsParentTab
+ or type(self.tabs[tab_id]) is AutoConnectTab
+ ):
+ mode = self.tabs[tab_id].get_mode()
+ if mode:
+ mode.tor_connection_stopped()
class TabBar(QtWidgets.QTabBar):
diff --git a/desktop/onionshare/tor_connection.py b/desktop/onionshare/tor_connection.py
index 30cd1814..839757fd 100644
--- a/desktop/onionshare/tor_connection.py
+++ b/desktop/onionshare/tor_connection.py
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import time
-from PySide2 import QtCore, QtWidgets, QtGui
+from PySide2 import QtCore, QtWidgets
from onionshare_cli.onion import (
BundledTorCanceled,
@@ -39,122 +39,6 @@ from onionshare_cli.onion import (
)
from . import strings
-from .gui_common import GuiCommon
-from .widgets import Alert
-
-
-class TorConnectionDialog(QtWidgets.QProgressDialog):
- """
- Connecting to Tor dialog.
- """
-
- open_tor_settings = QtCore.Signal()
- success = QtCore.Signal()
-
- def __init__(
- self, common, custom_settings=False, testing_settings=False, onion=None
- ):
- super(TorConnectionDialog, self).__init__(None)
-
- self.common = common
- self.testing_settings = testing_settings
-
- if custom_settings:
- self.settings = custom_settings
- else:
- self.settings = self.common.settings
-
- self.common.log("TorConnectionDialog", "__init__")
-
- if self.testing_settings:
- self.title = strings._("gui_settings_connection_type_test_button")
- self.onion = onion
- else:
- self.title = "OnionShare"
- self.onion = self.common.gui.onion
-
- self.setWindowTitle(self.title)
-
- self.setWindowIcon(QtGui.QIcon(GuiCommon.get_resource_path("images/logo.png")))
- self.setModal(True)
- self.setFixedSize(400, 150)
-
- # Label
- self.setLabelText(strings._("connecting_to_tor"))
-
- # Progress bar ticks from 0 to 100
- self.setRange(0, 100)
- # Don't show if connection takes less than 100ms (for non-bundled tor)
- self.setMinimumDuration(100)
-
- # Start displaying the status at 0
- self._tor_status_update(0, "")
-
- def start(self):
- self.common.log("TorConnectionDialog", "start")
-
- t = TorConnectionThread(self.common, self.settings, self)
- t.tor_status_update.connect(self._tor_status_update)
- t.connected_to_tor.connect(self._connected_to_tor)
- t.canceled_connecting_to_tor.connect(self._canceled_connecting_to_tor)
- t.error_connecting_to_tor.connect(self._error_connecting_to_tor)
- t.start()
-
- # The main thread needs to remain active, and checking for Qt events,
- # until the thread is finished. Otherwise it won't be able to handle
- # accepting signals.
- self.active = True
- while self.active:
- time.sleep(0.1)
- self.common.gui.qtapp.processEvents()
-
- def _tor_status_update(self, progress, summary):
- self.setValue(int(progress))
- self.setLabelText(
- f"<strong>{strings._('connecting_to_tor')}</strong><br>{summary}"
- )
-
- def _connected_to_tor(self):
- self.common.log("TorConnectionDialog", "_connected_to_tor")
- self.active = False
- # Close the dialog after connecting
- self.setValue(self.maximum())
- self.success.emit()
-
- def _canceled_connecting_to_tor(self):
- self.common.log("TorConnectionDialog", "_canceled_connecting_to_tor")
- self.active = False
- self.onion.cleanup()
-
- # Cancel connecting to Tor
- QtCore.QTimer.singleShot(1, self.cancel)
-
- def _error_connecting_to_tor(self, msg):
- self.common.log("TorConnectionDialog", "_error_connecting_to_tor")
- self.active = False
-
- if self.testing_settings:
- # If testing, just display the error but don't open settings
- def alert():
- Alert(self.common, msg, QtWidgets.QMessageBox.Warning, title=self.title)
-
- else:
- # If not testing, open settings after displaying the error
- def alert():
- Alert(
- self.common,
- f"{msg}\n\n{strings._('gui_tor_connection_error_settings')}",
- QtWidgets.QMessageBox.Warning,
- title=self.title,
- )
-
- # Open settings
- self.open_tor_settings.emit()
-
- QtCore.QTimer.singleShot(1, alert)
-
- # Cancel connecting to Tor
- QtCore.QTimer.singleShot(1, self.cancel)
class TorConnectionWidget(QtWidgets.QWidget):
@@ -165,6 +49,7 @@ class TorConnectionWidget(QtWidgets.QWidget):
open_tor_settings = QtCore.Signal()
success = QtCore.Signal()
fail = QtCore.Signal(str)
+ update_progress = QtCore.Signal(int)
def __init__(self, common, status_bar):
super(TorConnectionWidget, self).__init__(None)
@@ -186,14 +71,10 @@ class TorConnectionWidget(QtWidgets.QWidget):
progress_layout.addWidget(self.progress)
progress_layout.addWidget(self.cancel_button)
- inner_layout = QtWidgets.QVBoxLayout()
- inner_layout.addWidget(self.label)
- inner_layout.addLayout(progress_layout)
+ layout = QtWidgets.QVBoxLayout()
+ layout.addWidget(self.label)
+ layout.addLayout(progress_layout)
- layout = QtWidgets.QHBoxLayout()
- layout.addStretch()
- layout.addLayout(inner_layout)
- layout.addStretch()
self.setLayout(layout)
# Start displaying the status at 0
@@ -233,12 +114,14 @@ class TorConnectionWidget(QtWidgets.QWidget):
def cancel_clicked(self):
self.was_canceled = True
self.fail.emit("")
+ self._reset()
def wasCanceled(self):
return self.was_canceled
def _tor_status_update(self, progress, summary):
self.progress.setValue(int(progress))
+ self.update_progress.emit(int(progress))
self.label.setText(
f"<strong>{strings._('connecting_to_tor')}</strong><br>{summary}"
)
@@ -250,8 +133,10 @@ class TorConnectionWidget(QtWidgets.QWidget):
# Close the dialog after connecting
self.progress.setValue(self.progress.maximum())
+ self.update_progress.emit(int(self.progress.maximum()))
self.success.emit()
+ self._reset()
def _canceled_connecting_to_tor(self):
self.common.log("TorConnectionWidget", "_canceled_connecting_to_tor")
@@ -260,11 +145,18 @@ class TorConnectionWidget(QtWidgets.QWidget):
# Cancel connecting to Tor
QtCore.QTimer.singleShot(1, self.cancel_clicked)
+ self._reset()
def _error_connecting_to_tor(self, msg):
self.common.log("TorConnectionWidget", "_error_connecting_to_tor")
self.active = False
self.fail.emit(msg)
+ self._reset()
+
+ def _reset(self):
+ self.label.setText("")
+ self.progress.setValue(0)
+ self.update_progress.emit(0)
class TorConnectionThread(QtCore.QThread):
diff --git a/desktop/onionshare/tor_settings_tab.py b/desktop/onionshare/tor_settings_tab.py
index 089cf1fe..0e72c3b8 100644
--- a/desktop/onionshare/tor_settings_tab.py
+++ b/desktop/onionshare/tor_settings_tab.py
@@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from PySide2 import QtCore, QtWidgets, QtGui
import sys
import platform
-import re
import os
from onionshare_cli.meek import Meek
@@ -43,7 +42,15 @@ class TorSettingsTab(QtWidgets.QWidget):
tor_is_connected = QtCore.Signal()
tor_is_disconnected = QtCore.Signal()
- def __init__(self, common, tab_id, are_tabs_active, status_bar):
+ def __init__(
+ self,
+ common,
+ tab_id,
+ are_tabs_active,
+ status_bar,
+ from_autoconnect=False,
+ parent=None,
+ ):
super(TorSettingsTab, self).__init__()
self.common = common
@@ -54,6 +61,8 @@ class TorSettingsTab(QtWidgets.QWidget):
self.system = platform.system()
self.tab_id = tab_id
+ self.parent = parent
+ self.from_autoconnect = from_autoconnect
# Connection type: either automatic, control port, or socket file
@@ -303,6 +312,21 @@ class TorSettingsTab(QtWidgets.QWidget):
)
connection_type_radio_group.setLayout(connection_type_radio_group_layout)
+ # Quickstart settings
+ self.autoconnect_checkbox = QtWidgets.QCheckBox(
+ strings._("gui_enable_autoconnect_checkbox")
+ )
+ self.autoconnect_checkbox.toggled.connect(self.autoconnect_toggled)
+ left_column_settings = QtWidgets.QVBoxLayout()
+ connection_type_radio_group.setFixedHeight(300)
+ left_column_settings.addWidget(connection_type_radio_group)
+ left_column_settings.addSpacing(20)
+ left_column_settings.addWidget(self.autoconnect_checkbox)
+ left_column_settings.addStretch()
+ left_column_settings.setContentsMargins(0, 0, 0, 0)
+ left_column_setting_widget = QtWidgets.QWidget()
+ left_column_setting_widget.setLayout(left_column_settings)
+
# The Bridges options are not exclusive (enabling Bridges offers obfs4 or custom bridges)
connection_type_bridges_radio_group_layout = QtWidgets.QVBoxLayout()
connection_type_bridges_radio_group_layout.addWidget(self.bridges)
@@ -322,7 +346,7 @@ class TorSettingsTab(QtWidgets.QWidget):
# Settings are in columns
columns_layout = QtWidgets.QHBoxLayout()
- columns_layout.addWidget(connection_type_radio_group)
+ columns_layout.addWidget(left_column_setting_widget)
columns_layout.addSpacing(20)
columns_layout.addLayout(connection_type_layout, stretch=1)
columns_wrapper = QtWidgets.QWidget()
@@ -391,6 +415,10 @@ class TorSettingsTab(QtWidgets.QWidget):
self.old_settings = Settings(self.common)
self.old_settings.load()
+ # Check if autoconnect was enabled
+ if self.old_settings.get("auto_connect"):
+ self.autoconnect_checkbox.setCheckState(QtCore.Qt.Checked)
+
connection_type = self.old_settings.get("connection_type")
if connection_type == "bundled":
if self.connection_type_bundled_radio.isEnabled():
@@ -477,6 +505,12 @@ class TorSettingsTab(QtWidgets.QWidget):
self.bridge_use_checkbox.setCheckState(QtCore.Qt.Unchecked)
self.bridge_settings.hide()
+ def autoconnect_toggled(self):
+ """
+ Auto connect checkbox clicked
+ """
+ self.common.log("TorSettingsTab", "autoconnect_checkbox_clicked")
+
def active_tabs_changed(self, are_tabs_active):
if are_tabs_active:
self.main_widget.hide()
@@ -664,7 +698,9 @@ class TorSettingsTab(QtWidgets.QWidget):
# If Tor isn't connected, or if Tor settings have changed, Reinitialize
# the Onion object
reboot_onion = False
- if not self.common.gui.local_only:
+ if not self.common.gui.local_only and not (
+ self.from_autoconnect and not settings.get("auto_connect")
+ ):
if self.common.gui.onion.is_authenticated():
self.common.log(
"TorSettingsTab", "save_clicked", "Connected to Tor"
@@ -717,9 +753,9 @@ class TorSettingsTab(QtWidgets.QWidget):
self.tor_con.show()
self.tor_con.start(settings)
else:
- self.close_this_tab.emit()
+ self.parent.close_this_tab.emit()
else:
- self.close_this_tab.emit()
+ self.parent.close_this_tab.emit()
def tor_con_success(self):
"""
@@ -750,7 +786,7 @@ class TorSettingsTab(QtWidgets.QWidget):
# Tell the tabs that Tor is connected
self.tor_is_connected.emit()
# Close the tab
- self.close_this_tab.emit()
+ self.parent.close_this_tab.emit()
self.tor_con_type = None
@@ -777,6 +813,9 @@ class TorSettingsTab(QtWidgets.QWidget):
settings = Settings(self.common)
settings.load() # To get the last update timestamp
+ # autoconnect
+ settings.set("auto_connect", self.autoconnect_checkbox.isChecked())
+
# Tor connection
if self.connection_type_bundled_radio.isChecked():
settings.set("connection_type", "bundled")
@@ -835,35 +874,10 @@ class TorSettingsTab(QtWidgets.QWidget):
if self.bridge_custom_radio.isChecked():
settings.set("bridges_type", "custom")
- new_bridges = []
bridges = self.bridge_custom_textbox.toPlainText().split("\n")
- bridges_valid = False
- for bridge in bridges:
- if bridge != "":
- # Check the syntax of the custom bridge to make sure it looks legitimate
- ipv4_pattern = re.compile(
- "(obfs4\s+)?(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):([0-9]+)(\s+)([A-Z0-9]+)(.+)$"
- )
- ipv6_pattern = re.compile(
- "(obfs4\s+)?\[(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\]:[0-9]+\s+[A-Z0-9]+(.+)$"
- )
- meek_lite_pattern = re.compile(
- "(meek_lite)(\s)+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)(\s)+([0-9A-Z]+)(\s)+url=(.+)(\s)+front=(.+)"
- )
- snowflake_pattern = re.compile(
- "(snowflake)(\s)+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)(\s)+([0-9A-Z]+)"
- )
- if (
- ipv4_pattern.match(bridge)
- or ipv6_pattern.match(bridge)
- or meek_lite_pattern.match(bridge)
- or snowflake_pattern.match(bridge)
- ):
- new_bridges.append(bridge)
- bridges_valid = True
-
+ bridges_valid = self.common.check_bridges_valid(bridges)
if bridges_valid:
- new_bridges = "\n".join(new_bridges) + "\n"
+ new_bridges = "\n".join(bridges_valid) + "\n"
settings.set("bridges_custom", new_bridges)
else:
self.error_label.setText(
diff --git a/desktop/scripts/countries-update-list.py b/desktop/scripts/countries-update-list.py
new file mode 100755
index 00000000..248e0f30
--- /dev/null
+++ b/desktop/scripts/countries-update-list.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+import os
+import tempfile
+import subprocess
+import json
+
+import onionshare_cli
+
+
+def main():
+ # Clone the country-list repo
+ tmp_dir = tempfile.TemporaryDirectory()
+ subprocess.run(
+ ["git", "clone", "https://github.com/umpirsky/country-list.git"],
+ cwd=tmp_dir.name,
+ )
+ repo_dir = os.path.join(tmp_dir.name, "country-list")
+
+ # Get the list of enabled languages
+ common = onionshare_cli.common.Common()
+ settings = onionshare_cli.settings.Settings(common)
+ available_locales = list(settings.available_locales)
+
+ # Make a dictionary that makes a language's ISO 3166-1 to its name in all enabled languages
+ os.makedirs(os.path.join("onionshare", "resources", "countries"), exist_ok=True)
+ for locale in available_locales:
+ with open(os.path.join(repo_dir, "data", locale, "country.json")) as f:
+ countries = json.loads(f.read())
+
+ # Remove countries we don't have images for
+ for key in ["JE", "MH", "FM", "MP", "PS", "TV", "UM"]:
+ del countries[key]
+
+ with open(
+ os.path.join("onionshare", "resources", "countries", f"{locale}.json"),
+ "w",
+ ) as f:
+ f.write(json.dumps(countries))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/desktop/scripts/get-tor-linux.py b/desktop/scripts/get-tor-linux.py
index 2882a591..f7b96b2e 100755
--- a/desktop/scripts/get-tor-linux.py
+++ b/desktop/scripts/get-tor-linux.py
@@ -35,10 +35,10 @@ from bridges import UpdateTorBridges
def main():
- tarball_url = "https://dist.torproject.org/torbrowser/11.0.4/tor-browser-linux64-11.0.4_en-US.tar.xz"
- tarball_filename = "tor-browser-linux64-11.0.4_en-US.tar.xz"
+ tarball_url = "https://dist.torproject.org/torbrowser/11.0.9/tor-browser-linux64-11.0.9_en-US.tar.xz"
+ tarball_filename = "tor-browser-linux64-11.0.9_en-US.tar.xz"
expected_tarball_sha256 = (
- "05a5fd6d633ca84c33bbd3e2f8ffca2d2fa2105032a430b07d3c0cf062d9e15f"
+ "baa5ccafb5c68f1c46f9ae983b9b0a0419f66d41e0483ba5aacb3462fa0a8032"
)
# Build paths
diff --git a/desktop/scripts/get-tor-osx.py b/desktop/scripts/get-tor-osx.py
index b973a90a..95065cf1 100755
--- a/desktop/scripts/get-tor-osx.py
+++ b/desktop/scripts/get-tor-osx.py
@@ -36,10 +36,10 @@ from bridges import UpdateTorBridges
def main():
- dmg_url = "https://dist.torproject.org/torbrowser/11.0.4/TorBrowser-11.0.4-osx64_en-US.dmg"
- dmg_filename = "TorBrowser-11.0.4-osx64_en-US.dmg"
+ dmg_url = "https://dist.torproject.org/torbrowser/11.0.9/TorBrowser-11.0.9-osx64_en-US.dmg"
+ dmg_filename = "TorBrowser-11.0.9-osx64_en-US.dmg"
expected_dmg_sha256 = (
- "309a67c8a82ae266756d7cf5ea00e94d9242e59d55eaff97dcd6201da3c8449c"
+ "e34629a178a92983924a5a89c7a988285d2d27f21832413a7f7e33af7871c8d6"
)
# Build paths
diff --git a/desktop/scripts/get-tor-windows.py b/desktop/scripts/get-tor-windows.py
index 513ff168..581a476b 100644
--- a/desktop/scripts/get-tor-windows.py
+++ b/desktop/scripts/get-tor-windows.py
@@ -35,10 +35,10 @@ from bridges import UpdateTorBridges
def main():
- exe_url = "https://dist.torproject.org/torbrowser/11.0.4/torbrowser-install-11.0.4_en-US.exe"
- exe_filename = "torbrowser-install-11.0.4_en-US.exe"
+ exe_url = "https://dist.torproject.org/torbrowser/11.0.9/torbrowser-install-11.0.9_en-US.exe"
+ exe_filename = "torbrowser-install-11.0.9_en-US.exe"
expected_exe_sha256 = (
- "c7073f58f49a225bcf7668a5630e94f5f5e96fb7bed095feebf3bf8417bd3d07"
+ "e938433028b6ffb5d312db6268b19e419626b071f08209684c8e5b9f3d3df2bc"
)
# Build paths
root_path = os.path.dirname(
diff --git a/docs/source/advanced.rst b/docs/source/advanced.rst
index 870f8777..3f5a70ce 100644
--- a/docs/source/advanced.rst
+++ b/docs/source/advanced.rst
@@ -6,19 +6,19 @@ Advanced Usage
Save Tabs
---------
-Everything in OnionShare is temporary by default. If you close an OnionShare tab, its address no longer exists and it can't be used again.
-Sometimes you might want an OnionShare service to be persistent.
-This is useful if you want to host a website available from the same OnionShare address even if you reboot your computer.
+Everything in OnionShare is temporary by default. When OnionShare tabs are closed, addresses no longer exist and can't be used again.
+Your OnionShare service can also be persistent.
+If you host a website, persistence means it will be available on the same OnionShare address even if you reboot your computer.
-To make any tab persistent, check the "Save this tab, and automatically open it when I open OnionShare" box before starting the server.
-When a tab is saved a purple pin icon appears to the left of its server status.
+To make any tab persistent, check the "Save this tab, and automatically open it when I open OnionShare" box before starting your server.
+A purple pin icon appears to the left of its server status to tell you the tab is saved.
.. image:: _static/screenshots/advanced-save-tabs.png
-When you quit OnionShare and then open it again, your saved tabs will start opened.
-You'll have to manually start each service, but when you do they will start with the same OnionShare address and private key.
+When opening OnionShare, your saved tabs from the prior session will start opened.
+Each service then can be started manually, and will be available on the same OnionShare address and be protected by the same private key.
-If you save a tab, a copy of that tab's onion service secret key will be stored on your computer with your OnionShare settings.
+If you save a tab, a copy of its onion service secret key is stored on your computer.
.. _turn_off_private_key:
@@ -27,37 +27,40 @@ Turn Off Private Key
By default, all OnionShare services are protected with a private key, which Tor calls "client authentication".
-When browsing to an OnionShare service in Tor Browser, Tor Browser will prompt for the private key to be entered.
+The Tor Browser will ask you to enter your private key when you load an OnionShare service.
+If you want allow the public to use your service, it's better to disable the private key altogether.
-Sometimes you might want your OnionShare service to be accessible to the public, like if you want to set up an OnionShare receive service so the public can securely and anonymously send you files.
-In this case, it's better to disable the private key altogether.
-
-To turn off the private key for any tab, check the "This is a public OnionShare service (disables private key)" box before starting the server. Then the server will be public and won't need a private key to view in Tor Browser.
+To turn off the private key for any tab, check the "This is a public OnionShare service (disables private key)" box before starting the server.
+Then the server will be public and a private key is not needed to load it in the Tor Browser.
.. _custom_titles:
Custom Titles
-------------
-By default, when people load an OnionShare service in Tor Browser they see the default title for the type of service. For example, the default title of a chat service is "OnionShare Chat".
+When people load OnionShare services in the Tor Browser they see the default title for each type of service.
+For example, the default title for chat services is "OnionShare Chat".
-If you want to choose a custom title, set the "Custom title" setting before starting a server.
+If you edit the "Custom title" setting before starting a server you can change it.
Scheduled Times
---------------
OnionShare supports scheduling exactly when a service should start and stop.
-Before starting a server, click "Show advanced settings" in its tab and then check the boxes next to either "Start onion service at scheduled time", "Stop onion service at scheduled time", or both, and set the respective desired dates and times.
+Before starting a server, click "Show advanced settings" in its tab and then check the boxes next to either
+"Start onion service at scheduled time", "Stop onion service at scheduled time", or both, and set the respective desired dates and times.
-If you scheduled a service to start in the future, when you click the "Start sharing" button you will see a timer counting down until it starts.
-If you scheduled it to stop in the future, after it's started you will see a timer counting down to when it will stop automatically.
+Services scheduled to start in the future display a countdown timer when when the "Start sharing" button is clicked.
+Services scheduled to stop in the future display a countdown timer when started.
-**Scheduling an OnionShare service to automatically start can be used as a dead man's switch**, where your service will be made public at a given time in the future if anything happens to you.
+**Scheduling an OnionShare service to automatically start can be used as a dead man's switch**.
+This means your service is made public at a given time in the future if you are not there to prevent it.
If nothing happens to you, you can cancel the service before it's scheduled to start.
.. image:: _static/screenshots/advanced-schedule-start-timer.png
-**Scheduling an OnionShare service to automatically stop can be useful to limit exposure**, like if you want to share secret documents while making sure they're not available on the internet for more than a few days.
+**Scheduling an OnionShare service to automatically stop limits its exposure**.
+If you want to share secret info or something that will be outdated, you can do so for selected limited time.
.. image:: _static/screenshots/advanced-schedule-stop-timer.png
@@ -78,14 +81,14 @@ Then run it like this::
onionshare-cli --help
-For information about installing it on different operating systems, see the `CLI readme file <https://github.com/onionshare/onionshare/blob/develop/cli/README.md>`_ in the git repository.
+Info about installing it on different operating systems can be found in the `CLI README file <https://github.com/onionshare/onionshare/blob/develop/cli/README.md>`_ in the Git repository.
-If you installed OnionShare using the Linux Snapcraft package, you can also just run ``onionshare.cli`` to access the command-line interface version.
+If you installed OnionShare using the Snap package, you can also just run ``onionshare.cli`` to access the command-line interface version.
Usage
^^^^^
-You can browse the command-line documentation by running ``onionshare --help``::
+Browse the command-line documentation by running ``onionshare --help``::
$ onionshare-cli --help
╭───────────────────────────────────────────╮
@@ -119,7 +122,7 @@ You can browse the command-line documentation by running ``onionshare --help``::
filename List of files or folders to share
optional arguments:
- -h, --help show this help message and exit
+ -h, --help Show this help message and exit
--receive Receive files
--website Publish website
--chat Start chat server
@@ -133,8 +136,8 @@ You can browse the command-line documentation by running ``onionshare --help``::
--auto-start-timer SECONDS
Start onion service at scheduled time (N seconds from now)
--auto-stop-timer SECONDS
- Stop onion service at schedule time (N seconds from now)
- --no-autostop-sharing Share files: Continue sharing after files have been sent (default is to stop sharing)
+ Stop onion service at scheduled time (N seconds from now)
+ --no-autostop-sharing Share files: Continue sharing after files have been sent (the default is to stop sharing)
--data-dir data_dir Receive files: Save files received to this directory
--webhook-url webhook_url
Receive files: URL to receive webhook notifications
diff --git a/docs/source/install.rst b/docs/source/install.rst
index c5dd8197..c3fe5d16 100644
--- a/docs/source/install.rst
+++ b/docs/source/install.rst
@@ -12,13 +12,13 @@ Linux
-----
There are various ways to install OnionShare for Linux, but the recommended way is to use either the `Flatpak <https://flatpak.org/>`_ or the `Snap <https://snapcraft.io/>`_ package.
-Flatpak and Snap ensure that you'll always use the newest version and run OnionShare inside of a sandbox.
+Flatpak and Snapcraft ensure that you'll always use the newest version and run OnionShare inside of a sandbox.
-Snap support is built-in to Ubuntu and Fedora comes with Flatpak support, but which you use is up to you. Both work in all Linux distributions.
+Snapcraft support is built-in to Ubuntu and Fedora comes with Flatpak support, but which you use is up to you. Both work in all Linux distributions.
**Install OnionShare using Flatpak**: https://flathub.org/apps/details/org.onionshare.OnionShare
-**Install OnionShare using Snap**: https://snapcraft.io/onionshare
+**Install OnionShare using Snapcraft**: https://snapcraft.io/onionshare
You can also download and install PGP-signed ``.flatpak`` or ``.snap`` packages from https://onionshare.org/dist/ if you prefer.
@@ -27,7 +27,7 @@ You can also download and install PGP-signed ``.flatpak`` or ``.snap`` packages
Command-line only
-----------------
-You can install just the command line version of OnionShare on any operating system using the Python package manager ``pip``. See :ref:`cli` for more information.
+You can install just the command-line version of OnionShare on any operating system using the Python package manager ``pip``. :ref:`cli` has more info.
.. _verifying_sigs:
@@ -40,7 +40,8 @@ For Windows and macOS, this step is optional and provides defense in depth: the
Signing key
^^^^^^^^^^^
-Packages are signed by Micah Lee, the core developer, using his PGP public key with fingerprint ``927F419D7EC82C2F149C1BD1403C2657CD994F73``. You can download Micah's key `from the keys.openpgp.org keyserver <https://keys.openpgp.org/vks/v1/by-fingerprint/927F419D7EC82C2F149C1BD1403C2657CD994F73>`_.
+Packages are signed by Micah Lee, the core developer, using his PGP public key with fingerprint ``927F419D7EC82C2F149C1BD1403C2657CD994F73``.
+You can download Micah's key `from the keys.openpgp.org keyserver <https://keys.openpgp.org/vks/v1/by-fingerprint/927F419D7EC82C2F149C1BD1403C2657CD994F73>`_.
You must have GnuPG installed to verify signatures. For macOS you probably want `GPGTools <https://gpgtools.org/>`_, and for Windows you probably want `Gpg4win <https://www.gpg4win.org/>`_.
@@ -73,6 +74,6 @@ The expected output looks like this::
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 927F 419D 7EC8 2C2F 149C 1BD1 403C 2657 CD99 4F73
-If you don't see ``Good signature from``, there might be a problem with the integrity of the file (malicious or otherwise), and you should not install the package. (The ``WARNING:`` shown above, is not a problem with the package, it only means you haven't defined a level of "trust" of Micah's PGP key.)
+If you don't see ``Good signature from``, there might be a problem with the integrity of the file (malicious or otherwise), and you should not install the package. (The ``WARNING:`` shown above, is not a problem with the package, it only means you haven't defined a level of "trust" of Micah's (the core developer) PGP key.)
If you want to learn more about verifying PGP signatures, the guides for `Qubes OS <https://www.qubes-os.org/security/verifying-signatures/>`_ and the `Tor Project <https://support.torproject.org/tbb/how-to-verify-signature/>`_ may be useful.
diff --git a/docs/source/security.rst b/docs/source/security.rst
index 0727b957..25f4d5cb 100644
--- a/docs/source/security.rst
+++ b/docs/source/security.rst
@@ -8,17 +8,38 @@ Like all software, OnionShare may contain bugs or vulnerabilities.
What OnionShare protects against
--------------------------------
-**Third parties don't have access to anything that happens in OnionShare.** Using OnionShare means hosting services directly on your computer. When sharing files with OnionShare, they are not uploaded to any server. If you make an OnionShare chat room, your computer acts as a server for that too. This avoids the traditional model of having to trust the computers of others.
-
-**Network eavesdroppers can't spy on anything that happens in OnionShare in transit.** The connection between the Tor onion service and Tor Browser is end-to-end encrypted. This means network attackers can't eavesdrop on anything except encrypted Tor traffic. Even if an eavesdropper is a malicious rendezvous node used to connect the Tor Browser with OnionShare's onion service, the traffic is encrypted using the onion service's private key.
-
-**Anonymity of OnionShare users are protected by Tor.** OnionShare and Tor Browser protect the anonymity of the users. As long as the OnionShare user anonymously communicates the OnionShare address with the Tor Browser users, the Tor Browser users and eavesdroppers can't learn the identity of the OnionShare user.
-
-**If an attacker learns about the onion service, it still can't access anything.** Prior attacks against the Tor network to enumerate onion services allowed the attacker to discover private ``.onion`` addresses. If an attack discovers a private OnionShare address, they will also need to guess the private key used for client authentication in order to access it (unless the OnionShare user chooses make their service public by turning off the private key -- see :ref:`turn_off_private_key`).
+**Third parties don't have access to anything that happens in OnionShare.**
+Using OnionShare means hosting services directly on your computer.
+When sharing your files with OnionShare, they are not uploaded to any third-party server.
+If you make an OnionShare chat room, your computer acts as a server for that too.
+This avoids the traditional model of having to trust the computers of others.
+
+**Network eavesdroppers can't spy on anything that happens in OnionShare in transit.**
+The connection between the Tor onion service and Tor Browser is end-to-end encrypted.
+This means network attackers can't eavesdrop on anything except encrypted Tor traffic.
+Even if an eavesdropper is a malicious rendezvous node used to connect the Tor Browser with OnionShare's onion service,
+the traffic is encrypted using the onion service's private key.
+
+**Anonymity of OnionShare users are protected by Tor.**
+OnionShare and Tor Browser protect the anonymity of the users.
+As long as the OnionShare user anonymously communicates the OnionShare address with the Tor Browser users,
+the Tor Browser users and eavesdroppers can't learn the identity of the OnionShare user.
+
+**If an attacker learns about the onion service, it still can't access anything.**
+Prior attacks against the Tor network to enumerate onion services allowed attackers to discover private ``.onion`` addresses.
+To access an OnionShare service from its address, the private key used for client authentication must be guessed (unless the service is already made public by turning off the private key -- see :ref:`turn_off_private_key`).
What OnionShare doesn't protect against
---------------------------------------
-**Communicating the OnionShare address and private key might not be secure.** Communicating the OnionShare address to people is the responsibility of the OnionShare user. If sent insecurely (such as through an email message monitored by an attacker), an eavesdropper can tell that OnionShare is being used. If the eavesdropper loads the address in Tor Browser while the service is still up, they can access it. To avoid this, the address must be communicated securely, via encrypted text message (probably with disappearing messages enabled), encrypted email, or in person. This isn't necessary when using OnionShare for something that isn't secret.
-
-**Communicating the OnionShare address and private key might not be anonymous.** Extra precautions must be taken to ensure the OnionShare address is communicated anonymously. A new email or chat account, only accessed over Tor, can be used to share the address. This isn't necessary unless anonymity is a goal.
+**Communicating the OnionShare address and private key might not be secure.**
+Communicating the OnionShare address to people is the responsibility of the OnionShare user.
+If sent insecurely (such as through an e-mail message monitored by an attacker), an eavesdropper can tell that OnionShare is being used.
+Eavesdroppers can access services that are still up by loading their addresses and/or lost key in the Tor Browser.
+Avoid this by communicating the address securely, via encrypted text message (probably with disappearing messages enabled), encrypted e-mail, or in person.
+This isn't necessary when using OnionShare for something that isn't secret.
+
+**Communicating the OnionShare address and private key might not be anonymous.**
+Extra precaution must be taken to ensure the OnionShare address is communicated anonymously.
+A new e-mail or chat account, only accessed over Tor, can be used to share the address.
+This isn't necessary unless anonymity is a goal.