feat(i18n): add multi-language support (ja/ko/vi/ru/zh-TW) with system auto-detection
- Extend AppLanguage to 7 locales: zh-CN, zh-TW, en, ja, ko, vi, ru - Auto-detect system language via navigator.languages; fallback to English - Add BCP47 locale mapping for date formatting and sorting - Create 50 translation JSON files (5 languages × 10 namespaces, 1137 keys each) - Update language selector with native language names - Extend locale key parity test to cover all 7 languages (70 assertions) - Add VNC/RDP desktop, serial terminal, AI agent, port forwarding, and SFTP features - Add credential encryption, host metrics, session backup crypto, and zmodem bridge - Update Rust backend: desktop services, host metrics, SSH/SFTP enhancements
This commit is contained in:
1 parent
fea6d8db04
commit
b0d0e3a5f3
301 files changed
+28002
-2705
No files matched your search
@@ -1,6 +1,11 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { expandSnippetVariables } from '../../src/utils/snippetVariables'
|
||||
import { applyKeywordHighlights, DEFAULT_KEYWORD_HIGHLIGHT_RULES } from '../../src/utils/keywordHighlight'
|
||||
import {
|
||||
StreamingKeywordHighlight,
|
||||
trailingIncompleteEscape,
|
||||
} from '../../src/utils/streamingKeywordHighlight'
|
||||
import { localShellEnterKey, normalizeTerminalInject } from '../../src/utils/platformShells'
|
||||
|
||||
describe('expandSnippetVariables', () => {
|
||||
it('replaces known placeholders', () => {
|
||||
@@ -35,4 +40,87 @@ describe('applyKeywordHighlights', () => {
|
||||
const text = 'no highlight'
|
||||
expect(applyKeywordHighlights(text, rules)).toBe(text)
|
||||
})
|
||||
|
||||
it('does not inject SGR inside OSC window-title sequences (SSH title leak)', () => {
|
||||
const rules = [
|
||||
{
|
||||
id: 'ipv4',
|
||||
label: 'IPv4',
|
||||
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
||||
isRegex: true,
|
||||
color: '#8be9fd',
|
||||
enabled: true,
|
||||
},
|
||||
]
|
||||
const osc = '\x1b]0;ssh root@165.154.155.48\x07'
|
||||
const out = applyKeywordHighlights(`${osc}Welcome to Ubuntu`, rules)
|
||||
expect(out).toContain(osc)
|
||||
expect(out).not.toMatch(/\x1b\]0;.*\x1b\[38/)
|
||||
expect(out).toContain('Welcome to Ubuntu')
|
||||
})
|
||||
|
||||
it('still highlights IPs in plain text when the ipv4 rule is enabled', () => {
|
||||
const rules = [
|
||||
{
|
||||
id: 'ipv4',
|
||||
label: 'IPv4',
|
||||
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
||||
isRegex: true,
|
||||
color: '#8be9fd',
|
||||
enabled: true,
|
||||
},
|
||||
]
|
||||
const out = applyKeywordHighlights('peer 10.0.0.1 online', rules)
|
||||
expect(out).toContain('\x1b[38;2;')
|
||||
expect(out).toContain('10.0.0.1')
|
||||
expect(out).toContain('\x1b[39m')
|
||||
})
|
||||
|
||||
it('leaves existing CSI color sequences intact', () => {
|
||||
const colored = '\x1b[01;32mroot\x1b[00m@host'
|
||||
const out = applyKeywordHighlights(colored, DEFAULT_KEYWORD_HIGHLIGHT_RULES)
|
||||
expect(out).toContain('\x1b[01;32mroot\x1b[00m')
|
||||
})
|
||||
})
|
||||
|
||||
describe('StreamingKeywordHighlight', () => {
|
||||
const ipv4Rules = [
|
||||
{
|
||||
id: 'ipv4',
|
||||
label: 'IPv4',
|
||||
pattern: '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b',
|
||||
isRegex: true,
|
||||
color: '#8be9fd',
|
||||
enabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
it('holds incomplete OSC across chunks', () => {
|
||||
expect(trailingIncompleteEscape('\x1b]0;ssh root@1.2.3.4')).toBe('\x1b]0;ssh root@1.2.3.4')
|
||||
const stream = new StreamingKeywordHighlight()
|
||||
expect(stream.push('\x1b]0;ssh root@1.2.3.4', ipv4Rules)).toBe('')
|
||||
const done = stream.push('\x07Welcome', ipv4Rules)
|
||||
expect(done).toContain('\x1b]0;ssh root@1.2.3.4\x07')
|
||||
expect(done).toContain('Welcome')
|
||||
expect(done).not.toMatch(/\x1b\]0;.*\x1b\[38/)
|
||||
})
|
||||
|
||||
it('holds incomplete CSI across chunks', () => {
|
||||
const stream = new StreamingKeywordHighlight()
|
||||
expect(stream.push('\x1b[38;2;139', ipv4Rules)).toBe('')
|
||||
const out = stream.push(';233;253m10.0.0.1 done', ipv4Rules)
|
||||
expect(out.startsWith('\x1b[38;2;139;233;253m')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('normalizeTerminalInject', () => {
|
||||
it('converts LF to CR like xterm paste', () => {
|
||||
expect(normalizeTerminalInject('echo hi\n', '')).toBe('echo hi\r')
|
||||
expect(normalizeTerminalInject('echo hi', '\r')).toBe('echo hi\r')
|
||||
})
|
||||
|
||||
it('uses CR enter for unix local shells', () => {
|
||||
expect(localShellEnterKey('zsh')).toBe('\r')
|
||||
expect(localShellEnterKey('pwsh')).toBe('\r\n')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user