mirror of https://github.com/ospab/ostp.git
175 lines
7.5 KiB
JavaScript
175 lines
7.5 KiB
JavaScript
// ── OSTP GUI Internationalization ─────────────────────────────────────────────
|
||
// Supports: English (en), Russian (ru)
|
||
|
||
const translations = {
|
||
en: {
|
||
// Home screen
|
||
status_disconnected: 'Disconnected',
|
||
status_connecting: 'Connecting...',
|
||
status_connected: 'Connected',
|
||
hint_tap: 'Tap to protect your traffic',
|
||
hint_connecting: 'Establishing secure tunnel...',
|
||
hint_connected: 'Your traffic is encrypted',
|
||
download: 'Download',
|
||
upload: 'Upload',
|
||
// Settings
|
||
settings_title: 'Configuration',
|
||
import_placeholder: 'Paste ostp:// share link here...',
|
||
import_btn: 'Import',
|
||
label_server: 'Server Address',
|
||
label_key: 'Access Key',
|
||
ph_key: 'Enter secure access key',
|
||
label_socks: 'Local Proxy Address',
|
||
label_dns: 'Custom DNS Server',
|
||
label_owndns: 'Built-in Server DNS',
|
||
owndns_hint: 'Route DNS queries through the VPN server (10.1.0.1)',
|
||
label_tun: 'TUN Tunnel Mode',
|
||
tun_hint: 'Route all system traffic (Admin req.)',
|
||
label_kill_switch: 'Kill Switch',
|
||
kill_switch_hint: 'Block non-VPN traffic when tunnel drops',
|
||
label_transport: 'Transport Protocol',
|
||
label_mtu: 'MTU Size',
|
||
label_transport: 'Transport Protocol',
|
||
label_sni: 'Stealth SNI (Fake Host)',
|
||
|
||
label_mtu: 'MTU Size',
|
||
label_mux: 'Multiplexing (Mux)',
|
||
mux_hint: 'Run multiple streams over one connection',
|
||
label_mux_sessions: 'Mux Sessions',
|
||
label_debug: 'Debug Logs',
|
||
debug_hint: 'Enable verbose internal event outputs',
|
||
excl_title: 'Exclusions',
|
||
excl_hint: '(one per line)',
|
||
excl_domains: 'Bypass Domains',
|
||
excl_ips: 'Bypass IPs / CIDR Ranges',
|
||
excl_processes: 'Bypass Processes',
|
||
save_btn: 'Save & Apply',
|
||
toast_saved: 'Configuration saved',
|
||
toast_imported: 'Configuration imported',
|
||
toast_error: 'Error',
|
||
err_server_req: 'Server address is required',
|
||
err_key_req: 'Access key is required',
|
||
label_autoconnect: 'Auto-connect',
|
||
autoconnect_hint: 'Connect automatically on startup',
|
||
label_launch_startup: 'Launch at Startup',
|
||
launch_startup_hint: 'Start OSTP with Windows',
|
||
cancel_btn: 'Cancel',
|
||
share_btn: 'Share',
|
||
share_title: 'Share configuration',
|
||
share_desc: 'Scan the QR or copy the link. The QR is generated locally — the access key never leaves this device.',
|
||
copy_btn: 'Copy link',
|
||
close_btn: 'Close',
|
||
wintun_missing_title: 'Wintun Driver Missing',
|
||
wintun_missing_desc: 'TUN mode requires the Wintun network driver (wintun.dll).',
|
||
wintun_step1: 'Download wintun.zip from the official site',
|
||
wintun_step2: 'Extract amd64\\wintun.dll from the archive',
|
||
wintun_step3: 'Place it here:',
|
||
wintun_step4: 'Restart the connection',
|
||
wintun_open_btn: 'Open wintun.net ↗',
|
||
},
|
||
ru: {
|
||
// Главный экран
|
||
status_disconnected: 'Отключено',
|
||
status_connecting: 'Подключение...',
|
||
status_connected: 'Подключено',
|
||
hint_tap: 'Нажмите для защиты трафика',
|
||
hint_connecting: 'Установка защищённого туннеля...',
|
||
hint_connected: 'Ваш трафик зашифрован',
|
||
download: 'Входящий',
|
||
upload: 'Исходящий',
|
||
// Настройки
|
||
settings_title: 'Настройки',
|
||
import_placeholder: 'Вставьте ostp:// ссылку...',
|
||
import_btn: 'Импорт',
|
||
label_server: 'Адрес сервера',
|
||
label_key: 'Ключ доступа',
|
||
ph_key: 'Введите ключ доступа',
|
||
label_socks: 'Адрес локального прокси',
|
||
label_dns: 'DNS сервер',
|
||
label_owndns: 'Встроенный DNS сервера',
|
||
owndns_hint: 'Направлять DNS-запросы через VPN сервер (10.1.0.1)',
|
||
label_tun: 'Режим TUN-туннеля',
|
||
tun_hint: 'Направить весь трафик (нужны права администратора)',
|
||
label_kill_switch: 'Kill Switch',
|
||
kill_switch_hint: 'Блокировать трафик вне VPN при обрыве связи',
|
||
label_transport: 'Транспортный протокол',
|
||
label_mtu: 'Размер MTU',
|
||
label_transport: 'Транспортный протокол',
|
||
label_sni: 'Маскировочный SNI',
|
||
|
||
label_mtu: 'Размер MTU',
|
||
label_mux: 'Мультиплексирование (Mux)',
|
||
mux_hint: 'Несколько потоков через одно соединение',
|
||
label_mux_sessions: 'Сессий Mux',
|
||
label_debug: 'Журнал отладки',
|
||
debug_hint: 'Включить подробный вывод событий',
|
||
excl_title: 'Исключения',
|
||
excl_hint: '(по одному на строку)',
|
||
excl_domains: 'Обход для доменов',
|
||
excl_ips: 'Обход для IP / CIDR',
|
||
excl_processes: 'Обход для процессов',
|
||
save_btn: 'Сохранить',
|
||
toast_saved: 'Настройки сохранены',
|
||
toast_imported: 'Настройки импортированы',
|
||
toast_error: 'Ошибка',
|
||
err_server_req: 'Укажите адрес сервера',
|
||
err_key_req: 'Укажите ключ доступа',
|
||
label_autoconnect: 'Автоподключение',
|
||
autoconnect_hint: 'Подключаться автоматически при запуске',
|
||
label_launch_startup: 'Запуск вместе с Windows',
|
||
launch_startup_hint: 'Автозапуск OSTP при входе в систему',
|
||
cancel_btn: 'Отмена',
|
||
share_btn: 'Поделиться',
|
||
share_title: 'Поделиться конфигурацией',
|
||
share_desc: 'Отсканируйте QR или скопируйте ссылку. QR генерируется локально — ключ доступа не покидает устройство.',
|
||
copy_btn: 'Копировать ссылку',
|
||
close_btn: 'Закрыть',
|
||
wintun_missing_title: 'Отсутствует драйвер Wintun',
|
||
wintun_missing_desc: 'Режим TUN требует сетевой драйвер Wintun (wintun.dll).',
|
||
wintun_step1: 'Скачайте wintun.zip с официального сайта',
|
||
wintun_step2: 'Извлеките amd64\\wintun.dll из архива',
|
||
wintun_step3: 'Поместите файл сюда:',
|
||
wintun_step4: 'Перезапустите подключение',
|
||
wintun_open_btn: 'Открыть wintun.net ↗',
|
||
},
|
||
};
|
||
|
||
let currentLang = localStorage.getItem('ostp_lang') || 'en';
|
||
|
||
export function t(key) {
|
||
const dict = translations[currentLang] || translations.en;
|
||
return dict[key] || translations.en[key] || key;
|
||
}
|
||
|
||
export function getLang() {
|
||
return currentLang;
|
||
}
|
||
|
||
export function setLang(lang) {
|
||
if (!translations[lang]) return;
|
||
currentLang = lang;
|
||
localStorage.setItem('ostp_lang', lang);
|
||
applyTranslations();
|
||
}
|
||
|
||
export function toggleLang() {
|
||
const next = currentLang === 'en' ? 'ru' : 'en';
|
||
setLang(next);
|
||
return next;
|
||
}
|
||
|
||
export function applyTranslations() {
|
||
document.querySelectorAll('[data-i18n]').forEach(el => {
|
||
const key = el.getAttribute('data-i18n');
|
||
const value = t(key);
|
||
if (value) el.textContent = value;
|
||
});
|
||
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
|
||
const key = el.getAttribute('data-i18n-placeholder');
|
||
const value = t(key);
|
||
if (value) el.placeholder = value;
|
||
});
|
||
const langLabel = document.getElementById('lang-label');
|
||
if (langLabel) langLabel.textContent = currentLang.toUpperCase();
|
||
}
|