From e75a4c2a9527bc29f450161a5d9251d4a9ab05d0 Mon Sep 17 00:00:00 2001 From: Your Name <10572974+eraiza0816@users.noreply.github.com> Date: Sun, 5 Jul 2026 00:51:27 +0900 Subject: [PATCH 1/3] support i18n & translate japanese --- html/bandwidth.html | 9 +- html/bandwidth.js | 26 +-- html/eee.html | 13 +- html/eee.js | 6 +- html/i18n.js | 402 ++++++++++++++++++++++++++++++++++++++++++++ html/index.html | 7 +- html/l2.html | 7 +- html/l2.js | 30 ++-- html/lag.html | 13 +- html/login.html | 14 +- html/main.js | 33 ++-- html/mirror.html | 17 +- html/mirror_sub.js | 4 +- html/navigation.js | 35 ++-- html/ports.html | 9 +- html/ports.js | 28 +-- html/stat.html | 11 +- html/stat.js | 26 +-- html/system.html | 46 ++--- html/system.js | 6 +- html/update.html | 9 +- html/vlan.html | 43 ++--- html/vlan.js | 4 +- html/vlan_sub.js | 2 +- 24 files changed, 613 insertions(+), 187 deletions(-) create mode 100644 html/i18n.js diff --git a/html/bandwidth.html b/html/bandwidth.html index 68a6b75..9b6b96f 100644 --- a/html/bandwidth.html +++ b/html/bandwidth.html @@ -1,17 +1,18 @@ + - Ingress and Egress Bandwidth + Ingress and Egress Bandwidth
-

Ingress and Egress Bandwidth

+

Ingress and Egress Bandwidth

