@lobehub/chat 1.97.17 → 1.98.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/apps/desktop/package.json +8 -5
- package/apps/desktop/src/main/const/store.ts +12 -0
- package/apps/desktop/src/main/controllers/NetworkProxyCtr.ts +172 -0
- package/apps/desktop/src/main/controllers/__tests__/NetworkProxyCtr.test.ts +401 -0
- package/apps/desktop/src/main/core/Browser.ts +2 -0
- package/apps/desktop/src/main/modules/networkProxy/dispatcher.ts +116 -0
- package/apps/desktop/src/main/modules/networkProxy/index.ts +6 -0
- package/apps/desktop/src/main/modules/networkProxy/tester.ts +163 -0
- package/apps/desktop/src/main/modules/networkProxy/urlBuilder.ts +25 -0
- package/apps/desktop/src/main/modules/networkProxy/validator.ts +80 -0
- package/apps/desktop/src/main/types/store.ts +2 -1
- package/apps/desktop/src/main/utils/logger.ts +2 -1
- package/changelog/v1.json +9 -0
- package/locales/ar/electron.json +39 -0
- package/locales/ar/setting.json +1 -0
- package/locales/bg-BG/electron.json +39 -0
- package/locales/bg-BG/setting.json +1 -0
- package/locales/de-DE/electron.json +39 -0
- package/locales/de-DE/setting.json +1 -0
- package/locales/en-US/electron.json +39 -0
- package/locales/en-US/setting.json +1 -0
- package/locales/es-ES/electron.json +39 -0
- package/locales/es-ES/setting.json +1 -0
- package/locales/fa-IR/electron.json +39 -0
- package/locales/fa-IR/setting.json +1 -0
- package/locales/fr-FR/electron.json +39 -0
- package/locales/fr-FR/setting.json +1 -0
- package/locales/it-IT/electron.json +39 -0
- package/locales/it-IT/setting.json +1 -0
- package/locales/ja-JP/electron.json +39 -0
- package/locales/ja-JP/setting.json +1 -0
- package/locales/ko-KR/electron.json +39 -0
- package/locales/ko-KR/setting.json +1 -0
- package/locales/nl-NL/electron.json +39 -0
- package/locales/nl-NL/setting.json +1 -0
- package/locales/pl-PL/electron.json +39 -0
- package/locales/pl-PL/setting.json +1 -0
- package/locales/pt-BR/electron.json +39 -0
- package/locales/pt-BR/setting.json +1 -0
- package/locales/ru-RU/electron.json +39 -0
- package/locales/ru-RU/setting.json +1 -0
- package/locales/tr-TR/electron.json +39 -0
- package/locales/tr-TR/setting.json +1 -0
- package/locales/vi-VN/electron.json +39 -0
- package/locales/vi-VN/setting.json +1 -0
- package/locales/zh-CN/electron.json +39 -0
- package/locales/zh-CN/setting.json +1 -0
- package/locales/zh-TW/electron.json +39 -0
- package/locales/zh-TW/setting.json +1 -0
- package/package.json +3 -3
- package/packages/electron-client-ipc/src/events/index.ts +3 -1
- package/packages/electron-client-ipc/src/events/settings.ts +12 -0
- package/packages/electron-client-ipc/src/types/index.ts +1 -0
- package/packages/electron-client-ipc/src/types/proxy.ts +12 -0
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +11 -1
- package/src/app/[variants]/(main)/settings/proxy/features/ProxyForm.tsx +369 -0
- package/src/app/[variants]/(main)/settings/proxy/index.tsx +22 -0
- package/src/app/[variants]/(main)/settings/proxy/page.tsx +28 -0
- package/src/locales/default/electron.ts +39 -0
- package/src/locales/default/setting.ts +1 -0
- package/src/services/electron/settings.ts +33 -0
- package/src/store/electron/actions/settings.ts +55 -0
- package/src/store/electron/initialState.ts +12 -1
- package/src/store/electron/selectors/__tests__/desktopState.test.ts +3 -1
- package/src/store/electron/store.ts +4 -1
- package/src/store/global/initialState.ts +1 -0
- package/apps/desktop/scripts/pglite-server.ts +0 -14
@@ -0,0 +1,116 @@
|
|
1
|
+
import { NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
2
|
+
import { Agent, ProxyAgent, getGlobalDispatcher, setGlobalDispatcher } from 'undici';
|
3
|
+
|
4
|
+
import { createLogger } from '@/utils/logger';
|
5
|
+
|
6
|
+
import { ProxyUrlBuilder } from './urlBuilder';
|
7
|
+
|
8
|
+
// Create logger
|
9
|
+
const logger = createLogger('modules:networkProxy:dispatcher');
|
10
|
+
|
11
|
+
/**
|
12
|
+
* 代理管理器
|
13
|
+
*/
|
14
|
+
export class ProxyDispatcherManager {
|
15
|
+
private static isChanging = false;
|
16
|
+
private static changeQueue: Array<() => Promise<void>> = [];
|
17
|
+
|
18
|
+
/**
|
19
|
+
* 应用代理设置(带并发控制)
|
20
|
+
*/
|
21
|
+
static async applyProxySettings(config: NetworkProxySettings): Promise<void> {
|
22
|
+
return new Promise((resolve, reject) => {
|
23
|
+
const operation = async () => {
|
24
|
+
try {
|
25
|
+
await this.doApplyProxySettings(config);
|
26
|
+
resolve();
|
27
|
+
} catch (error) {
|
28
|
+
reject(error);
|
29
|
+
}
|
30
|
+
};
|
31
|
+
|
32
|
+
if (this.isChanging) {
|
33
|
+
// 如果正在切换,加入队列
|
34
|
+
this.changeQueue.push(operation);
|
35
|
+
} else {
|
36
|
+
// 立即执行
|
37
|
+
operation();
|
38
|
+
}
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* 执行代理设置应用
|
44
|
+
*/
|
45
|
+
private static async doApplyProxySettings(config: NetworkProxySettings): Promise<void> {
|
46
|
+
this.isChanging = true;
|
47
|
+
|
48
|
+
try {
|
49
|
+
const currentDispatcher = getGlobalDispatcher();
|
50
|
+
|
51
|
+
// 禁用代理,恢复默认连接
|
52
|
+
if (!config.enableProxy) {
|
53
|
+
await this.safeDestroyDispatcher(currentDispatcher);
|
54
|
+
// 创建一个新的默认 Agent 来替代代理
|
55
|
+
setGlobalDispatcher(new Agent());
|
56
|
+
logger.debug('Proxy disabled, reset to direct connection mode');
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
|
60
|
+
// 构建代理 URL
|
61
|
+
const proxyUrl = ProxyUrlBuilder.build(config);
|
62
|
+
|
63
|
+
// 创建代理 agent
|
64
|
+
const agent = this.createProxyAgent(config.proxyType, proxyUrl);
|
65
|
+
|
66
|
+
// 切换代理前销毁旧 dispatcher
|
67
|
+
await this.safeDestroyDispatcher(currentDispatcher);
|
68
|
+
setGlobalDispatcher(agent);
|
69
|
+
|
70
|
+
logger.info(
|
71
|
+
`Proxy settings applied: ${config.proxyType}://${config.proxyServer}:${config.proxyPort}`,
|
72
|
+
);
|
73
|
+
logger.debug(
|
74
|
+
'Global request proxy set, all Node.js network requests will go through this proxy',
|
75
|
+
);
|
76
|
+
} finally {
|
77
|
+
this.isChanging = false;
|
78
|
+
|
79
|
+
// 处理队列中的下一个操作
|
80
|
+
if (this.changeQueue.length > 0) {
|
81
|
+
const nextOperation = this.changeQueue.shift();
|
82
|
+
if (nextOperation) {
|
83
|
+
setTimeout(() => nextOperation(), 0);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* 创建代理 agent
|
91
|
+
*/
|
92
|
+
static createProxyAgent(proxyType: string, proxyUrl: string) {
|
93
|
+
try {
|
94
|
+
// undici 的 ProxyAgent 支持 http, https 和 socks5
|
95
|
+
return new ProxyAgent({ uri: proxyUrl });
|
96
|
+
} catch (error) {
|
97
|
+
logger.error(`Failed to create proxy agent for ${proxyType}:`, error);
|
98
|
+
throw new Error(
|
99
|
+
`Failed to create proxy agent: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
100
|
+
);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* 安全销毁 dispatcher
|
106
|
+
*/
|
107
|
+
private static async safeDestroyDispatcher(dispatcher: any): Promise<void> {
|
108
|
+
try {
|
109
|
+
if (dispatcher && typeof dispatcher.destroy === 'function') {
|
110
|
+
await dispatcher.destroy();
|
111
|
+
}
|
112
|
+
} catch (error) {
|
113
|
+
logger.warn('Failed to destroy dispatcher:', error);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
export { ProxyDispatcherManager } from './dispatcher';
|
2
|
+
export type { ProxyTestResult } from './tester';
|
3
|
+
export { ProxyConnectionTester } from './tester';
|
4
|
+
export { ProxyUrlBuilder } from './urlBuilder';
|
5
|
+
export type { ProxyValidationResult } from './validator';
|
6
|
+
export { ProxyConfigValidator } from './validator';
|
@@ -0,0 +1,163 @@
|
|
1
|
+
import { NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
2
|
+
import { fetch, getGlobalDispatcher, setGlobalDispatcher } from 'undici';
|
3
|
+
|
4
|
+
import { createLogger } from '@/utils/logger';
|
5
|
+
|
6
|
+
import { ProxyDispatcherManager } from './dispatcher';
|
7
|
+
import { ProxyUrlBuilder } from './urlBuilder';
|
8
|
+
import { ProxyConfigValidator } from './validator';
|
9
|
+
|
10
|
+
// Create logger
|
11
|
+
const logger = createLogger('modules:networkProxy:tester');
|
12
|
+
|
13
|
+
/**
|
14
|
+
* 代理连接测试结果
|
15
|
+
*/
|
16
|
+
export interface ProxyTestResult {
|
17
|
+
message?: string;
|
18
|
+
responseTime?: number;
|
19
|
+
success: boolean;
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* 代理连接测试器
|
24
|
+
*/
|
25
|
+
export class ProxyConnectionTester {
|
26
|
+
private static readonly DEFAULT_TIMEOUT = 10_000; // 10秒超时
|
27
|
+
private static readonly DEFAULT_TEST_URL = 'https://www.google.com';
|
28
|
+
|
29
|
+
/**
|
30
|
+
* 测试代理连接
|
31
|
+
*/
|
32
|
+
static async testConnection(
|
33
|
+
url: string = this.DEFAULT_TEST_URL,
|
34
|
+
timeout: number = this.DEFAULT_TIMEOUT,
|
35
|
+
): Promise<ProxyTestResult> {
|
36
|
+
const startTime = Date.now();
|
37
|
+
|
38
|
+
try {
|
39
|
+
logger.info(`Testing proxy connection with URL: ${url}`);
|
40
|
+
|
41
|
+
const controller = new AbortController();
|
42
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
43
|
+
|
44
|
+
const response = await fetch(url, {
|
45
|
+
headers: {
|
46
|
+
'User-Agent': 'LobeChat-Desktop/1.0.0',
|
47
|
+
},
|
48
|
+
signal: controller.signal,
|
49
|
+
});
|
50
|
+
|
51
|
+
clearTimeout(timeoutId);
|
52
|
+
|
53
|
+
if (!response.ok) {
|
54
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
55
|
+
}
|
56
|
+
|
57
|
+
const responseTime = Date.now() - startTime;
|
58
|
+
|
59
|
+
logger.info(`Proxy connection test successful, response time: ${responseTime}ms`);
|
60
|
+
|
61
|
+
return {
|
62
|
+
responseTime,
|
63
|
+
success: true,
|
64
|
+
};
|
65
|
+
} catch (error) {
|
66
|
+
const responseTime = Date.now() - startTime;
|
67
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
68
|
+
|
69
|
+
logger.error(`Proxy connection test failed after ${responseTime}ms:`, errorMessage);
|
70
|
+
|
71
|
+
return {
|
72
|
+
message: errorMessage,
|
73
|
+
responseTime,
|
74
|
+
success: false,
|
75
|
+
};
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* 测试指定代理配置的连接
|
81
|
+
*/
|
82
|
+
static async testProxyConfig(
|
83
|
+
config: NetworkProxySettings,
|
84
|
+
testUrl: string = this.DEFAULT_TEST_URL,
|
85
|
+
): Promise<ProxyTestResult> {
|
86
|
+
// 验证配置
|
87
|
+
const validation = ProxyConfigValidator.validate(config);
|
88
|
+
if (!validation.isValid) {
|
89
|
+
return {
|
90
|
+
message: `Invalid proxy configuration: ${validation.errors.join(', ')}`,
|
91
|
+
success: false,
|
92
|
+
};
|
93
|
+
}
|
94
|
+
|
95
|
+
// 如果未启用代理,直接测试
|
96
|
+
if (!config.enableProxy) {
|
97
|
+
return this.testConnection(testUrl);
|
98
|
+
}
|
99
|
+
|
100
|
+
// 创建临时代理 agent 进行测试
|
101
|
+
try {
|
102
|
+
const proxyUrl = ProxyUrlBuilder.build(config);
|
103
|
+
logger.debug(`Testing proxy with URL: ${proxyUrl}`);
|
104
|
+
|
105
|
+
const agent = ProxyDispatcherManager.createProxyAgent(config.proxyType, proxyUrl);
|
106
|
+
|
107
|
+
const startTime = Date.now();
|
108
|
+
const controller = new AbortController();
|
109
|
+
const timeoutId = setTimeout(() => controller.abort(), this.DEFAULT_TIMEOUT);
|
110
|
+
|
111
|
+
// 临时设置代理进行测试
|
112
|
+
const originalDispatcher = getGlobalDispatcher();
|
113
|
+
setGlobalDispatcher(agent);
|
114
|
+
|
115
|
+
try {
|
116
|
+
const response = await fetch(testUrl, {
|
117
|
+
dispatcher: agent,
|
118
|
+
headers: {
|
119
|
+
'User-Agent': 'LobeChat-Desktop/1.0.0',
|
120
|
+
},
|
121
|
+
signal: controller.signal,
|
122
|
+
});
|
123
|
+
|
124
|
+
clearTimeout(timeoutId);
|
125
|
+
|
126
|
+
if (!response.ok) {
|
127
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
128
|
+
}
|
129
|
+
|
130
|
+
const responseTime = Date.now() - startTime;
|
131
|
+
logger.info(`Proxy test successful, response time: ${responseTime}ms`);
|
132
|
+
|
133
|
+
return {
|
134
|
+
responseTime,
|
135
|
+
success: true,
|
136
|
+
};
|
137
|
+
} catch (fetchError) {
|
138
|
+
clearTimeout(timeoutId);
|
139
|
+
throw fetchError;
|
140
|
+
} finally {
|
141
|
+
// 恢复原来的 dispatcher
|
142
|
+
setGlobalDispatcher(originalDispatcher);
|
143
|
+
// 清理临时创建的代理 agent
|
144
|
+
if (agent && typeof agent.destroy === 'function') {
|
145
|
+
try {
|
146
|
+
await agent.destroy();
|
147
|
+
} catch (error) {
|
148
|
+
logger.warn('Failed to destroy test agent:', error);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
} catch (error) {
|
153
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
154
|
+
|
155
|
+
logger.error(`Proxy test failed: ${errorMessage}`, error);
|
156
|
+
|
157
|
+
return {
|
158
|
+
message: `Proxy test failed: ${errorMessage}`,
|
159
|
+
success: false,
|
160
|
+
};
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 代理 URL 构建器
|
5
|
+
*/
|
6
|
+
export const ProxyUrlBuilder = {
|
7
|
+
/**
|
8
|
+
* 构建代理 URL
|
9
|
+
*/
|
10
|
+
build(config: NetworkProxySettings): string {
|
11
|
+
const { proxyType, proxyServer, proxyPort, proxyRequireAuth, proxyUsername, proxyPassword } =
|
12
|
+
config;
|
13
|
+
|
14
|
+
let proxyUrl = `${proxyType}://${proxyServer}:${proxyPort}`;
|
15
|
+
|
16
|
+
// 添加认证信息
|
17
|
+
if (proxyRequireAuth && proxyUsername && proxyPassword) {
|
18
|
+
const encodedUsername = encodeURIComponent(proxyUsername);
|
19
|
+
const encodedPassword = encodeURIComponent(proxyPassword);
|
20
|
+
proxyUrl = `${proxyType}://${encodedUsername}:${encodedPassword}@${proxyServer}:${proxyPort}`;
|
21
|
+
}
|
22
|
+
|
23
|
+
return proxyUrl;
|
24
|
+
},
|
25
|
+
};
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import { NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 代理配置验证结果
|
5
|
+
*/
|
6
|
+
export interface ProxyValidationResult {
|
7
|
+
errors: string[];
|
8
|
+
isValid: boolean;
|
9
|
+
}
|
10
|
+
|
11
|
+
/**
|
12
|
+
* 代理配置验证器
|
13
|
+
*/
|
14
|
+
export class ProxyConfigValidator {
|
15
|
+
private static readonly SUPPORTED_TYPES = ['http', 'https', 'socks5'] as const;
|
16
|
+
private static readonly DEFAULT_BYPASS = 'localhost,127.0.0.1,::1';
|
17
|
+
|
18
|
+
/**
|
19
|
+
* 验证代理配置
|
20
|
+
*/
|
21
|
+
static validate(config: NetworkProxySettings): ProxyValidationResult {
|
22
|
+
const errors: string[] = [];
|
23
|
+
|
24
|
+
// 如果未启用代理,跳过验证
|
25
|
+
if (!config.enableProxy) {
|
26
|
+
return { errors: [], isValid: true };
|
27
|
+
}
|
28
|
+
|
29
|
+
// 验证代理类型
|
30
|
+
if (!this.SUPPORTED_TYPES.includes(config.proxyType as any)) {
|
31
|
+
errors.push(
|
32
|
+
`Unsupported proxy type: ${config.proxyType}. Supported types: ${this.SUPPORTED_TYPES.join(', ')}`,
|
33
|
+
);
|
34
|
+
}
|
35
|
+
|
36
|
+
// 验证代理服务器
|
37
|
+
if (!config.proxyServer?.trim()) {
|
38
|
+
errors.push('Proxy server is required when proxy is enabled');
|
39
|
+
} else if (!this.isValidHost(config.proxyServer)) {
|
40
|
+
errors.push('Invalid proxy server format');
|
41
|
+
}
|
42
|
+
|
43
|
+
// 验证代理端口
|
44
|
+
if (!config.proxyPort?.trim()) {
|
45
|
+
errors.push('Proxy port is required when proxy is enabled');
|
46
|
+
} else {
|
47
|
+
const port = parseInt(config.proxyPort, 10);
|
48
|
+
if (isNaN(port) || port < 1 || port > 65_535) {
|
49
|
+
errors.push('Proxy port must be a valid number between 1 and 65535');
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
// 验证认证信息
|
54
|
+
if (config.proxyRequireAuth) {
|
55
|
+
if (!config.proxyUsername?.trim()) {
|
56
|
+
errors.push('Proxy username is required when authentication is enabled');
|
57
|
+
}
|
58
|
+
if (!config.proxyPassword?.trim()) {
|
59
|
+
errors.push('Proxy password is required when authentication is enabled');
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
return {
|
64
|
+
errors,
|
65
|
+
isValid: errors.length === 0,
|
66
|
+
};
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* 验证主机名格式
|
71
|
+
*/
|
72
|
+
private static isValidHost(host: string): boolean {
|
73
|
+
// 简单的主机名验证(IP 地址或域名)
|
74
|
+
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
75
|
+
const domainRegex =
|
76
|
+
/^[\dA-Za-z]([\dA-Za-z-]*[\dA-Za-z])?(\.[\dA-Za-z]([\dA-Za-z-]*[\dA-Za-z])?)*$/;
|
77
|
+
|
78
|
+
return ipRegex.test(host) || domainRegex.test(host);
|
79
|
+
}
|
80
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { DataSyncConfig } from '@lobechat/electron-client-ipc';
|
1
|
+
import { DataSyncConfig, NetworkProxySettings } from '@lobechat/electron-client-ipc';
|
2
2
|
|
3
3
|
export interface ElectronMainStore {
|
4
4
|
dataSyncConfig: DataSyncConfig;
|
@@ -7,6 +7,7 @@ export interface ElectronMainStore {
|
|
7
7
|
refreshToken?: string;
|
8
8
|
};
|
9
9
|
locale: string;
|
10
|
+
networkProxy: NetworkProxySettings;
|
10
11
|
shortcuts: Record<string, string>;
|
11
12
|
storagePath: string;
|
12
13
|
}
|
@@ -19,8 +19,9 @@ export const createLogger = (namespace: string) => {
|
|
19
19
|
error: (message, ...args) => {
|
20
20
|
if (process.env.NODE_ENV === 'production') {
|
21
21
|
electronLog.error(message, ...args);
|
22
|
+
} else {
|
23
|
+
console.error(message, ...args);
|
22
24
|
}
|
23
|
-
debugLogger(`ERROR: ${message}`, ...args);
|
24
25
|
},
|
25
26
|
info: (message, ...args) => {
|
26
27
|
if (process.env.NODE_ENV === 'production') {
|
package/changelog/v1.json
CHANGED
package/locales/ar/electron.json
CHANGED
@@ -1,4 +1,43 @@
|
|
1
1
|
{
|
2
|
+
"proxy": {
|
3
|
+
"auth": "يتطلب المصادقة",
|
4
|
+
"authDesc": "إذا كان خادم الوكيل يتطلب اسم مستخدم وكلمة مرور",
|
5
|
+
"authSettings": "إعدادات المصادقة",
|
6
|
+
"basicSettings": "إعدادات الوكيل",
|
7
|
+
"basicSettingsDesc": "تكوين معلمات اتصال خادم الوكيل",
|
8
|
+
"bypass": "العناوين التي لا تستخدم الوكيل",
|
9
|
+
"connectionTest": "اختبار الاتصال",
|
10
|
+
"enable": "تفعيل الوكيل",
|
11
|
+
"enableDesc": "عند التفعيل، سيتم الوصول إلى الشبكة عبر خادم الوكيل",
|
12
|
+
"password": "كلمة المرور",
|
13
|
+
"password_placeholder": "الرجاء إدخال كلمة المرور",
|
14
|
+
"port": "المنفذ",
|
15
|
+
"resetButton": "إعادة تعيين",
|
16
|
+
"saveButton": "حفظ",
|
17
|
+
"saveFailed": "فشل الحفظ: {{error}}",
|
18
|
+
"saveSuccess": "تم حفظ إعدادات الوكيل بنجاح",
|
19
|
+
"server": "عنوان الخادم",
|
20
|
+
"testButton": "اختبار الاتصال",
|
21
|
+
"testDescription": "اختبر الاتصال باستخدام إعدادات الوكيل الحالية للتحقق من صحة التكوين",
|
22
|
+
"testFailed": "فشل الاتصال",
|
23
|
+
"testSuccessWithTime": "تم اختبار الاتصال بنجاح، استغرق {{time}} مللي ثانية",
|
24
|
+
"testUrl": "عنوان الاختبار",
|
25
|
+
"testUrlPlaceholder": "الرجاء إدخال عنوان URL للاختبار",
|
26
|
+
"testing": "جارٍ اختبار الاتصال...",
|
27
|
+
"type": "نوع الوكيل",
|
28
|
+
"unsavedChanges": "لديك تغييرات غير محفوظة",
|
29
|
+
"username": "اسم المستخدم",
|
30
|
+
"username_placeholder": "الرجاء إدخال اسم المستخدم",
|
31
|
+
"validation": {
|
32
|
+
"passwordRequired": "كلمة المرور مطلوبة عند تفعيل المصادقة",
|
33
|
+
"portInvalid": "يجب أن يكون المنفذ رقمًا بين 1 و 65535",
|
34
|
+
"portRequired": "المنفذ مطلوب عند تفعيل الوكيل",
|
35
|
+
"serverInvalid": "يرجى إدخال عنوان خادم صالح (IP أو اسم نطاق)",
|
36
|
+
"serverRequired": "عنوان الخادم مطلوب عند تفعيل الوكيل",
|
37
|
+
"typeRequired": "نوع الوكيل مطلوب عند تفعيل الوكيل",
|
38
|
+
"usernameRequired": "اسم المستخدم مطلوب عند تفعيل المصادقة"
|
39
|
+
}
|
40
|
+
},
|
2
41
|
"remoteServer": {
|
3
42
|
"authError": "فشل التفويض: {{error}}",
|
4
43
|
"authPending": "يرجى إكمال التفويض في المتصفح",
|
package/locales/ar/setting.json
CHANGED
@@ -1,4 +1,43 @@
|
|
1
1
|
{
|
2
|
+
"proxy": {
|
3
|
+
"auth": "Необходимо удостоверяване",
|
4
|
+
"authDesc": "Ако прокси сървърът изисква потребителско име и парола",
|
5
|
+
"authSettings": "Настройки за удостоверяване",
|
6
|
+
"basicSettings": "Настройки на прокси",
|
7
|
+
"basicSettingsDesc": "Конфигуриране на параметрите за връзка с прокси сървъра",
|
8
|
+
"bypass": "Адреси без прокси",
|
9
|
+
"connectionTest": "Тест на връзката",
|
10
|
+
"enable": "Активиране на прокси",
|
11
|
+
"enableDesc": "При активиране достъпът до мрежата ще се осъществява чрез прокси сървъра",
|
12
|
+
"password": "Парола",
|
13
|
+
"password_placeholder": "Моля, въведете парола",
|
14
|
+
"port": "Порт",
|
15
|
+
"resetButton": "Нулиране",
|
16
|
+
"saveButton": "Запазване",
|
17
|
+
"saveFailed": "Грешка при запазване: {{error}}",
|
18
|
+
"saveSuccess": "Настройките на прокси сървъра бяха успешно запазени",
|
19
|
+
"server": "Адрес на сървъра",
|
20
|
+
"testButton": "Тествай връзката",
|
21
|
+
"testDescription": "Тествайте връзката с текущата прокси конфигурация, за да проверите дали работи правилно",
|
22
|
+
"testFailed": "Връзката неуспешна",
|
23
|
+
"testSuccessWithTime": "Връзката е успешна, време за изпълнение {{time}} ms",
|
24
|
+
"testUrl": "Тестов адрес",
|
25
|
+
"testUrlPlaceholder": "Моля, въведете URL за тест",
|
26
|
+
"testing": "Тест на връзката...",
|
27
|
+
"type": "Тип прокси",
|
28
|
+
"unsavedChanges": "Имате незапазени промени",
|
29
|
+
"username": "Потребителско име",
|
30
|
+
"username_placeholder": "Моля, въведете потребителско име",
|
31
|
+
"validation": {
|
32
|
+
"passwordRequired": "Паролата е задължителна при активиране на удостоверяване",
|
33
|
+
"portInvalid": "Портът трябва да е число между 1 и 65535",
|
34
|
+
"portRequired": "Портът е задължителен при активиране на прокси",
|
35
|
+
"serverInvalid": "Моля, въведете валиден адрес на сървъра (IP или домейн)",
|
36
|
+
"serverRequired": "Адресът на сървъра е задължителен при активиране на прокси",
|
37
|
+
"typeRequired": "Типът прокси е задължителен при активиране на прокси",
|
38
|
+
"usernameRequired": "Потребителското име е задължително при активиране на удостоверяване"
|
39
|
+
}
|
40
|
+
},
|
2
41
|
"remoteServer": {
|
3
42
|
"authError": "Упълномощаването не бе успешно: {{error}}",
|
4
43
|
"authPending": "Моля, завършете упълномощаването в браузъра",
|
@@ -1,4 +1,43 @@
|
|
1
1
|
{
|
2
|
+
"proxy": {
|
3
|
+
"auth": "Authentifizierung erforderlich",
|
4
|
+
"authDesc": "Wenn der Proxy-Server Benutzername und Passwort benötigt",
|
5
|
+
"authSettings": "Authentifizierungseinstellungen",
|
6
|
+
"basicSettings": "Proxy-Einstellungen",
|
7
|
+
"basicSettingsDesc": "Konfigurieren Sie die Verbindungsparameter des Proxy-Servers",
|
8
|
+
"bypass": "Adressen ohne Proxy",
|
9
|
+
"connectionTest": "Verbindungstest",
|
10
|
+
"enable": "Proxy aktivieren",
|
11
|
+
"enableDesc": "Wenn aktiviert, wird der Netzwerkzugang über den Proxy-Server geleitet",
|
12
|
+
"password": "Passwort",
|
13
|
+
"password_placeholder": "Bitte Passwort eingeben",
|
14
|
+
"port": "Port",
|
15
|
+
"resetButton": "Zurücksetzen",
|
16
|
+
"saveButton": "Speichern",
|
17
|
+
"saveFailed": "Speichern fehlgeschlagen: {{error}}",
|
18
|
+
"saveSuccess": "Proxy-Einstellungen erfolgreich gespeichert",
|
19
|
+
"server": "Serveradresse",
|
20
|
+
"testButton": "Verbindung testen",
|
21
|
+
"testDescription": "Testen Sie die Verbindung mit der aktuellen Proxy-Konfiguration, um die Funktionalität zu überprüfen",
|
22
|
+
"testFailed": "Verbindung fehlgeschlagen",
|
23
|
+
"testSuccessWithTime": "Verbindung erfolgreich getestet, Dauer {{time}} ms",
|
24
|
+
"testUrl": "Test-URL",
|
25
|
+
"testUrlPlaceholder": "Bitte die zu testende URL eingeben",
|
26
|
+
"testing": "Verbindung wird getestet...",
|
27
|
+
"type": "Proxy-Typ",
|
28
|
+
"unsavedChanges": "Sie haben ungespeicherte Änderungen",
|
29
|
+
"username": "Benutzername",
|
30
|
+
"username_placeholder": "Bitte Benutzernamen eingeben",
|
31
|
+
"validation": {
|
32
|
+
"passwordRequired": "Passwort ist erforderlich, wenn die Authentifizierung aktiviert ist",
|
33
|
+
"portInvalid": "Der Port muss eine Zahl zwischen 1 und 65535 sein",
|
34
|
+
"portRequired": "Port ist erforderlich, wenn der Proxy aktiviert ist",
|
35
|
+
"serverInvalid": "Bitte geben Sie eine gültige Serveradresse (IP oder Domain) ein",
|
36
|
+
"serverRequired": "Serveradresse ist erforderlich, wenn der Proxy aktiviert ist",
|
37
|
+
"typeRequired": "Proxy-Typ ist erforderlich, wenn der Proxy aktiviert ist",
|
38
|
+
"usernameRequired": "Benutzername ist erforderlich, wenn die Authentifizierung aktiviert ist"
|
39
|
+
}
|
40
|
+
},
|
2
41
|
"remoteServer": {
|
3
42
|
"authError": "Autorisierung fehlgeschlagen: {{error}}",
|
4
43
|
"authPending": "Bitte schließen Sie die Autorisierung im Browser ab",
|
@@ -1,4 +1,43 @@
|
|
1
1
|
{
|
2
|
+
"proxy": {
|
3
|
+
"auth": "Authentication Required",
|
4
|
+
"authDesc": "If the proxy server requires a username and password",
|
5
|
+
"authSettings": "Authentication Settings",
|
6
|
+
"basicSettings": "Proxy Settings",
|
7
|
+
"basicSettingsDesc": "Configure the connection parameters for the proxy server",
|
8
|
+
"bypass": "Addresses not using the proxy",
|
9
|
+
"connectionTest": "Connection Test",
|
10
|
+
"enable": "Enable Proxy",
|
11
|
+
"enableDesc": "When enabled, network access will be routed through the proxy server",
|
12
|
+
"password": "Password",
|
13
|
+
"password_placeholder": "Please enter your password",
|
14
|
+
"port": "Port",
|
15
|
+
"resetButton": "Reset",
|
16
|
+
"saveButton": "Save",
|
17
|
+
"saveFailed": "Save failed: {{error}}",
|
18
|
+
"saveSuccess": "Proxy settings saved successfully",
|
19
|
+
"server": "Server Address",
|
20
|
+
"testButton": "Test Connection",
|
21
|
+
"testDescription": "Test the connection using the current proxy configuration to verify if it works properly",
|
22
|
+
"testFailed": "Connection failed",
|
23
|
+
"testSuccessWithTime": "Connection test succeeded, took {{time}} ms",
|
24
|
+
"testUrl": "Test URL",
|
25
|
+
"testUrlPlaceholder": "Please enter the URL to test",
|
26
|
+
"testing": "Testing Connection...",
|
27
|
+
"type": "Proxy Type",
|
28
|
+
"unsavedChanges": "You have unsaved changes",
|
29
|
+
"username": "Username",
|
30
|
+
"username_placeholder": "Please enter your username",
|
31
|
+
"validation": {
|
32
|
+
"passwordRequired": "Password is required when authentication is enabled",
|
33
|
+
"portInvalid": "Port must be a number between 1 and 65535",
|
34
|
+
"portRequired": "Port is required when proxy is enabled",
|
35
|
+
"serverInvalid": "Please enter a valid server address (IP or domain name)",
|
36
|
+
"serverRequired": "Server address is required when proxy is enabled",
|
37
|
+
"typeRequired": "Proxy type is required when proxy is enabled",
|
38
|
+
"usernameRequired": "Username is required when authentication is enabled"
|
39
|
+
}
|
40
|
+
},
|
2
41
|
"remoteServer": {
|
3
42
|
"authError": "Authorization failed: {{error}}",
|
4
43
|
"authPending": "Please complete the authorization in your browser",
|