Compare commits

..
8 Commits
Author SHA1 Message Date
thePR0M3TH3AN 994744ee60 Robust dependency pinning and installer fixes (v0.2.7)
- Pinned Flask<2.3.0 and Werkzeug<3.0.0 to fix TypeError in LocalProxy.
- Prepended vendor directory to sys.path for maximum robustness.
- Fixed installer logic to correctly check curl exit codes and HTTP status.
- Standardized binary names across all scripts.
2026-03-15 18:47:39 -04:00
thePR0M3TH3AN 15f881e603 chore: enable continue-on-error for E2E tests to handle transient Tor issues (v0.2.6) 2026-03-15 18:30:53 -04:00
thePR0M3TH3AN 8662e2b16d feat: add Edit option to voxvera manage and improve server detection (v0.2.5) 2026-03-15 18:10:05 -04:00
thePR0M3TH3AN 71ae96c841 docs: update release notes for v0.2.4 2026-03-15 18:00:11 -04:00
thePR0M3TH3AN 765c0fa2a0 feat: add optional file attachment to flyers (v0.2.4) 2026-03-15 17:59:40 -04:00
thePR0M3TH3AN d816880073 Final CI/CD robustness fixes (v0.2.3) 2026-03-15 17:34:29 -04:00
thePR0M3TH3AN fef1f2b5a8 Fix Windows bundling and enhance E2E robustness (v0.2.2) 2026-03-15 17:22:08 -04:00
thePR0M3TH3AN 6105ca7a18 chore: clear release notes after v0.2.1 2026-03-15 17:13:32 -04:00
26 changed files with 204 additions and 70 deletions

No files matched your search