- - + +
Ingress Egress
Port Limit Bandwidth [kBit/s] Flow Control Limit Bandwidth [kBit/s] Apply
Ingress Egress
Port Limit Bandwidth [kBit/s] Flow Control Limit Bandwidth [kBit/s] Apply
diff --git a/html/bandwidth.js b/html/bandwidth.js index 6b7f203..1c020ef 100644 --- a/html/bandwidth.js +++ b/html/bandwidth.js @@ -6,18 +6,18 @@ function createBW() { console.log("CREATING TABLE ", tbl.rows.length); for (let i = 2; i < 2 + numPorts; i++) { const tr = tbl.insertRow(); - let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`)); + let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i-1))); td = tr.insertCell(); td.innerHTML = limit.replaceAll("limit_port", "ilimit_port_" + i).replace("exec()", "iClicked(" + i + ")"); td = tr.insertCell(); - td.innerHTML = 'UNLIMITED'; - td = tr.insertCell(); - td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;"); - td = tr.insertCell(); - td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")"); - td = tr.insertCell(); - td.innerHTML = 'UNLIMITED'; - var button = ''; + td.innerHTML = t('bw_unlimited'); + td = tr.insertCell(); + td.innerHTML = limit.replaceAll("limit_port", "fc_port_" + i).replace("exec()", "document.getElementById('bwapply_" + i + "').disabled=false;"); + td = tr.insertCell(); + td.innerHTML = limit.replaceAll("limit_port", "elimit_port_" + i).replace("exec()", "eClicked(" + i + ")"); + td = tr.insertCell(); + td.innerHTML = t('bw_unlimited'); + var button = ''; td = tr.insertCell(); td.innerHTML = button; document.getElementById("bwapply_" + i).disabled = true; @@ -31,7 +31,7 @@ function iClicked(i) var tbl = document.getElementById('bwtable'); var tr = tbl.rows[i]; if (!document.getElementById("ilimit_port_" + i).checked) { - tr.cells[2].innerHTML = "UNLIMITED"; + tr.cells[2].innerHTML = t('bw_unlimited'); document.getElementById("fc_port_" + i).disabled = true; document.getElementById("fc_port_" + i).checked = true; } else { @@ -47,7 +47,7 @@ function eClicked(i) var tbl = document.getElementById('bwtable'); var tr = tbl.rows[i]; if (!document.getElementById("elimit_port_" + i).checked) { - tr.cells[5].innerHTML = "UNLIMITED"; + tr.cells[5].innerHTML = t('bw_unlimited'); } else { tr.cells[5].innerHTML = ''; } @@ -110,12 +110,12 @@ function getBW() { document.getElementById("ilimit_port_" + (n+1)).checked = p.iLimited; document.getElementById("elimit_port_" + (n+1)).checked = p.eLimited; if (!p.iLimited) { - tr.cells[2].innerHTML = "UNLIMITED"; + tr.cells[2].innerHTML = t('bw_unlimited'); } else { tr.cells[2].innerHTML = ''; } if (!p.eLimited) { - tr.cells[5].innerHTML = "UNLIMITED"; + tr.cells[5].innerHTML = t('bw_unlimited'); } else { tr.cells[5].innerHTML = ''; } diff --git a/html/eee.html b/html/eee.html index e5ec472..499c223 100644 --- a/html/eee.html +++ b/html/eee.html @@ -1,21 +1,22 @@ + - EEE Configuration + EEE Configuration
-

EEE Status

+

EEE Status

- - + +
Advertising Link-Partner advertises
Port 2.5G 1G 100M 2.5G 1G 100M Active?
Advertising Link-Partner advertises
Port 2.5G 1G 100M 2.5G 1G 100M Active?
- - + +
diff --git a/html/eee.js b/html/eee.js index af423ea..9225569 100644 --- a/html/eee.js +++ b/html/eee.js @@ -5,7 +5,7 @@ function createEEE() { for (let i = 2; i < 2 + numPorts; i++) { console.log("Table row: " + i + "pState: " + pState[i-2]); const tr = tbl.insertRow(); - let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i-1}`)); + let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i-1))); for (let j = 0; j < 7; j++) { td = tr.insertCell(); td.appendChild(document.createTextNode(" ")); } @@ -28,8 +28,8 @@ function getEEE() { let tr = tbl.rows[n+1]; if (!p.isSFP) { let eee = parseInt(p.eee,2); let lp = parseInt(p.eee_lp,2); - tr.cells[1].innerHTML = `${eee&4?"ON":"OFF"}`; tr.cells[2].innerHTML = `${eee&2?"ON":"OFF"}`; tr.cells[3].innerHTML = `${eee&1?"ON":"OFF"}`; - tr.cells[4].innerHTML = `${lp&4?"ON":"OFF"}`; tr.cells[5].innerHTML = `${lp&2?"ON":"OFF"}`; tr.cells[6].innerHTML = `${lp&1?"ON":"OFF"}`; + tr.cells[1].innerHTML = `${eee&4?t('eee_on'):t('eee_off')}`; tr.cells[2].innerHTML = `${eee&2?t('eee_on'):t('eee_off')}`; tr.cells[3].innerHTML = `${eee&1?t('eee_on'):t('eee_off')}`; + tr.cells[4].innerHTML = `${lp&4?t('eee_on'):t('eee_off')}`; tr.cells[5].innerHTML = `${lp&2?t('eee_on'):t('eee_off')}`; tr.cells[6].innerHTML = `${lp&1?t('eee_on'):t('eee_off')}`; tr.cells[7].innerHTML = `${p.active}`; tr.classList.toggle('disabled', pState[i-2] < 0); tr.classList.toggle('isNOK', !p.active); tr.classList.toggle('isOK', p.active); } diff --git a/html/i18n.js b/html/i18n.js new file mode 100644 index 0000000..e72df8c --- /dev/null +++ b/html/i18n.js @@ -0,0 +1,402 @@ +var LANG = { + en: { + nav_overview: 'Overview', + nav_port_config: 'Port Configuration', + nav_port_stat: 'Port Statistics', + nav_l2: 'L2 Configuration', + nav_mirror: 'Mirroring', + nav_lag: 'Link Aggregation', + nav_eee: 'EEE', + nav_bandwidth: 'Bandwidth Limits', + nav_system: 'System Settings', + nav_fw_update: 'Firmware Update', + + port_name: 'Name', + port_status: 'Status', + port_not_enabled: 'Not enabled.', + port_link_speed: 'Link speed', + port_vendor: 'Vendor', + port_model: 'Model', + port_serial: 'Serial', + port_temp: 'Temp', + port_vcc: 'Vcc', + port_tx_fault: 'TX-Fault', + port_tx_disabled: 'TX-Disabled', + port_tx_bias: 'TX-Bias', + port_tx_power: 'TX-Power', + port_rx_power: 'RX-Power', + port_rx_los: 'RX-LOS', + + speed_disabled: 'Disabled', + speed_down: 'Down', + + port_title: 'FreeSwitchOS Port Configuration', + port_heading: 'Port Configuration', + port_col_port: 'Port', + port_col_name: 'Name', + port_col_speed: 'Current Link Speed', + port_col_set_speed: 'Set Speed', + port_col_disabled: 'Disabled', + port_col_apply: 'Apply', + port_mtu_heading: 'Configure Maximum Frame Size (MTU) forwarded at Port', + port_auto: 'Auto', + port_2500m: '2500MBit/Full', + port_1000m: '1000MBit/Full', + port_100m_f: '100MBit/Full', + port_100m_h: '100MBit/Half', + port_10m_f: '10MBit/Full', + port_10m_h: '10MBit/Half', + port_apply: 'Apply', + + stat_title: 'FreeSwitchOS Port Statistics', + stat_heading: 'Port Statistics', + stat_detailed: 'Detailed Port Statistics', + stat_close: 'Close', + stat_col_port: 'Port', + stat_col_name: 'Name', + stat_col_link: 'link', + stat_col_tx_good: 'TX Good', + stat_col_tx_bad: 'TX Bad', + stat_col_rx_good: 'RX Good', + stat_col_rx_bad: 'RX Bad', + stat_col_all: 'All Counters', + stat_counter: 'Counter', + stat_value: 'Value', + stat_show: 'Show', + + vlan_title: 'FreeSwitchOS VLAN Configuration', + vlan_heading: 'VLAN Configuration', + vlan_select: 'VLAN Select:', + vlan_choose: '— VLAN Choose —', + vlan_id: 'VLAN ID:', + vlan_get_config: 'Get Configuration', + vlan_name: 'VLAN Name:', + vlan_tagged: 'Tagged Ports', + vlan_untagged: 'Untagged Ports', + vlan_select_all: 'Select all', + vlan_pvid: 'Use as default VLAN for incoming traffic (PVID)', + vlan_update: 'Update / Create', + vlan_configured: 'Configured VLANs', + vlan_col_name: 'Name', + vlan_col_member: 'Member Ports', + vlan_col_tagged: 'Tagged Ports', + vlan_col_untagged: 'Untagged Ports', + vlan_col_pvid: 'PVID Ports', + vlan_col_delete: 'Delete', + vlan_set_id_first: 'Set VLAN ID first', + vlan_delete_confirm: 'Delete VLAN ', + + lag_title: 'Link Aggregation Configuration', + lag_heading: 'Link Aggregation Groups Configuration', + lag_update: 'Update / Create', + + mirror_title: 'Mirror Configuration', + mirror_heading: 'Mirror Configuration', + mirror_enabled: 'Enabled:', + mirror_port: 'Mirroring Port:', + mirror_tx: 'Mirrored Ports (TX)', + mirror_rx: 'Mirrored Ports (RX)', + mirror_update: 'Update / Create', + mirror_disable: 'Disable Mirroring', + mirror_set_port_first: 'Set Mirroring Port first', + mirror_select_ports: 'Select Mirrored Ports', + + eee_title: 'EEE Configuration', + eee_heading: 'EEE Status', + eee_advertising: 'Advertising', + eee_partner: 'Link-Partner advertises', + eee_port: 'Port', + eee_active: 'Active?', + eee_enable: 'Enable EEE', + eee_disable: 'Disable EEE', + eee_on: 'ON', + eee_off: 'OFF', + + l2_title: 'FreeSwitchOS L2 Configuration', + l2_heading: 'L2 Configuration', + l2_col_port: 'Port', + l2_col_type: 'Type', + l2_col_remove: 'Remove Entry', + l2_delete: 'Delete', + l2_static: 'static', + l2_learned: 'learned', + + bw_title: 'Ingress and Egress Bandwidth', + bw_heading: 'Ingress and Egress Bandwidth', + bw_ingress: 'Ingress', + bw_egress: 'Egress', + bw_col_port: 'Port', + bw_col_limit: 'Limit', + bw_col_bandwidth: 'Bandwidth [kBit/s]', + bw_col_flow: 'Flow Control', + bw_col_apply: 'Apply', + bw_unlimited: 'UNLIMITED', + + sys_title: 'System Settings', + sys_tab_system: 'System', + sys_tab_advanced: 'Advanced', + sys_tab_console: 'Console', + sys_heading: 'System Settings', + sys_ip: 'IP address:', + sys_netmask: 'Netmask:', + sys_gateway: 'Gateway:', + sys_ip_note: 'When updating the above settings, remember to point your browser to the new IP afterwards:', + sys_update: 'Update Settings', + sys_save_label: 'Save all current settings to Flash:', + sys_save: 'Save Settings to Flash', + sys_advanced: 'Advanced Settings', + sys_startup_config: 'Startup configuration:', + sys_startup_warn: 'Be careful when saving the directly edited startup configuration, you can lock yourself out:', + sys_clear_config: 'Clear Startup Config', + sys_save_startup: 'Save Startup Settings to Flash', + sys_reset: 'Reset Switch', + sys_console: 'Console Command', + sys_enter_cmd: 'Enter command:', + sys_send_cmd: 'Send Command', + sys_console_warn: 'Be careful when entering console commands, you can lock yourself out!', + sys_invalid_ip: 'Invalid ip:', + sys_reset_confirm: 'Are you sure you want to reset the switch?', + sys_resetting: 'Switch is resetting. Please wait and refresh the page.', + + login_title: 'RTL Switch Login', + login_heading: 'RTL Switch Login', + login_wrong: 'Wrong password!', + login_password: 'Password', + login_login: 'Login', + + index_title: 'FreeSwitchOS Main Page', + index_heading: 'Switch Configuration', + index_settings: 'Settings', + + update_title: 'Firmware update', + update_heading: 'Firmware Update', + update_instruction: 'Choose a firmware update file to upload:', + update_upload: 'Upload File', + + lang_switch: 'Language:', + common_port: 'Port ', + common_pkts: ' pkts', + }, + + ja: { + nav_overview: '概要', + nav_port_config: 'ポート設定', + nav_port_stat: 'ポート統計', + nav_l2: 'L2 設定', + nav_mirror: 'ミラーリング', + nav_lag: 'リンクアグリゲーション', + nav_eee: 'EEE', + nav_bandwidth: '帯域制限', + nav_system: 'システム設定', + nav_fw_update: 'ファームウェア更新', + + port_name: '名前', + port_status: '状態', + port_not_enabled: '無効', + port_link_speed: 'リンク速度', + port_vendor: 'ベンダー', + port_model: 'モデル', + port_serial: 'シリアル', + port_temp: '温度', + port_vcc: '電圧', + port_tx_fault: 'TX 障害', + port_tx_disabled: 'TX 無効', + port_tx_bias: 'TX バイアス', + port_tx_power: 'TX 電力', + port_rx_power: 'RX 電力', + port_rx_los: 'RX 信号ロス', + + speed_disabled: '無効', + speed_down: 'リンクダウン', + + port_title: 'FreeSwitchOS ポート設定', + port_heading: 'ポート設定', + port_col_port: 'ポート', + port_col_name: '名前', + port_col_speed: '現在のリンク速度', + port_col_set_speed: '速度設定', + port_col_disabled: '無効', + port_col_apply: '適用', + port_mtu_heading: 'ポートの最大フレームサイズ (MTU) 設定', + port_auto: '自動', + port_2500m: '2500Mbps/全二重', + port_1000m: '1000Mbps/全二重', + port_100m_f: '100Mbps/全二重', + port_100m_h: '100Mbps/半二重', + port_10m_f: '10Mbps/全二重', + port_10m_h: '10Mbps/半二重', + port_apply: '適用', + + stat_title: 'FreeSwitchOS ポート統計', + stat_heading: 'ポート統計', + stat_detailed: '詳細ポート統計', + stat_close: '閉じる', + stat_col_port: 'ポート', + stat_col_name: '名前', + stat_col_link: 'リンク', + stat_col_tx_good: 'TX 正常', + stat_col_tx_bad: 'TX 異常', + stat_col_rx_good: 'RX 正常', + stat_col_rx_bad: 'RX 異常', + stat_col_all: '全カウンタ', + stat_counter: 'カウンタ', + stat_value: '値', + stat_show: '表示', + + vlan_title: 'FreeSwitchOS VLAN 設定', + vlan_heading: 'VLAN 設定', + vlan_select: 'VLAN 選択:', + vlan_choose: '— VLAN 選択 —', + vlan_id: 'VLAN ID:', + vlan_get_config: '設定取得', + vlan_name: 'VLAN 名:', + vlan_tagged: 'タグ付きポート', + vlan_untagged: 'タグ無しポート', + vlan_select_all: 'すべて選択', + vlan_pvid: '受信トラフィックのデフォルト VLAN (PVID)', + vlan_update: '更新 / 作成', + vlan_configured: '設定済み VLAN', + vlan_col_name: '名前', + vlan_col_member: 'メンバーポート', + vlan_col_tagged: 'タグ付きポート', + vlan_col_untagged: 'タグ無しポート', + vlan_col_pvid: 'PVID ポート', + vlan_col_delete: '削除', + vlan_set_id_first: 'VLAN ID を先に設定してください', + vlan_delete_confirm: 'VLAN 削除 ', + + lag_title: 'リンクアグリゲーション設定', + lag_heading: 'リンクアグリゲーショングループ設定', + lag_update: '更新 / 作成', + + mirror_title: 'ミラーリング設定', + mirror_heading: 'ミラーリング設定', + mirror_enabled: '有効:', + mirror_port: 'ミラーポート:', + mirror_tx: 'ミラー元ポート (TX)', + mirror_rx: 'ミラー元ポート (RX)', + mirror_update: '更新 / 作成', + mirror_disable: 'ミラーリング無効化', + mirror_set_port_first: 'ミラーポートを先に設定してください', + mirror_select_ports: 'ミラー元ポートを選択してください', + + eee_title: 'EEE 設定', + eee_heading: 'EEE 状態', + eee_advertising: 'EEE アドバタイジング', + eee_partner: 'リンクパートナー広告', + eee_port: 'ポート', + eee_active: '有効?', + eee_enable: 'EEE 有効化', + eee_disable: 'EEE 無効化', + eee_on: 'オン', + eee_off: 'オフ', + + l2_title: 'FreeSwitchOS L2 設定', + l2_heading: 'L2 設定', + l2_col_port: 'ポート', + l2_col_type: 'タイプ', + l2_col_remove: 'エントリ削除', + l2_delete: '削除', + l2_static: '静的', + l2_learned: '学習', + + bw_title: '入力/出力帯域制限', + bw_heading: '入力/出力帯域制限', + bw_ingress: '入力', + bw_egress: '出力', + bw_col_port: 'ポート', + bw_col_limit: '制限', + bw_col_bandwidth: '帯域 [kbps]', + bw_col_flow: 'フロー制御', + bw_col_apply: '適用', + bw_unlimited: '制限無し', + + sys_title: 'システム設定', + sys_tab_system: 'システム', + sys_tab_advanced: '詳細設定', + sys_tab_console: 'コンソール', + sys_heading: 'システム設定', + sys_ip: 'IP アドレス:', + sys_netmask: 'ネットマスク:', + sys_gateway: 'ゲートウェイ:', + sys_ip_note: '上記設定を変更した場合は、ブラウザで新しい IP にアクセスしてください:', + sys_update: '設定更新', + sys_save_label: '現在の設定をフラッシュに保存:', + sys_save: '設定をフラッシュに保存', + sys_advanced: '詳細設定', + sys_startup_config: '起動設定:', + sys_startup_warn: '起動設定を直接編集する際は注意してください。ロックアウトされる可能性があります:', + sys_clear_config: '起動設定クリア', + sys_save_startup: '起動設定をフラッシュに保存', + sys_reset: 'スイッチ再起動', + sys_console: 'コンソールコマンド', + sys_enter_cmd: 'コマンド入力:', + sys_send_cmd: 'コマンド送信', + sys_console_warn: 'コンソールコマンドは注意して入力してください。ロックアウトされる可能性があります!', + sys_invalid_ip: '無効な IP: ', + sys_reset_confirm: 'スイッチを再起動してもよろしいですか?', + sys_resetting: 'スイッチを再起動中です。しばらく待ってからページをリロードしてください。', + + login_title: 'RTL スイッチ ログイン', + login_heading: 'RTL スイッチ ログイン', + login_wrong: 'パスワードが違います!', + login_password: 'パスワード', + login_login: 'ログイン', + + index_title: 'FreeSwitchOS メインページ', + index_heading: 'スイッチ設定', + index_settings: '設定', + + update_title: 'ファームウェア更新', + update_heading: 'ファームウェア更新', + update_instruction: 'アップロードするファームウェアファイルを選択:', + update_upload: 'ファイルをアップロード', + + lang_switch: '言語:', + common_port: 'ポート ', + common_pkts: ' pkts', + } +}; + +var rtlLang = (function() { + var saved = localStorage.getItem('rtl_lang'); + if (saved && LANG[saved]) return saved; + var browser = (navigator.language || navigator.userLanguage || 'en').substring(0, 2); + return LANG[browser] ? browser : 'en'; +})(); + +function t(key) { + return LANG[rtlLang][key] || LANG['en'][key] || key; +} + +function setLang(lang) { + if (LANG[lang]) { + localStorage.setItem('rtl_lang', lang); + rtlLang = lang; + document.querySelectorAll('[data-i18n]').forEach(function(el) { + applyTranslation(el); + }); + var sel = document.getElementById('rtl-lang-select'); + if (sel) sel.value = lang; + } +} + +function applyTranslation(el) { + var key = el.getAttribute('data-i18n'); + if (!key) return; + if (el.tagName === 'INPUT' && (el.type === 'submit' || el.type === 'button')) { + el.value = t(key); + } else if (el.tagName === 'OPTION') { + el.textContent = t(key); + } else if (el.tagName === 'TITLE') { + el.textContent = t(key); + } else { + el.innerHTML = t(key); + } +} + +document.addEventListener('DOMContentLoaded', function() { + document.querySelectorAll('[data-i18n]').forEach(function(el) { + applyTranslation(el); + }); +}); diff --git a/html/index.html b/html/index.html index c9d1b31..4975df2 100644 --- a/html/index.html +++ b/html/index.html @@ -2,6 +2,7 @@ + - FreeSwitchOS Main Page + FreeSwitchOS Main Page
-

Switch Configuration

+

Switch Configuration

- + diff --git a/html/l2.html b/html/l2.html index 298c82a..029c4e9 100644 --- a/html/l2.html +++ b/html/l2.html @@ -1,16 +1,17 @@ + - FreeSwitchOS L2 Configuration + FreeSwitchOS L2 Configuration
-

L2 Configuration

+

L2 Configuration

SettingsSettings
- +
Port MAC VLAN Type Remove Entry
Port MAC VLAN Type Remove Entry
diff --git a/html/l2.js b/html/l2.js index c39dd27..25b1b1d 100644 --- a/html/l2.js +++ b/html/l2.js @@ -9,22 +9,22 @@ function fillStats() { if (tbl.rows.length > 1) { for (let i = 0; i < numPorts; i++) { console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]); - tbl.rows[i+1].cells[1].innerHTML = `${linkS[pState[i]+1]}`; - tbl.rows[i+1].cells[2].innerHTML = `${txG[i]} pkts`; - tbl.rows[i+1].cells[3].innerHTML = `${txB[i]} pkts`; - tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]} pkts`; - tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]} pkts`; + tbl.rows[i+1].cells[1].innerHTML = linkText(pState[i]+1); + tbl.rows[i+1].cells[2].innerHTML = `${txG[i]}` + t('common_pkts'); + tbl.rows[i+1].cells[3].innerHTML = `${txB[i]}` + t('common_pkts'); + tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]}` + t('common_pkts'); + tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]}` + t('common_pkts'); } } else { for (let i = 0; i < numPorts; i++) { console.log("Table row: " + i); const tr = tbl.insertRow(); - let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`)); - td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`)); - td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`)); - td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`)); - td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]} pkts`)); - td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]} pkts`)); + let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + (i+1))); + td = tr.insertCell(); td.appendChild(document.createTextNode(linkText(pState[i]+1))); + td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]}` + t('common_pkts'))); + td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]}` + t('common_pkts'))); + td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]}` + t('common_pkts'))); + td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]}` + t('common_pkts'))); } } } @@ -71,7 +71,7 @@ function fillL2(s) return; s.sort(l2CMP); s = uniq(s); - var s = s.map(function(e) { e.port = e.port != 9 ? e.port : "CPU"; return e; }); + var s = s.map(function(e) { e.port = e.port != 9 ? e.port : 'CPU'; return e; }); console.log("L2: ", JSON.stringify(s)); for (let i = 0; i < s.length; i++) { var e = s[i]; @@ -80,14 +80,14 @@ function fillL2(s) tbl.rows[i+1].cells[0].innerHTML = `${e.port}`; tbl.rows[i+1].cells[1].innerHTML = `${e.mac}`; tbl.rows[i+1].cells[2].innerHTML = `${e.vlan}`; - tbl.rows[i+1].cells[4].innerHTML = ''; + tbl.rows[i+1].cells[4].innerHTML = ''; } else { const tr = tbl.insertRow(); let td = tr.insertCell(); td.innerHTML = `${e.port}`; td = tr.insertCell(); td.innerHTML = `${e.mac}`; td = tr.insertCell(); td.innerHTML = `${e.vlan}`; td = tr.insertCell(); td.innerHTML = `${e.type}`; - td = tr.insertCell(); td.innerHTML = ''; + td = tr.insertCell(); td.innerHTML = ''; } } for (let i = tbl.rows.length - 1; i > s.length; i--) @@ -103,7 +103,7 @@ function getL2() { var s = s.map(function(e) { e.vlan = parseInt(e.vlan, 16); e.idx = parseInt(e.idx, 16); - e.type = e.type == "s" ? "static" : "learned"; + e.type = e.type == "s" ? t('l2_static') : t('l2_learned'); e.port = e.port == 9 ? 9 : logToPhysPort[e.port]; return e; }); diff --git a/html/lag.html b/html/lag.html index 29b2b66..7a5e5f7 100644 --- a/html/lag.html +++ b/html/lag.html @@ -1,24 +1,25 @@ + - Link Aggregation Configuration + Link Aggregation Configuration
-

Link Aggregation Groups Configuration

-

LAG 1

+

Link Aggregation Groups Configuration

+

LAG 1


-

LAG 2

+

LAG 2


-

LAG 3

+

LAG 3


-

LAG 4

+

LAG 4

diff --git a/html/login.html b/html/login.html index 81a96ea..dcb6089 100644 --- a/html/login.html +++ b/html/login.html @@ -1,30 +1,30 @@ - RTL Switch Login + RTL Switch Login + +
-

RTL Switch Login

+

RTL Switch Login

- +
- +

- diff --git a/html/main.js b/html/main.js index 08499af..f82b232 100644 --- a/html/main.js +++ b/html/main.js @@ -2,11 +2,12 @@ var txG = new BigInt64Array(10); var txB = new BigInt64Array(10); var rxG = new BigInt64Array(10); var rxB = new BigInt64Array(10); -const linkS = ["Disabled", "Down", "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"]; +const linkS = [function(){return t('speed_disabled')}, function(){return t('speed_down')}, "10M", "100M", "1000M", "500M", "10G", "2.5G", "5G"]; var pState = new Int8Array(10); var pIsSFP = new Int8Array(10); var pAdvertised = new Int8Array(10); var numPorts = 0; +function linkText(idx) { var v = linkS[idx]; return typeof v === 'function' ? v() : v; } var logToPhysPort = new Int8Array(10); var physToLogPort = new Int8Array(10); var portNames = new Array(10); @@ -21,7 +22,7 @@ function drawPorts() { d.classList.add('tooltip'); const s = document.createElement("span"); s.classList.add("tooltiptext"); - s.innerHTML = "Tooltip text"; + s.innerHTML = t('common_port'); s.id="tt_" + (i+1); const l = document.createElement("object"); d.appendChild(l); @@ -152,13 +153,13 @@ function update(callback) { continue; const portName = p.name || portNames[p.logPort] || ''; var iHTML = ""; - if (portName) iHTML += ""; + if (portName) iHTML += ""; if (p.enabled == 0) { pState[n] = -1; bgs[0].style.fill = "red"; leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4; - iHTML += ""; + iHTML += ""; iHTML += "
Name:" + portName + "
" + t('port_name') + ":" + portName + "
Status:Not enabled.
" + t('port_status') + ":" + t('port_not_enabled') + "
"; tt.innerHTML = iHTML; } else { @@ -174,31 +175,31 @@ function update(callback) { leds[0].style.fill = "black"; leds[1].style.fill = "black"; psvg.style.opacity = 0.4 } - iHTML += "Link speed:" + linkS[p.link + 1] + ""; + iHTML += "" + t('port_link_speed') + ":" + linkText(p.link + 1) + ""; if (p.isSFP) { pAdvertised[n] = 0; const hasExtendedStatus = p.sfp_options & 0x40; - iHTML += "Vendor:" + p.sfp_vendor + ""; - iHTML += "Model:" + p.sfp_model + ""; - iHTML += "Serial:" + p.sfp_serial + ""; + iHTML += "" + t('port_vendor') + ":" + p.sfp_vendor + ""; + iHTML += "" + t('port_model') + ":" + p.sfp_model + ""; + iHTML += "" + t('port_serial') + ":" + p.sfp_serial + ""; if (hasExtendedStatus) { let txPower = decodeSfpTxPower(p.sfp_txpower, p.sfp_txpower_cal); let txPowerdBm = convertPowerTodBm(txPower); let rxPower = decodeSfpRxPower(p.sfp_rxpower, p.sfp_rxpower_cal); let rxPowerdBm = convertPowerTodBm(rxPower); - iHTML += "Temp:" + decodeSfpTemp(p.sfp_temp, p.sfp_temp_cal).toFixed(2) + " ℃"; - iHTML += "Vcc:" + decodeSfpVcc(p.sfp_vcc, p.sfp_vcc_cal).toFixed(2) + " V"; - iHTML += "TX-Fault:" + (Boolean(Number(p.sfp_state) & 0x4)) + ""; - iHTML += "TX-Disabled:" + (Boolean(Number(p.sfp_state) & 0x80)) + ""; - iHTML += "TX-Bias:" + decodeSfpTxBias(p.sfp_txbias, p.sfp_txbias_cal).toFixed(1) + " mA"; - iHTML += "TX-Power:" + txPower.toFixed(3) + " mW / " + txPowerdBm.toFixed(2) + " dBm"; - iHTML += "RX-Power:" + rxPower.toFixed(3) + " mW / " + rxPowerdBm.toFixed(2) + " dBm"; + iHTML += "" + t('port_temp') + ":" + decodeSfpTemp(p.sfp_temp, p.sfp_temp_cal).toFixed(2) + " ℃"; + iHTML += "" + t('port_vcc') + ":" + decodeSfpVcc(p.sfp_vcc, p.sfp_vcc_cal).toFixed(2) + " V"; + iHTML += "" + t('port_tx_fault') + ":" + (Boolean(Number(p.sfp_state) & 0x4)) + ""; + iHTML += "" + t('port_tx_disabled') + ":" + (Boolean(Number(p.sfp_state) & 0x80)) + ""; + iHTML += "" + t('port_tx_bias') + ":" + decodeSfpTxBias(p.sfp_txbias, p.sfp_txbias_cal).toFixed(1) + " mA"; + iHTML += "" + t('port_tx_power') + ":" + txPower.toFixed(3) + " mW / " + txPowerdBm.toFixed(2) + " dBm"; + iHTML += "" + t('port_rx_power') + ":" + rxPower.toFixed(3) + " mW / " + rxPowerdBm.toFixed(2) + " dBm"; } // Not all devices & modules have LOS pin... const rx_los_pin = p.sfp_los !== null ? Boolean(Number(p.sfp_los)) : null; const rx_los_module = hasExtendedStatus ? Boolean(Number(p.sfp_state) & 0x2) : null; if (rx_los_module !== null || rx_los_pin !== null) { - iHTML += `RX-LOS:${rxLosHTML(rx_los_pin, rx_los_module)}`; + iHTML += `` + t('port_rx_los') + `:${rxLosHTML(rx_los_pin, rx_los_module)}`; } } else { pAdvertised[n] = parseInt(p.adv, 2); diff --git a/html/mirror.html b/html/mirror.html index edf5b77..22c5af3 100644 --- a/html/mirror.html +++ b/html/mirror.html @@ -1,23 +1,24 @@ + - Mirror Configuration + Mirror Configuration
-

Mirror Configuration

-
- -

Mirrored Ports (TX)

+

Mirror Configuration

+
+ +

Mirrored Ports (TX)


-

Mirrored Ports (RX)

+

Mirrored Ports (RX)

-
- +
+
diff --git a/html/mirror_sub.js b/html/mirror_sub.js index 7d8c0bb..da5b6cd 100644 --- a/html/mirror_sub.js +++ b/html/mirror_sub.js @@ -2,7 +2,7 @@ async function mirrorSub() { var cmd = "mirror "; var mp=document.getElementById('mp').value if (!mp) { - alert("Set Mirroring Port first"); + alert(t('mirror_set_port_first')); return; } document.getElementById(mirrors[0]+mp).checked=false;document.getElementById(mirrors[1]+mp).checked=false; @@ -16,7 +16,7 @@ async function mirrorSub() { cmd = cmd + ` ${i}r`; } if (cmd.length < 10) { - alert("Select Mirrored Ports"); + alert(t('mirror_select_ports')); return; } try { diff --git a/html/navigation.js b/html/navigation.js index 99a603e..8a92cb2 100644 --- a/html/navigation.js +++ b/html/navigation.js @@ -1,12 +1,25 @@ document.getElementById('sidebar').innerHTML = - ""; + "" + + "

" + + "
"; + +document.addEventListener('DOMContentLoaded', function() { + var sel = document.getElementById('rtl-lang-select'); + if (sel) sel.value = rtlLang; + var links = document.querySelectorAll('#sidebar a[data-i18n]'); + links.forEach(function(el) { + var key = el.getAttribute('data-i18n'); + if (key) el.textContent = t(key); + }); +}); diff --git a/html/ports.html b/html/ports.html index 9e27808..8d9409f 100644 --- a/html/ports.html +++ b/html/ports.html @@ -1,19 +1,20 @@ + - FreeSwitchOS Port Configuration + FreeSwitchOS Port Configuration
-

Port Configuration

+

Port Configuration

- +
Port Name Current Link SpeedSet SpeedDisabledApply
Port Name Current Link SpeedSet SpeedDisabledApply
-

Configure Maximum Frame Size (MTU) forwarded at Port

+

Configure Maximum Frame Size (MTU) forwarded at Port

diff --git a/html/ports.js b/html/ports.js index 6fc4f40..9079ca1 100644 --- a/html/ports.js +++ b/html/ports.js @@ -3,29 +3,29 @@ var clicked = new Int8Array(10); function createPortTable() { var tbl = document.getElementById('speedtable'); if (tbl.rows.length <= 2 && numPorts) { - const sSelect = ''; + const sSelect = ''; const dSwitch = '' for (let i = 1; i <= numPorts; i++) { if (pIsSFP[i-1]) continue; console.log("Table row: " + i + "pState: " + pState[i-2]); const tr = tbl.insertRow(); - let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i}`)); + let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + i)); let portName = portNames[physToLogPort[i-1]] || ''; td = tr.insertCell(); td.appendChild(document.createTextNode(portName)); - td = tr.insertCell(); td.innerHTML = linkS[pState[i] + 1]; + td = tr.insertCell(); td.innerHTML = linkText(pState[i] + 1); td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i); td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i) .replace("portOnOff()", "portOnOff(" + i + ")"); - var button = ''; + var button = ''; td = tr.insertCell(); td.innerHTML = button; } @@ -55,7 +55,7 @@ function createPortTable() { tr = tbl.insertRow(); for (let i = 1; i <= numPorts; i++) { let td = tr.insertCell(); - td.innerHTML = ''; + td.innerHTML = ''; } } } @@ -68,7 +68,7 @@ function updatePortTable() { for (let i = 1; i <= numPorts ; i++) { if (pIsSFP[i-1]) continue; - tbl.rows[i].cells[2].innerHTML = `${linkS[pState[i-1]+1]}`; + tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1); if (!clicked[i] && pState[i - 1] < 0) { document.getElementById('speed_sel_' + i).disabled = true; document.getElementById('disable_port_' + i).checked = true; diff --git a/html/stat.html b/html/stat.html index 03b0367..993eede 100644 --- a/html/stat.html +++ b/html/stat.html @@ -1,8 +1,9 @@ + - FreeSwitchOS Port Statistics + FreeSwitchOS Port Statistics