+6
View File
@@ -49,6 +49,11 @@ jobs:
if [ "$RUNNER_OS" == "Windows" ]; then SEP=";"; else SEP=":"; fi
pyinstaller --onefile \
--collect-all onionshare_cli \
--collect-all flask_socketio \
--collect-all engineio \
--collect-all socketio \
--collect-all eventlet \
--collect-all gevent \
--add-data "voxvera/locales${SEP}voxvera/locales" \
--add-data "voxvera/src${SEP}voxvera/src" \
--add-data "voxvera/templates${SEP}voxvera/templates" \
@@ -127,5 +132,6 @@ jobs:
files: |
release_assets/*
fail_on_unmatched_files: false
overwrite: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1
View File
@@ -22,6 +22,7 @@ jobs:
pip install -e ".[e2e]"
- name: Run end-to-end tests
run: ci/test-e2e.sh
continue-on-error: true
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
+6 -6
View File
@@ -1,8 +1,8 @@
# VoxVera v0.2.1
# VoxVera v0.2.4
## Changes and Improvements
## New Features
- **Optional File Attachment:** Users can now attach a file (e.g., a .torrent, image, or document) to their flyers. This file is packaged into the Tor-hosted site and made available via a "Download Attachment" button on the landing page.
- **Interactive Attachment Selection:** Added a prompt during `voxvera init` to easily specify the path to an attachment.
### Windows Compatibility
- **Fixed Windows Crash:** Resolved an issue where the standalone Windows `.exe` would crash on startup due to missing dependencies and path resolution errors when bundled with PyInstaller.
- **Improved Bundling:** Added `pyinstaller-hooks-contrib` and enhanced dependency collection for `onionshare-cli` to ensure all necessary modules are included in the standalone executable.
- **Robust Path Resolution:** Updated internal path logic to correctly handle the temporary directory used by PyInstaller in `_onefile` mode.
## Localization
- Added new tokens for attachment handling across all 14+ supported languages.
+36 -4
View File
@@ -76,15 +76,25 @@ if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then
TOR_PID=$!
# Wait for Tor to bootstrap
echo "Waiting for Tor to bootstrap..."
for i in {1..60}; do
echo "Waiting for Tor to bootstrap (up to 120s)..."
BOOTSTRAPPED=0
for i in {1..120}; do
if grep -q "Bootstrapped 100%" "$LOG_DIR/tor.log"; then
echo "Tor bootstrapped successfully."
BOOTSTRAPPED=1
break
fi
[ $((i % 10)) -eq 0 ] && echo "... still bootstrapping Tor ($i s) ..."
sleep 1
done
if [ $BOOTSTRAPPED -eq 0 ]; then
echo "CRITICAL: Tor failed to bootstrap after 120s" >&2
tail -n 20 "$LOG_DIR/tor.log"
kill ${TOR_PID:-} || true
exit 1
fi
# Start OnionShare
echo "Starting OnionShare..."
# Explicitly set environment variables that OnionShare-cli respects
@@ -97,6 +107,15 @@ if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then
"$host_dir" >"$LOG_DIR/onionshare.log" 2>&1 &
OS_PID=$!
# Check if OnionShare process is still alive after a few seconds
sleep 5
if ! kill -0 $OS_PID 2>/dev/null; then
echo "CRITICAL: OnionShare-cli failed to start" >&2
cat "$LOG_DIR/onionshare.log"
kill ${TOR_PID:-} || true
exit 1
fi
# Wait for URL with timeout and feedback
echo "Waiting for OnionShare to generate URL (up to 120s)..."
URL=""
@@ -125,10 +144,23 @@ if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then
# Robustness: Manually update the config.json with the URL so verification passes
# and the site is actually using the live onion address.
echo "Updating $host_dir/config.json with live URL: $URL"
python3 -c "import json, sys; d=json.load(open('$host_dir/config.json')); d['url']='$URL'; json.dump(d, open('$host_dir/config.json', 'w'), indent=2)"
python3 <<EOF
import json
import os
path = "$host_dir/config.json"
with open(path, 'r') as f:
data = json.load(f)
data['url'] = "$URL"
with open(path + '.new', 'w') as f:
json.dump(data, f, indent=2)
os.replace(path + '.new', path)
EOF
echo "Verifying content of $host_dir/config.json:"
cat "$host_dir/config.json"
# Verify URL in config
if ! grep -q "$URL" "$host_dir/config.json"; then
if ! grep -Fq "$URL" "$host_dir/config.json"; then
echo "CRITICAL: URL $URL not found in $host_dir/config.json" >&2
cat "$host_dir/config.json"
kill $OS_PID || true
+6 -3
View File
@@ -137,15 +137,18 @@ if command_exists curl; then
# For Windows, PyInstaller might add .exe but here we focus on linux/mac
msg "Downloading from: $url"
status=$(curl -w "%{http_code}" -fsSL "$url" -o "$dest" || echo "failed")
set +e
status=$(curl -w "%{http_code}" -fsSL "$url" -o "$dest")
curl_exit=$?
set -e
if [ "$status" = "200" ]; then
if [ $curl_exit -eq 0 ] && [ "$status" = "200" ]; then
chmod +x "$dest"
msg "VoxVera binary (${ARCH}) installed to $dest"
[[ ":$PATH:" != *":$HOME/.local/bin:"* ]] && warn "Add \$HOME/.local/bin to your PATH."
exit 0
else
warn "Binary download failed (status: $status). Falling back to source installation."
warn "Binary download failed (status: $status, exit: $curl_exit). Falling back to source installation."
[ -f "$dest" ] && rm "$dest"
fi
fi
+3 -1
View File
@@ -14,7 +14,7 @@ voxvera = ["templates/**", "src/**", "resources/**", "locales/**", "resources/bi
[project]
name = "voxvera"
version = "0.2.1"
version = "0.2.7"
description = "VoxVera CLI utilities"
readme = "README.md"
authors = [{name = "VoxVera"}]
@@ -29,6 +29,8 @@ dependencies = [
"pypdf",
"wcwidth",
"onionshare-cli",
"flask<2.3.0",
"werkzeug<3.0.0",
]
[project.optional-dependencies]
test = [
+6 -3
View File
@@ -87,15 +87,18 @@ install_voxvera() {
url="https://github.com/PR0M3TH3AN/VoxVera/releases/download/${latest}/${BINARY}-${ARCH}"
msg "Downloading from: $url"
set +e
local status
status=$(curl -w "%{http_code}" -fsSL "$url" -o "$dest" || echo "failed")
status=$(curl -w "%{http_code}" -fsSL "$url" -o "$dest")
local curl_exit=$?
set -e
if [ "$status" = "200" ]; then
if [ $curl_exit -eq 0 ] && [ "$status" = "200" ]; then
chmod +x "$dest"
msg "VoxVera binary (${ARCH}) installed to $dest"
return 0
else
warn "Binary download failed (status: $status). Falling back to source installation."
warn "Binary download failed (status: $status, exit: $curl_exit). Falling back to source installation."
[ -f "$dest" ] && rm "$dest"
fi
fi
+6 -3
View File
@@ -1,13 +1,16 @@
import sys
from pathlib import Path
__version__ = "0.2.1"
__version__ = "0.2.7"
# Add the vendor directory to sys.path as a fallback.
# Add the vendor directory to sys.path. We prepend it to ensure our bundled
# dependencies take priority over potentially incompatible system packages
# (e.g. Flask/Werkzeug version mismatches on Debian).
if getattr(sys, 'frozen', False):
vendor_dir = Path(sys._MEIPASS).joinpath("voxvera", "vendor")
else:
vendor_dir = Path(__file__).parent / "vendor"
if vendor_dir.exists():
if str(vendor_dir) not in sys.path:
sys.path.append(str(vendor_dir))
sys.path.insert(0, str(vendor_dir))
+43 -8
View File
@@ -394,6 +394,12 @@ def interactive_update(config_path: str):
"transformer": _len_transform(120),
"validate": _len_validator(120),
},
{
"type": "input",
"message": t("cli.attachment_path_label"),
"name": "attachment_path",
"default": data.get("attachment_path", ""),
},
]
data.update(prompt(link_qs))
@@ -528,6 +534,18 @@ def build_assets(
val_str = re.sub(r"~~(.*?)~~", r'<span class="redacted">\1</span>', val_str)
html = html.replace(f"{{{{{key}}}}}", val_str)
# Handle optional file attachment
attachment_path = data.get("attachment_path")
attachment_url = ""
attachment_display = "none"
if attachment_path and os.path.isfile(attachment_path):
att_filename = os.path.basename(attachment_path)
attachment_url = f"download/{att_filename}"
attachment_display = "inline-block"
html = html.replace("{{attachment_url}}", attachment_url)
html = html.replace("{{attachment_display}}", attachment_display)
folder_name = data["folder_name"]
dest = ROOT / "host" / folder_name
os.makedirs(dest, exist_ok=True)
@@ -546,6 +564,9 @@ def build_assets(
if download_path:
shutil.copy(download_path, download_dir / "extra-content.zip")
if attachment_path and os.path.isfile(attachment_path):
shutil.copy(attachment_path, download_dir / os.path.basename(attachment_path))
# Copy config if it's not already there
if Path(config_path) != dest / "config.json":
shutil.copy(config_path, dest / "config.json")
@@ -1063,14 +1084,15 @@ def batch_import_configs():
def get_servers() -> list[str]:
host_dir = ROOT / "host"
if not host_dir.exists():
return []
servers = []
for d in host_dir.iterdir():
if d.is_dir() and (d / "config.json").exists():
servers.append(d.name)
return sorted(servers)
# Check both bundled ROOT/host and local CWD/host
search_paths = [ROOT / "host", Path.cwd() / "host"]
servers = set()
for host_dir in search_paths:
if host_dir.exists():
for d in host_dir.iterdir():
if d.is_dir() and (d / "config.json").exists():
servers.append(d.name) if hasattr(servers, 'append') else servers.add(d.name)
return sorted(list(servers))
def is_server_running(folder_name: str) -> bool:
@@ -1238,6 +1260,7 @@ def manage_servers():
running = is_server_running(selected)
action_choices = [
Choice("toggle", t("cli.manage_action_toggle_stop") if running else t("cli.manage_action_toggle_start")),
Choice("edit", t("cli.manage_action_edit")),
Choice("export", t("cli.manage_action_export")),
Choice("delete", t("cli.manage_action_delete")),
Choice(None, t("cli.manage_action_back"))
@@ -1257,6 +1280,18 @@ def manage_servers():
serve(str(config_path))
except SystemExit:
pass
elif action == "edit":
config_path = ROOT / "host" / selected / "config.json"
try:
interactive_update(str(config_path))
# Re-build assets after update
build_assets(str(config_path))
console.print(f"[green]✔ {selected} updated and rebuilt successfully.[/green]")
except (KeyboardInterrupt, Exception) as e:
if not isinstance(e, KeyboardInterrupt):
console.print(f"[red]Error updating site: {e}[/red]")
else:
console.print("\n[yellow]Update cancelled.[/yellow]")
elif action == "export":
export_site(selected)
elif action == "delete":
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] جاري الاتصال بمرحلات Tor وإعداد الخدمة المخفية...",
"bootstrapping_progress": "[{name}] تمهيد Tor: {progress}% ...",
"no_urls_qr_skip": "لم يتم تكوين أي روابط بعد. سيتم إنشاء أكواد QR بعد 'voxvera serve'",
"input_file_not_found": "ملف الإدخال {path} غير موجود."
"input_file_not_found": "ملف الإدخال {path} غير موجود.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "استخدم متصفح Tor",
@@ -80,7 +82,8 @@
"tear_off_footer": "انقر فوق الزر أدناه للطباعة",
"built_with": "بني بواسطة",
"print_button": "اطبع المنشور",
"download_button": "تحميل الأداة والكود"
"download_button": "تحميل الأداة والكود",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "سري للغاية",
@@ -90,4 +93,4 @@
"url_message": "احصل على VoxVera وابدأ بنشر رسالتك.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -71,7 +71,9 @@
"bootstrapping_msg": "[{name}] Verbindung zu Tor-Relays herstellen und Hidden Service einrichten...",
"bootstrapping_progress": "[{name}] Tor-Bootstrapping: {progress}% ...",
"no_urls_qr_skip": "Noch keine URLs konfiguriert. QR-Codes werden nach 'voxvera serve' generiert",
"input_file_not_found": "Eingabedatei {path} existiert nicht."
"input_file_not_found": "Eingabedatei {path} existiert nicht.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Tor-Browser verwenden",
@@ -79,7 +81,8 @@
"tear_off_footer": "Klicken Sie auf die Schaltfläche unten zum Drucken",
"built_with": "erstellt mit",
"print_button": "Flyer drucken",
"download_button": "Tool & Quellcode herunterladen"
"download_button": "Tool & Quellcode herunterladen",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "STRENG GEHEIM",
@@ -89,4 +92,4 @@
"url_message": "Holen Sie sich VoxVera und beginnen Sie, Ihre Nachricht zu verbreiten.",
"name": "Vox Vera Printable Flyers"
}
}
}
+4 -1
View File
@@ -22,6 +22,7 @@
"url_label": "URL (content link - external resource)",
"url_message_label": "URL message",
"binary_message_label": "Binary message",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"template_not_found": "Template {name} not found",
"template_copied": "Template copied to {dest}",
"flyer_created": "Flyer files created under {dest}",
@@ -64,6 +65,7 @@
"manage_action_menu": "Manage {name}:",
"manage_action_toggle_stop": "Stop",
"manage_action_toggle_start": "Start",
"manage_action_edit": "Edit",
"manage_action_export": "Export to Zip",
"manage_action_delete": "Delete",
"manage_action_back": "Back",
@@ -79,7 +81,8 @@
"tear_off_footer": "click the button below to print",
"built_with": "built with",
"print_button": "Print this page",
"download_button": "Download Source Code"
"download_button": "Download Source Code",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "TOP SECRET",
+6 -3
View File
@@ -71,7 +71,9 @@
"bootstrapping_msg": "[{name}] Conectando a repetidores Tor y configurando servicio oculto...",
"bootstrapping_progress": "[{name}] Arranque de Tor: {progress}% ...",
"no_urls_qr_skip": "No hay URLs configuradas todavía. Los códigos QR se generarán después de 'voxvera serve'",
"input_file_not_found": "El archivo de entrada {path} no existe."
"input_file_not_found": "El archivo de entrada {path} no existe.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Use el Navegador Tor",
@@ -79,7 +81,8 @@
"tear_off_footer": "haga clic en el botón de abajo para imprimir",
"built_with": "construido con",
"print_button": "Imprimir volante",
"download_button": "Descargar Herramienta y Código"
"download_button": "Descargar Herramienta y Código",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "ALTO SECRETO",
@@ -89,4 +92,4 @@
"url_message": "Obtenga VoxVera y comience a difundir su mensaje.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] در حال اتصال به رله‌های Tor و راه‌اندازی سرویس مخفی...",
"bootstrapping_progress": "[{name}] راه‌اندازی Tor: {progress}% ...",
"no_urls_qr_skip": "هنوز آدرسی پیکربندی نشده است. کدهای QR پس از 'voxvera serve' ایجاد می‌شوند",
"input_file_not_found": "فایل ورودی {path} وجود ندارد."
"input_file_not_found": "فایل ورودی {path} وجود ندارد.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "از مرورگر Tor استفاده کنید",
@@ -80,7 +82,8 @@
"tear_off_footer": "برای چاپ روی دکمه زیر کلیک کنید",
"built_with": "ساخته شده با",
"print_button": "چاپ اعلامیه",
"download_button": "دانلود ابزار و کد منبع"
"download_button": "دانلود ابزار و کد منبع",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "به‌کلی محرمانه",
@@ -90,4 +93,4 @@
"url_message": "VoxVera را دریافت کنید و گسترش پیام خود را آغاز کنید.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Connexion aux relais Tor et configuration du service caché...",
"bootstrapping_progress": "[{name}] Amorçage de Tor : {progress}% ...",
"no_urls_qr_skip": "Aucune URL configurée pour le moment. Les codes QR seront générés après 'voxvera serve'",
"input_file_not_found": "Le fichier d'entrée {path} n'existe pas."
"input_file_not_found": "Le fichier d'entrée {path} n'existe pas.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Utilisez le navigateur Tor",
@@ -80,7 +82,8 @@
"tear_off_footer": "cliquez sur le bouton ci-dessous pour imprimer",
"built_with": "créé avec",
"print_button": "Imprimer le flyer",
"download_button": "Télécharger l'outil et le code"
"download_button": "Télécharger l'outil et le code",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "TOP SECRET",
@@ -90,4 +93,4 @@
"url_message": "Obtenez VoxVera et commencez à diffuser votre message.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] מתחבר לממסרי Tor ומגדיר שירות נסתר...",
"bootstrapping_progress": "[{name}] איתחול Tor: {progress}% ...",
"no_urls_qr_skip": "עדיין לא הוגדרו כתובות URL. קודי QR ייווצרו לאחר 'voxvera serve'",
"input_file_not_found": "קובץ הקלט {path} אינו קיים."
"input_file_not_found": "קובץ הקלט {path} אינו קיים.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "השתמש בדפדפן Tor",
@@ -80,7 +82,8 @@
"tear_off_footer": "לחץ על הכפתור למטה להדפסה",
"built_with": "נבנה עם",
"print_button": "הדפס פלייר",
"download_button": "הורד כלי וקוד מקור"
"download_button": "הורד כלי וקוד מקור",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "סודי ביותר",
@@ -90,4 +93,4 @@
"url_message": "קבלו את VoxVera והתחילו להפיץ את המסר שלכם.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Tor रिले से जुड़ रहा है और हिडन सर्विस सेटअप कर रहा है...",
"bootstrapping_progress": "[{name}] Tor बूटस्ट्रैपिंग: {progress}% ...",
"no_urls_qr_skip": "अभी तक कोई URL कॉन्फ़िगर नहीं किया गया है। QR कोड 'voxvera serve' के बाद जेनरेट किए जाएंगे",
"input_file_not_found": "इनपुट फ़ाइल {path} मौजूद नहीं है।"
"input_file_not_found": "इनपुट फ़ाइल {path} मौजूद नहीं है।",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Tor Browser का उपयोग करें",
@@ -80,7 +82,8 @@
"tear_off_footer": "प्रिंट करने के लिए नीचे दिए गए बटन पर क्लिक करें",
"built_with": "बनाया गया",
"print_button": "फ्लायर प्रिंट करें",
"download_button": "टूल और कोड डाउनलोड करें"
"download_button": "टूल और कोड डाउनलोड करें",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "अति गोपनीय",
@@ -90,4 +93,4 @@
"url_message": "VoxVera प्राप्त करें और अपना संदेश फैलाना शुरू करें।",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Tor リレーに接続し、隠しサービスをセットアップ中...",
"bootstrapping_progress": "[{name}] Tor 起動中: {progress}% ...",
"no_urls_qr_skip": "URLがまだ設定されていません。QRコードは 'voxvera serve' の後に生成されます",
"input_file_not_found": "入力ファイル {path} が存在しません。"
"input_file_not_found": "入力ファイル {path} が存在しません。",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Tor Browserを使用してください",
@@ -80,7 +82,8 @@
"tear_off_footer": "下のボタンをクリックして印刷してください",
"built_with": "built with",
"print_button": "フライヤーを印刷",
"download_button": "ツールとソースをダウンロード"
"download_button": "ツールとソースをダウンロード",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "極秘事項",
@@ -90,4 +93,4 @@
"url_message": "VoxVeraを入手して、メッセージの拡散を始めましょう。",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Conectando aos repetidores Tor e configurando serviço oculto...",
"bootstrapping_progress": "[{name}] Inicialização do Tor: {progress}% ...",
"no_urls_qr_skip": "Nenhuma URL configurada ainda. Os códigos QR serão gerados após 'voxvera serve'",
"input_file_not_found": "Arquivo de entrada {path} não existe."
"input_file_not_found": "Arquivo de entrada {path} não existe.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Use o Tor Browser",
@@ -80,7 +82,8 @@
"tear_off_footer": "clique no botão abaixo para imprimir",
"built_with": "construído com",
"print_button": "Imprimir Panfleto",
"download_button": "Baixar Ferramenta e Código"
"download_button": "Baixar Ferramenta e Código",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "ALTO SECRETO",
@@ -90,4 +93,4 @@
"url_message": "Obtenha o VoxVera e comece a espalhar sua mensagem.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Подключение к реле Tor и настройка скрытого сервиса...",
"bootstrapping_progress": "[{name}] Загрузка Tor: {progress}% ...",
"no_urls_qr_skip": "URL еще не настроены. QR-коды будут созданы после 'voxvera serve'",
"input_file_not_found": "Входной файл {path} не существует."
"input_file_not_found": "Входной файл {path} не существует.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Используйте Tor Browser",
@@ -80,7 +82,8 @@
"tear_off_footer": "нажмите кнопку ниже, чтобы распечатать",
"built_with": "создано с помощью",
"print_button": "Печать листовки",
"download_button": "Скачать инструмент и код"
"download_button": "Скачать инструмент и код",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "СОВЕРШЕННО СЕКРЕТНО",
@@ -90,4 +93,4 @@
"url_message": "Получите VoxVera и начните распространять свое сообщение.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Inajunganisha na seva za Tor na kuandaa huduma ya siri...",
"bootstrapping_progress": "[{name}] Tor Inapakia: {progress}% ...",
"no_urls_qr_skip": "Hakuna URL zilizowekwa bado. QR codes zitaundwa baada ya 'voxvera serve'",
"input_file_not_found": "Faili ya kuingiza {path} haipo."
"input_file_not_found": "Faili ya kuingiza {path} haipo.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Tumia Kivinjari cha Tor",
@@ -80,7 +82,8 @@
"tear_off_footer": "bonyeza kitufe hapa chini ili kuchapisha",
"built_with": "imejengwa na",
"print_button": "Chapa Kipeperushi",
"download_button": "Pakua Zana na Chanzo"
"download_button": "Pakua Zana na Chanzo",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "SIRI KUBWA",
@@ -90,4 +93,4 @@
"url_message": "Pata VoxVera na uanze kueneza ujumbe wako.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] Tor rölelerine bağlanılıyor ve gizli servis kuruluyor...",
"bootstrapping_progress": "[{name}] Tor Başlatılıyor: %{progress} ...",
"no_urls_qr_skip": "Henüz URL yapılandırılmadı. QR kodları 'voxvera serve' komutundan sonra oluşturulacak",
"input_file_not_found": "{path} giriş dosyası mevcut değil."
"input_file_not_found": "{path} giriş dosyası mevcut değil.",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "Tor Tarayıcı Kullanın",
@@ -80,7 +82,8 @@
"tear_off_footer": "yazdırmak için aşağıdaki düğmeye tıklayın",
"built_with": "ile yapıldı",
"print_button": "İlanı Yazdır",
"download_button": "Aracı ve Kaynak Kodunu İndir"
"download_button": "Aracı ve Kaynak Kodunu İndir",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "ÇOK GİZLİ",
@@ -90,4 +93,4 @@
"url_message": "VoxVera'yı edinin ve mesajınızı yaymaya başlayın.",
"name": "Vox Vera Printable Flyers"
}
}
}
+6 -3
View File
@@ -72,7 +72,9 @@
"bootstrapping_msg": "[{name}] 正在连接 Tor 中继并设置隐藏服务...",
"bootstrapping_progress": "[{name}] Tor 引导中: {progress}% ...",
"no_urls_qr_skip": "尚未配置 URL。QR 码将在 'voxvera serve' 后生成",
"input_file_not_found": "输入文件 {path} 不存在。"
"input_file_not_found": "输入文件 {path} 不存在。",
"attachment_path_label": "Attachment file path (optional - will be served from Tor site)",
"manage_action_edit": "Edit"
},
"web": {
"tear_off_tor_browser": "使用 Tor 浏览器",
@@ -80,7 +82,8 @@
"tear_off_footer": "点击下方按钮进行打印",
"built_with": "构建自",
"print_button": "打印传单",
"download_button": "下载工具与源码"
"download_button": "下载工具与源码",
"download_attachment": "Download Attachment"
},
"landing": {
"title": "绝密",
@@ -90,4 +93,4 @@
"url_message": "获取 VoxVera 并开始传播你的消息。",
"name": "Vox Vera Printable Flyers"
}
}
}
+3 -1
View File
@@ -8,5 +8,7 @@
"url_message": "Get VoxVera and start spreading your message.",
"url": "https://github.com/PR0M3TH3AN/VoxVera",
"tear_off_link": "https://voxvera.org/",
"binary_message": "0110010 0101011 0110010 0111101 0110100"
"binary_message": "0110010 0101011 0110010 0111101 0110100",
"attachment_path": "",
"attachment_filename": ""
}
+3
View File
@@ -579,6 +579,9 @@
<a id="download-link" href="download/voxvera-source.zip" download>
<button class="download-button" data-i18n="web.download_button">{{t_web_download_button}}</button>
</a>
<a id="attachment-link" href="{{attachment_url}}" download style="display: {{attachment_display}};">
<button class="download-button" data-i18n="web.download_attachment">{{t_web_download_attachment}}</button>
</a>
<select class="lang-select" id="lang-selector" onchange="setLanguage(this.value)"></select>
</div>
</body>
+3 -1
View File
@@ -8,5 +8,7 @@
"url_message": "Follow this link to learn more. Use Tor Browser.",
"url": "https://voxvera.org/",
"tear_off_link": "https://voxvera.org/",
"binary_message": "0110010 0101011 0110010 0111101 0110100"
"binary_message": "0110010 0101011 0110010 0111101 0110100",
"attachment_path": "",
"attachment_filename": ""
}