Compare commits

..

569 Commits

Author SHA1 Message Date
Owen Schwartz
0b22ccfda3 New translations en-us.json (French)
[ci skip]
2026-06-08 16:08:49 -07:00
Owen Schwartz
e5a3b93f58 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-08 16:08:47 -07:00
Owen Schwartz
7a403b3deb New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-08 16:08:46 -07:00
Owen Schwartz
1e968acede New translations en-us.json (Turkish)
[ci skip]
2026-06-08 16:08:44 -07:00
Owen Schwartz
5d4a1ffd73 New translations en-us.json (Russian)
[ci skip]
2026-06-08 16:08:42 -07:00
Owen Schwartz
501770bee0 New translations en-us.json (Portuguese)
[ci skip]
2026-06-08 16:08:40 -07:00
Owen Schwartz
247f19ce4e New translations en-us.json (Polish)
[ci skip]
2026-06-08 16:08:38 -07:00
Owen Schwartz
2ad41154b3 New translations en-us.json (Dutch)
[ci skip]
2026-06-08 16:08:36 -07:00
Owen Schwartz
8a59930886 New translations en-us.json (Korean)
[ci skip]
2026-06-08 16:08:35 -07:00
Owen Schwartz
02a6959e3e New translations en-us.json (Italian)
[ci skip]
2026-06-08 16:08:33 -07:00
Owen Schwartz
e6f476dbf5 New translations en-us.json (German)
[ci skip]
2026-06-08 16:08:31 -07:00
Owen Schwartz
7837578672 New translations en-us.json (Czech)
[ci skip]
2026-06-08 16:08:29 -07:00
Owen Schwartz
c603acacd7 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-08 16:08:27 -07:00
Owen Schwartz
021857c738 New translations en-us.json (Spanish)
[ci skip]
2026-06-08 16:08:25 -07:00
Owen Schwartz
b96fe34e83 New translations en-us.json (French)
[ci skip]
2026-06-08 14:42:11 -07:00
Owen Schwartz
acda39d27a New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-08 14:42:09 -07:00
Owen Schwartz
068b7f3217 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-08 14:42:07 -07:00
Owen Schwartz
f3f1d8a161 New translations en-us.json (Turkish)
[ci skip]
2026-06-08 14:42:05 -07:00
Owen Schwartz
9edb126594 New translations en-us.json (Russian)
[ci skip]
2026-06-08 14:42:03 -07:00
Owen Schwartz
1b8b231c69 New translations en-us.json (Portuguese)
[ci skip]
2026-06-08 14:42:01 -07:00
Owen Schwartz
c7e27976c0 New translations en-us.json (Polish)
[ci skip]
2026-06-08 14:41:59 -07:00
Owen Schwartz
b795021014 New translations en-us.json (Dutch)
[ci skip]
2026-06-08 14:41:57 -07:00
Owen Schwartz
58d0f55480 New translations en-us.json (Korean)
[ci skip]
2026-06-08 14:41:56 -07:00
Owen Schwartz
f99df78f26 New translations en-us.json (Italian)
[ci skip]
2026-06-08 14:41:54 -07:00
Owen Schwartz
2af68672a8 New translations en-us.json (German)
[ci skip]
2026-06-08 14:41:52 -07:00
Owen Schwartz
985aba5e67 New translations en-us.json (Czech)
[ci skip]
2026-06-08 14:41:50 -07:00
Owen Schwartz
8329a2d6d9 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-08 14:41:48 -07:00
Owen Schwartz
da4559b28f New translations en-us.json (Spanish)
[ci skip]
2026-06-08 14:41:46 -07:00
Owen Schwartz
1e9c2b5bfd New translations en-us.json (French)
[ci skip]
2026-06-08 12:14:10 -07:00
Owen Schwartz
b5f5e2fa03 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-08 12:14:08 -07:00
Owen Schwartz
7748a07308 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-08 12:14:06 -07:00
Owen Schwartz
ed79c98115 New translations en-us.json (Turkish)
[ci skip]
2026-06-08 12:14:04 -07:00
Owen Schwartz
afc582dd81 New translations en-us.json (Russian)
[ci skip]
2026-06-08 12:14:02 -07:00
Owen Schwartz
2c93b004bc New translations en-us.json (Portuguese)
[ci skip]
2026-06-08 12:13:59 -07:00
Owen Schwartz
2c9b812ba2 New translations en-us.json (Polish)
[ci skip]
2026-06-08 12:13:56 -07:00
Owen Schwartz
c714e4fc9c New translations en-us.json (Dutch)
[ci skip]
2026-06-08 12:13:54 -07:00
Owen Schwartz
f6274fb789 New translations en-us.json (Korean)
[ci skip]
2026-06-08 12:13:52 -07:00
Owen Schwartz
2409165bfd New translations en-us.json (Italian)
[ci skip]
2026-06-08 12:13:50 -07:00
Owen Schwartz
d52ae1f5e1 New translations en-us.json (German)
[ci skip]
2026-06-08 12:13:47 -07:00
Owen Schwartz
f69d41ebc3 New translations en-us.json (Czech)
[ci skip]
2026-06-08 12:13:45 -07:00
Owen Schwartz
99a7dfa2e2 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-08 12:13:43 -07:00
Owen Schwartz
4ba08ba9ae New translations en-us.json (Spanish)
[ci skip]
2026-06-08 12:13:41 -07:00
Owen Schwartz
8a83be49ee New translations en-us.json (French)
[ci skip]
2026-06-08 11:01:56 -07:00
Owen Schwartz
f3a96f3db8 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-08 11:01:54 -07:00
Owen Schwartz
b5dd8b2598 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-08 11:01:52 -07:00
Owen Schwartz
abf3f3b0da New translations en-us.json (Turkish)
[ci skip]
2026-06-08 11:01:49 -07:00
Owen Schwartz
a44a762f64 New translations en-us.json (Russian)
[ci skip]
2026-06-08 11:01:47 -07:00
Owen Schwartz
259711990c New translations en-us.json (Portuguese)
[ci skip]
2026-06-08 11:01:45 -07:00
Owen Schwartz
58ff29700b New translations en-us.json (Polish)
[ci skip]
2026-06-08 11:01:43 -07:00
Owen Schwartz
6a4923a11d New translations en-us.json (Dutch)
[ci skip]
2026-06-08 11:01:40 -07:00
Owen Schwartz
1b7c6629ad New translations en-us.json (Korean)
[ci skip]
2026-06-08 11:01:38 -07:00
Owen Schwartz
be3f9819ac New translations en-us.json (Italian)
[ci skip]
2026-06-08 11:01:36 -07:00
Owen Schwartz
57c50dfc4c New translations en-us.json (German)
[ci skip]
2026-06-08 11:01:34 -07:00
Owen Schwartz
e89dce930b New translations en-us.json (Czech)
[ci skip]
2026-06-08 11:01:32 -07:00
Owen Schwartz
423dfd683f New translations en-us.json (Bulgarian)
[ci skip]
2026-06-08 11:01:30 -07:00
Owen Schwartz
806ec75a2b New translations en-us.json (Spanish)
[ci skip]
2026-06-08 11:01:28 -07:00
Owen Schwartz
03fa092e9e New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-06 12:41:18 -07:00
Owen Schwartz
7631555f00 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-06 12:41:16 -07:00
Owen Schwartz
297fb8f020 New translations en-us.json (Turkish)
[ci skip]
2026-06-06 12:41:15 -07:00
Owen Schwartz
d11a76bbef New translations en-us.json (Russian)
[ci skip]
2026-06-06 12:41:13 -07:00
Owen Schwartz
1323c11db9 New translations en-us.json (Portuguese)
[ci skip]
2026-06-06 12:41:11 -07:00
Owen Schwartz
6bbaad9fa2 New translations en-us.json (Polish)
[ci skip]
2026-06-06 12:41:09 -07:00
Owen Schwartz
1c2508013e New translations en-us.json (Dutch)
[ci skip]
2026-06-06 12:41:08 -07:00
Owen Schwartz
7e76c27b19 New translations en-us.json (French)
[ci skip]
2026-06-06 12:41:06 -07:00
Owen Schwartz
210b00db05 New translations en-us.json (Korean)
[ci skip]
2026-06-06 12:41:04 -07:00
Owen Schwartz
9e71dd1c17 New translations en-us.json (Italian)
[ci skip]
2026-06-06 12:41:02 -07:00
Owen Schwartz
cd8e16cab1 New translations en-us.json (German)
[ci skip]
2026-06-06 12:41:01 -07:00
Owen Schwartz
e943ed33fc New translations en-us.json (Czech)
[ci skip]
2026-06-06 12:40:59 -07:00
Owen Schwartz
f0f03c9da9 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-06 12:40:57 -07:00
Owen Schwartz
b6fae4299e New translations en-us.json (Spanish)
[ci skip]
2026-06-06 12:40:55 -07:00
Owen Schwartz
206a448752 New translations en-us.json (French)
[ci skip]
2026-06-05 14:57:47 -07:00
Owen Schwartz
29aae19cd5 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-05 14:57:45 -07:00
Owen Schwartz
6ea6d7ac0d New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-05 14:57:43 -07:00
Owen Schwartz
a8bb5c2972 New translations en-us.json (Turkish)
[ci skip]
2026-06-05 14:57:42 -07:00
Owen Schwartz
f1aa919b17 New translations en-us.json (Russian)
[ci skip]
2026-06-05 14:57:40 -07:00
Owen Schwartz
07196a2ae4 New translations en-us.json (Portuguese)
[ci skip]
2026-06-05 14:57:38 -07:00
Owen Schwartz
1cdfb3e765 New translations en-us.json (Polish)
[ci skip]
2026-06-05 14:57:36 -07:00
Owen Schwartz
751e295620 New translations en-us.json (Dutch)
[ci skip]
2026-06-05 14:57:34 -07:00
Owen Schwartz
f9d2c77b6c New translations en-us.json (Korean)
[ci skip]
2026-06-05 14:57:33 -07:00
Owen Schwartz
78726e42ad New translations en-us.json (Italian)
[ci skip]
2026-06-05 14:57:31 -07:00
Owen Schwartz
2af8ed695e New translations en-us.json (German)
[ci skip]
2026-06-05 14:57:29 -07:00
Owen Schwartz
bf9c68b8de New translations en-us.json (Czech)
[ci skip]
2026-06-05 14:57:27 -07:00
Owen Schwartz
a39a71c0af New translations en-us.json (Bulgarian)
[ci skip]
2026-06-05 14:57:26 -07:00
Owen Schwartz
e5dc402a7e New translations en-us.json (Spanish)
[ci skip]
2026-06-05 14:57:24 -07:00
Owen Schwartz
ce99fa18b4 New translations en-us.json (French)
[ci skip]
2026-06-05 12:49:01 -07:00
Owen Schwartz
265a51d22d New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-05 12:48:59 -07:00
Owen Schwartz
0d06192e3e New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-05 12:48:57 -07:00
Owen Schwartz
875c0acab7 New translations en-us.json (Turkish)
[ci skip]
2026-06-05 12:48:55 -07:00
Owen Schwartz
e9b214c3f3 New translations en-us.json (Russian)
[ci skip]
2026-06-05 12:48:53 -07:00
Owen Schwartz
372d6d685f New translations en-us.json (Portuguese)
[ci skip]
2026-06-05 12:48:51 -07:00
Owen Schwartz
0d09a63e81 New translations en-us.json (Polish)
[ci skip]
2026-06-05 12:48:50 -07:00
Owen Schwartz
cb8605656c New translations en-us.json (Dutch)
[ci skip]
2026-06-05 12:48:48 -07:00
Owen Schwartz
774147e8d2 New translations en-us.json (Korean)
[ci skip]
2026-06-05 12:48:46 -07:00
Owen Schwartz
3b13557f72 New translations en-us.json (Italian)
[ci skip]
2026-06-05 12:48:44 -07:00
Owen Schwartz
906d15a2cf New translations en-us.json (German)
[ci skip]
2026-06-05 12:48:42 -07:00
Owen Schwartz
0a465ebbc9 New translations en-us.json (Czech)
[ci skip]
2026-06-05 12:48:41 -07:00
Owen Schwartz
f99a823e11 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-05 12:48:39 -07:00
Owen Schwartz
550bacf7ad New translations en-us.json (Spanish)
[ci skip]
2026-06-05 12:48:37 -07:00
Owen Schwartz
f6746d7e13 New translations en-us.json (French)
[ci skip]
2026-06-05 11:51:33 -07:00
Owen Schwartz
e8b8234274 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-05 11:51:31 -07:00
Owen Schwartz
52709c04dc New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-05 11:51:29 -07:00
Owen Schwartz
80d522bba6 New translations en-us.json (Turkish)
[ci skip]
2026-06-05 11:51:28 -07:00
Owen Schwartz
899ffc89f0 New translations en-us.json (Russian)
[ci skip]
2026-06-05 11:51:26 -07:00
Owen Schwartz
69dd2513eb New translations en-us.json (Portuguese)
[ci skip]
2026-06-05 11:51:24 -07:00
Owen Schwartz
f691dae8f8 New translations en-us.json (Polish)
[ci skip]
2026-06-05 11:51:22 -07:00
Owen Schwartz
36421e4216 New translations en-us.json (Dutch)
[ci skip]
2026-06-05 11:51:20 -07:00
Owen Schwartz
7032feacbc New translations en-us.json (Korean)
[ci skip]
2026-06-05 11:51:18 -07:00
Owen Schwartz
56dc24440f New translations en-us.json (Italian)
[ci skip]
2026-06-05 11:51:16 -07:00
Owen Schwartz
24d94bebb5 New translations en-us.json (German)
[ci skip]
2026-06-05 11:51:14 -07:00
Owen Schwartz
901eea6ea1 New translations en-us.json (Czech)
[ci skip]
2026-06-05 11:51:12 -07:00
Owen Schwartz
eac4b7cf67 New translations en-us.json (Bulgarian)
[ci skip]
2026-06-05 11:51:10 -07:00
Owen Schwartz
c887b5cf32 New translations en-us.json (Spanish)
[ci skip]
2026-06-05 11:51:09 -07:00
Owen Schwartz
907012ee9b New translations en-us.json (French)
[ci skip]
2026-06-04 22:48:06 -07:00
Owen Schwartz
c28e7cebf1 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 22:48:04 -07:00
Owen Schwartz
810abf6526 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 22:48:02 -07:00
Owen Schwartz
7103d32902 New translations en-us.json (Turkish)
[ci skip]
2026-06-04 22:48:00 -07:00
Owen Schwartz
0014e55247 New translations en-us.json (Russian)
[ci skip]
2026-06-04 22:47:58 -07:00
Owen Schwartz
364d65ed00 New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 22:47:57 -07:00
Owen Schwartz
2869227667 New translations en-us.json (Polish)
[ci skip]
2026-06-04 22:47:55 -07:00
Owen Schwartz
935be5fe14 New translations en-us.json (Dutch)
[ci skip]
2026-06-04 22:47:53 -07:00
Owen Schwartz
babe85094b New translations en-us.json (Korean)
[ci skip]
2026-06-04 22:47:52 -07:00
Owen Schwartz
00c02a5092 New translations en-us.json (Italian)
[ci skip]
2026-06-04 22:47:50 -07:00
Owen Schwartz
fe2dc2f260 New translations en-us.json (German)
[ci skip]
2026-06-04 22:47:48 -07:00
Owen Schwartz
a008291eba New translations en-us.json (Czech)
[ci skip]
2026-06-04 22:47:46 -07:00
Owen Schwartz
87ab601e6d New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 22:47:44 -07:00
Owen Schwartz
a25d64a18e New translations en-us.json (Spanish)
[ci skip]
2026-06-04 22:47:43 -07:00
Owen Schwartz
05afeb60cd New translations en-us.json (French)
[ci skip]
2026-06-04 21:52:17 -07:00
Owen Schwartz
d89d595735 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 21:52:16 -07:00
Owen Schwartz
ef3c6f2533 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 21:52:14 -07:00
Owen Schwartz
a8759b223f New translations en-us.json (Turkish)
[ci skip]
2026-06-04 21:52:12 -07:00
Owen Schwartz
4e8802ea10 New translations en-us.json (Russian)
[ci skip]
2026-06-04 21:52:10 -07:00
Owen Schwartz
3d0882a9bb New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 21:52:08 -07:00
Owen Schwartz
c23927fd65 New translations en-us.json (Polish)
[ci skip]
2026-06-04 21:52:07 -07:00
Owen Schwartz
c3c2a7182a New translations en-us.json (Dutch)
[ci skip]
2026-06-04 21:52:05 -07:00
Owen Schwartz
ac03fc9b6a New translations en-us.json (Korean)
[ci skip]
2026-06-04 21:52:03 -07:00
Owen Schwartz
f9a26d0c3c New translations en-us.json (Italian)
[ci skip]
2026-06-04 21:52:02 -07:00
Owen Schwartz
e631cafdf9 New translations en-us.json (German)
[ci skip]
2026-06-04 21:52:00 -07:00
Owen Schwartz
29a716b0cb New translations en-us.json (Czech)
[ci skip]
2026-06-04 21:51:58 -07:00
Owen Schwartz
9da1d05b9a New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 21:51:57 -07:00
Owen Schwartz
47e9ceed16 New translations en-us.json (Spanish)
[ci skip]
2026-06-04 21:51:55 -07:00
Owen Schwartz
c29b80dafd New translations en-us.json (French)
[ci skip]
2026-06-04 19:38:46 -07:00
Owen Schwartz
a741922672 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 19:38:44 -07:00
Owen Schwartz
93ab8c344b New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 19:38:42 -07:00
Owen Schwartz
b39ef73874 New translations en-us.json (Turkish)
[ci skip]
2026-06-04 19:38:41 -07:00
Owen Schwartz
604dc7bb61 New translations en-us.json (Russian)
[ci skip]
2026-06-04 19:38:39 -07:00
Owen Schwartz
8cd0e85818 New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 19:38:37 -07:00
Owen Schwartz
e7026c40fd New translations en-us.json (Polish)
[ci skip]
2026-06-04 19:38:35 -07:00
Owen Schwartz
9335f1a7a6 New translations en-us.json (Dutch)
[ci skip]
2026-06-04 19:38:33 -07:00
Owen Schwartz
0827d666e2 New translations en-us.json (Korean)
[ci skip]
2026-06-04 19:38:32 -07:00
Owen Schwartz
84a7a0edf0 New translations en-us.json (Italian)
[ci skip]
2026-06-04 19:38:30 -07:00
Owen Schwartz
344650a97f New translations en-us.json (German)
[ci skip]
2026-06-04 19:38:28 -07:00
Owen Schwartz
5b5e45765e New translations en-us.json (Czech)
[ci skip]
2026-06-04 19:38:26 -07:00
Owen Schwartz
1b02367adb New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 19:38:25 -07:00
Owen Schwartz
f44b3260e2 New translations en-us.json (Spanish)
[ci skip]
2026-06-04 19:38:23 -07:00
Owen Schwartz
96825687fa New translations en-us.json (French)
[ci skip]
2026-06-04 17:52:08 -07:00
Owen Schwartz
33ee7e11ad New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 17:52:07 -07:00
Owen Schwartz
bc67bc69a2 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 17:52:05 -07:00
Owen Schwartz
8028c04789 New translations en-us.json (Turkish)
[ci skip]
2026-06-04 17:52:03 -07:00
Owen Schwartz
e531e02f2b New translations en-us.json (Russian)
[ci skip]
2026-06-04 17:52:01 -07:00
Owen Schwartz
7465f2b342 New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 17:51:59 -07:00
Owen Schwartz
40f2909ca1 New translations en-us.json (Polish)
[ci skip]
2026-06-04 17:51:57 -07:00
Owen Schwartz
2bbbe9c880 New translations en-us.json (Dutch)
[ci skip]
2026-06-04 17:51:55 -07:00
Owen Schwartz
20117a87d5 New translations en-us.json (Korean)
[ci skip]
2026-06-04 17:51:54 -07:00
Owen Schwartz
28667618dd New translations en-us.json (Italian)
[ci skip]
2026-06-04 17:51:52 -07:00
Owen Schwartz
60163bf3ae New translations en-us.json (German)
[ci skip]
2026-06-04 17:51:50 -07:00
Owen Schwartz
374e899216 New translations en-us.json (Czech)
[ci skip]
2026-06-04 17:51:48 -07:00
Owen Schwartz
cc3c9344cc New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 17:51:47 -07:00
Owen Schwartz
a87c213927 New translations en-us.json (Spanish)
[ci skip]
2026-06-04 17:51:45 -07:00
Owen Schwartz
df72b65ced New translations en-us.json (French)
[ci skip]
2026-06-04 16:46:42 -07:00
Owen Schwartz
b00c3c8b47 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 16:46:40 -07:00
Owen Schwartz
d0211ca37d New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 16:46:38 -07:00
Owen Schwartz
210057ddb1 New translations en-us.json (Turkish)
[ci skip]
2026-06-04 16:46:36 -07:00
Owen Schwartz
34e32f14b8 New translations en-us.json (Russian)
[ci skip]
2026-06-04 16:46:35 -07:00
Owen Schwartz
0870576f4c New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 16:46:33 -07:00
Owen Schwartz
2a50c1b4af New translations en-us.json (Polish)
[ci skip]
2026-06-04 16:46:31 -07:00
Owen Schwartz
b18b574c5f New translations en-us.json (Dutch)
[ci skip]
2026-06-04 16:46:29 -07:00
Owen Schwartz
ee4572ed64 New translations en-us.json (Korean)
[ci skip]
2026-06-04 16:46:27 -07:00
Owen Schwartz
b0f9fee4b0 New translations en-us.json (Italian)
[ci skip]
2026-06-04 16:46:26 -07:00
Owen Schwartz
2c3a11718d New translations en-us.json (German)
[ci skip]
2026-06-04 16:46:24 -07:00
Owen Schwartz
d7b98feb51 New translations en-us.json (Czech)
[ci skip]
2026-06-04 16:46:22 -07:00
Owen Schwartz
3736e27a4f New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 16:46:20 -07:00
Owen Schwartz
edd320ce0b New translations en-us.json (Spanish)
[ci skip]
2026-06-04 16:46:18 -07:00
Owen Schwartz
91b02e839d New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-04 00:40:34 -07:00
Owen Schwartz
8f7274a8b4 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-04 00:40:32 -07:00
Owen Schwartz
d9b7b8cec4 New translations en-us.json (Turkish)
[ci skip]
2026-06-04 00:40:30 -07:00
Owen Schwartz
170624017d New translations en-us.json (Russian)
[ci skip]
2026-06-04 00:40:28 -07:00
Owen Schwartz
43d5c1d8df New translations en-us.json (Portuguese)
[ci skip]
2026-06-04 00:40:26 -07:00
Owen Schwartz
f6a3951951 New translations en-us.json (Polish)
[ci skip]
2026-06-04 00:40:24 -07:00
Owen Schwartz
798497f437 New translations en-us.json (Dutch)
[ci skip]
2026-06-04 00:40:22 -07:00
Owen Schwartz
c090a52d6a New translations en-us.json (Korean)
[ci skip]
2026-06-04 00:40:20 -07:00
Owen Schwartz
44fb0afced New translations en-us.json (Italian)
[ci skip]
2026-06-04 00:40:17 -07:00
Owen Schwartz
0dbe95019b New translations en-us.json (German)
[ci skip]
2026-06-04 00:40:15 -07:00
Owen Schwartz
67c899e3a6 New translations en-us.json (Czech)
[ci skip]
2026-06-04 00:40:13 -07:00
Owen Schwartz
827707471e New translations en-us.json (Bulgarian)
[ci skip]
2026-06-04 00:40:11 -07:00
Owen Schwartz
ed221b09ac New translations en-us.json (Spanish)
[ci skip]
2026-06-04 00:40:09 -07:00
miloschwartz
4a3c201741 improve mfa autofill 2026-06-03 21:54:55 -07:00
miloschwartz
f5ab837cce remove idp user if unassociate idp, warn, and fix create user form bug 2026-06-03 21:42:18 -07:00
Owen Schwartz
00ec7a5c66 Merge pull request #3211 from fosrl/crowdin_dev
New Crowdin updates
2026-06-03 21:40:33 -07:00
Owen Schwartz
03df4d03ed New translations en-us.json (Spanish)
[ci skip]
2026-06-03 21:39:34 -07:00
Owen Schwartz
8488edd707 New translations en-us.json (Norwegian Bokmal)
[ci skip]
2026-06-03 21:39:32 -07:00
Owen Schwartz
920dbba2a3 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-03 21:39:31 -07:00
Owen Schwartz
71e065a8bc New translations en-us.json (Turkish)
[ci skip]
2026-06-03 21:39:29 -07:00
Owen Schwartz
e125c762b2 New translations en-us.json (Russian)
[ci skip]
2026-06-03 21:39:27 -07:00
Owen Schwartz
4f01f7c072 New translations en-us.json (Portuguese)
[ci skip]
2026-06-03 21:39:25 -07:00
Owen Schwartz
9a5ee9d489 New translations en-us.json (Polish)
[ci skip]
2026-06-03 21:39:24 -07:00
Owen Schwartz
665da931f1 New translations en-us.json (Dutch)
[ci skip]
2026-06-03 21:39:22 -07:00
Owen Schwartz
7595cf7ac7 New translations en-us.json (Korean)
[ci skip]
2026-06-03 21:39:20 -07:00
Owen Schwartz
aa6232d0fc New translations en-us.json (Italian)
[ci skip]
2026-06-03 21:39:18 -07:00
Owen Schwartz
beaf5dc843 New translations en-us.json (German)
[ci skip]
2026-06-03 21:39:17 -07:00
Owen Schwartz
7158855052 New translations en-us.json (Czech)
[ci skip]
2026-06-03 21:39:15 -07:00
Owen Schwartz
765b2d795f New translations en-us.json (Bulgarian)
[ci skip]
2026-06-03 21:39:13 -07:00
Owen Schwartz
66f00fcf94 New translations en-us.json (French)
[ci skip]
2026-06-03 21:39:11 -07:00
Owen
e408e735be Make alias cross compatable 2026-06-03 17:58:59 -07:00
Owen
e826d0dea6 Add better loading spinner 2026-06-03 17:41:56 -07:00
Owen
bc6fd0b399 Get user resources from the right table 2026-06-03 16:53:39 -07:00
Owen
d00b737412 Pull the sso from the policies as well 2026-06-03 16:16:42 -07:00
Owen
1f43713986 Fix saving the rules 2026-06-03 16:02:17 -07:00
Owen
cc5bec1d83 Pull the rules and the policy information 2026-06-03 15:33:15 -07:00
Owen
40125c717c Pull things in proper order 2026-06-03 14:52:36 -07:00
Owen
2b402f8fec Quiet logs 2026-06-03 14:48:51 -07:00
Owen
8e9071a336 Converting to use both inline and shared policy 2026-06-03 14:41:43 -07:00
Owen
18bcf40174 Merge branch 'dev' of github.com:fosrl/pangolin into dev 2026-06-03 13:50:54 -07:00
Owen Schwartz
42e9b913f1 Merge pull request #3201 from Fredkiss3/refactor/standardize-dropdowns
refactor: standardize dropdowns accross tables
2026-06-03 13:50:40 -07:00
Fred KISSIE
fcb73f78ea 🏷️ fix type imports 2026-06-03 20:23:32 +02:00
Fred KISSIE
a21569bd00 🏷️ fix types imports from a client component 2026-06-03 20:14:43 +02:00
Fred KISSIE
565727ad36 🏷️ import types correctly 2026-06-03 19:51:44 +02:00
Fred KISSIE
00dce19997 Merge branch 'dev' into refactor/standardize-dropdowns 2026-06-03 19:34:22 +02:00
Fred KISSIE
29717e19db ♻️ update machine client labels cell 2026-06-03 19:17:24 +02:00
Fred KISSIE
97aeee541a ♻️ Label table cell optimization 2026-06-03 19:15:44 +02:00
Owen
b70a2bee58 Native ssh push users is working 2026-06-02 22:00:29 -07:00
Owen
f2f56dc6c2 Properly paywall the new resource types 2026-06-02 18:06:42 -07:00
Owen
128db20755 Remove migration test 2026-06-02 17:13:10 -07:00
Owen
12cbd40596 Fix types 2026-06-02 16:56:58 -07:00
Owen
ffd0d17b58 Add proxy protocl support in blueprints 2026-06-02 16:42:26 -07:00
Owen
33fad57bf7 Restrict the number of sites in the api 2026-06-02 16:38:04 -07:00
Owen
8bcc130947 Make sure the right type of select shows 2026-06-02 16:33:05 -07:00
Owen
19feaf4bf2 Add the policy information into missing places 2026-06-02 15:47:55 -07:00
Owen
88ea4391e0 Show new types of resources right 2026-06-02 15:31:33 -07:00
Owen
fba37b7ad0 Add command to make other user server admin 2026-06-02 15:31:21 -07:00
Fred KISSIE
6c1798a8c5 💄 use checkbox for column filter with dropdown 2026-06-02 17:43:45 +02:00
Owen
b6d688f15e Support pin,pass,whitelist correctly on login 2026-06-01 21:34:39 -07:00
Owen
8a57d8dd9c Resource rules go first 2026-06-01 21:02:59 -07:00
Owen
8e0e32c2be Overriding is working 2026-06-01 20:54:37 -07:00
Owen
6b3a0a2113 Remove the admin from the picker 2026-06-01 20:33:37 -07:00
Owen
4d6ed7eec5 Pull from the policies to show to users 2026-06-01 17:49:09 -07:00
Owen
1625dd1add Include the new policy tables in the data 2026-06-01 17:04:33 -07:00
Owen
605dd2f3c9 Add tcp and udp specific pages 2026-06-01 16:05:20 -07:00
Owen
51bb149fd5 Update to latest badger 2026-06-01 15:27:34 -07:00
Owen
2ae4c29418 Add missing set 2026-06-01 15:27:30 -07:00
Owen
ba71016f87 Add inline policy migration 2026-06-01 15:18:40 -07:00
Owen
85c2bd807e Handle the new added mode column 2026-06-01 14:49:41 -07:00
Owen
517e1d15c8 Add 1.19.0 migrations 2026-06-01 14:42:32 -07:00
Owen
3d6d5f176a Hide verify button 2026-06-01 14:10:08 -07:00
Owen
5dd19edb56 Hold the hp error message until after 18 tries 2026-06-01 14:05:19 -07:00
Owen
c6a52ffc75 Dont run migration again when rc 2026-06-01 13:58:04 -07:00
Owen
09b2671759 Send hp error to olm 2026-06-01 13:57:54 -07:00
Owen
d11a244caa Push mode and sign key adjustments for native mode 2026-06-01 11:41:55 -07:00
miloschwartz
bf79768e05 update links 2026-05-31 20:20:37 -07:00
Owen
08a2923cfc Move proxy and client to public and private 2026-05-31 17:30:31 -07:00
Owen
b99e9a6468 Working on ui 2026-05-31 17:25:03 -07:00
Owen
cb2ee9c489 Fixing visual issues 2026-05-31 16:36:13 -07:00
Owen
c1d933259a Fix some ui form issues 2026-05-31 11:57:01 -07:00
Owen
3cf6abdf27 Rename internal resource -> private 2026-05-31 11:28:04 -07:00
Owen
0f2132e565 Merge branch 'main' into dev 2026-05-31 11:12:30 -07:00
Owen
5cc88dc73f Pull the session from badger 2026-05-31 11:11:26 -07:00
Owen Schwartz
ebe1c7a297 Improve OpenAPI response payload typing for Swagger data schemas (#3102)
* Fix custom parser OpenAPI types and add structured default response schema

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/73990123-9c27-444b-bc6e-77e890a0d57c

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>

* Document all registerPath responses and normalize OpenAPI parser schemas

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/73990123-9c27-444b-bc6e-77e890a0d57c

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>

* Add concrete OpenAPI data schemas for selected routes

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>

* Reformat generated OpenAPI response schemas for readability

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>

* Remove obsolete stoi import from blueprint OpenAPI route

Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-31 11:10:38 -07:00
Owen
0943cf5d4c Dont strip session 2026-05-30 12:10:06 -07:00
Owen
3b82ac568f Give auth feedback 2026-05-30 11:56:32 -07:00
Owen
b695f34dc8 Native ssh auth working 2026-05-30 11:54:01 -07:00
Owen
6df4bba3b6 Bump version 2026-05-29 17:12:26 -07:00
Owen
9f83c0a0e8 Show error right 2026-05-29 17:11:44 -07:00
Owen
0ab1854125 Fix import 2026-05-29 15:38:37 -07:00
Owen
b071fa2c9f Be able to pull users from the proxy 2026-05-29 15:34:34 -07:00
Owen
8e2a79a0f5 Move to private 2026-05-29 15:23:40 -07:00
Owen
71756812b6 Adjusting the ui 2026-05-29 10:57:28 -07:00
Owen
76cd716caa Add user id 2026-05-29 10:57:16 -07:00
Shlee
b0d1291cff Installer: Bootstrap optional PostgreSQL/Redis (#3152)
* Make optional postgres and redis in installer
2026-05-29 09:43:59 -07:00
Owen
9617eb2bd7 Add login formatting 2026-05-28 21:38:40 -07:00
Owen
c1ef5b4fbe Add allowedDevOrigins 2026-05-28 21:23:55 -07:00
Owen
8e14bdec95 Remove cloud 2026-05-28 21:20:12 -07:00
dependabot[bot]
b26dfaf57f Bump the prod-minor-updates group with 9 updates
Bumps the prod-minor-updates group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) | `3.1047.0` | `3.1056.0` |
| [@hookform/resolvers](https://github.com/react-hook-form/resolvers) | `5.2.2` | `5.4.0` |
| [helmet](https://github.com/helmetjs/helmet) | `8.1.0` | `8.2.0` |
| [ioredis](https://github.com/luin/ioredis) | `5.10.1` | `5.11.0` |
| [next-intl](https://github.com/amannn/next-intl) | `4.12.0` | `4.13.0` |
| [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) | `8.20.0` | `8.21.0` |
| [posthog-node](https://github.com/PostHog/posthog-js/tree/HEAD/packages/node) | `5.34.1` | `5.35.6` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.75.0` | `7.76.1` |
| [ws](https://github.com/websockets/ws) | `8.20.1` | `8.21.0` |

Updates `@aws-sdk/client-s3` from 3.1047.0 to 3.1056.0
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1056.0/clients/client-s3)

Updates `@hookform/resolvers` from 5.2.2 to 5.4.0
- [Release notes](https://github.com/react-hook-form/resolvers/releases)
- [Commits](https://github.com/react-hook-form/resolvers/compare/v5.2.2...v5.4.0)

Updates `helmet` from 8.1.0 to 8.2.0
- [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/helmetjs/helmet/compare/v8.1.0...v8.2.0)

Updates `ioredis` from 5.10.1 to 5.11.0
- [Release notes](https://github.com/luin/ioredis/releases)
- [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/luin/ioredis/compare/v5.10.1...v5.11.0)

Updates `next-intl` from 4.12.0 to 4.13.0
- [Release notes](https://github.com/amannn/next-intl/releases)
- [Changelog](https://github.com/amannn/next-intl/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amannn/next-intl/compare/v4.12.0...v4.13.0)

Updates `pg` from 8.20.0 to 8.21.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.21.0/packages/pg)

Updates `posthog-node` from 5.34.1 to 5.35.6
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/packages/node/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/commits/posthog-node@5.35.6/packages/node)

Updates `react-hook-form` from 7.75.0 to 7.76.1
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.75.0...v7.76.1)

Updates `ws` from 8.20.1 to 8.21.0
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.20.1...8.21.0)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-version: 3.1056.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: "@hookform/resolvers"
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: helmet
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: ioredis
  dependency-version: 5.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: next-intl
  dependency-version: 4.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: posthog-node
  dependency-version: 5.35.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.76.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: ws
  dependency-version: 8.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 21:15:00 -07:00
dependabot[bot]
1a1c19b24e Bump the dev-patch-updates group with 4 updates
Bumps the dev-patch-updates group with 4 updates: [@tanstack/react-query-devtools](https://github.com/TanStack/query/tree/HEAD/packages/react-query-devtools), [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react), [postcss](https://github.com/postcss/postcss) and [tsx](https://github.com/privatenumber/tsx).


Updates `@tanstack/react-query-devtools` from 5.100.10 to 5.100.14
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-devtools@5.100.14/packages/react-query-devtools)

Updates `@types/react` from 19.2.14 to 19.2.15
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `postcss` from 8.5.14 to 8.5.15
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.14...8.5.15)

Updates `tsx` from 4.22.0 to 4.22.3
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.22.0...v4.22.3)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query-devtools"
  dependency-version: 5.100.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@types/react"
  dependency-version: 19.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: postcss
  dependency-version: 8.5.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: tsx
  dependency-version: 4.22.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 21:14:14 -07:00
dependabot[bot]
9d214b18af Bump stripe from 20.4.1 to 22.2.0
Bumps [stripe](https://github.com/stripe/stripe-node) from 20.4.1 to 22.2.0.
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v20.4.1...v22.2.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-version: 22.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 21:14:14 -07:00
dependabot[bot]
e67b50b356 Bump lucide-react from 0.577.0 to 1.17.0
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.577.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 21:14:14 -07:00
rinseaid
616caf76cb Auto-create roles referenced in blueprints
When a blueprint references a role that doesn't exist, create it
automatically with default permissions (getOrg, getResource,
listResources) instead of throwing an error or silently dropping
the association.
2026-05-28 21:14:14 -07:00
Owen
9a1db4948b Shape the ssh/vnc/rdp login ui to match auth 2026-05-28 21:14:13 -07:00
Owen Schwartz
1215aa8122 Merge pull request #3184 from fosrl/dependabot/npm_and_yarn/prod-minor-updates-1701004488
Bump the prod-minor-updates group with 9 updates
2026-05-28 20:36:43 -07:00
Owen Schwartz
d318a756a8 Merge pull request #3183 from fosrl/dependabot/npm_and_yarn/dev-patch-updates-60744307c2
Bump the dev-patch-updates group with 4 updates
2026-05-28 20:36:17 -07:00
Owen Schwartz
b3c1e49c0c Merge pull request #3185 from fosrl/dependabot/npm_and_yarn/stripe-22.2.0
Bump stripe from 20.4.1 to 22.2.0
2026-05-28 20:35:52 -07:00
Owen Schwartz
dc12b00502 Merge pull request #3186 from fosrl/dependabot/npm_and_yarn/lucide-react-1.17.0
Bump lucide-react from 0.577.0 to 1.17.0
2026-05-28 20:35:39 -07:00
Owen Schwartz
5b814e37c4 Merge pull request #2434 from NHClaessens/feature-share-link-redirect-path
feat: Add path setting to share links (resourceAccessToken)
2026-05-28 20:28:28 -07:00
Owen
8483616b04 Unstage ignored files 2026-05-28 20:27:25 -07:00
Owen
ffe198839a Reset translations 2026-05-28 20:25:34 -07:00
NHClaessens
db5d1d4a16 Update postgres schema 2026-05-28 20:20:34 -07:00
NHClaessens
ad7dcddf24 Add translations 2026-05-28 20:20:33 -07:00
Owen
94408aad21 Add path onto redirectUrl 2026-05-28 20:19:19 -07:00
NHClaessens
b84a7996a9 Adjust validation to allow creation with (optional) path 2026-05-28 20:15:22 -07:00
Owen
a9b0bd8b47 Alter schema + add form field 2026-05-28 20:15:13 -07:00
Owen
a32acf7c69 Fix ui 2026-05-28 20:14:39 -07:00
Owen Schwartz
1e27acbf88 Merge pull request #2980 from rinseaid/blueprint-auto-create-roles
Auto-create roles referenced in blueprints
2026-05-28 20:10:53 -07:00
dependabot[bot]
4012cc658d Bump lucide-react from 0.577.0 to 1.17.0
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.577.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:44:09 +00:00
dependabot[bot]
84d7a87609 Bump stripe from 20.4.1 to 22.2.0
Bumps [stripe](https://github.com/stripe/stripe-node) from 20.4.1 to 22.2.0.
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v20.4.1...v22.2.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-version: 22.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:43:42 +00:00
dependabot[bot]
9a92be532a Bump the prod-minor-updates group with 9 updates
Bumps the prod-minor-updates group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) | `3.1047.0` | `3.1056.0` |
| [@hookform/resolvers](https://github.com/react-hook-form/resolvers) | `5.2.2` | `5.4.0` |
| [helmet](https://github.com/helmetjs/helmet) | `8.1.0` | `8.2.0` |
| [ioredis](https://github.com/luin/ioredis) | `5.10.1` | `5.11.0` |
| [next-intl](https://github.com/amannn/next-intl) | `4.12.0` | `4.13.0` |
| [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) | `8.20.0` | `8.21.0` |
| [posthog-node](https://github.com/PostHog/posthog-js/tree/HEAD/packages/node) | `5.34.1` | `5.35.6` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.75.0` | `7.76.1` |
| [ws](https://github.com/websockets/ws) | `8.20.1` | `8.21.0` |


Updates `@aws-sdk/client-s3` from 3.1047.0 to 3.1056.0
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1056.0/clients/client-s3)

Updates `@hookform/resolvers` from 5.2.2 to 5.4.0
- [Release notes](https://github.com/react-hook-form/resolvers/releases)
- [Commits](https://github.com/react-hook-form/resolvers/compare/v5.2.2...v5.4.0)

Updates `helmet` from 8.1.0 to 8.2.0
- [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/helmetjs/helmet/compare/v8.1.0...v8.2.0)

Updates `ioredis` from 5.10.1 to 5.11.0
- [Release notes](https://github.com/luin/ioredis/releases)
- [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/luin/ioredis/compare/v5.10.1...v5.11.0)

Updates `next-intl` from 4.12.0 to 4.13.0
- [Release notes](https://github.com/amannn/next-intl/releases)
- [Changelog](https://github.com/amannn/next-intl/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amannn/next-intl/compare/v4.12.0...v4.13.0)

Updates `pg` from 8.20.0 to 8.21.0
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.21.0/packages/pg)

Updates `posthog-node` from 5.34.1 to 5.35.6
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/packages/node/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/commits/posthog-node@5.35.6/packages/node)

Updates `react-hook-form` from 7.75.0 to 7.76.1
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.75.0...v7.76.1)

Updates `ws` from 8.20.1 to 8.21.0
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.20.1...8.21.0)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-version: 3.1056.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: "@hookform/resolvers"
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: helmet
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: ioredis
  dependency-version: 5.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: next-intl
  dependency-version: 4.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: pg
  dependency-version: 8.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: posthog-node
  dependency-version: 5.35.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: react-hook-form
  dependency-version: 7.76.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
- dependency-name: ws
  dependency-version: 8.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:43:25 +00:00
dependabot[bot]
18ac542e30 Bump the dev-patch-updates group with 4 updates
Bumps the dev-patch-updates group with 4 updates: [@tanstack/react-query-devtools](https://github.com/TanStack/query/tree/HEAD/packages/react-query-devtools), [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react), [postcss](https://github.com/postcss/postcss) and [tsx](https://github.com/privatenumber/tsx).


Updates `@tanstack/react-query-devtools` from 5.100.10 to 5.100.14
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query-devtools/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query-devtools@5.100.14/packages/react-query-devtools)

Updates `@types/react` from 19.2.14 to 19.2.15
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `postcss` from 8.5.14 to 8.5.15
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.14...8.5.15)

Updates `tsx` from 4.22.0 to 4.22.3
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.22.0...v4.22.3)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query-devtools"
  dependency-version: 5.100.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: "@types/react"
  dependency-version: 19.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: postcss
  dependency-version: 8.5.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
- dependency-name: tsx
  dependency-version: 4.22.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:36:20 +00:00
Owen
322475fb5c Fix errors 2026-05-28 17:59:21 -07:00
Owen
2f124bffc4 Merge branch 'main' into dev 2026-05-28 17:46:42 -07:00
Owen Schwartz
86367383e7 Merge pull request #3026 from immanuwell/fix-validator-test-exit
fix: make validators test failures exit non-zero
2026-05-28 17:43:43 -07:00
Owen Schwartz
d22ba3566d Merge pull request #2618 from LunarECL/fix-docker-label-partial-validation
Skip invalid Docker resources instead of failing entire blueprint (#1784)
2026-05-28 17:41:15 -07:00
Owen Schwartz
c74b423bae Merge pull request #3119 from Adityakk9031/#3086
Sort resource filter options in audit logs
2026-05-28 15:50:27 -07:00
Owen
f8a757c55f Merge branch 'resource-policies' into dev 2026-05-28 15:30:16 -07:00
Owen
6aea3f1643 Merge branch 'auto-update' into dev 2026-05-28 13:59:34 -07:00
Owen
073dc34522 Merge branch 'rdp-ssh' into dev 2026-05-28 13:59:14 -07:00
Owen
3f5970a1f9 Merge branch 'dev' of github.com:fosrl/pangolin into dev 2026-05-28 13:56:18 -07:00
Owen
e2f2608358 Merge branch 'main' into dev 2026-05-28 13:56:08 -07:00
Owen Schwartz
6d17bb04c4 Merge pull request #3167 from shleeable/patch-1
Installer: format main.go
2026-05-28 12:13:45 -07:00
Owen Schwartz
957e7ba127 Merge pull request #3175 from shleeable/patch-4
Fix:  OLM token rate limit uses wrong field name
2026-05-28 12:13:04 -07:00
Owen Schwartz
def710cba8 Merge pull request #3176 from shleeable/patch-5
Fix: Update external.ts windowMs rate limit for milliseconds
2026-05-28 12:12:39 -07:00
Owen Schwartz
44da854575 Merge pull request #3177 from shleeable/patch-6
Fix: Missing return
2026-05-28 12:11:40 -07:00
miloschwartz
d3d2474855 update blueprints to say blueprints log 2026-05-28 12:11:20 -07:00
Owen Schwartz
d7d37c6f6e Merge pull request #3179 from fosrl/dependabot/npm_and_yarn/dev-minor-updates-545c73ecbb
Bump the dev-minor-updates group across 1 directory with 6 updates
2026-05-28 12:10:40 -07:00
dependabot[bot]
3c80b9a229 Bump the dev-minor-updates group across 1 directory with 6 updates
Bumps the dev-minor-updates group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@dotenvx/dotenvx](https://github.com/dotenvx/dotenvx) | `1.66.0` | `1.69.1` |
| [@react-email/ui](https://github.com/resend/react-email/tree/HEAD/packages/ui) | `6.1.4` | `6.5.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.8.0` | `25.9.1` |
| [eslint](https://github.com/eslint/eslint) | `10.3.0` | `10.4.0` |
| [react-email](https://github.com/resend/react-email/tree/HEAD/packages/react-email) | `6.1.4` | `6.5.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.59.3` | `8.60.0` |



Updates `@dotenvx/dotenvx` from 1.66.0 to 1.69.1
- [Release notes](https://github.com/dotenvx/dotenvx/releases)
- [Changelog](https://github.com/dotenvx/dotenvx/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dotenvx/dotenvx/compare/v1.66.0...v1.69.1)

Updates `@react-email/ui` from 6.1.4 to 6.5.0
- [Release notes](https://github.com/resend/react-email/releases)
- [Changelog](https://github.com/resend/react-email/blob/canary/packages/ui/CHANGELOG.md)
- [Commits](https://github.com/resend/react-email/commits/@react-email/ui@6.5.0/packages/ui)

Updates `@types/node` from 25.8.0 to 25.9.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 10.3.0 to 10.4.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.3.0...v10.4.0)

Updates `react-email` from 6.1.4 to 6.5.0
- [Release notes](https://github.com/resend/react-email/releases)
- [Changelog](https://github.com/resend/react-email/blob/canary/packages/react-email/CHANGELOG.md)
- [Commits](https://github.com/resend/react-email/commits/react-email@6.5.0/packages/react-email)

Updates `typescript-eslint` from 8.59.3 to 8.60.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.60.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@dotenvx/dotenvx"
  dependency-version: 1.69.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@react-email/ui"
  dependency-version: 6.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: "@types/node"
  dependency-version: 25.9.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: eslint
  dependency-version: 10.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: react-email
  dependency-version: 6.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
- dependency-name: typescript-eslint
  dependency-version: 8.60.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 19:10:09 +00:00
Owen Schwartz
a998a35482 Merge pull request #3181 from fosrl/remove-resend
Remove resend
2026-05-28 12:07:20 -07:00
Owen
20e0e5ebd0 Remove resend 2026-05-28 12:06:29 -07:00
Owen Schwartz
4d831effe1 Merge pull request #3180 from fosrl/dependabot/npm_and_yarn/prod-patch-updates-203742b32f
Bump the prod-patch-updates group across 1 directory with 5 updates
2026-05-28 12:06:08 -07:00
dependabot[bot]
80f4dd0e60 Bump the prod-patch-updates group across 1 directory with 5 updates
Bumps the prod-patch-updates group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@simplewebauthn/server](https://github.com/MasterKale/SimpleWebAuthn/tree/HEAD/packages/server) | `13.3.0` | `13.3.1` |
| [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.100.10` | `5.100.14` |
| [nodemailer](https://github.com/nodemailer/nodemailer) | `8.0.7` | `8.0.9` |
| [resend](https://github.com/resend/resend-node) | `6.12.3` | `6.12.4` |
| [semver](https://github.com/npm/node-semver) | `7.8.0` | `7.8.1` |



Updates `@simplewebauthn/server` from 13.3.0 to 13.3.1
- [Release notes](https://github.com/MasterKale/SimpleWebAuthn/releases)
- [Changelog](https://github.com/MasterKale/SimpleWebAuthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MasterKale/SimpleWebAuthn/commits/v13.3.1/packages/server)

Updates `@tanstack/react-query` from 5.100.10 to 5.100.14
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.100.14/packages/react-query)

Updates `nodemailer` from 8.0.7 to 8.0.9
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v8.0.7...v8.0.9)

Updates `resend` from 6.12.3 to 6.12.4
- [Release notes](https://github.com/resend/resend-node/releases)
- [Commits](https://github.com/resend/resend-node/compare/v6.12.3...v6.12.4)

Updates `semver` from 7.8.0 to 7.8.1
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.8.0...v7.8.1)

---
updated-dependencies:
- dependency-name: "@simplewebauthn/server"
  dependency-version: 13.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.100.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: nodemailer
  dependency-version: 8.0.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: resend
  dependency-version: 6.12.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
- dependency-name: semver
  dependency-version: 7.8.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-patch-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 19:02:31 +00:00
Owen Schwartz
eafa3076d8 Merge pull request #3137 from fosrl/dependabot/npm_and_yarn/qs-6.15.2
Bump qs from 6.15.1 to 6.15.2
2026-05-28 12:01:50 -07:00
Owen Schwartz
fef3cd8354 Merge pull request #2908 from fosrl/dependabot/github_actions/actions/setup-node-6.4.0
Bump actions/setup-node from 6.3.0 to 6.4.0
2026-05-28 12:00:48 -07:00
Owen Schwartz
36ada0705e Merge pull request #3044 from fosrl/dependabot/github_actions/sigstore/cosign-installer-4.1.2
Bump sigstore/cosign-installer from 4.1.1 to 4.1.2
2026-05-28 12:00:38 -07:00
Owen Schwartz
8ae3c06df7 Merge pull request #3143 from fosrl/dependabot/github_actions/actions/stale-10.3.0
Bump actions/stale from 10.2.0 to 10.3.0
2026-05-28 12:00:25 -07:00
dependabot[bot]
ba127a8536 Bump qs from 6.15.1 to 6.15.2
Bumps [qs](https://github.com/ljharb/qs) from 6.15.1 to 6.15.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.15.1...v6.15.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.15.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-28 18:59:36 +00:00
Owen Schwartz
5c024f3a3a Merge pull request #3142 from fosrl/dependabot/github_actions/docker/login-action-4.2.0
Bump docker/login-action from 4.1.0 to 4.2.0
2026-05-28 11:57:53 -07:00
Owen Schwartz
4fdb8583f6 Merge pull request #3178 from fosrl/sec-updates
Advance security updates to main
2026-05-28 11:56:57 -07:00
Owen Schwartz
2946df3b8e Merge pull request #3085 from marcschaeferger-org/security-updates
Normalize request parameters and update dependencies for Security
2026-05-28 11:54:23 -07:00
Shlee
c3b0c4e5e9 Update verifyApiKeyOrgAccess.ts 2026-05-28 15:55:34 +09:30
Shlee
a79d0f1677 Update external.ts 2026-05-28 15:45:06 +09:30
Shlee
bfd7a7f561 Update external.ts 2026-05-28 15:31:45 +09:30
Owen
64c901d91f Properly lock the ip selection through writes to db 2026-05-27 21:08:45 -07:00
Owen
cd9e56fdb7 Make the destination optional 2026-05-27 17:52:04 -07:00
Owen
1b6b112e92 Add auth daemon to blueprints 2026-05-27 17:29:19 -07:00
Owen
0ff0e83c9f Complete removal of http and protocol from public 2026-05-27 17:19:04 -07:00
Owen
6d491b7bb9 Cache wildcard certs for easy lookup 2026-05-27 14:58:36 -07:00
Owen
06cc13c637 Moving to mode replacing http and protocol fields 2026-05-27 12:04:00 -07:00
Owen
464d4990df Fix cascading errors 2026-05-27 11:34:34 -07:00
Owen
cb90672573 Trying to get these forms to work 2026-05-26 21:20:34 -07:00
Owen
e19b6ebc82 Hide the destination and the alias 2026-05-26 20:38:04 -07:00
Owen
5a6de12f74 Revert to the mode on top and make it 2 x 2 2026-05-26 20:30:33 -07:00
Owen
6e6c91a27c Move site down 2026-05-26 20:16:54 -07:00
Shlee
cf12ab1ac3 Update main.go 2026-05-27 12:12:48 +09:30
Owen
aa7004b2ff Add new ssh config for private resources 2026-05-26 17:50:46 -07:00
Owen
eca87b66f0 Use the create api 2026-05-26 17:11:45 -07:00
Owen
cc8c89eeae Cleaning up some react 2026-05-26 16:53:22 -07:00
Owen
6ea4aa1920 Suppoter key 2026-05-26 16:35:28 -07:00
Owen
f12451b8f9 Consolidate target components 2026-05-26 16:33:54 -07:00
Owen
0d4bb65a92 Adjusting the create ui 2026-05-26 16:10:06 -07:00
Owen
d47ad9ac40 Fix height problem 2026-05-26 16:08:52 -07:00
Owen
f81ae24ba7 Clean up the ui a bit 2026-05-26 15:05:30 -07:00
Owen
df1e28aabd Pass one on the new create screen 2026-05-26 14:29:13 -07:00
Owen Schwartz
ddabfb5ca1 Merge pull request #3154 from RitwijParmar/codex/pangolin-refresh-live-log-window
fix(logs): refresh default end time
2026-05-26 11:52:10 -07:00
Owen Schwartz
ec0666a612 Merge pull request #3151 from shleeable/patch-1
Installer: Handle both Maxmind Country and ASN databases.
2026-05-26 09:50:08 -07:00
Shlee
bbf42c5802 Update main.go 2026-05-26 17:14:06 +09:30
Ritwij Aryan Parmar
6aa1d3b094 fix(logs): refresh default end time 2026-05-26 01:26:53 -04:00
Shlee
f1ec1a2fb1 Update docker-compose.yml 2026-05-26 13:49:06 +09:30
Shlee
32fcf90467 Update docker-compose.yml 2026-05-26 13:48:00 +09:30
Shlee
5a53f88fd6 Update main.go 2026-05-26 13:37:28 +09:30
Shlee
51971c7ef2 Update config.yml 2026-05-26 13:36:01 +09:30
Shlee
491096109a Update main.go 2026-05-26 13:31:07 +09:30
Shlee
802a41b1bd Update main.go 2026-05-26 13:25:53 +09:30
Shlee
f59fbabede Update main.go 2026-05-26 13:12:48 +09:30
Shlee
5a7d54058e Update main.go 2026-05-26 13:06:35 +09:30
Owen Schwartz
5ef4490692 Merge pull request #3148 from bishnubista/fix-audit-log-replica-routing
fix(audit-logs): route request audit log reads through logsDb
2026-05-25 12:02:24 -07:00
bishnubista
817e848d08 fix(audit-logs): route request audit log reads through logsDb
Route the read paths in queryRequestAuditLog.ts and
queryRequestAnalytics.ts through `logsDb` instead of
`primaryLogsDb`, matching the existing private audit log routes
(queryActionAuditLog, queryAccessAuditLog, queryConnectionAuditLog
all already use `logsDb`). In PostgreSQL deployments configured
with a read replica via `withReplicas` (see server/db/pg/logsDriver.ts),
this keeps high-volume audit log reads off the primary. No-op
in OSS-SQLite where `logsDb === primaryDb`.

Investigated rewriting `queryUniqueFilterAttributes` per the
in-line TODO ("SOMEONE PLEASE OPTIMIZE THIS!!!!!"). A candidate
rewrite using UNION ALL with six GROUP BY...LIMIT 500 arms
benchmarked 48-61% slower than the current SELECT DISTINCT
LIMIT 501 approach on SQLite (100k/300k/1M rows, 20 runs each):
each grouped arm materializes a temp B-tree before applying LIMIT,
while DISTINCT short-circuits via hash dedup with early exit.
A materialized facets table is likely the right long-term fix,
not a query-shape rewrite.
2026-05-25 10:37:47 -07:00
dependabot[bot]
166c8326c5 Bump actions/stale from 10.2.0 to 10.3.0
Bumps [actions/stale](https://github.com/actions/stale) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](b5d41d4e1d...eb5cf3af3a)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: 10.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-25 01:52:46 +00:00
dependabot[bot]
673f1e93f4 Bump docker/login-action from 4.1.0 to 4.2.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](4907a6ddec...650006c6eb)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-25 01:52:42 +00:00
Owen
4c1e1daf07 All page types are there and look mostly correct 2026-05-22 17:37:37 -07:00
Owen
7c54df7ed1 Rework page to be functional 2026-05-22 16:09:02 -07:00
Owen
9d77fcc457 Make the first ssh page and conditional http page 2026-05-22 15:12:37 -07:00
Owen
454449ec8a Add support for push pam users 2026-05-22 12:12:55 -07:00
Owen
fe67e8e384 Clean up types 2026-05-22 12:12:46 -07:00
Owen
715b957660 Support not push ssh method 2026-05-22 11:19:35 -07:00
Owen
f1e4bf8d36 Add hint about invoices for the license key 2026-05-22 10:30:41 -07:00
Owen
3539b9ddb4 Working 2026-05-21 17:30:06 -07:00
Owen
4530aac4f3 Update setting is working
Adjust the ui

Adjust description
2026-05-21 16:34:32 -07:00
Owen
6d4afd0953 Control updates from the ui 2026-05-21 15:43:31 -07:00
Owen
dee0ca6864 Add permissions check, shasum check, & build info 2026-05-21 14:34:16 -07:00
Owen
ed73d089d0 Auto update newt 2026-05-21 14:13:32 -07:00
Owen Schwartz
35ad235f49 Merge pull request #3129 from fosrl/fix-site-delete
Improve delete function speed & order of ops
2026-05-21 12:06:18 -07:00
Owen
834672c846 Improve delete function speed & order of ops 2026-05-21 12:05:16 -07:00
Owen Schwartz
b8180d848a Merge pull request #3118 from Adityakk9031/#3105
Fix public resource health with unknown WireGuard targets
2026-05-20 16:20:25 -07:00
Owen Schwartz
fef7563e14 Merge pull request #3125 from fosrl/fix-3104
Fix #3104
2026-05-20 16:15:21 -07:00
Owen
6337cf4359 Fix #3104 2026-05-20 16:14:47 -07:00
Aditya kumar singh
73e9e830c3 Sort resource filter options in audit logs 2026-05-20 11:13:50 +05:30
Aditya kumar singh
a6469e67a8 Fix public resource health with unknown WireGuard targets 2026-05-20 09:05:05 +05:30
Owen
23ca3efbf4 Merge branch 'dev' into rdp-ssh 2026-05-19 20:12:05 -07:00
Owen
0f9100fd3a Merge branch 'rdp-ssh' of github.com:fosrl/pangolin into rdp-ssh 2026-05-19 20:06:48 -07:00
Owen
832d45e32b Move pages back 2026-05-19 20:02:27 -07:00
Owen
69e3ac3cd4 Move login page locations 2026-05-19 20:02:27 -07:00
Owen
50865f4265 Remove terminate button 2026-05-19 20:02:27 -07:00
Owen
0d1a8d9695 Only switch if we are actually connected 2026-05-19 20:02:27 -07:00
Owen
5d8486dd7f Sure up some things with browserAccessType 2026-05-19 20:02:27 -07:00
Owen
3c25932787 Adjust page to be editable 2026-05-19 20:02:27 -07:00
Owen
1d0e1eb126 Temp credential storage 2026-05-19 20:02:27 -07:00
Owen
57c0dc8618 Support private key 2026-05-19 20:02:27 -07:00
Owen
526a147570 Clean up toasts 2026-05-19 20:02:27 -07:00
Owen
0938997548 Add crud for browser targets 2026-05-19 20:02:27 -07:00
Owen
0876b482f8 Remove extra fields 2026-05-19 20:02:27 -07:00
Owen
d558c31f88 Standardize the ui 2026-05-19 20:02:26 -07:00
Owen
6010515da0 Pull in the destination from the api 2026-05-19 20:02:26 -07:00
Owen
868bcd8e34 USe right table 2026-05-19 20:02:26 -07:00
Owen
20c4904965 Add internal api get for proxy information 2026-05-19 20:02:26 -07:00
Owen
5a5536b38c Reinstall packages 2026-05-19 20:02:26 -07:00
Owen
53e2296de8 Clean up forms a bit 2026-05-19 20:02:26 -07:00
Owen
d2423919e9 Add favicon passthrough 2026-05-19 20:02:26 -07:00
Owen
2250fcd177 Serve the resource from the right place 2026-05-19 20:02:26 -07:00
Owen
2a33256d17 Add gateway endpoints into the traefik config 2026-05-19 20:02:26 -07:00
Owen
117aa750f8 Working on new target type 2026-05-19 20:02:26 -07:00
Owen
15f161274f Add browserGatewayTarget table 2026-05-19 20:02:26 -07:00
Owen
09779aca3e Add basic vnc test 2026-05-19 20:02:25 -07:00
Owen
1d1f7cecf4 Support rdp 2026-05-19 20:02:25 -07:00
Owen
dc00668cbe Add first iteration of ssh proxy 2026-05-19 20:02:25 -07:00
Owen
57701e13eb Comment out some fields 2026-05-19 20:02:25 -07:00
Owen
46545cb003 Initial rdp working 2026-05-19 20:02:21 -07:00
copilot-swe-agent[bot]
81ed391efb Remove obsolete stoi import from blueprint OpenAPI route
Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-17 21:30:23 +00:00
copilot-swe-agent[bot]
f3bee70c23 Reformat generated OpenAPI response schemas for readability
Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-17 21:28:39 +00:00
copilot-swe-agent[bot]
15a9eb28d9 Add concrete OpenAPI data schemas for selected routes
Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/7b395a8e-7fae-4f4d-952e-4030fea08262

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-17 21:25:53 +00:00
copilot-swe-agent[bot]
a0a093ed0b Document all registerPath responses and normalize OpenAPI parser schemas
Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/73990123-9c27-444b-bc6e-77e890a0d57c

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-17 06:43:10 +00:00
copilot-swe-agent[bot]
9cec711427 Fix custom parser OpenAPI types and add structured default response schema
Agent-Logs-Url: https://github.com/fosrl/pangolin/sessions/73990123-9c27-444b-bc6e-77e890a0d57c

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
2026-05-17 06:38:44 +00:00
dependabot[bot]
e4fd2b656d Bump sigstore/cosign-installer from 4.1.1 to 4.1.2
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v4.1.1...6f9f17788090df1f26f669e9d70d6ae9567deba6)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-16 21:55:15 +00:00
Owen
987b5d580e Sure up some things with browserAccessType 2026-05-15 17:26:58 -07:00
Owen
cb75ffc3b7 Adjust page to be editable 2026-05-15 16:46:43 -07:00
Owen
540f0a754d Temp credential storage 2026-05-15 16:11:23 -07:00
Owen
0f9a6fd968 Support private key 2026-05-15 16:07:14 -07:00
Owen
82112abc34 Clean up toasts 2026-05-15 15:01:37 -07:00
Owen
75b5afd544 Add crud for browser targets 2026-05-15 14:09:33 -07:00
Owen
00e1675f7b Remove extra fields 2026-05-15 12:08:40 -07:00
Owen
2ddbdf977b Standardize the ui 2026-05-15 12:06:05 -07:00
Owen
4c8f0cc9ec Pull in the destination from the api 2026-05-15 11:48:13 -07:00
Owen
e822b681cd Merge branch 'dev' into rdp-ssh 2026-05-15 11:18:31 -07:00
Owen
e1583a58aa USe right table 2026-05-14 11:33:42 -07:00
Owen
7d922ac95f Add internal api get for proxy information 2026-05-13 21:54:58 -07:00
Owen
795a3d351e Reinstall packages 2026-05-13 21:16:40 -07:00
Owen
4b4c86b4b7 Clean up forms a bit 2026-05-13 21:16:00 -07:00
Owen
013af49137 Add favicon passthrough 2026-05-13 21:11:25 -07:00
Owen
a6ae9290f2 Serve the resource from the right place 2026-05-13 18:01:36 -07:00
Owen
de70d72e0d Add gateway endpoints into the traefik config 2026-05-13 17:33:16 -07:00
Owen
4e07e9c52c Working on new target type 2026-05-13 11:56:23 -07:00
Owen
743621eb25 Add browserGatewayTarget table 2026-05-12 21:48:59 -07:00
Owen
e9df995e76 Merge branch 'dev' into resource-policies 2026-05-12 21:12:40 -07:00
Owen
943923ff4b Add basic vnc test 2026-05-12 21:12:01 -07:00
Owen
3f17f1a468 Support rdp 2026-05-12 21:12:01 -07:00
Owen
436996a43d Add first iteration of ssh proxy 2026-05-12 21:12:01 -07:00
Owen
d42b6076d2 Comment out some fields 2026-05-12 21:12:01 -07:00
Owen
89cc99f915 Initial rdp working 2026-05-12 21:12:00 -07:00
immanuwell
0611ceb5c3 fix: make validators test failures exit non-zero 2026-05-07 20:13:56 +04:00
Owen
c4b3656fad Update UI to support additions on the resource 2026-05-06 10:09:05 -07:00
Owen
54c1dd3bae Make path the default 2026-05-05 21:05:42 -07:00
Owen
a8f4d2b7d1 Add new user and role selectors for pagination 2026-05-05 20:53:36 -07:00
Owen
51f1693dbd Merge branch 'dev' into resource-policies 2026-05-05 18:02:27 -07:00
Owen
b33a6e6fac Wipe the old tables if you are using inline 2026-05-04 20:54:43 -07:00
Owen
fc2c13a686 Add policies to blueprints 2026-05-04 20:44:04 -07:00
Owen
f4602a120e Merge branch 'dev' into resource-policies 2026-05-04 17:57:09 -07:00
Owen
7ccceeea0d Ignore extra sqlite files 2026-05-04 17:43:02 -07:00
Owen
f81f78f294 Merge branch 'dev' into resource-policies 2026-05-04 17:41:49 -07:00
Owen
6cab223f12 Adjust verify session queries to use policies 2026-05-04 17:30:10 -07:00
Owen
7b05c02508 Adjust translation 2026-05-04 16:19:04 -07:00
Owen
5922bfb1a0 Fix API endpoint action issues 2026-05-04 16:01:40 -07:00
Owen
43f2e32231 Paywall resource policies 2026-05-04 15:30:49 -07:00
Owen
20ebdc6289 Fix openapi zod issue error 2026-05-04 15:04:54 -07:00
Owen
a80ae49a33 Support multiple roles 2026-05-04 14:54:20 -07:00
Owen
660197eef1 Merge branch 'feat/resource-policies' into resource-policies 2026-05-04 14:40:44 -07:00
rinseaid
4786fc3a31 Auto-create roles referenced in blueprints
When a blueprint references a role that doesn't exist, create it
automatically with default permissions (getOrg, getResource,
listResources) instead of throwing an error or silently dropping
the association.
2026-05-03 13:37:47 -04:00
dependabot[bot]
f286d66cbc Bump actions/setup-node from 6.3.0 to 6.4.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to 6.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](53b83947a5...48b55a011b)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-27 01:36:02 +00:00
Fred KISSIE
f3eb823bc3 🐛 fix sqlite tables 2026-03-12 22:36:29 +01:00
Fred KISSIE
61c13db090 Merge branch 'dev' into feat/resource-policies 2026-03-12 22:19:37 +01:00
Fred KISSIE
ccbd793f52 💬 show error 2026-03-12 22:13:27 +01:00
Fred KISSIE
d13e6896a8 ♻️ update 2026-03-12 22:11:39 +01:00
Fred KISSIE
83a36ead10 ♻️ show success toast on resource policy update 2026-03-12 20:22:16 +01:00
Fred KISSIE
b61b74b0b5 💬 update text 2026-03-12 20:04:02 +01:00
Fred KISSIE
01b068c50f ♻️ do not edit tags if readonly 2026-03-12 18:53:18 +01:00
Fred KISSIE
fee44ce960 navigate to policy to edit 2026-03-12 18:52:13 +01:00
Fred KISSIE
1906504a86 update shared policy when selected 2026-03-12 18:35:50 +01:00
Fred KISSIE
36bcba332c 🚧 wip 2026-03-11 05:18:22 +01:00
Fred KISSIE
304ab1964c 🚧 wip 2026-03-11 04:21:55 +01:00
Fred KISSIE
b286096c7b 🌐 text 2026-03-11 03:47:31 +01:00
Fred KISSIE
a22a4b6e74 ♻️ mark forms as readonly 2026-03-11 03:47:15 +01:00
Fred KISSIE
9a680d2374 update resource should update policy 2026-03-11 03:46:40 +01:00
Fred KISSIE
f80e212b07 🚧 wip 2026-03-11 00:27:27 +01:00
Fred KISSIE
8a39b3fd45 🙈 do not include solo.yml to git 2026-03-10 18:55:12 +01:00
Fred KISSIE
61ec938b00 🚧 WIP 2026-03-10 18:54:26 +01:00
Fred KISSIE
6686de6788 ♻️ refactor 2026-03-10 17:48:17 +01:00
Fred KISSIE
79636cbb30 ♻️ delete default resource policy ID when deleting a resource 2026-03-10 17:38:19 +01:00
LunarECL
90d6178a0b Skip invalid Docker resources instead of failing entire blueprint (#1784) 2026-03-09 02:42:21 +09:00
Fred KISSIE
2fa1bc6cdc 🚧 wip 2026-03-07 03:55:30 +01:00
Fred KISSIE
c5f6d822ca ♻️ refactor auth info to use resource policies 2026-03-07 03:45:10 +01:00
Fred KISSIE
4de4bf9625 use resource policies for auth check 2026-03-07 03:35:26 +01:00
Fred KISSIE
5d956080f2 create default policy when creating a resource 2026-03-07 02:29:36 +01:00
Fred KISSIE
f8e18de2fc ♻️ prevent deleting resource policies if they have attached resources 2026-03-07 01:12:10 +01:00
Fred KISSIE
884482ec35 ♻️ delete resource policy endpoint 2026-03-06 23:57:23 +01:00
Fred KISSIE
9b43948fa4 delete resource policy endpoint 2026-03-06 22:39:44 +01:00
Fred KISSIE
bcd6cd99cc 🚧 wip 2026-03-06 04:37:57 +01:00
Fred KISSIE
37ceba6b81 💄 show attached resources in policy list 2026-03-06 04:36:12 +01:00
Fred KISSIE
dfe42e9016 ♻️ refactor 2026-03-06 04:03:40 +01:00
Fred KISSIE
38aa2dace8 ♻️ show list of resources on policy list 2026-03-06 04:03:25 +01:00
Fred KISSIE
136c3eff0c ♻️ padding bottom 2026-03-05 19:46:16 +01:00
Fred KISSIE
642999c8b1 ♻️ separate create form into multiple ones 2026-03-05 19:45:13 +01:00
Fred KISSIE
c5fc49b4fa 🚧 wip 2026-03-05 19:31:19 +01:00
Fred KISSIE
cd5a38b1eb 🚧 WIP: create policy form 2026-03-05 18:56:35 +01:00
Fred KISSIE
595842c2c9 finish create policy endpoint 2026-03-05 18:48:33 +01:00
Fred KISSIE
82d5276ade 🚧 wip: create resource policy 2026-03-05 18:24:04 +01:00
Fred KISSIE
51eb782831 🚧 wip 2026-03-05 18:14:46 +01:00
Fred KISSIE
de2980e1bc apply rules on resource policies 2026-03-05 18:13:30 +01:00
Fred KISSIE
8a3c0d9a08 ♻️ add openapi schema types 2026-03-05 17:51:55 +01:00
Fred KISSIE
1a5e9f1005 🚧 resource policy rules 2026-03-04 19:31:59 +01:00
Fred KISSIE
f42c013f33 ♻️ refactor 2026-03-04 17:41:55 +01:00
Fred KISSIE
42c9bda939 Merge branch 'dev' into feat/resource-policies 2026-03-04 16:46:33 +01:00
Fred KISSIE
cbce9fae3a 🚧 wip 2026-03-04 16:36:49 +01:00
Fred KISSIE
e44b15ecd5 set opt email whitelist 2026-03-04 01:54:50 +01:00
Fred KISSIE
7f6ca31757 🚧 Email whiteList for resource policy 2026-03-04 01:46:56 +01:00
Fred KISSIE
a1eb248474 🔨 remove docker compose mail 2026-03-04 01:10:48 +01:00
Fred KISSIE
be2b1fd1ce 🚧 wip: email whitelist 2026-03-03 20:26:17 +01:00
Fred KISSIE
20b65f549e Update resource policy pincode 2026-03-03 19:49:24 +01:00
Fred KISSIE
1dc8be373c 🚧 wip: add password 2026-03-03 18:54:35 +01:00
Fred KISSIE
22b2e6b3d4 🚧 wip: separating form sections 2026-03-03 18:41:04 +01:00
Fred KISSIE
89e7107a47 ♻️ use put and return 200 OK 2026-03-03 03:31:43 +01:00
Fred KISSIE
0a69131c38 ♻️ merge header auth & extended compability to one table 2026-03-03 03:27:02 +01:00
Fred KISSIE
590f2c29b3 🚧 prepare tables for auth methods 2026-03-03 03:20:03 +01:00
Fred KISSIE
0ddcce6fe1 🗃️ create resource policy specific tables for auth methods 2026-03-03 02:47:21 +01:00
Fred KISSIE
8a54fb7f23 🚧 auth methods 2026-03-03 02:11:05 +01:00
Fred KISSIE
5c280b024e update policy access control 2026-03-03 01:33:37 +01:00
Fred KISSIE
033cc62ce7 🚧 wip 2026-03-02 19:37:23 +01:00
Fred KISSIE
4c69b7a64e update policy access control 2026-03-02 19:26:51 +01:00
Fred KISSIE
e7ab9b3f37 🚧 wip 2026-03-02 18:32:08 +01:00
Fred KISSIE
3143662f82 Merge branch 'dev' into feat/resource-policies 2026-03-02 15:53:00 +01:00
Fred KISSIE
18964ba2a3 🚧 wip 2026-02-28 14:22:41 +01:00
Fred KISSIE
f862404c5c Merge branch 'dev' into feat/resource-policies 2026-02-28 01:17:51 +01:00
Fred KISSIE
c292578f80 Merge branch 'dev' into feat/resource-policies 2026-02-28 01:08:12 +01:00
Fred KISSIE
7b02d4104d 🚧 wip 2026-02-28 00:47:27 +01:00
Fred KISSIE
2ef5d90e13 ♻️ update policy in integration API 2026-02-27 04:24:33 +01:00
Fred KISSIE
d6a8021613 🚧 wip: update resource policy form 2026-02-27 04:21:20 +01:00
Fred KISSIE
c5231d37f6 🚧 wip 2026-02-26 19:20:15 +01:00
Fred KISSIE
4d803a40c9 🚧 wip 2026-02-25 06:00:19 +01:00
Fred KISSIE
1d709b551a create policy endpoitn 2026-02-24 06:31:43 +01:00
Fred KISSIE
335411de4c ♻️ create table for resource policies associations with users 2026-02-24 03:05:51 +01:00
Fred KISSIE
0e4abdf4b6 ♻️ usewatch 2026-02-20 02:06:23 +01:00
Fred KISSIE
267b40b73c 🚧 wip 2026-02-19 05:27:05 +01:00
Fred KISSIE
ba9a0c5e3c ♻️ refactor 2026-02-19 05:23:20 +01:00
Fred KISSIE
9e0b7ff0d7 ♻️ some other ux changes 2026-02-19 05:22:06 +01:00
Fred KISSIE
003bf7fdf3 🚸 hide otp, rules and resource rules config by default 2026-02-19 04:59:51 +01:00
Fred KISSIE
c3fdda026b ♻️ separate into diff components 2026-02-19 04:36:42 +01:00
Fred KISSIE
a53363d064 💄 include rules in create policy form 2026-02-19 03:23:54 +01:00
Fred KISSIE
ee21e1faa7 🚧 list authentication items from policy APIs 2026-02-18 05:08:42 +01:00
Fred KISSIE
e409a34a09 🚧 create policy form 2026-02-18 05:08:27 +01:00
Fred KISSIE
7177ab7f77 🚧 create resource policy table 2026-02-14 05:08:41 +01:00
Fred KISSIE
801f6fb661 🚚 move policies page to (private) folder 2026-02-14 05:03:40 +01:00
Fred KISSIE
805d82b8d9 policies table 2026-02-14 04:59:35 +01:00
Fred KISSIE
bd6d790495 Merge branch 'refactor/paginated-tables' into feat/resource-policies 2026-02-14 04:25:43 +01:00
Fred KISSIE
2305163474 🚧 wip 2026-02-14 03:24:01 +01:00
Fred KISSIE
dda53dcb16 Merge branch 'refactor/paginated-tables' into feat/resource-policies 2026-02-13 06:05:32 +01:00
Fred KISSIE
2c3e768867 🚧 wip: list resource endpoints finished 2026-02-13 05:54:45 +01:00
Fred KISSIE
8d682ed9ad 🚧 list policies endpoint + list policies table 2026-02-13 05:39:35 +01:00
Fred KISSIE
47fe497ca1 🚧 add sidebar item for policies 2026-02-13 05:39:16 +01:00
Fred KISSIE
4d5f364663 ♻️ use the correct types 2026-02-13 05:38:57 +01:00
Fred KISSIE
c3db8b972f ♻️ schema updates for policies 2026-02-13 05:36:42 +01:00
Fred KISSIE
cfced63ba1 Merge branch 'dev' into feat/resource-policies 2026-02-13 02:14:14 +01:00
Fred KISSIE
51aa55f963 revert changes already included in another PR 2026-02-13 00:25:00 +01:00
Fred KISSIE
e7df24841e ♻️ update sqlite DB 2026-02-12 03:50:30 +01:00
Fred KISSIE
e6fd4c32c4 ♻️ update DB 2026-02-12 03:50:09 +01:00
Fred KISSIE
f6590aedbd ♻️ add default sso: true to resource policy table 2026-02-12 03:22:24 +01:00
Fred KISSIE
3cb9e02533 ♻️ make resourcePolicyId non nullable 2026-02-12 02:56:45 +01:00
Fred KISSIE
4d792350ef 🗃️ add resource policy table 2026-02-12 02:53:04 +01:00
424 changed files with 35762 additions and 10843 deletions

View File

@@ -34,3 +34,4 @@ build.ts
tsconfig.json
Dockerfile*
drizzle.config.ts
allowedDevOrigins.json

View File

@@ -77,7 +77,7 @@ jobs:
fi
- name: Log in to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -149,7 +149,7 @@ jobs:
fi
- name: Log in to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -204,7 +204,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Log in to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: docker.io
username: ${{ secrets.DOCKER_HUB_USERNAME }}
@@ -407,7 +407,7 @@ jobs:
shell: bash
- name: Login to GitHub Container Registry (for cosign)
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}

View File

@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '24'

View File

@@ -23,7 +23,7 @@ jobs:
skopeo --version
- name: Install cosign
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Input check
run: |

View File

@@ -14,7 +14,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
with:
days-before-stale: 14
days-before-close: 14

View File

@@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '24'

6
.gitignore vendored
View File

@@ -17,9 +17,9 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
*.db
*.sqlite
*.sqlite*
!Dockerfile.sqlite
*.sqlite3
*.sqlite3*
*.log
.machinelogs*.json
*-audit.json
@@ -54,3 +54,5 @@ hydrateSaas.ts
CLAUDE.md
drizzle.config.ts
server/setup/migrations.ts
solo.yml
allowedDevOrigins.json

View File

@@ -107,7 +107,7 @@ the docs to illustrate some basic ideas.
## Licensing
Pangolin is dual licensed under the AGPL-3 and the [Fossorial Commercial License](https://pangolin.net/fcl.html). For inquiries about commercial licensing, please contact us at [contact@pangolin.net](mailto:contact@pangolin.net).
Pangolin is dual licensed under the AGPL-3 and the [Fossorial Commercial License](https://pangolin.net/fcl). For inquiries about commercial licensing, please contact us at [contact@pangolin.net](mailto:contact@pangolin.net).
## Contributions

View File

@@ -0,0 +1,51 @@
import { CommandModule } from "yargs";
import { db, users } from "@server/db";
import { eq } from "drizzle-orm";
type SetServerAdminArgs = {
email: string;
};
export const setServerAdmin: CommandModule<{}, SetServerAdminArgs> = {
command: "set-server-admin",
describe: "Mark any user as a server admin by email address",
builder: (yargs) => {
return yargs.option("email", {
type: "string",
demandOption: true,
describe: "User email address"
});
},
handler: async (argv: { email: string }) => {
try {
const email = argv.email.trim().toLowerCase();
const [user] = await db
.select()
.from(users)
.where(eq(users.email, email))
.limit(1);
if (!user) {
console.error(`User with email '${email}' not found`);
process.exit(1);
}
if (user.serverAdmin) {
console.log(`User '${email}' is already a server admin`);
process.exit(0);
}
await db
.update(users)
.set({ serverAdmin: true })
.where(eq(users.userId, user.userId));
console.log(`User '${email}' has been marked as a server admin`);
process.exit(0);
} catch (error) {
console.error("Error:", error);
process.exit(1);
}
}
};

View File

@@ -11,6 +11,7 @@ import { deleteClient } from "./commands/deleteClient";
import { generateOrgCaKeys } from "./commands/generateOrgCaKeys";
import { clearCertificates } from "./commands/clearCertificates";
import { disableUser2fa } from "./commands/disableUser2fa";
import { setServerAdmin } from "./commands/setServerAdmin";
yargs(hideBin(process.argv))
.scriptName("pangctl")
@@ -23,5 +24,6 @@ yargs(hideBin(process.argv))
.command(generateOrgCaKeys)
.command(clearCertificates)
.command(disableUser2fa)
.command(setServerAdmin)
.demandCommand()
.help().argv;

View File

@@ -1,54 +1,47 @@
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
endpoint: http://pangolin:3001/api/v1/traefik-config
pollInterval: 5s
file:
filename: "/etc/traefik/dynamic_config.yml"
filename: /etc/traefik/dynamic_config.yml
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "{{.BadgerVersion}}"
moduleName: github.com/fosrl/badger
version: v1.4.1
log:
level: "INFO"
format: "common"
level: INFO
format: common
maxSize: 100
maxBackups: 3
maxAge: 3
compress: true
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: "{{.LetsEncryptEmail}}"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
email: '{{.LetsEncryptEmail}}'
storage: /letsencrypt/acme.json
caServer: https://acme-v02.api.letsencrypt.org/directory
entryPoints:
web:
address: ":80"
address: ':80'
websecure:
address: ":443"
address: ':443'
transport:
respondingTimeouts:
readTimeout: "30m"
readTimeout: 30m
http:
tls:
certResolver: "letsencrypt"
certResolver: letsencrypt
encodedCharacters:
allowEncodedSlash: true
allowEncodedQuestionMark: true
serversTransport:
insecureSkipVerify: true
ping:
entryPoint: "web"
entryPoint: web

View File

@@ -22,7 +22,8 @@ server:
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
allowed_headers: ["X-CSRF-Token", "Content-Type"]
credentials: false
{{if .EnableGeoblocking}}maxmind_db_path: "./config/GeoLite2-Country.mmdb"{{end}}
{{if .EnableMaxMind}}maxmind_db_path: "./config/GeoLite2-Country.mmdb"{{end}}
{{if .EnableMaxMind}}maxmind_asn_path: "./config/GeoLite2-ASN.mmdb"{{end}}
{{if .EnableEmail}}
email:
smtp_host: "{{.EmailSMTPHost}}"
@@ -36,3 +37,8 @@ flags:
disable_signup_without_invite: true
disable_user_create_org: false
allow_raw_resources: true
{{if .IsPostgreSQL}}
postgres:
connection_string: postgresql://pangolin:{{.IsPostgreSQLPass}}@postgres:5432/pangolin
{{end}}

View File

@@ -1,7 +1,7 @@
name: pangolin
services:
pangolin:
image: docker.io/fosrl/pangolin:{{if .IsEnterprise}}ee-{{end}}{{.PangolinVersion}}
image: docker.io/fosrl/pangolin:{{if .IsEnterprise}}ee-{{end}}{{if .IsPostgreSQL}}postgresql-{{end}}{{.PangolinVersion}}
container_name: pangolin
restart: unless-stopped
deploy:
@@ -10,6 +10,20 @@ services:
memory: 1g
reservations:
memory: 256m
{{if or .IsPostgreSQL .IsRedis}}
depends_on:
{{if .IsPostgreSQL}}
postgres:
condition: service_healthy
{{end}}
{{if .IsRedis}}
redis:
condition: service_healthy
{{end}}
networks:
- default
- backend
{{end}}
volumes:
- ./config:/app/config
healthcheck:
@@ -60,8 +74,56 @@ services:
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
{{if .IsPostgreSQL}}
postgres:
image: postgres:18
container_name: postgres
restart: unless-stopped
environment:
POSTGRES_USER: pangolin
POSTGRES_PASSWORD: {{.IsPostgreSQLPass}}
POSTGRES_DB: pangolin
volumes:
- ./postgres18:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U pangolin"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
{{end}}
{{if .IsRedis}}
redis:
image: redis:8-trixie
container_name: redis
restart: unless-stopped
command: >
redis-server
--save 3600 1000
--appendonly yes
--requirepass {{.IsRedisPass}}
volumes:
- ./redis8:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "{{.IsRedisPass}}", "ping"]
interval: 10s
timeout: 3s
retries: 3
start_period: 10s
networks:
- backend
{{end}}
networks:
default:
driver: bridge
name: pangolin
name: pangolin_frontend
{{if .EnableIPv6}} enable_ipv6: true{{end}}
{{if or .IsPostgreSQL .IsRedis}}
backend:
driver: bridge
name: pangolin_backend
internal: true
{{end}}

View File

@@ -0,0 +1,6 @@
{{if .IsRedis}}
redis:
host: "redis"
port: 6379
password: "{{.IsRedisPass}}"
{{end}}

View File

@@ -54,9 +54,13 @@ type Config struct {
InstallGerbil bool
TraefikBouncerKey string
DoCrowdsecInstall bool
EnableGeoblocking bool
EnableMaxMind bool
Secret string
IsEnterprise bool
IsPostgreSQL bool
IsPostgreSQLPass string
IsRedis bool
IsRedisPass string
}
type SupportedContainer string
@@ -123,11 +127,11 @@ func main() {
fmt.Println("\nConfiguration files created successfully!")
// Download MaxMind database if requested
if config.EnableGeoblocking {
fmt.Println("\n=== Downloading MaxMind Database ===")
// Download MaxMind Country / ASN database if requested
if config.EnableMaxMind {
fmt.Println("\n=== Downloading MaxMind Country and ASN Databases ===")
if err := downloadMaxMindDatabase(); err != nil {
fmt.Printf("Error downloading MaxMind database: %v\n", err)
fmt.Printf("Error downloading MaxMind databases: %v\n", err)
fmt.Println("You can download it manually later if needed.")
}
}
@@ -188,15 +192,15 @@ func main() {
fmt.Println("\n=== MaxMind Database Update ===")
if _, err := os.Stat("config/GeoLite2-Country.mmdb"); err == nil {
fmt.Println("MaxMind GeoLite2 Country database found.")
if readBool("Would you like to update the MaxMind database to the latest version?", false) {
if readBool("Would you like to update the MaxMind databases (Country and ASN) to the latest version?", false) {
if err := downloadMaxMindDatabase(); err != nil {
fmt.Printf("Error updating MaxMind database: %v\n", err)
fmt.Println("You can try updating it manually later if needed.")
}
}
} else {
fmt.Println("MaxMind GeoLite2 Country database not found.")
if readBool("Would you like to download the MaxMind GeoLite2 database for geoblocking functionality?", false) {
fmt.Println("MaxMind GeoLite2 Country and ASN databases not found.")
if readBool("Would you like to download the MaxMind GeoLite2 databases for blocking functionality?", false) {
if err := downloadMaxMindDatabase(); err != nil {
fmt.Printf("Error downloading MaxMind database: %v\n", err)
fmt.Println("You can try downloading it manually later if needed.")
@@ -204,8 +208,10 @@ func main() {
// Now you need to update your config file accordingly to enable geoblocking
fmt.Print("Please remember to update your config/config.yml file to enable geoblocking! \n\n")
// add maxmind_db_path: "./config/GeoLite2-Country.mmdb" under server
fmt.Println("Add the following line under the 'server' section:")
// add maxmind_asn_path: "./config/GeoLite2-ASN.mmdb" under server
fmt.Println("Add the following lines under the 'server' section:")
fmt.Println(" maxmind_db_path: \"./config/GeoLite2-Country.mmdb\"")
fmt.Println(" maxmind_asn_path: \"./config/GeoLite2-ASN.mmdb\"")
}
}
}
@@ -484,6 +490,17 @@ func collectUserInput() Config {
fmt.Println("\n=== Basic Configuration ===")
config.IsEnterprise = readBoolNoDefault("Do you want to install the Enterprise version of Pangolin? The EE is free for personal use or for businesses making less than 100k USD annually.")
if config.IsEnterprise {
config.IsRedis = readBool("Do you want to run the Redis containers locally? Required for HA.")
if config.IsRedis {
config.IsRedisPass = readPassword("Enter a unique password for the Redis service.")
}
}
config.IsPostgreSQL = readBool("Do you want to run the PostgreSQL containers locally? Otherwise, default to the local SQLite database only.", false)
if config.IsPostgreSQL {
config.IsPostgreSQLPass = readPassword("Enter a unique password for the PostgreSQL pangolin user.")
}
config.BaseDomain = readString("Enter your base domain (no subdomain e.g. example.com)", "")
@@ -527,7 +544,7 @@ func collectUserInput() Config {
fmt.Println("\n=== Advanced Configuration ===")
config.EnableIPv6 = readBool("Is your server IPv6 capable?", true)
config.EnableGeoblocking = readBool("Do you want to download the MaxMind GeoLite2 database for geoblocking functionality?", true)
config.EnableMaxMind = readBool("Do you want to download the MaxMind GeoLite2 Country and ADN databases for blocking functionality?", true)
if config.DashboardDomain == "" {
fmt.Println("Error: Dashboard Domain name is required")
@@ -780,29 +797,42 @@ func checkPortsAvailable(port int) error {
}
func downloadMaxMindDatabase() error {
fmt.Println("Downloading MaxMind GeoLite2 Country database...")
fmt.Println("Downloading MaxMind GeoLite2 Country and ASN databases...")
// Download the GeoLite2 Country database
// Download the GeoLite2 Country databases
if err := run("curl", "-L", "-o", "GeoLite2-Country.tar.gz",
"https://github.com/GitSquared/node-geolite2-redist/raw/refs/heads/master/redist/GeoLite2-Country.tar.gz"); err != nil {
return fmt.Errorf("failed to download GeoLite2 database: %v", err)
return fmt.Errorf("failed to download GeoLite2 Country database: %v", err)
}
if err := run("curl", "-L", "-o", "GeoLite2-ASN.tar.gz",
"https://github.com/GitSquared/node-geolite2-redist/raw/refs/heads/master/redist/GeoLite2-ASN.tar.gz"); err != nil {
return fmt.Errorf("failed to download GeoLite2 ASN database: %v", err)
}
// Extract the database
// Extract the Country database
if err := run("tar", "-xzf", "GeoLite2-Country.tar.gz"); err != nil {
return fmt.Errorf("failed to extract GeoLite2 database: %v", err)
return fmt.Errorf("failed to extract GeoLite2 Country database: %v", err)
}
if err := run("tar", "-xzf", "GeoLite2-ASN.tar.gz"); err != nil {
return fmt.Errorf("failed to extract GeoLite2 ASN database: %v", err)
}
// Find the .mmdb file and move it to the config directory
if err := run("bash", "-c", "mv GeoLite2-Country_*/GeoLite2-Country.mmdb config/"); err != nil {
return fmt.Errorf("failed to move GeoLite2 database to config directory: %v", err)
return fmt.Errorf("failed to move GeoLite2 Country database to config directory: %v", err)
}
if err := run("bash", "-c", "mv GeoLite2-ASN_*/GeoLite2-ASN.mmdb config/"); err != nil {
return fmt.Errorf("failed to move GeoLite2 ASN database to config directory: %v", err)
}
// Clean up the downloaded files
if err := run("rm", "-rf", "GeoLite2-Country.tar.gz", "GeoLite2-Country_*"); err != nil {
fmt.Printf("Warning: failed to clean up temporary files: %v\n", err)
if err := run("sh", "-c", "rm -rf GeoLite2-Country.tar.gz GeoLite2-Country_*"); err != nil {
fmt.Printf("Warning: failed to clean up temporary country files: %v\n", err)
}
if err := run("sh", "-c", "rm -rf GeoLite2-ASN.tar.gz GeoLite2-ASN_*"); err != nil {
fmt.Printf("Warning: failed to clean up temporary ASN files: %v\n", err)
}
fmt.Println("MaxMind GeoLite2 Country database downloaded successfully!")
fmt.Println("MaxMind GeoLite2 Country and ASN database downloaded successfully!")
return nil
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Вижте частни ресурси",
"siteInstallNewt": "Инсталирайте Newt",
"siteInstallNewtDescription": "Пуснете Newt на вашата система",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard конфигурация",
"WgConfigurationDescription": "Използвайте следната конфигурация, за да се свържете с мрежата",
"operatingSystem": "Операционна система",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Ще можете да виждате това само веднъж. Уверете се да го копирате на сигурно място.",
"siteInfo": "Информация за сайта",
"status": "Статус",
"shareTitle": "Управление на връзки за споделяне",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Създайте споделими връзки, за да предоставите временен или постоянен достъп до прокси ресурсите",
"shareSearch": "Търсене на връзки за споделяне...",
"shareCreate": "Създайте връзка за споделяне",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Неуспешно изтриване на връзката",
"shareErrorDeleteMessage": "Възникна грешка при изтриване на връзката",
"shareDeleted": "Връзката беше изтрита",
"shareDeletedDescription": "Връзката беше премахната",
"shareDelete": "Изтрийте споделената връзка",
"shareDeleteConfirm": "Потвърдете изтриването на споделената връзка",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Сигурни ли сте, че искате да изтриете тази споделена връзка?",
"shareMessageRemove": "След изтриване връзката вече няма да работи и всеки, който я използва, ще загуби достъп до ресурса.",
"shareTokenDescription": "Достъпният токен може да бъде предаван по два начина: като параметър или в хедърите на заявките. Те трябва да бъдат предавани от клиента при всяка заявка за удостоверен достъп.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Възникна грешка при създаването на връзката за споделяне",
"shareCreateDescription": "Всеки с тази връзка може да получи достъп до ресурса",
"shareTitleOptional": "Заглавие (по избор)",
"sharePathOptional": "Път (по избор)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Изтече",
"neverExpire": "Никога не изтича",
"shareExpireDescription": "Времето на изтичане е колко дълго връзката ще бъде използваема и ще предоставя достъп до ресурса. След това време, връзката няма да работи и потребителите, които са я използвали, ще загубят достъп до ресурса.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Моля, изберете ресурс",
"proxyResourceTitle": "Управление на обществени ресурси",
"proxyResourceDescription": "Създайте и управлявайте ресурси, които са общодостъпни чрез уеб браузър.",
"proxyResourcesBannerTitle": "Публичен достъп чрез уеб.",
"proxyResourcesBannerDescription": "Публичните ресурси са HTTPS или TCP/UDP проксита, достъпни за всеки в интернет чрез уеб браузър. За разлика от частните ресурси, те не изискват софтуер от страна на клиента и могат да включват издентити и контексто-осъзнати политики за достъп.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Управление на частни ресурси",
"clientResourceDescription": "Създайте и управлявайте ресурси, които са достъпни само чрез свързан клиент.",
"privateResourcesBannerTitle": "Достъп до частни ресурси с нулево доверие.",
@@ -208,11 +212,36 @@
"resourcesSearch": "Търсене на ресурси...",
"resourceAdd": "Добавете ресурс",
"resourceErrorDelte": "Грешка при изтриване на ресурс",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} ресурс(а)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "няма ресурси",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Търсене на политики...",
"resourcePoliciesAdd": "Добавяне на политика",
"resourcePoliciesDefaultBadgeText": "Стандартна политика",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Следвайте стъпките по-долу, за да създадете нова политика",
"resourcePolicyName": "Име на политика",
"resourcePolicyNameDescription": "Дайте на тази политика име, за да я идентифицирате в цялото ви ресурси",
"resourcePolicyNamePlaceholder": "например Политика за вътрешен достъп",
"resourcePoliciesSeeAll": "Вижте всички политики",
"resourcePolicyAuthMethodAdd": "Добавяне на метод за идентификация",
"resourcePolicyOtpEmailAdd": "Добавяне на имейли за еднократна парола",
"resourcePolicyRulesAdd": "Добавяне на правила",
"resourcePolicyAuthMethodsDescription": "Позволете достъп до ресурси чрез допълнителни методи за идентификация",
"resourcePolicyUsersRolesDescription": "Конфигурирайте потребителите и ролите, които могат да посетят свързаните ресурси",
"rulesResourcePolicyDescription": "Конфигурирайте правилата за контрол на достъп до ресурси, свързани с тази политика",
"authentication": "Удостоверяване",
"protected": "Защита",
"notProtected": "Не защитен",
"resourceMessageRemove": "След като се премахне, ресурсът няма повече да бъде достъпен. Всички цели, свързани с ресурса, също ще бъдат премахнати.",
"resourceQuestionRemove": "Сигурни ли сте, че искате да премахнете ресурса от организацията?",
"resourcePolicyMessageRemove": "След премахването, политиката за ресурс няма да бъде повече достъпна. Всички ресурси, свързани с ресурса, ще бъдат нерешени и оставени без идентификация.",
"resourcePolicyQuestionRemove": "Сигурни ли сте, че искате да премахнете политиката за ресурс от организацията?",
"resourceHTTP": "HTTPS ресурс",
"resourceHTTPDescription": "Прокси заявки чрез HTTPS, използвайки напълно квалифицирано име на домейн.",
"resourceRaw": "Суров TCP/UDP ресурс",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Получавайте заявки чрез суров TCP/UDP с използване на портен номер. Изисква се сайтовете да се свързват към отдалечен възел.",
"resourceCreate": "Създайте ресурс",
"resourceCreateDescription": "Следвайте стъпките по-долу, за да създадете нов ресурс",
"resourceCreateGeneralDescription": "Конфигуриране на основните настройки на ресурса, включително име и тип",
"resourceSeeAll": "Вижте всички ресурси",
"resourceInfo": "Информация за ресурса",
"resourceCreateGeneral": "Основни параметри",
"resourceNameDescription": "Това е дисплейното име на ресурса.",
"siteSelect": "Изберете сайт",
"siteSearch": "Търсене на сайт",
@@ -231,12 +261,15 @@
"noCountryFound": "Не е намерена държава.",
"siteSelectionDescription": "Този сайт ще осигури свързаност до целта.",
"resourceType": "Тип ресурс",
"resourceTypeDescription": "Определете как да се достъпи ресурсът",
"resourceTypeDescription": "Това контролира протокола на ресурса и как той ще се визуализира в браузъра. Това не може да бъде променено по-късно.",
"resourceDomainDescription": "Ресурсът ще се обслужва на това напълно квалифицирано име на домейн.",
"resourceHTTPSSettings": "HTTPS настройки",
"resourceHTTPSSettingsDescription": "Конфигурирайте как ресурсът ще бъде достъпен по HTTPS",
"resourcePortDescription": "Външен порт на инстанцията или възела на Панголиин, където ресурсът ще бъде достъпен.",
"domainType": "Тип домейн",
"subdomain": "Субдомейн",
"baseDomain": "Базов домейн",
"configure": "Конфигуриране",
"subdomnainDescription": "Поддомейнът, където ресурсът ще бъде достъпен.",
"resourceRawSettings": "TCP/UDP настройки",
"resourceRawSettingsDescription": "Конфигурирайте как ресурсът ще бъде достъпен чрез TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Научете как да конфигурирате TCP/UDP ресурси",
"resourceBack": "Назад към ресурсите",
"resourceGoTo": "Отидете към ресурса",
"resourcePolicyDelete": "Изтриване на политика за ресурс",
"resourcePolicyDeleteConfirm": "Потвърдете изтриване на политика за ресурс",
"resourceDelete": "Изтрийте ресурс",
"resourceDeleteConfirm": "Потвърдете изтриване на ресурс",
"labelDelete": "Изтриване на етикета",
"labelAdd": "Добавяне на етикет",
"labelCreateSuccessMessage": "Етикетът е създаден успешно",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Етикетът е променен успешно",
"labelNameField": "Име на етикет",
"labelColorField": "Цвят на етикет",
"labelPlaceholder": "Пр.: homelab",
"labelCreate": "Създаване на етикет",
"createLabelDialogTitle": "Създаване на етикет",
"createLabelDialogDescription": "Създайте нов етикет, който може да се прикачи към тази организация",
"labelEdit": "Редактиране на етикет",
"editLabelDialogTitle": "Актуализиране на етикет",
"editLabelDialogDescription": "Редактирайте нов етикет, който може да се прикачи към тази организация",
"labelDeleteConfirm": "Потвърдете изтриването на етикета",
"labelErrorDelete": "Неуспешно изтриване на етикета",
"labelMessageRemove": "Това действие е постоянно. Всички сайтове, ресурси и клиенти, маркирани с този етикет, ще бъдат отмаркирани.",
"labelQuestionRemove": "Сигурни ли сте, че искате да премахнете етикета от организацията?",
"visibility": "Видимост",
"enabled": "Активиран",
"disabled": "Деактивиран",
@@ -265,6 +319,8 @@
"rules": "Правила",
"resourceSettingDescription": "Конфигурирайте настройките на ресурса",
"resourceSetting": "Настройки на {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Настройки за {policyName}",
"alwaysAllow": "Заобикаляне на Ауторизацията",
"alwaysDeny": "Блокиране на Достъпа",
"passToAuth": "Прехвърляне към удостоверяване",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Дубликат на правило",
"rulesErrorDuplicateDescription": "Правило с тези настройки вече съществува",
"rulesErrorInvalidIpAddressRange": "Невалиден CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Моля, въведете валидна стойност на CIDR",
"rulesErrorInvalidUrl": "Невалиден URL път",
"rulesErrorInvalidUrlDescription": "Моля, въведете валидна стойност за URL път",
"rulesErrorInvalidIpAddress": "Невалиден IP",
"rulesErrorInvalidIpAddressDescription": "Моля, въведете валиден IP адрес",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Неуспешно актуализиране на правилата",
"rulesErrorUpdateDescription": "Възникна грешка при актуализиране на правилата",
"rulesUpdated": "Активиране на правилата",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Въведете адрес във формат CIDR (напр. 103.21.244.0/22)",
"rulesMatchIpAddress": "Въведете IP адрес (напр. 103.21.244.12)",
"rulesMatchUrl": "Въведете URL път или модел (напр. /api/v1/todos или /api/v1/*)",
"rulesErrorInvalidPriority": "Невалиден приоритет",
"rulesErrorInvalidPriorityDescription": "Моля, въведете валиден приоритет",
"rulesErrorDuplicatePriority": "Дублирани приоритети",
"rulesErrorDuplicatePriorityDescription": "Моля, въведете уникални приоритети",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Правилата са актуализирани",
"ruleUpdatedDescription": "Правилата бяха успешно актуализирани",
"ruleErrorUpdate": "Операцията не бе успешна",
"ruleErrorUpdateDescription": "Възникна грешка по време на операцията за запис",
"rulesPriority": "Приоритет",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Действие",
"rulesMatchType": "Тип на съвпадение",
"value": "Стойност",
@@ -744,9 +809,60 @@
"rulesResource": "Конфигурация на правилата за ресурси",
"rulesResourceDescription": "Конфигурирайте правила за контролиране на достъпа до ресурса",
"ruleSubmit": "Добави правило",
"rulesNoOne": "Няма правила. Добавете правило чрез формуляра.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Правилата се оценяват по приоритет в нарастващ ред.",
"rulesSubmit": "Запазване на правилата",
"policyErrorCreate": "Грешка при създаване на политика",
"policyErrorCreateDescription": "Възникна грешка при създаването на политиката",
"policyErrorCreateMessageDescription": "Възникна неочаквана грешка",
"policyErrorUpdate": "Грешка при актуализиране на политика",
"policyErrorUpdateDescription": "Възникна грешка при актуализиране на политиката",
"policyErrorUpdateMessageDescription": "Възникна неочаквана грешка",
"policyCreatedSuccess": "Политиката за ресурс е създадена успешно",
"policyUpdatedSuccess": "Политиката за ресурс е актуализирана успешно",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Запазете правилата",
"resourceErrorCreate": "Грешка при създаване на ресурс",
"resourceErrorCreateDescription": "Възникна грешка при създаването на ресурса",
"resourceErrorCreateMessage": "Грешка при създаване на ресурс:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Възникна грешка при актуализиране на ресурса",
"access": "Достъп",
"accessControl": "Контрол на достъпа",
"shareLink": "{resource} Сподели връзка",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Изберете ресурс",
"shareLinks": "Споделени връзки",
"shareLinks": "Shareable Links",
"share": "Споделени връзки",
"shareDescription2": "Създайте връзки за достъп до ресурси. Връзките предоставят временен или неограничен достъп до вашия ресурс. Можете да конфигурирате продължителността на изтичане на връзката, когато я създавате.",
"shareEasyCreate": "Лесно за създаване и споделяне",
@@ -810,6 +926,17 @@
"pincodeAdd": "Добави ПИН код",
"pincodeRemove": "Премахни ПИН код",
"resourceAuthMethods": "Методи за автентикация",
"resourcePolicyAuthMethodsEmpty": "Няма метод за идентификация",
"resourcePolicyOtpEmpty": "Без еднократна парола",
"resourcePolicyReadOnly": "Тази политика е само за четене",
"resourcePolicyReadOnlyDescription": "Тази политика за ресурс се споделя между множество ресурси, не можете да я редактирате на тази страница.",
"editSharedPolicy": "Редактирай споделена политика",
"resourcePolicyTypeSave": "Запазете типа на ресурс",
"resourcePolicySelect": "Изберете политика за ресурс",
"resourcePolicySelectError": "Изберете политика за ресурс",
"resourcePolicyNotFound": "Политиката не е намерена",
"resourcePolicySearch": "Търсене на политики",
"resourcePolicyRulesEmpty": "Няма правила за идентификация",
"resourceAuthMethodsDescriptions": "Позволете достъп до ресурса чрез допълнителни методи за автентикация",
"resourceAuthSettingsSave": "Запазено успешно",
"resourceAuthSettingsSaveDescription": "Настройките за автентикация са запазени успешно",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Задай ПИН код",
"resourcePincodeSetupTitleDescription": "Задайте ПИН код, за да защитите този ресурс",
"resourceRoleDescription": "Администраторите винаги могат да имат достъп до този ресурс.",
"resourcePolicySelectTitle": "Политика за достъп до ресурс",
"resourcePolicySelectDescription": "Изберете типа на политиката за ресурс за идентификация",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Инлайн Политика за Ресурс",
"resourcePolicyInlineDescription": "Политика за достъп, ограничена само до този ресурс",
"resourcePolicyShared": "Споделена Политика за Ресурс",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Контроли за достъп",
"resourceUsersRolesDescription": "Конфигурирайте кои потребители и роли могат да посещават този ресурс",
"resourceUsersRolesSubmit": "Запазване на управлението на достъп.",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Имаше проблем със свързването към {name}. Моля, свържете се с вашия администратор.",
"idpErrorNotFound": "Не е намерен идентификационен доставчик",
"inviteInvalid": "Невалидна покана",
"labels": "Етикети",
"orgLabelsDescription": "Управление на етикети в тази организация.",
"addLabels": "Добавяне на етикети",
"siteLabelsTab": "Етикети",
"siteLabelsDescription": "Управление на етикети, свързани с този сайт.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Търсене на етикети",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# етикет} other {# етикети}}",
"labelOverflowCount": "+{count, plural, one {# етикет} other {# етикети}}",
"accessLabelFilterClear": "Изчисти филтрите за етикети",
"accessFilterClear": "Clear filters",
"selectColor": "Изберете цвят",
"createNewLabel": "Създайте нов организационен етикет \"{label}\"",
"inviteInvalidDescription": "Линкът към поканата е невалиден.",
"inviteErrorWrongUser": "Поканата не е за този потребител",
"inviteErrorUserNotExists": "Потребителят не съществува. Моля, създайте акаунт първо.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Ресурси",
"sidebarProxyResources": "Публично",
"sidebarClientResources": "Частно",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Контрол на достъпа",
"sidebarLogsAndAnalytics": "Дневници и анализи",
"sidebarTeam": "Екип",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Администратор",
"sidebarInvitations": "Покани",
"sidebarRoles": "Роли",
"sidebarShareableLinks": "Връзки",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API ключове",
"sidebarProvisioning": "Осигуряване",
"sidebarSettings": "Настройки",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Сайт {id}",
"standaloneHcFilterResourceIdFallback": "Ресурс {id}",
"blueprints": "Чертежи",
"blueprintsDescription": "Прилагайте декларативни конфигурации и преглеждайте предишни изпълнения",
"blueprintsLog": "Регистър на скицописи",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Добави Чертеж",
"blueprintGoBack": "Виж всички Чертежи",
"blueprintCreate": "Създай Чертеж",
@@ -1575,7 +1732,17 @@
"contents": "Съдържание",
"parsedContents": "Парсирано съдържание (само за четене)",
"enableDockerSocket": "Активиране на Docker Чернова",
"enableDockerSocketDescription": "Активиране на Docker Socket маркировка за изтегляне на етикети на чернова. Пътят на гнездото трябва да бъде предоставен на Newt.",
"enableDockerSocketDescription": "Активирайте изтегляне с етикети на Docker Socket за скицописи. Пътят на гнездото трябва да бъде предоставен на конектора на сайта. Прочетете как работи това в <docsLink>документацията</docsLink>.",
"newtAutoUpdate": "Активиране на автоматично обновяване на сайта",
"newtAutoUpdateDescription": "Когато е активно, конекторите на сайта автоматично ще се актуализират до най-новата версия при наличието на ново издание.",
"siteAutoUpdate": "Автоматично обновяване на сайта",
"siteAutoUpdateLabel": "Активиране на автоматично обновяване",
"siteAutoUpdateDescription": "Управлявайте дали конекторът за този сайт автоматично изтегля последната версия.",
"siteAutoUpdateOrgDefault": "По подразбиране за организацията: {state}",
"siteAutoUpdateOverriding": "Преодоляване на настройката на организацията",
"siteAutoUpdateResetToOrg": "Възстановяване към организацията по подразбиране",
"siteAutoUpdateEnabled": "активиран",
"siteAutoUpdateDisabled": "деактивиран",
"viewDockerContainers": "Преглед на Docker контейнери",
"containersIn": "Контейнери в {siteName}",
"selectContainerDescription": "Изберете контейнер, който да ползвате като име на хост за целта. Натиснете порт, за да ползвате порт",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Сертификат",
"certificateStatusAutoRefreshHint": "Състоянието се опреснява автоматично.",
"loading": "Зареждане",
"loadingEllipsis": "Зареждане...",
"loadingAnalytics": "Зареждане на анализи",
"restart": "Рестарт",
"domains": "Домейни",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Управлявайте абонамента си за платени самостоятелно хоствани лицензионни ключове",
"billingCurrentKeys": "Текущи ключове",
"billingModifyCurrentPlan": "Промяна на текущия план",
"billingManageLicenseSubscriptionDescription": "Управление на вашия абонамент за платени самообслужвани лицензионни ключове и изтегляне на фактури.",
"billingConfirmUpgrade": "Потвърдете повишаването",
"billingConfirmDowngrade": "Потвърдете понижението",
"billingConfirmUpgradeDescription": "Предстои ви да повишите плана си. Прегледайте новите ограничения и цени по-долу.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Неизвестен",
"healthCheck": "Проверка на здравето",
"configureHealthCheck": "Конфигуриране на проверка на здравето",
"configureHealthCheckDescription": "Настройте мониторинг на здравето за {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Разрешаване на проверки на здравето",
"healthCheckDisabledStateDescription": "Когато е деактивиран, сайтът не изпълнява проверки и състоянието се счита за неизвестно.",
"enableHealthChecksDescription": "Мониторинг на здравето на тази цел. Можете да наблюдавате различен краен пункт от целта, ако е необходимо.",
"healthScheme": "Метод",
"healthSelectScheme": "Избор на метод",
"healthCheckPortInvalid": "Портът за проверка на състоянието трябва да е между 1 и 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Път",
"healthHostname": "IP / Хост",
"healthPort": "Порт",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Времето е в секунди",
"requireDeviceApproval": "Изискват одобрение на устройства",
"requireDeviceApprovalDescription": "Потребители с тази роля трябва да имат нови устройства одобрени от администратор преди да могат да се свържат и да имат достъп до ресурси.",
"sshAccess": "SSH достъп",
"sshSettings": "Настройки за SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Настройки за RDP",
"vncSettings": "Настройки за VNC",
"sshServer": "SSH сървър",
"rdpServer": "RDP сървър",
"vncServer": "VNC сървър",
"sshServerDescription": "Настройте метода на идентификация, местоположението на демона и дестинацията на сървъра",
"rdpServerDescription": "Конфигуриране на дестинацията и порта на RDP сървъра",
"vncServerDescription": "Конфигуриране на дестинацията и порта на VNC сървъра",
"sshServerMode": "Режим",
"sshServerModeStandard": "Стандартен SSH сървър",
"sshServerModePangolin": "Панголиин SSH",
"sshServerModeStandardDescription": "Насочва командите към мрежата до SSH сървър, като например OpenSSH.",
"sshServerModeNative": "Нативен SSH сървър",
"sshServerModeNativeDescription": "Изпълнява команди директно на хоста чрез конектора на сайта. Не е необходима мрежова конфигурация.",
"sshAuthenticationMethod": "Метод на идентификация",
"sshAuthMethodManual": "Ръчна идентификация",
"sshAuthMethodManualDescription": "Изисква съществуващи идентификационни данни за хоста. Пропуска автоматичното осигуряване.",
"sshAuthMethodAutomated": "Автоматично осигуряване",
"sshAuthMethodAutomatedDescription": "Създава автоматично потребители, групи и sudo разрешения на хоста.",
"sshAuthDaemonLocation": "Местоположение на демона за идентификация",
"sshDaemonLocationSiteDescription": "Изпълнява се локално на машината, която хоства конектора на сайта.",
"sshDaemonLocationRemote": "На отдалечен хост",
"sshDaemonLocationRemoteDescription": "Изпълнява се на отделна целева машина в същата мрежа.",
"sshDaemonDisclaimer": "Уверете се, че вашата целева хост машина е правилно конфигурирана за изпълнение на демона за идентификация преди завършване на тази настройка, в противен случай осигуряването ще се провали.",
"sshDaemonPort": "Порт на демона",
"sshServerDestination": "Дестинация на сървъра",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Дестинация",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Избиране на множество сайтове позволява устойчиво маршрутизиране и сокетно превключване за висока наличност.",
"roleAllowSsh": "Разреши SSH",
"roleAllowSshAllow": "Разреши",
"roleAllowSshDisallow": "Забрани",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Потребителят може да изпълнява само определени команди с sudo.",
"sshSudo": "Разреши sudo",
"sshSudoCommands": "Sudo команди",
"sshSudoCommandsDescription": "Списък, разделен със запетаи, с команди, които потребителят е позволено да изпълнява с sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Създай начална директория",
"sshUnixGroups": "Unix групи",
"sshUnixGroupsDescription": "Списък, разделен със запетаи, с Unix групи, към които да се добави потребителят на целевия хост.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Опити за повторно",
"expectedResponseCodes": "Очаквани кодове за отговор",
"expectedResponseCodesDescription": "HTTP статус код, указващ здравословно състояние. Ако бъде оставено празно, между 200-300 се счита за здравословно.",
@@ -2049,8 +2268,9 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Метод",
"editInternalResourceDialogEnableSsl": "Активирайте TLS",
"editInternalResourceDialogEnableSsl": "Активиране на TLS",
"editInternalResourceDialogEnableSslDescription": "Активирайте SSL/TLS криптиране за сигурни HTTPS връзки към целта.",
"editInternalResourceDialogDestination": "Дестинация",
"editInternalResourceDialogDestinationHostDescription": "IP адресът или името на хоста на ресурса в мрежата на сайта.",
@@ -2098,9 +2318,10 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Метод",
"createInternalResourceDialogScheme": "Метод",
"createInternalResourceDialogEnableSsl": "Активирайте TLS",
"createInternalResourceDialogEnableSsl": "Активиране на TLS",
"createInternalResourceDialogEnableSslDescription": "Активирайте SSL/TLS криптиране за сигурни HTTPS връзки към целта.",
"createInternalResourceDialogDestination": "Дестинация",
"createInternalResourceDialogDestinationHostDescription": "IP адресът или името на хоста на ресурса в мрежата на сайта.",
@@ -2233,7 +2454,7 @@
"description": "По-надежден и по-нисък поддръжка на Самостоятелно-хостван Панголиин сървър с допълнителни екстри",
"introTitle": "Управлявано Самостоятелно-хостван Панголиин",
"introDescription": "е опция за внедряване, предназначена за хора, които искат простота и допълнителна надеждност, като същевременно запазят данните си частни и самостоятелно-хоствани.",
"introDetail": "С тази опция все още управлявате свой собствен Панголиин възел - вашите тунели, TLS терминатора и трафик остават на вашия сървър. Разликата е, че управлението и мониторингът се обработват чрез нашия облачен панел за контрол, който отключва редица предимства:",
"introDetail": "С тази опция все още управлявате свой собствен възел на Панголиин - вашите тунели, SSL прекратяване и трафик остават на вашия сървър. Разликата е, че управлението и мониторингът се обработват чрез нашия облачен панел, който отключва редица предимства:",
"benefitSimplerOperations": {
"title": "По-прости операции",
"description": "Няма нужда да управлявате свой собствен имейл сървър или да настройвате сложни аларми. Ще получите проверки и предупреждения при прекъсване от самото начало."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Въведете потвърждение.",
"blueprintViewDetails": "Подробности.",
"defaultIdentityProvider": "По подразбиране доставчик на идентичност.",
"defaultIdentityProviderDescription": "Когато е избран основен доставчик на идентичност, потребителят ще бъде автоматично пренасочен към доставчика за удостоверяване.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Мрежови настройки.",
"editInternalResourceDialogAccessPolicy": "Политика за достъп.",
"editInternalResourceDialogAddRoles": "Добавяне на роли.",
@@ -2937,11 +3158,12 @@
"learnMore": "Научете повече.",
"backToHome": "Връщане към началната страница.",
"needToSignInToOrg": "Трябва ли да използвате доставчика на идентичност на организацията си?",
"maintenanceMode": "Режим на поддръжка.",
"maintenanceMode": "Страница за поддръжка",
"maintenanceModeDescription": "Показване на страницата за поддръжка на посетители.",
"maintenanceModeType": "Тип режим на поддръжка.",
"showMaintenancePage": "Показване на страницата за поддръжка на посетители.",
"enableMaintenanceMode": "Активиране на режим на поддръжка.",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Автоматично.",
"automaticModeDescription": "Показване на страницата за поддръжка само когато всички целеви подсистеми са неработоспособни или в лошо състояние. Вашият ресурс продължава да работи нормално, докато поне един целеви подсистемен елемент е в здравия диапазон.",
"forced": "Наложително.",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Прогнозно завършване:",
"createInternalResourceDialogDestinationRequired": "Дестинацията е задължителна.",
"available": "Налично",
"disabledResourceDescription": "Когато е деактивиран, ресурсът ще бъде недостъпен от всеки.",
"archived": "Архивирано",
"noArchivedDevices": "Не са намерени архивирани устройства.",
"deviceArchived": "Устройството е архивирано.",
@@ -3136,7 +3359,7 @@
"httpDestNamePlaceholder": "Моята HTTP дестинация",
"httpDestUrlLabel": "Дестинация URL",
"httpDestUrlErrorHttpRequired": "URL адресът трябва да използва http или https",
"httpDestUrlErrorHttpsRequired": "HTTPS е необходимо за облачни инсталации",
"httpDestUrlErrorHttpsRequired": "SSL е необходимо за облачни инсталации",
"httpDestUrlErrorInvalid": "Въведете валиден URL (напр. https://example.com/webhook)",
"httpDestAuthTitle": "Удостоверяване",
"httpDestAuthDescription": "Изберете как заявленията ви се удостоверяват.",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Сигурни ли сте, че искате да отвържете този доставчик на самоличност от тази организация?",
"idpUnassociateDescription": "Всички потребители, свързани с този доставчик на самоличност, ще бъдат премахнати от тази организация, но доставчика на самоличност ще продължи да съществува за други свързани организации.",
"idpUnassociateConfirm": "Потвърдете отвързване на доставчика на самоличност",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Това не може да бъде отменено за тази организация.",
"idpUnassociatedDescription": "Доставчика на самоличност е успешно отвързан от тази организация",
"idpUnassociateMenu": "Отвързване",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Ресурсът е деактивиран",
"memberPortalShowingResources": "Показва {start}-{end} от {total} ресурси",
"memberPortalPrevious": "Предишен",
"memberPortalNext": "Следващ"
"memberPortalNext": "Следващ",
"httpSettings": "HTTP настройки",
"tcpSettings": "TCP настройки",
"udpSettings": "UDP настройки",
"sshTitle": "SSH",
"sshConnectingDescription": "Установяване на защитена връзка…",
"sshConnecting": "Свързване…",
"sshInitializing": "Инициализиране…",
"sshSignInTitle": "Вход в SSH",
"sshSignInDescription": "Въведете данните за SSH",
"sshPasswordTab": "Парола",
"sshPrivateKeyTab": "Частен ключ",
"sshPrivateKeyField": "Частен ключ",
"sshPrivateKeyDisclaimer": "Частният ви ключ не се съхранява или видима за Панголиин. Като алтернатива, можете да използвате краткотрайни сертификати за безпроблемна автентикация с вашата съществуваща идентичност в Панголиин.",
"sshLearnMore": "Научете повече",
"sshPrivateKeyFile": "Файл с частен ключ",
"sshAuthenticate": "Идентичност",
"sshTerminate": "Прекратяване",
"sshPoweredBy": "Подпомогнато от",
"sshErrorNoTarget": "Няма посочена цел",
"sshErrorWebSocket": "Неуспешно създаване на WebSocket връзка",
"sshErrorAuthFailed": "Неуспешна идентификация",
"sshErrorConnectionClosed": "Връзката е затворена преди завършване на идентификацията",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Zobrazit soukromé zdroje",
"siteInstallNewt": "Nainstalovat Newt",
"siteInstallNewtDescription": "Spustit Newt na vašem systému",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Konfigurace WireGuard",
"WgConfigurationDescription": "K připojení k síti použijte následující konfiguraci",
"operatingSystem": "Operační systém",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Toto nastavení uvidíte pouze jednou. Ujistěte se, že jej zkopírujete na bezpečné místo.",
"siteInfo": "Údaje o lokalitě",
"status": "Stav",
"shareTitle": "Spravovat sdílení odkazů",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Vytvořit sdílitelné odkazy pro udělení dočasného nebo trvalého přístupu ke zdrojům proxy",
"shareSearch": "Hledat sdílené odkazy...",
"shareCreate": "Vytvořit odkaz",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Nepodařilo se odstranit odkaz",
"shareErrorDeleteMessage": "Došlo k chybě při odstraňování odkazu",
"shareDeleted": "Odkaz odstraněn",
"shareDeletedDescription": "Odkaz byl odstraněn",
"shareDelete": "Smazat odkaz ke sdílení",
"shareDeleteConfirm": "Potvrdit smazání odkazu ke sdílení",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Jste si jisti, že chcete smazat tento odkaz ke sdílení?",
"shareMessageRemove": "Jakmile bude smazán, odkaz přestane fungovat a všichni, kdo jej používají, ztratí přístup k prostředku.",
"shareTokenDescription": "Přístupový token může být předán dvěma způsoby: jako parametr dotazu nebo v záhlaví požadavku. Tyto údaje musí být předány klientovi na každé žádosti o ověřený přístup.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Při vytváření odkazu došlo k chybě",
"shareCreateDescription": "Kdokoliv s tímto odkazem může přistupovat ke zdroji",
"shareTitleOptional": "Název (volitelné)",
"sharePathOptional": "Cesta (volitelně)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Platnost vyprší za",
"neverExpire": "Nikdy nevyprší",
"shareExpireDescription": "Doba platnosti určuje, jak dlouho bude odkaz použitelný a bude poskytovat přístup ke zdroji. Po této době odkaz již nebude fungovat a uživatelé kteří tento odkaz používali ztratí přístup ke zdroji.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Zvolte prosím zdroj",
"proxyResourceTitle": "Spravovat veřejné zdroje",
"proxyResourceDescription": "Vytváření a správa zdrojů, které jsou veřejně přístupné prostřednictvím webového prohlížeče",
"proxyResourcesBannerTitle": "Veřejný přístup založený na webu",
"proxyResourcesBannerDescription": "Veřejné prostředky jsou HTTPS nebo TCP/UDP proxy, které jsou přístupné každému na internetu prostřednictvím webového prohlížeče. Na rozdíl od soukromých prostředků nevyžadují software na straně klienta a mohou zahrnovat politiky přístupu orientované na identitu a kontext.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Spravovat soukromé zdroje",
"clientResourceDescription": "Vytváření a správa zdrojů, které jsou přístupné pouze prostřednictvím připojeného klienta",
"privateResourcesBannerTitle": "Zero-Trust soukromý přístup",
@@ -208,11 +212,36 @@
"resourcesSearch": "Prohledat zdroje...",
"resourceAdd": "Přidat zdroj",
"resourceErrorDelte": "Chyba při odstraňování zdroje",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} zdroj(e/ů)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "žádné zdroje",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Hledat zásady...",
"resourcePoliciesAdd": "Přidat zásadu",
"resourcePoliciesDefaultBadgeText": "Výchozí zásada",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Postupujte podle následujících kroků k vytvoření nové zásady",
"resourcePolicyName": "Název zásady",
"resourcePolicyNameDescription": "Pojmenujte tuto zásadu, aby byla rozpoznatelná napříč vašimi zdroji",
"resourcePolicyNamePlaceholder": "např. Zásada interního přístupu",
"resourcePoliciesSeeAll": "Zobrazit všechny zásady",
"resourcePolicyAuthMethodAdd": "Přidat metodu ověřování",
"resourcePolicyOtpEmailAdd": "Přidat OTP emaily",
"resourcePolicyRulesAdd": "Přidat pravidla",
"resourcePolicyAuthMethodsDescription": "Povolit přístup ke zdrojům prostřednictvím dodatečných metod ověřování",
"resourcePolicyUsersRolesDescription": "Nakonfigurujte, kteří uživatelé a role mohou navštívit připojené zdroje",
"rulesResourcePolicyDescription": "Nakonfigurujte pravidla k řízení přístupu ke zdrojům spojeným s touto zásadou",
"authentication": "Autentifikace",
"protected": "Chráněno",
"notProtected": "Nechráněno",
"resourceMessageRemove": "Jakmile zdroj odstraníte, nebude dostupný. Všechny související služby a cíle budou také odstraněny.",
"resourceQuestionRemove": "Jste si jisti, že chcete odstranit zdroj z organizace?",
"resourcePolicyMessageRemove": "Jakmile je zásada odstraněna, ke zdroji již nebude možný přístup. Všechny související zdroje budou odpojeny a zůstanou bez ověření.",
"resourcePolicyQuestionRemove": "Jste si jisti, že chcete odstranit zásadu zdroje z organizace?",
"resourceHTTP": "Zdroj HTTPS",
"resourceHTTPDescription": "Proxy požadavky přes HTTPS pomocí plně kvalifikovaného názvu domény.",
"resourceRaw": "Surový TCP/UDP zdroj",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy požadavky na syrové TCP/UDP pomocí čísla portu. Vyžaduje připojení stránek ke vzdálenému uzlu.",
"resourceCreate": "Vytvořit zdroj",
"resourceCreateDescription": "Postupujte podle níže uvedených kroků, abyste vytvořili a připojili nový zdroj",
"resourceCreateGeneralDescription": "Konfigurace základních nastavení zdroje včetně názvu a typu",
"resourceSeeAll": "Zobrazit všechny zdroje",
"resourceInfo": "Informace o zdroji",
"resourceCreateGeneral": "Obecné",
"resourceNameDescription": "Toto je zobrazovaný název zdroje.",
"siteSelect": "Vybrat lokalitu",
"siteSearch": "Hledat lokalitu",
@@ -231,12 +261,15 @@
"noCountryFound": "Nebyla nalezena žádná země.",
"siteSelectionDescription": "Tato lokalita poskytne připojení k cíli.",
"resourceType": "Typ zdroje",
"resourceTypeDescription": "Určete, jak přistupovat ke zdroji",
"resourceTypeDescription": "Toto určuje protokol zdroje a jak bude zobrazen v prohlížeči. Později to nelze změnit.",
"resourceDomainDescription": "Zdroji bude obsluhován tento plně kvalifikovaný doménový název.",
"resourceHTTPSSettings": "Nastavení HTTPS",
"resourceHTTPSSettingsDescription": "Nakonfigurujte, jak bude dokument přístupný přes HTTPS",
"resourcePortDescription": "Externí port na instanci nebo uzlu Pangolin, kde bude zdroj dostupný.",
"domainType": "Typ domény",
"subdomain": "Subdoména",
"baseDomain": "Základní doména",
"configure": "Konfigurovat",
"subdomnainDescription": "Subdoména, kde bude zdroj přístupný.",
"resourceRawSettings": "Nastavení TCP/UDP",
"resourceRawSettingsDescription": "Nakonfigurujte, jak bude dokument přístupný přes TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Naučte se konfigurovat zdroje TCP/UDP",
"resourceBack": "Zpět na zdroje",
"resourceGoTo": "Přejít na dokument",
"resourcePolicyDelete": "Smazat zásadu zdroje",
"resourcePolicyDeleteConfirm": "Potvrdit smazání zásady zdroje",
"resourceDelete": "Odstranit dokument",
"resourceDeleteConfirm": "Potvrdit odstranění dokumentu",
"labelDelete": "Smazat štítek",
"labelAdd": "Přidat štítek",
"labelCreateSuccessMessage": "Štítek byl úspěšně vytvořen",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Štítek byl úspěšně změněn",
"labelNameField": "Název štítku",
"labelColorField": "Barva štítku",
"labelPlaceholder": "Př. domací laboratoř",
"labelCreate": "Vytvořit štítek",
"createLabelDialogTitle": "Vytvořit štítek",
"createLabelDialogDescription": "Vytvořte nový štítek, který může být přiřazen této organizaci",
"labelEdit": "Upravit štítek",
"editLabelDialogTitle": "Aktualizovat štítek",
"editLabelDialogDescription": "Upravte nový štítek, který může být přiřazen této organizaci",
"labelDeleteConfirm": "Potvrdit smazání štítku",
"labelErrorDelete": "Nepodařilo se smazat štítek",
"labelMessageRemove": "Tato akce je trvalá. Všechny weby, zdroje a klienti označeni tímto štítkem budou neoznačeni.",
"labelQuestionRemove": "Jste si jisti, že chcete odebrat štítek z organizace?",
"visibility": "Viditelnost",
"enabled": "Povoleno",
"disabled": "Zakázáno",
@@ -265,6 +319,8 @@
"rules": "Pravidla",
"resourceSettingDescription": "Konfigurace nastavení na zdroji",
"resourceSetting": "Nastavení {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Nastavení {policyName}",
"alwaysAllow": "Obejít Auth",
"alwaysDeny": "Blokovat přístup",
"passToAuth": "Předat k ověření",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Duplikovat pravidlo",
"rulesErrorDuplicateDescription": "Pravidlo s těmito nastaveními již existuje",
"rulesErrorInvalidIpAddressRange": "Neplatný CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Zadejte prosím platnou hodnotu CIDR",
"rulesErrorInvalidUrl": "Neplatná URL cesta",
"rulesErrorInvalidUrlDescription": "Zadejte platnou hodnotu URL cesty",
"rulesErrorInvalidIpAddress": "Neplatná IP adresa",
"rulesErrorInvalidIpAddressDescription": "Zadejte prosím platnou IP adresu",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Aktualizace pravidel se nezdařila",
"rulesErrorUpdateDescription": "Při aktualizaci pravidel došlo k chybě",
"rulesUpdated": "Povolit pravidla",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Zadejte adresu ve formátu CIDR (např. 103.21.244.0/22)",
"rulesMatchIpAddress": "Zadejte IP adresu (např. 103.21.244.12)",
"rulesMatchUrl": "Zadejte URL cestu nebo vzor (např. /api/v1/todos nebo /api/v1/*)",
"rulesErrorInvalidPriority": "Neplatná Priorita",
"rulesErrorInvalidPriorityDescription": "Zadejte prosím platnou prioritu",
"rulesErrorDuplicatePriority": "Duplikovat priority",
"rulesErrorDuplicatePriorityDescription": "Zadejte prosím unikátní priority",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Pravidla byla aktualizována",
"ruleUpdatedDescription": "Pravidla byla úspěšně aktualizována",
"ruleErrorUpdate": "Operace selhala",
"ruleErrorUpdateDescription": "Při ukládání došlo k chybě",
"rulesPriority": "Priorita",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Akce",
"rulesMatchType": "Typ shody",
"value": "Hodnota",
@@ -744,9 +809,60 @@
"rulesResource": "Konfigurace pravidel zdroje",
"rulesResourceDescription": "Nastavit pravidla pro kontrolu přístupu ke zdroji",
"ruleSubmit": "Přidat pravidlo",
"rulesNoOne": "Žádná pravidla. Přidejte pravidlo pomocí formuláře.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Pravidla jsou hodnocena podle priority vzestupně.",
"rulesSubmit": "Uložit pravidla",
"policyErrorCreate": "Chyba při vytváření zásady",
"policyErrorCreateDescription": "Při vytváření zásady došlo k chybě",
"policyErrorCreateMessageDescription": "Došlo k neočekávané chybě",
"policyErrorUpdate": "Chyba při aktualizaci zásady",
"policyErrorUpdateDescription": "Při aktualizaci zásady došlo k chybě",
"policyErrorUpdateMessageDescription": "Došlo k neočekávané chybě",
"policyCreatedSuccess": "Zásada zdroje byla úspěšně vytvořena",
"policyUpdatedSuccess": "Zásada zdroje byla úspěšně aktualizována",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Uložit pravidla",
"resourceErrorCreate": "Chyba při vytváření zdroje",
"resourceErrorCreateDescription": "Při vytváření zdroje došlo k chybě",
"resourceErrorCreateMessage": "Chyba při vytváření zdroje:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Došlo k chybě při aktualizaci zdroje",
"access": "Přístup",
"accessControl": "Kontrola přístupu",
"shareLink": "{resource} Sdílet odkaz",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Vyberte zdroj",
"shareLinks": "Sdílet odkazy",
"shareLinks": "Shareable Links",
"share": "Sdílené odkazy",
"shareDescription2": "Vytvořte sdílitelné odkazy na zdroje. Odkazy poskytují dočasný nebo neomezený přístup k vašemu zdroji. Můžete nakonfigurovat dobu vypršení platnosti odkazu při jeho vytvoření.",
"shareEasyCreate": "Snadné vytváření a sdílení",
@@ -810,6 +926,17 @@
"pincodeAdd": "Přidat PIN kód",
"pincodeRemove": "Odstranit PIN kód",
"resourceAuthMethods": "Metody ověřování",
"resourcePolicyAuthMethodsEmpty": "Žádná metoda ověřování",
"resourcePolicyOtpEmpty": "Žádné jednorázové hesla",
"resourcePolicyReadOnly": "Tato zásada je pouze ke čtení",
"resourcePolicyReadOnlyDescription": "Tato zásada zdroje je sdílena mezi více zdroji, nelze ji upravovat na této stránce.",
"editSharedPolicy": "Upravit sdílenou zásadu",
"resourcePolicyTypeSave": "Uložit typ zdroje",
"resourcePolicySelect": "Vybrat zásadu zdroje",
"resourcePolicySelectError": "Vyberte zásadu zdroje",
"resourcePolicyNotFound": "Zásada nenalezena",
"resourcePolicySearch": "Hledat zásady",
"resourcePolicyRulesEmpty": "Žádná pravidla ověřování",
"resourceAuthMethodsDescriptions": "Povolit přístup ke zdroji pomocí dodatečných metod autorizace",
"resourceAuthSettingsSave": "Úspěšně uloženo",
"resourceAuthSettingsSaveDescription": "Nastavení ověřování bylo uloženo",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Nastavit anonymní kód",
"resourcePincodeSetupTitleDescription": "Nastavit pincode pro ochranu tohoto zdroje",
"resourceRoleDescription": "Administrátoři mají vždy přístup k tomuto zdroji.",
"resourcePolicySelectTitle": "Zásada přístupu ke zdrojům",
"resourcePolicySelectDescription": "Vyberte typ zásady zdroje ověřování",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Inline Zásada Zdroje",
"resourcePolicyInlineDescription": "Zásada přístupu se zaměřením pouze na tento zdroj",
"resourcePolicyShared": "Sdílená Zásada Zdroje",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Kontrola přístupu",
"resourceUsersRolesDescription": "Nastavení, kteří uživatelé a role mohou navštívit tento zdroj",
"resourceUsersRolesSubmit": "Uložit přístupové řízení",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Při připojování k {name}došlo k chybě. Obraťte se na správce.",
"idpErrorNotFound": "IdP nenalezen",
"inviteInvalid": "Neplatná pozvánka",
"labels": "Štítky",
"orgLabelsDescription": "Spravujte štítky v této organizaci.",
"addLabels": "Přidat štítky",
"siteLabelsTab": "Štítky",
"siteLabelsDescription": "Spravujte štítky přiřazené k této lokalitě.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Hledat štítky",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# štítek} few {# štítky} other {# štítků}}",
"labelOverflowCount": "+{count, plural, one {# štítek} few {# štítky} other {# štítků}}",
"accessLabelFilterClear": "Vymazat filtry štítků",
"accessFilterClear": "Clear filters",
"selectColor": "Vybrat barvu",
"createNewLabel": "Vytvořit nový štítek organizace \"{label}\"",
"inviteInvalidDescription": "Odkaz pro pozvání je neplatný.",
"inviteErrorWrongUser": "Pozvat není pro tohoto uživatele",
"inviteErrorUserNotExists": "Uživatel neexistuje. Nejprve si vytvořte účet.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Zdroje",
"sidebarProxyResources": "Veřejnost",
"sidebarClientResources": "Soukromé",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Kontrola přístupu",
"sidebarLogsAndAnalytics": "Logy & Analytika",
"sidebarTeam": "Tým",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Admin",
"sidebarInvitations": "Pozvánky",
"sidebarRoles": "Role",
"sidebarShareableLinks": "Odkazy",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API klíče",
"sidebarProvisioning": "Zajištění",
"sidebarSettings": "Nastavení",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Stránka {id}",
"standaloneHcFilterResourceIdFallback": "Zdroj {id}",
"blueprints": "Plány",
"blueprintsDescription": "Použít deklarativní konfigurace a zobrazit předchozí běhy",
"blueprintsLog": "Protokol plánů",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Přidat plán",
"blueprintGoBack": "Zobrazit všechny plány",
"blueprintCreate": "Vytvořit plán",
@@ -1575,7 +1732,17 @@
"contents": "Obsah",
"parsedContents": "Parsed content (Pouze pro čtení)",
"enableDockerSocket": "Povolit Docker plán",
"enableDockerSocketDescription": "Povolte seškrábání štítků na Docker Socket pro popisky plánů. Nová cesta musí být k dispozici.",
"enableDockerSocketDescription": "Povolte seškrábání štítků pro Docker Socket pro štítky plánů. Před připojením na lokalitní konektor musí být uvedena cesta k soketu. Přečtěte si, jak to funguje <docsLink>v dokumentaci</docsLink>.",
"newtAutoUpdate": "Povolit automatickou aktualizaci stránek",
"newtAutoUpdateDescription": "Když je zapnuto, konektory lokality se automaticky aktualizují na nejnovější verzi, když je k dispozici nové vydání.",
"siteAutoUpdate": "Automatická aktualizace stránek",
"siteAutoUpdateLabel": "Povolte automatickou aktualizaci",
"siteAutoUpdateDescription": "Ovládněte, zda bude konektor tohoto webu automaticky stahovat nejnovější verzi.",
"siteAutoUpdateOrgDefault": "Výchozí organizace: {state}",
"siteAutoUpdateOverriding": "Přepsání nastavení organizace",
"siteAutoUpdateResetToOrg": "Obnovit na výchozí organizaci",
"siteAutoUpdateEnabled": "povoleno",
"siteAutoUpdateDisabled": "zakázáno",
"viewDockerContainers": "Zobrazit kontejnery Dockeru",
"containersIn": "Kontejnery v {siteName}",
"selectContainerDescription": "Vyberte jakýkoli kontejner pro použití jako název hostitele pro tento cíl. Klikněte na port pro použití portu.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certifikát",
"certificateStatusAutoRefreshHint": "Stav se automaticky obnovuje.",
"loading": "Načítání",
"loadingEllipsis": "Načítání...",
"loadingAnalytics": "Načítání analytiky",
"restart": "Restartovat",
"domains": "Domény",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Spravujte své předplatné za placené samohostované licenční klíče",
"billingCurrentKeys": "Aktuální klíče",
"billingModifyCurrentPlan": "Upravit aktuální tarif",
"billingManageLicenseSubscriptionDescription": "Spravujte své předplatné pro placené licence k samoobslužnému hostingu a stahujte faktury.",
"billingConfirmUpgrade": "Potvrdit aktualizaci",
"billingConfirmDowngrade": "Potvrdit downgrade",
"billingConfirmUpgradeDescription": "Chystáte se povýšit svůj tarif. Přečtěte si nové limity a ceny.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Neznámý",
"healthCheck": "Kontrola stavu",
"configureHealthCheck": "Konfigurace kontroly stavu",
"configureHealthCheckDescription": "Nastavit sledování zdravotního stavu pro {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Povolit kontrolu stavu",
"healthCheckDisabledStateDescription": "Pokud je zakázáno, web nebude provádět zdravotní kontroly a stav bude považován za neznámý.",
"enableHealthChecksDescription": "Sledujte zdraví tohoto cíle. V případě potřeby můžete sledovat jiný cílový bod, než je cíl.",
"healthScheme": "Způsob",
"healthSelectScheme": "Vybrat metodu",
"healthCheckPortInvalid": "Přístav kontroly stavu musí být mezi 1 a 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Cesta",
"healthHostname": "IP / Hostitel",
"healthPort": "Přístav",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Čas je v sekundách",
"requireDeviceApproval": "Vyžadovat schválení zařízení",
"requireDeviceApprovalDescription": "Uživatelé s touto rolí potřebují nová zařízení schválená správcem, než se mohou připojit a přistupovat ke zdrojům.",
"sshAccess": "SSH přístup",
"sshSettings": "Nastavení SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Nastavení RDP",
"vncSettings": "Nastavení VNC",
"sshServer": "SSH server",
"rdpServer": "RDP server",
"vncServer": "VNC server",
"sshServerDescription": "Nastavit metodu ověřování, umístění démona a cíl serveru",
"rdpServerDescription": "Nakonfigurujte cíl a port serveru RDP",
"vncServerDescription": "Nakonfigurujte cíl a port serveru VNC",
"sshServerMode": "Režim",
"sshServerModeStandard": "Standardní SSH server",
"sshServerModePangolin": "SSH Pangolin",
"sshServerModeStandardDescription": "Příkazy zpracovávané po síti na SSH server jako např. OpenSSH.",
"sshServerModeNative": "Nativní SSH server",
"sshServerModeNativeDescription": "Příkazy se provádí přímo na hostiteli přes Konektor lokality. Nastavení sítě není vyžadováno.",
"sshAuthenticationMethod": "Metoda ověřování",
"sshAuthMethodManual": "Ruční ověřování",
"sshAuthMethodManualDescription": "Vyžaduje existující přihlašovací údaje hostitele. Obchází automatické zřizování.",
"sshAuthMethodAutomated": "Automatické zřizování",
"sshAuthMethodAutomatedDescription": "Automaticky vytváří uživatele, skupiny a oprávnění sudo na hostiteli.",
"sshAuthDaemonLocation": "Umístění ověřovacího démona",
"sshDaemonLocationSiteDescription": "Spouští se lokálně na počítači s konektorem stránky.",
"sshDaemonLocationRemote": "Na vzdáleném hostiteli",
"sshDaemonLocationRemoteDescription": "Spouští se na jiném cílovém počítači v téže síti.",
"sshDaemonDisclaimer": "Ujistěte se, že váš cílový hostitel je správně nakonfigurován k přímu spuštění ověřovacího démona, jinak zřizování selže.",
"sshDaemonPort": "Port démona",
"sshServerDestination": "Cíl serveru",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Cíl",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Výběr více lokalit umožňuje odolné směrování a převzetí služeb při selhání pro vysokou dostupnost.",
"roleAllowSsh": "Povolit SSH",
"roleAllowSshAllow": "Povolit",
"roleAllowSshDisallow": "Zakázat",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Uživatel může spustit pouze zadané příkazy s sudo.",
"sshSudo": "Povolit sudo",
"sshSudoCommands": "Sudo příkazy",
"sshSudoCommandsDescription": "Čárkami oddělený seznam příkazů, které může uživatel spouštět s sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Vytvořit domovský adresář",
"sshUnixGroups": "Unixové skupiny",
"sshUnixGroupsDescription": "Čárkou oddělené skupiny Unix přidají uživatele do cílového hostitele.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Opakovat pokusy",
"expectedResponseCodes": "Očekávané kódy odezvy",
"expectedResponseCodesDescription": "HTTP kód stavu, který označuje zdravý stav. Ponecháte-li prázdné, 200-300 je považováno za zdravé.",
@@ -2049,8 +2268,9 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Schéma",
"editInternalResourceDialogEnableSsl": "Povolit SSL",
"editInternalResourceDialogEnableSsl": "Povolit TLS",
"editInternalResourceDialogEnableSslDescription": "Povolit šifrování SSL/TLS pro zabezpečené HTTPS připojení k cíli.",
"editInternalResourceDialogDestination": "Místo určení",
"editInternalResourceDialogDestinationHostDescription": "IP adresa nebo název hostitele zdroje v síti webu.",
@@ -2098,9 +2318,10 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Schéma",
"createInternalResourceDialogScheme": "Schéma",
"createInternalResourceDialogEnableSsl": "Povolit SSL",
"createInternalResourceDialogEnableSsl": "Povolit TLS",
"createInternalResourceDialogEnableSslDescription": "Povolit šifrování SSL/TLS pro zabezpečené HTTPS připojení k cíli.",
"createInternalResourceDialogDestination": "Místo určení",
"createInternalResourceDialogDestinationHostDescription": "IP adresa nebo název hostitele zdroje v síti webu.",
@@ -2233,7 +2454,7 @@
"description": "Spolehlivější a nízko udržovaný Pangolinův server s dalšími zvony a bičkami",
"introTitle": "Spravovaný Pangolin",
"introDescription": "je možnost nasazení určená pro lidi, kteří chtějí jednoduchost a spolehlivost při zachování soukromých a samoobslužných dat.",
"introDetail": "Pomocí této volby stále provozujete vlastní uzel Pangolin - tunely, SSL terminály a provoz všech pobytů na vašem serveru. Rozdíl spočívá v tom, že řízení a monitorování se řeší prostřednictvím našeho cloudového panelu, který odemkne řadu výhod:",
"introDetail": "Pomocí této volby stále provozujete vlastní uzel Pangolin - vaše tunely, ukončení TLS a provoz zůstávají na vašem serveru. Rozdíl spočívá v tom, že správa a monitoring jsou řešeny prostřednictvím naší cloudové řídící desky, což odemyká řadu výhod:",
"benefitSimplerOperations": {
"title": "Jednoduchý provoz",
"description": "Není třeba spouštět svůj vlastní poštovní server nebo nastavit komplexní upozornění. Ze schránky dostanete upozornění na zdravotní kontrolu a výpadek."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Zadejte potvrzení",
"blueprintViewDetails": "Detaily",
"defaultIdentityProvider": "Výchozí poskytovatel identity",
"defaultIdentityProviderDescription": "Pokud je vybrán výchozí poskytovatel identity, uživatel bude automaticky přesměrován na poskytovatele pro ověření.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Nastavení sítě",
"editInternalResourceDialogAccessPolicy": "Přístupová politika",
"editInternalResourceDialogAddRoles": "Přidat role",
@@ -2937,11 +3158,12 @@
"learnMore": "Zjistit více",
"backToHome": "Zpět na domovskou stránku",
"needToSignInToOrg": "Potřebujete použít identitního poskytovatele vaší organizace?",
"maintenanceMode": "Režim údržby",
"maintenanceMode": "Údržbová stránka",
"maintenanceModeDescription": "Zobrazit stránku údržby návštěvníkům",
"maintenanceModeType": "Typ režimu údržby",
"showMaintenancePage": "Zobrazit stránku údržby návštěvníkům",
"enableMaintenanceMode": "Povolit režim údržby",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatické",
"automaticModeDescription": "Zobrazte stránku údržby pouze, když jsou všechny cílové servery uživatele nebo prostředku nefunkční nebo nezdravé. Vaše prostředky budou nadále fungovat normálně, pokud je alespoň jeden cíl v pořádku.",
"forced": "Nucené",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Odhadované dokončení:",
"createInternalResourceDialogDestinationRequired": "Cíl je povinný",
"available": "Dostupné",
"disabledResourceDescription": "Když je deaktivován, zdroj bude nedostupný pro každého.",
"archived": "Archivováno",
"noArchivedDevices": "Nebyla nalezena žádná archivovaná zařízení",
"deviceArchived": "Zařízení archivováno",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Opravdu chcete odpojit tohoto poskytovatele identity od této organizace?",
"idpUnassociateDescription": "Všichni uživatelé spojení s tímto poskytovatelem identity budou odstraněni z této organizace, ale poskytovatel identity zůstane nadále existovat pro ostatní přidružené organizace.",
"idpUnassociateConfirm": "Potvrdit odpojení poskytovatele identity",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Toto nelze pro tuto organizaci vrátit.",
"idpUnassociatedDescription": "Poskytovatel identity byl úspěšně odpojen od této organizace",
"idpUnassociateMenu": "Odpojit",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Zdroj je zakázán",
"memberPortalShowingResources": "Zobrazeny {start}-{end} z {total} zdrojů",
"memberPortalPrevious": "Předchozí",
"memberPortalNext": "Následující"
"memberPortalNext": "Následující",
"httpSettings": "Nastavení HTTP",
"tcpSettings": "Nastavení TCP",
"udpSettings": "Nastavení UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Zřizování bezpečného připojení…",
"sshConnecting": "Připojení…",
"sshInitializing": "Inicializace…",
"sshSignInTitle": "Přihlášení do SSH",
"sshSignInDescription": "Zadejte své SSH přihlašovací údaje",
"sshPasswordTab": "Heslo",
"sshPrivateKeyTab": "Soukromý klíč",
"sshPrivateKeyField": "Soukromý klíč",
"sshPrivateKeyDisclaimer": "Váš soukromý klíč není ukládán ani viditelný pro Pangolin. Alternativně můžete použít krátkodobé certifikáty pro bezproblémové ověřování pomocí vaší stávající identity Pangolin.",
"sshLearnMore": "Přečtěte si více",
"sshPrivateKeyFile": "Soubor soukromého klíče",
"sshAuthenticate": "Ověřit",
"sshTerminate": "Ukončit",
"sshPoweredBy": "Vytváří",
"sshErrorNoTarget": "Cíl nebyl určen",
"sshErrorWebSocket": "Chyba připojení WebSocketu",
"sshErrorAuthFailed": "Ověření selhalo",
"sshErrorConnectionClosed": "Připojení bylo uzavřeno před dokončením ověřování",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Private Ressourcen anzeigen",
"siteInstallNewt": "Newt installieren",
"siteInstallNewtDescription": "Installiere Newt auf deinem System.",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard Konfiguration",
"WgConfigurationDescription": "Verwenden Sie folgende Konfiguration, um sich mit dem Netzwerk zu verbinden",
"operatingSystem": "Betriebssystem",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Du kannst das nur einmal sehen. Stelle sicher, dass du es an einen sicheren Ort kopierst.",
"siteInfo": "Standortinformationen",
"status": "Status",
"shareTitle": "Freigabelinks verwalten",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Erstelle teilbare Links, um temporären oder permanenten Zugriff auf Proxy-Ressourcen zu gewähren",
"shareSearch": "Freigabelinks suchen...",
"shareCreate": "Freigabelink erstellen",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Link konnte nicht gelöscht werden",
"shareErrorDeleteMessage": "Fehler beim Löschen des Links",
"shareDeleted": "Link gelöscht",
"shareDeletedDescription": "Der Link wurde gelöscht",
"shareDelete": "Freigabelink löschen",
"shareDeleteConfirm": "Löschen des Freigabelinks bestätigen",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Sind Sie sicher, dass Sie diesen Freigabelink löschen möchten?",
"shareMessageRemove": "Nach dem Löschen funktioniert der Link nicht mehr, und jeder, der ihn nutzt, verliert den Zugriff auf die Ressource.",
"shareTokenDescription": "Das Zugriffstoken kann auf zwei Arten übergeben werden: als Abfrageparameter oder in den Request-Headern. Diese müssen vom Client auf jeder Anfrage für authentifizierten Zugriff weitergegeben werden.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Beim Erstellen des Freigabelinks ist ein Fehler aufgetreten",
"shareCreateDescription": "Jeder mit diesem Link kann auf die Ressource zugreifen",
"shareTitleOptional": "Titel (optional)",
"sharePathOptional": "Pfad (optional)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Läuft ab in",
"neverExpire": "Läuft nie ab",
"shareExpireDescription": "Ablaufzeit ist, wie lange der Link verwendet werden kann und bietet Zugriff auf die Ressource. Nach dieser Zeit wird der Link nicht mehr funktionieren und Benutzer, die diesen Link benutzt haben, verlieren den Zugriff auf die Ressource.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Bitte wählen Sie eine Ressource",
"proxyResourceTitle": "Öffentliche Ressourcen verwalten",
"proxyResourceDescription": "Erstelle und verwalte Ressourcen, die über einen Webbrowser öffentlich zugänglich sind",
"proxyResourcesBannerTitle": "Web-basierter öffentlicher Zugang",
"proxyResourcesBannerDescription": "Öffentliche Ressourcen sind HTTPS oder TCP/UDP-Proxys, die über einen Webbrowser für jeden zugänglich sind. Im Gegensatz zu privaten Ressourcen benötigen sie keine Client-seitige Software und können Identitäts- und kontextbezogene Zugriffsrichtlinien beinhalten.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Private Ressourcen verwalten",
"clientResourceDescription": "Erstelle und verwalte Ressourcen, die nur über einen verbundenen Client zugänglich sind",
"privateResourcesBannerTitle": "Zero-Trust-Zugriff auf private Ressourcen",
@@ -208,11 +212,36 @@
"resourcesSearch": "Suche Ressourcen...",
"resourceAdd": "Ressource hinzufügen",
"resourceErrorDelte": "Fehler beim Löschen der Ressource",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} Ressource(n)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "keine Ressourcen",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Richtlinien suchen...",
"resourcePoliciesAdd": "Richtlinie hinzufügen",
"resourcePoliciesDefaultBadgeText": "Standardrichtlinie",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Befolgen Sie die unten stehenden Schritte, um eine neue Richtlinie zu erstellen",
"resourcePolicyName": "Richtlinienname",
"resourcePolicyNameDescription": "Geben Sie dieser Richtlinie einen Namen, um sie für Ihre Ressourcen zu identifizieren",
"resourcePolicyNamePlaceholder": "z. B. Richtlinie für internen Zugriff",
"resourcePoliciesSeeAll": "Alle Richtlinien anzeigen",
"resourcePolicyAuthMethodAdd": "Authentifizierungsmethode hinzufügen",
"resourcePolicyOtpEmailAdd": "OTP-E-Mails hinzufügen",
"resourcePolicyRulesAdd": "Regeln hinzufügen",
"resourcePolicyAuthMethodsDescription": "Ermöglichen Sie den Zugriff auf Ressourcen über zusätzliche Authentifizierungsmethoden",
"resourcePolicyUsersRolesDescription": "Konfigurieren Sie, welche Benutzer und Rollen diese Ressource besuchen können",
"rulesResourcePolicyDescription": "Konfigurieren Sie Regeln, um den Zugang zu den mit dieser Richtlinie verbundenen Ressourcen zu kontrollieren",
"authentication": "Authentifizierung",
"protected": "Geschützt",
"notProtected": "Nicht geschützt",
"resourceMessageRemove": "Einmal entfernt, wird die Ressource nicht mehr zugänglich sein. Alle mit der Ressource verbundenen Ziele werden ebenfalls entfernt.",
"resourceQuestionRemove": "Sind Sie sicher, dass Sie die Ressource aus der Organisation entfernen möchten?",
"resourcePolicyMessageRemove": "Einmal entfernt, wird die Ressourcenrichtlinie nicht mehr zugänglich sein. Alle mit der Ressource verbundenen Ressourcen werden nicht mehr zugeordnet und bleiben ohne Authentifizierung.",
"resourcePolicyQuestionRemove": "Sind Sie sicher, dass Sie die Ressourcenrichtlinie aus der Organisation entfernen möchten?",
"resourceHTTP": "HTTPS-Ressource",
"resourceHTTPDescription": "Proxy-Anfragen über HTTPS mit einem voll qualifizierten Domain-Namen.",
"resourceRaw": "Direkte TCP/UDP Ressource (raw)",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy-Anfragen über rohe TCP/UDP mit Portnummer. Benötigt Sites, um sich mit einem entfernten Knoten zu verbinden.",
"resourceCreate": "Ressource erstellen",
"resourceCreateDescription": "Folgen Sie den Schritten unten, um eine neue Ressource zu erstellen",
"resourceCreateGeneralDescription": "Konfigurieren Sie die Grundeinstellungen der Ressource, einschließlich Name und Typ",
"resourceSeeAll": "Alle Ressourcen anzeigen",
"resourceInfo": "Ressourcen-Informationen",
"resourceCreateGeneral": "Allgemein",
"resourceNameDescription": "Dies ist der Anzeigename für die Ressource.",
"siteSelect": "Standort auswählen",
"siteSearch": "Standorte durchsuchen",
@@ -231,12 +261,15 @@
"noCountryFound": "Kein Land gefunden.",
"siteSelectionDescription": "Dieser Standort wird die Verbindung zum Ziel herstellen.",
"resourceType": "Ressourcentyp",
"resourceTypeDescription": "Legen Sie fest, wie Sie auf die Ressource zugreifen",
"resourceTypeDescription": "Dies steuert das Ressourcenprotokoll und wie es im Browser gerendert wird. Dies kann später nicht geändert werden.",
"resourceDomainDescription": "Die Ressource wird unter diesem vollständig qualifizierten Domainnamen bereitgestellt.",
"resourceHTTPSSettings": "HTTPS-Einstellungen",
"resourceHTTPSSettingsDescription": "Konfigurieren Sie den Zugriff auf die Ressource über HTTPS",
"resourcePortDescription": "Der externe Port auf der Pangolin-Instanz oder dem Knoten, an dem die Ressource zugänglich ist.",
"domainType": "Domain-Typ",
"subdomain": "Subdomain",
"baseDomain": "Basis-Domain",
"configure": "Konfiguration",
"subdomnainDescription": "Die Subdomäne, auf die die Ressource zugegriffen werden soll.",
"resourceRawSettings": "TCP/UDP Einstellungen",
"resourceRawSettingsDescription": "Konfigurieren, wie auf die Ressource über TCP/UDP zugegriffen wird",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Lernen Sie, wie Sie TCP/UDP Ressourcen konfigurieren",
"resourceBack": "Zurück zu den Ressourcen",
"resourceGoTo": "Zu Ressource gehen",
"resourcePolicyDelete": "Ressourcenrichtlinie löschen",
"resourcePolicyDeleteConfirm": "Löschen der Ressourcenrichtlinie bestätigen",
"resourceDelete": "Ressource löschen",
"resourceDeleteConfirm": "Ressource löschen bestätigen",
"labelDelete": "Etikett löschen",
"labelAdd": "Etikett hinzufügen",
"labelCreateSuccessMessage": "Etikett erfolgreich erstellt",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etikett erfolgreich bearbeitet",
"labelNameField": "Etikettenname",
"labelColorField": "Etikettenfarbe",
"labelPlaceholder": "Beispiel: Heimlabor",
"labelCreate": "Etikett erstellen",
"createLabelDialogTitle": "Etikett erstellen",
"createLabelDialogDescription": "Erstellen Sie ein neues Etikett, das dieser Organisation zugeordnet werden kann",
"labelEdit": "Etikett bearbeiten",
"editLabelDialogTitle": "Etikett aktualisieren",
"editLabelDialogDescription": "Bearbeiten Sie ein neues Etikett, das dieser Organisation zugeordnet werden kann",
"labelDeleteConfirm": "Löschen des Etiketts bestätigen",
"labelErrorDelete": "Etikett konnte nicht gelöscht werden",
"labelMessageRemove": "Diese Aktion ist dauerhaft. Alle Standorte, Ressourcen und Clients, die mit diesem Etikett versehen sind, werden nicht mehr zugeordnet.",
"labelQuestionRemove": "Sind Sie sicher, dass Sie das Etikett aus der Organisation entfernen möchten?",
"visibility": "Sichtbarkeit",
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
@@ -265,6 +319,8 @@
"rules": "Regeln",
"resourceSettingDescription": "Einstellungen für die Ressource konfigurieren",
"resourceSetting": "{resourceName} Einstellungen",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} Einstellungen",
"alwaysAllow": "Authentifizierung umgehen",
"alwaysDeny": "Zugriff blockieren",
"passToAuth": "Weiterleiten zur Authentifizierung",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Doppelte Regel",
"rulesErrorDuplicateDescription": "Eine Regel mit diesen Einstellungen existiert bereits",
"rulesErrorInvalidIpAddressRange": "Ungültiger CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Bitte geben Sie einen gültigen CIDR-Wert ein",
"rulesErrorInvalidUrl": "Ungültiger URL-Pfad",
"rulesErrorInvalidUrlDescription": "Bitte geben Sie einen gültigen URL-Pfad-Wert ein",
"rulesErrorInvalidIpAddress": "Ungültige IP",
"rulesErrorInvalidIpAddressDescription": "Bitte geben Sie eine gültige IP-Adresse ein",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Fehler beim Aktualisieren der Regeln",
"rulesErrorUpdateDescription": "Beim Aktualisieren der Regeln ist ein Fehler aufgetreten",
"rulesUpdated": "Regeln aktivieren",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Geben Sie eine Adresse im CIDR-Format ein (z.B. 103.21.244.0/22)",
"rulesMatchIpAddress": "Geben Sie eine IP-Adresse ein (z.B. 103.21.244.12)",
"rulesMatchUrl": "Geben Sie einen URL-Pfad oder -Muster ein (z.B. /api/v1/todos oder /api/v1/*)",
"rulesErrorInvalidPriority": "Ungültige Priorität",
"rulesErrorInvalidPriorityDescription": "Bitte geben Sie eine gültige Priorität ein",
"rulesErrorDuplicatePriority": "Doppelte Prioritäten",
"rulesErrorDuplicatePriorityDescription": "Bitte geben Sie eindeutige Prioritäten ein",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Regeln aktualisiert",
"ruleUpdatedDescription": "Regeln erfolgreich aktualisiert",
"ruleErrorUpdate": "Operation fehlgeschlagen",
"ruleErrorUpdateDescription": "Während des Speichervorgangs ist ein Fehler aufgetreten",
"rulesPriority": "Priorität",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Aktion",
"rulesMatchType": "Übereinstimmungstyp",
"value": "Wert",
@@ -744,9 +809,60 @@
"rulesResource": "Ressourcen-Regelkonfiguration",
"rulesResourceDescription": "Regeln konfigurieren, um den Zugriff auf die Ressource zu steuern",
"ruleSubmit": "Regel hinzufügen",
"rulesNoOne": "Keine Regeln. Fügen Sie eine Regel über das Formular hinzu.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Regeln werden nach aufsteigender Priorität ausgewertet.",
"rulesSubmit": "Regeln speichern",
"policyErrorCreate": "Fehler beim Erstellen der Richtlinie",
"policyErrorCreateDescription": "Beim Erstellen der Richtlinie ist ein Fehler aufgetreten",
"policyErrorCreateMessageDescription": "Ein unerwarteter Fehler ist aufgetreten",
"policyErrorUpdate": "Fehler beim Aktualisieren der Richtlinie",
"policyErrorUpdateDescription": "Beim Aktualisieren der Richtlinie ist ein Fehler aufgetreten",
"policyErrorUpdateMessageDescription": "Ein unerwarteter Fehler ist aufgetreten",
"policyCreatedSuccess": "Ressourcenrichtlinie erfolgreich erstellt",
"policyUpdatedSuccess": "Ressourcenrichtlinie erfolgreich aktualisiert",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Regeln speichern",
"resourceErrorCreate": "Fehler beim Erstellen der Ressource",
"resourceErrorCreateDescription": "Beim Erstellen der Ressource ist ein Fehler aufgetreten",
"resourceErrorCreateMessage": "Fehler beim Erstellen der Ressource:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Beim Aktualisieren der Ressource ist ein Fehler aufgetreten",
"access": "Zugriff",
"accessControl": "Zugriffskontrolle",
"shareLink": "{resource} Freigabe-Link",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Ressource auswählen",
"shareLinks": "Freigabe-Links",
"shareLinks": "Shareable Links",
"share": "Teilbare Links",
"shareDescription2": "Erstellen Sie teilbare Links zu Ressourcen. Links bieten temporären oder unbegrenzten Zugriff auf Ihre Ressource. Sie können die Verfallsdauer des Links beim Erstellen eines Links festlegen.",
"shareEasyCreate": "Einfach zu erstellen und zu teilen",
@@ -810,6 +926,17 @@
"pincodeAdd": "PIN-Code hinzufügen",
"pincodeRemove": "PIN-Code entfernen",
"resourceAuthMethods": "Authentifizierungsmethoden",
"resourcePolicyAuthMethodsEmpty": "Keine Authentifizierungsmethode",
"resourcePolicyOtpEmpty": "Kein Einmal-Passwort",
"resourcePolicyReadOnly": "Diese Richtlinie ist nur lesbar",
"resourcePolicyReadOnlyDescription": "Diese Ressourcenrichtlinie wird über mehrere Ressourcen geteilt, Sie können sie auf dieser Seite nicht bearbeiten.",
"editSharedPolicy": "Geteilte Richtlinie bearbeiten",
"resourcePolicyTypeSave": "Ressourcentyp speichern",
"resourcePolicySelect": "Ressourcenrichtlinie auswählen",
"resourcePolicySelectError": "Wählen Sie eine Ressourcenrichtlinie aus",
"resourcePolicyNotFound": "Richtlinie nicht gefunden",
"resourcePolicySearch": "Richtlinien suchen",
"resourcePolicyRulesEmpty": "Keine Authentifizierungsregeln",
"resourceAuthMethodsDescriptions": "Ermöglichen Sie den Zugriff auf die Ressource über zusätzliche Authentifizierungsmethoden",
"resourceAuthSettingsSave": "Erfolgreich gespeichert",
"resourceAuthSettingsSaveDescription": "Authentifizierungseinstellungen wurden gespeichert",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "PIN-Code festlegen",
"resourcePincodeSetupTitleDescription": "Legen Sie einen PIN-Code fest, um diese Ressource zu schützen",
"resourceRoleDescription": "Administratoren haben immer Zugriff auf diese Ressource.",
"resourcePolicySelectTitle": "Zugriffsrichtlinie für Ressourcen",
"resourcePolicySelectDescription": "Wählen Sie den Ressourcentransfertyp für die Authentifizierung",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Inline-Ressourcenrichtlinie",
"resourcePolicyInlineDescription": "Zugriffsrichtlinie nur für diese Ressource",
"resourcePolicyShared": "Geteilte Ressourcenrichtlinie",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Zugriffskontrolle",
"resourceUsersRolesDescription": "Konfigurieren Sie, welche Benutzer und Rollen diese Ressource besuchen können",
"resourceUsersRolesSubmit": "Zugriffskontrollen speichern",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Es gab ein Problem bei der Verbindung zu {name}. Bitte kontaktieren Sie Ihren Administrator.",
"idpErrorNotFound": "IdP nicht gefunden",
"inviteInvalid": "Ungültige Einladung",
"labels": "Etiketten",
"orgLabelsDescription": "Etiketten in dieser Organisation verwalten.",
"addLabels": "Etiketten hinzufügen",
"siteLabelsTab": "Etiketten",
"siteLabelsDescription": "Verwalten Sie die mit diesem Standort verbundenen Etiketten.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Etiketten suchen",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# Etikett} other {# Etiketten}}",
"labelOverflowCount": "+{count, plural, one {# Etikett} other {# Etiketten}}",
"accessLabelFilterClear": "Etikettenfilter löschen",
"accessFilterClear": "Clear filters",
"selectColor": "Farbe auswählen",
"createNewLabel": "Neues Org-Etikett \"{label}\" erstellen",
"inviteInvalidDescription": "Der Einladungslink ist ungültig.",
"inviteErrorWrongUser": "Einladung ist nicht für diesen Benutzer",
"inviteErrorUserNotExists": "Benutzer existiert nicht. Bitte erstelle zuerst ein Konto.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Ressourcen",
"sidebarProxyResources": "Öffentlich",
"sidebarClientResources": "Privat",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Zugriffskontrolle",
"sidebarLogsAndAnalytics": "Protokolle & Analysen",
"sidebarTeam": "Team",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Admin",
"sidebarInvitations": "Einladungen",
"sidebarRoles": "Rollen",
"sidebarShareableLinks": "Links",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API-Schlüssel",
"sidebarProvisioning": "Bereitstellung",
"sidebarSettings": "Einstellungen",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Standort {id}",
"standaloneHcFilterResourceIdFallback": "Ressource {id}",
"blueprints": "Blaupausen",
"blueprintsDescription": "Deklarative Konfigurationen anwenden und vorherige Abläufe anzeigen",
"blueprintsLog": "Blaupausen-Protokoll",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Blueprint hinzufügen",
"blueprintGoBack": "Alle Blueprints ansehen",
"blueprintCreate": "Blueprint erstellen",
@@ -1575,7 +1732,17 @@
"contents": "Inhalt",
"parsedContents": "Analysierte Inhalte (Nur lesen)",
"enableDockerSocket": "Docker Blueprint aktivieren",
"enableDockerSocketDescription": "Aktiviere Docker-Socket-Label-Scraping für Blueprintbeschriftungen. Der Socket-Pfad muss neu angegeben werden.",
"enableDockerSocketDescription": "Aktiviere Docker-Socket-Label-Scraping für Blueprint-Etiketten. Der Socket-Pfad muss dem Site-Connector angegeben werden. Lesen Sie, wie dies in <docsLink>der Dokumentation</docsLink> funktioniert.",
"newtAutoUpdate": "Standort-Auto-Update aktivieren",
"newtAutoUpdateDescription": "Wenn aktiviert, aktualisieren sich die Standort-Connectoren automatisch auf die neueste Version, sobald eine neue Version verfügbar ist.",
"siteAutoUpdate": "Standort-Auto-Update",
"siteAutoUpdateLabel": "Autoupdate aktivieren",
"siteAutoUpdateDescription": "Steuern Sie, ob der Connector dieses Standorts automatisch die neueste Version herunterlädt.",
"siteAutoUpdateOrgDefault": "Standard der Organisation: {state}",
"siteAutoUpdateOverriding": "Organisations-Einstellung überschreiben",
"siteAutoUpdateResetToOrg": "Auf Standard der Organisation zurücksetzen",
"siteAutoUpdateEnabled": "aktiviert",
"siteAutoUpdateDisabled": "deaktiviert",
"viewDockerContainers": "Docker Container anzeigen",
"containersIn": "Container in {siteName}",
"selectContainerDescription": "Wählen Sie einen Container, der als Hostname für dieses Ziel verwendet werden soll. Klicken Sie auf einen Port, um einen Port zu verwenden.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Zertifikat",
"certificateStatusAutoRefreshHint": "Der Status wird automatisch aktualisiert.",
"loading": "Laden",
"loadingEllipsis": "Laden...",
"loadingAnalytics": "Analytik wird geladen",
"restart": "Neustart",
"domains": "Domänen",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Verwalten Sie Ihr Abonnement für kostenpflichtige selbstgehostete Lizenzschlüssel",
"billingCurrentKeys": "Aktuelle Tasten",
"billingModifyCurrentPlan": "Aktuelles Paket ändern",
"billingManageLicenseSubscriptionDescription": "Verwalten Sie Ihr Abonnement für bezahlte selbst gehostete Lizenzschlüssel und laden Sie Rechnungen herunter.",
"billingConfirmUpgrade": "Upgrade bestätigen",
"billingConfirmDowngrade": "Downgrade bestätigen",
"billingConfirmUpgradeDescription": "Sie sind dabei, Ihr Paket zu aktualisieren. Schauen Sie sich die neuen Limits und Preise unten an.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Unbekannt",
"healthCheck": "Gesundheits-Check",
"configureHealthCheck": "Gesundheits-Check konfigurieren",
"configureHealthCheckDescription": "Richten Sie die Gesundheitsüberwachung für {target} ein",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Gesundheits-Checks aktivieren",
"healthCheckDisabledStateDescription": "Wenn deaktiviert, führt der Standort keine Gesundheitsprüfungen durch und der Zustand wird als unbekannt betrachtet.",
"enableHealthChecksDescription": "Überwachen Sie die Gesundheit dieses Ziels. Bei Bedarf können Sie einen anderen Endpunkt als das Ziel überwachen.",
"healthScheme": "Methode",
"healthSelectScheme": "Methode auswählen",
"healthCheckPortInvalid": "Der Gesundheitskontroll-Port muss zwischen 1 und 65535 liegen",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Pfad",
"healthHostname": "IP / Host",
"healthPort": "Port",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Zeit ist in Sekunden",
"requireDeviceApproval": "Gerätegenehmigungen erforderlich",
"requireDeviceApprovalDescription": "Benutzer mit dieser Rolle benötigen neue Geräte, die von einem Administrator genehmigt wurden, bevor sie sich verbinden und auf Ressourcen zugreifen können.",
"sshAccess": "SSH-Zugriff",
"sshSettings": "SSH-Einstellungen",
"sshAccess": "SSH Access",
"rdpSettings": "RDP-Einstellungen",
"vncSettings": "VNC-Einstellungen",
"sshServer": "SSH-Server",
"rdpServer": "RDP-Server",
"vncServer": "VNC-Server",
"sshServerDescription": "Richten Sie die Authentifizierungsmethode, den Daemon-Standort und das Serverziel ein",
"rdpServerDescription": "Konfigurieren Sie das Ziel und den Port des RDP-Servers",
"vncServerDescription": "Konfigurieren Sie das Ziel und den Port des VNC-Servers",
"sshServerMode": "Modus",
"sshServerModeStandard": "Standard-SSH-Server",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Routen Befehle über Netzwerk zu einem SSH-Server wie OpenSSH.",
"sshServerModeNative": "Nativer SSH-Server",
"sshServerModeNativeDescription": "Führt Befehle direkt auf dem Host über den Site Connector aus. Keine Netzwerkkonfiguration erforderlich.",
"sshAuthenticationMethod": "Authentifizierungsmethode",
"sshAuthMethodManual": "Manuelle Authentifizierung",
"sshAuthMethodManualDescription": "Erfordert vorhandene Host-Anmeldeinformationen. Umgeht die automatische Bereitstellung.",
"sshAuthMethodAutomated": "Automatisierte Bereitstellung",
"sshAuthMethodAutomatedDescription": "Erstellt automatisch Benutzer, Gruppen und Sudo-Berechtigungen auf dem Host.",
"sshAuthDaemonLocation": "Standort des Auth-Daemon",
"sshDaemonLocationSiteDescription": "Wird lokal auf dem Rechner ausgeführt, der den Site-Connector beherbergt.",
"sshDaemonLocationRemote": "Auf Remote-Host",
"sshDaemonLocationRemoteDescription": "Wird auf einem separaten Zielrechner im gleichen Netzwerk ausgeführt.",
"sshDaemonDisclaimer": "Stellen Sie sicher, dass Ihr Zielhost korrekt konfiguriert ist, um den Auth-Daemon auszuführen, bevor Sie dieses Setup abschließen, andernfalls wird die Bereitstellung fehlschlagen.",
"sshDaemonPort": "Daemon-Port",
"sshServerDestination": "Serverziel",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Ziel",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Die Auswahl mehrerer Standorte ermöglicht eine widerstandsfähige Weiterleitung und einen Failover für hohe Verfügbarkeit.",
"roleAllowSsh": "SSH erlauben",
"roleAllowSshAllow": "Erlauben",
"roleAllowSshDisallow": "Nicht zulassen",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Benutzer kann nur die angegebenen Befehle mit sudo ausführen.",
"sshSudo": "sudo erlauben",
"sshSudoCommands": "Sudo-Befehle",
"sshSudoCommandsDescription": "Kommagetrennte Liste von Befehlen, die der Benutzer mit sudo ausführen darf.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Home-Verzeichnis erstellen",
"sshUnixGroups": "Unix-Gruppen",
"sshUnixGroupsDescription": "Durch Komma getrennte Unix-Gruppen, um den Benutzer auf dem Zielhost hinzuzufügen.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Wiederholungsversuche",
"expectedResponseCodes": "Erwartete Antwortcodes",
"expectedResponseCodesDescription": "HTTP-Statuscode, der einen gesunden Zustand anzeigt. Wenn leer gelassen, wird 200-300 als gesund angesehen.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Schema",
"editInternalResourceDialogEnableSsl": "TLS aktivieren",
"editInternalResourceDialogEnableSslDescription": "SSL/TLS-Verschlüsselung für sichere HTTPS-Verbindungen zum Ziel aktivieren.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Schema",
"createInternalResourceDialogScheme": "Schema",
"createInternalResourceDialogEnableSsl": "TLS aktivieren",
@@ -2233,7 +2454,7 @@
"description": "Zuverlässiger und wartungsarmer Pangolin Server mit zusätzlichen Glocken und Pfeifen",
"introTitle": "Verwalteter selbstgehosteter Pangolin",
"introDescription": "ist eine Deployment-Option, die für Personen konzipiert wurde, die Einfachheit und zusätzliche Zuverlässigkeit wünschen, während sie ihre Daten privat und selbstgehostet halten.",
"introDetail": "Mit dieser Option haben Sie immer noch Ihren eigenen Pangolin-Knoten Ihre Tunnel, TLS-Terminierung und Traffic bleiben auf Ihrem Server. Der Unterschied besteht darin, dass Verwaltung und Überwachung über unser Cloud-Dashboard abgewickelt werden, das eine Reihe von Vorteilen freischaltet:",
"introDetail": "Mit dieser Option betreiben Sie weiterhin Ihren eigenen Pangolin-Knoten Ihre Tunnel, TLS-Terminierung und der gesamte Datenverkehr bleiben auf Ihrem Server. Der Unterschied besteht darin, dass die Verwaltung und Überwachung über unser Cloud-Dashboard erfolgt, was eine Reihe von Vorteilen freischaltet:",
"benefitSimplerOperations": {
"title": "Einfachere Operationen",
"description": "Sie brauchen keinen eigenen Mail-Server auszuführen oder komplexe Warnungen einzurichten. Sie erhalten Gesundheitschecks und Ausfallwarnungen aus dem Box."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Bestätigung eingeben",
"blueprintViewDetails": "Details",
"defaultIdentityProvider": "Standard Identitätsanbieter",
"defaultIdentityProviderDescription": "Wenn ein Standard-Identity Provider ausgewählt ist, wird der Benutzer zur Authentifizierung automatisch an den Anbieter weitergeleitet.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Netzwerkeinstellungen",
"editInternalResourceDialogAccessPolicy": "Zugriffsrichtlinie",
"editInternalResourceDialogAddRoles": "Rollen hinzufügen",
@@ -2937,11 +3158,12 @@
"learnMore": "Mehr erfahren",
"backToHome": "Zurück zur Startseite",
"needToSignInToOrg": "Benötigen Sie den Identitätsanbieter Ihres Unternehmens?",
"maintenanceMode": "Wartungsmodus",
"maintenanceMode": "Wartungsseite",
"maintenanceModeDescription": "Eine Wartungsseite für Besucher anzeigen",
"maintenanceModeType": "Art des Wartungsmodus",
"showMaintenancePage": "Eine Wartungsseite für Besucher anzeigen",
"enableMaintenanceMode": "Wartungsmodus aktivieren",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatisch",
"automaticModeDescription": " Wartungsseite nur anzeigen, wenn alle Backend-Ziele deaktiviert oder ungesund sind. Deine Ressource funktioniert normal, solange mindestens ein Ziel gesund ist.",
"forced": "Erzwungen",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Geschätzter Abschluss:",
"createInternalResourceDialogDestinationRequired": "Ziel ist erforderlich",
"available": "Verfügbar",
"disabledResourceDescription": "Wenn deaktiviert, ist die Ressource für alle unzugänglich.",
"archived": "Archiviert",
"noArchivedDevices": "Keine archivierten Geräte gefunden",
"deviceArchived": "Gerät archiviert",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Sind Sie sicher, dass Sie die Verknüpfung dieses Identitätsanbieters mit dieser Organisation aufheben möchten?",
"idpUnassociateDescription": "Alle Benutzer, die mit diesem Identitätsanbieter verbunden sind, werden aus dieser Organisation entfernt, aber der Identitätsanbieter bleibt für andere verbundene Organisationen weiterhin bestehen.",
"idpUnassociateConfirm": "Verknüpfung des Identitätsanbieters aufheben bestätigen",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Dies kann für diese Organisation nicht rückgängig gemacht werden.",
"idpUnassociatedDescription": "Identitätsanbieter erfolgreich von dieser Organisation gelöst",
"idpUnassociateMenu": "Verknüpfung aufheben",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Ressource deaktiviert",
"memberPortalShowingResources": "Zeige {start}-{end} von {total} Ressourcen",
"memberPortalPrevious": "Vorherige",
"memberPortalNext": "Nächste"
"memberPortalNext": "Nächste",
"httpSettings": "HTTP-Einstellungen",
"tcpSettings": "TCP-Einstellungen",
"udpSettings": "UDP-Einstellungen",
"sshTitle": "SSH",
"sshConnectingDescription": "Aufbau einer sicheren Verbindung…",
"sshConnecting": "Verbindung wird hergestellt…",
"sshInitializing": "Initialisieren…",
"sshSignInTitle": "Anmelden bei SSH",
"sshSignInDescription": "Geben Sie Ihre SSH-Anmeldedaten ein",
"sshPasswordTab": "Passwort",
"sshPrivateKeyTab": "Privater Schlüssel",
"sshPrivateKeyField": "Privater Schlüssel",
"sshPrivateKeyDisclaimer": "Ihr privater Schlüssel wird von Pangolin nicht gespeichert oder angezeigt. Alternativ können Sie kurzlebige Zertifikate für nahtlose Authentifizierung mit Ihrer bestehenden Pangolin-Identität verwenden.",
"sshLearnMore": "Mehr erfahren",
"sshPrivateKeyFile": "Private Schlüsseldatei",
"sshAuthenticate": "Authentifizieren",
"sshTerminate": "Beenden",
"sshPoweredBy": "Bereitgestellt von",
"sshErrorNoTarget": "Kein Ziel angegeben",
"sshErrorWebSocket": "WebSocket-Verbindung fehlgeschlagen",
"sshErrorAuthFailed": "Authentifizierung fehlgeschlagen",
"sshErrorConnectionClosed": "Verbindung geschlossen, bevor die Authentifizierung abgeschlossen wurde",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -176,6 +176,7 @@
"shareErrorCreateDescription": "An error occurred while creating the share link",
"shareCreateDescription": "Anyone with this link can access the resource",
"shareTitleOptional": "Title (optional)",
"sharePathOptional": "Path (optional)",
"expireIn": "Expire In",
"neverExpire": "Never expire",
"shareExpireDescription": "Expiration time is how long the link will be usable and provide access to the resource. After this time, the link will no longer work, and users who used this link will lose access to the resource.",
@@ -208,11 +209,33 @@
"resourcesSearch": "Search resources...",
"resourceAdd": "Add Resource",
"resourceErrorDelte": "Error deleting resource",
"resourcePoliciesTitle": "Manage Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Attached resources",
"resourcePoliciesAttachedResources": "{count} resource(s)",
"resourcePoliciesAttachedResourcesEmpty": "no resources",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your resources",
"resourcePoliciesSearch": "Search policies...",
"resourcePoliciesAdd": "Add Policy",
"resourcePoliciesDefaultBadgeText": "Default policy",
"resourcePoliciesCreate": "Create Resource Policy",
"resourcePoliciesCreateDescription": "Follow the steps below to create a new policy",
"resourcePolicyName": "Policy Name",
"resourcePolicyNameDescription": "Give this policy a name to identify it across your resources",
"resourcePolicyNamePlaceholder": "e.g. Internal Access Policy",
"resourcePoliciesSeeAll": "See All Policies",
"resourcePolicyAuthMethodAdd": "Add Authentication Method",
"resourcePolicyOtpEmailAdd": "Add OTP emails",
"resourcePolicyRulesAdd": "Add Rules",
"resourcePolicyAuthMethodsDescription": "Allow access to resources via additional auth methods",
"resourcePolicyUsersRolesDescription": "Configure which users and roles can visit associated resources",
"rulesResourcePolicyDescription": "Configure rules to control access resources associated to this policy",
"authentication": "Authentication",
"protected": "Protected",
"notProtected": "Not Protected",
"resourceMessageRemove": "Once removed, the resource will no longer be accessible. All targets associated with the resource will also be removed.",
"resourceQuestionRemove": "Are you sure you want to remove the resource from the organization?",
"resourcePolicyMessageRemove": "Once removed, the resource policy will no longer be accessible. All resources associated with the resource will be unlinked and left without authentication.",
"resourcePolicyQuestionRemove": "Are you sure you want to remove the resource policy from the organization?",
"resourceHTTP": "HTTPS Resource",
"resourceHTTPDescription": "Proxy requests over HTTPS using a fully qualified domain name.",
"resourceRaw": "Raw TCP/UDP Resource",
@@ -220,8 +243,9 @@
"resourceRawDescriptionCloud": "Proxy requests over raw TCP/UDP using a port number. Requires sites to connect to a remote node.",
"resourceCreate": "Create Resource",
"resourceCreateDescription": "Follow the steps below to create a new resource",
"resourceCreateGeneralDescription": "Configure the basic resource settings including the name and the type",
"resourceSeeAll": "See All Resources",
"resourceInfo": "Resource Information",
"resourceCreateGeneral": "General",
"resourceNameDescription": "This is the display name for the resource.",
"siteSelect": "Select site",
"siteSearch": "Search site",
@@ -231,12 +255,15 @@
"noCountryFound": "No country found.",
"siteSelectionDescription": "This site will provide connectivity to the target.",
"resourceType": "Resource Type",
"resourceTypeDescription": "Determine how to access the resource",
"resourceTypeDescription": "This controls the resource protocol and how it will be rendered in the browser. This cant be changed later.",
"resourceDomainDescription": "The resource will be served at this fully qualified domain name.",
"resourceHTTPSSettings": "HTTPS Settings",
"resourceHTTPSSettingsDescription": "Configure how the resource will be accessed over HTTPS",
"resourcePortDescription": "The external port on the Pangolin instance or node where the resource will be accessible.",
"domainType": "Domain Type",
"subdomain": "Subdomain",
"baseDomain": "Base Domain",
"configure": "Configure",
"subdomnainDescription": "The subdomain where the resource will be accessible.",
"resourceRawSettings": "TCP/UDP Settings",
"resourceRawSettingsDescription": "Configure how the resource will be accessed over TCP/UDP",
@@ -253,6 +280,8 @@
"resourceLearnRaw": "Learn how to configure TCP/UDP resources",
"resourceBack": "Back to Resources",
"resourceGoTo": "Go to Resource",
"resourcePolicyDelete": "Delete Resource Policy",
"resourcePolicyDeleteConfirm": "Confirm Delete Resource Policy",
"resourceDelete": "Delete Resource",
"resourceDeleteConfirm": "Confirm Delete Resource",
"labelDelete": "Delete Label",
@@ -282,6 +311,8 @@
"rules": "Rules",
"resourceSettingDescription": "Configure the settings on the resource",
"resourceSetting": "{resourceName} Settings",
"resourcePolicySettingDescription": "Configure the settings on the resource policy",
"resourcePolicySetting": "{policyName} Settings",
"alwaysAllow": "Bypass Auth",
"alwaysDeny": "Block Access",
"passToAuth": "Pass to Auth",
@@ -764,6 +795,16 @@
"rulesNoOne": "No rules. Add a rule using the form.",
"rulesOrder": "Rules are evaluated by priority in ascending order.",
"rulesSubmit": "Save Rules",
"policyErrorCreate": "Error creating policy",
"policyErrorCreateDescription": "An error occurred when creating the policy",
"policyErrorCreateMessageDescription": "An unexpected error occurred",
"policyErrorUpdate": "Error updating policy",
"policyErrorUpdateDescription": "An error occurred when updating the policy",
"policyErrorUpdateMessageDescription": "An unexpected error occurred",
"policyCreatedSuccess": "Resource policy succesfully created",
"policyUpdatedSuccess": "Resource policy succesfully updated",
"authMethodsSave": "Save auth methods",
"rulesSave": "Save Rules",
"resourceErrorCreate": "Error creating resource",
"resourceErrorCreateDescription": "An error occurred when creating the resource",
"resourceErrorCreateMessage": "Error creating resource:",
@@ -827,6 +868,17 @@
"pincodeAdd": "Add PIN Code",
"pincodeRemove": "Remove PIN Code",
"resourceAuthMethods": "Authentication Methods",
"resourcePolicyAuthMethodsEmpty": "No authentication method",
"resourcePolicyOtpEmpty": "No one time password",
"resourcePolicyReadOnly": "This policy is Read only",
"resourcePolicyReadOnlyDescription": "This resource policy is shared accross multiple resources, you cannot edit it on this page.",
"editSharedPolicy": "Edit Shared Policy",
"resourcePolicyTypeSave": "Save Resource type",
"resourcePolicySelect": "Select resource policy",
"resourcePolicySelectError": "Select a resource policy",
"resourcePolicyNotFound": "Policy not found",
"resourcePolicySearch": "Search policies",
"resourcePolicyRulesEmpty": "No authentication rules",
"resourceAuthMethodsDescriptions": "Allow access to the resource via additional auth methods",
"resourceAuthSettingsSave": "Saved successfully",
"resourceAuthSettingsSaveDescription": "Authentication settings have been saved",
@@ -862,6 +914,12 @@
"resourcePincodeSetupTitle": "Set Pincode",
"resourcePincodeSetupTitleDescription": "Set a pincode to protect this resource",
"resourceRoleDescription": "Admins can always access this resource.",
"resourcePolicySelectTitle": "Resource Access Policy",
"resourcePolicySelectDescription": "Select the resource policy type for authentication",
"resourcePolicyInline": "Inline Resource Policy",
"resourcePolicyInlineDescription": "Access Policy scoped to only this resource",
"resourcePolicyShared": "Shared Resource Policy",
"resourcePolicySharedDescription": "This resource uses a shared policy. Policy-level settings (auth methods, email whitelist) are locked. You can add resource-specific rules, roles, and users below.",
"resourceUsersRoles": "Access Controls",
"resourceUsersRolesDescription": "Configure which users and roles can visit this resource",
"resourceUsersRolesSubmit": "Save Access Controls",
@@ -1354,29 +1412,6 @@
"otpAuthBack": "Back to Password",
"navbar": "Navigation Menu",
"navbarDescription": "Main navigation menu for the application",
"commandPaletteTitle": "Command palette",
"commandPaletteDescription": "Search for pages, organizations, resources, and actions",
"commandPaletteSearchPlaceholder": "Search pages, resources, actions...",
"commandPaletteNoResults": "No results found.",
"commandPaletteSearching": "Searching...",
"commandPaletteNavigation": "Navigation",
"commandPaletteOrganizations": "Organizations",
"commandPaletteSites": "Sites",
"commandPaletteResources": "Resources",
"commandPaletteUsers": "Users",
"commandPaletteClients": "Machine clients",
"commandPaletteActions": "Actions",
"commandPaletteCreateSite": "Create site",
"commandPaletteCreateProxyResource": "Create public resource",
"commandPaletteCreateUser": "Create user",
"commandPaletteCreateApiKey": "Create API key",
"commandPaletteCreateMachineClient": "Create machine client",
"commandPaletteCreateAlertRule": "Create alert rule",
"commandPaletteCreateIdentityProvider": "Create identity provider",
"commandPaletteToggleTheme": "Toggle theme",
"commandPaletteChooseOrganization": "Choose organization",
"commandPaletteShortcutMac": "⌘K",
"commandPaletteShortcutWindows": "Ctrl K",
"navbarDocsLink": "Documentation",
"otpErrorEnable": "Unable to enable 2FA",
"otpErrorEnableDescription": "An error occurred while enabling 2FA",
@@ -1426,6 +1461,8 @@
"sidebarResources": "Resources",
"sidebarProxyResources": "Public",
"sidebarClientResources": "Private",
"sidebarPolicies": "Policies",
"sidebarResourcePolicies": "Resources",
"sidebarAccessControl": "Access Control",
"sidebarLogsAndAnalytics": "Logs & Analytics",
"sidebarTeam": "Team",
@@ -1609,7 +1646,8 @@
"standaloneHcFilterSiteIdFallback": "Site {id}",
"standaloneHcFilterResourceIdFallback": "Resource {id}",
"blueprints": "Blueprints",
"blueprintsDescription": "Apply declarative configurations and view previous runs",
"blueprintsLog": "Blueprints Log",
"blueprintsDescription": "View past blueprint applications and their results",
"blueprintAdd": "Add Blueprint",
"blueprintGoBack": "See all Blueprints",
"blueprintCreate": "Create Blueprint",
@@ -1627,7 +1665,17 @@
"contents": "Contents",
"parsedContents": "Parsed Contents (Read Only)",
"enableDockerSocket": "Enable Docker Blueprint",
"enableDockerSocketDescription": "Enable Docker Socket label scraping for blueprint labels. Socket path must be provided to Newt. Read about how this works in <docsLink>the documentation</docsLink>.",
"enableDockerSocketDescription": "Enable Docker Socket label scraping for blueprint labels. Socket path must be provided to the site connector. Read about how this works in <docsLink>the documentation</docsLink>.",
"newtAutoUpdate": "Enable Site Auto-Update",
"newtAutoUpdateDescription": "When enabled, site connectors will automatically update to the latest version when a new release is available.",
"siteAutoUpdate": "Site Auto-Update",
"siteAutoUpdateLabel": "Enable Auto-Update",
"siteAutoUpdateDescription": "Control whether this site's connector automatically downloads the latest version.",
"siteAutoUpdateOrgDefault": "Organization default: {state}",
"siteAutoUpdateOverriding": "Overriding organization setting",
"siteAutoUpdateResetToOrg": "Reset to Organization Default",
"siteAutoUpdateEnabled": "enabled",
"siteAutoUpdateDisabled": "disabled",
"viewDockerContainers": "View Docker Containers",
"containersIn": "Containers in {siteName}",
"selectContainerDescription": "Select any container to use as a hostname for this target. Click a port to use a port.",
@@ -1899,6 +1947,7 @@
"billingManageLicenseSubscription": "Manage your subscription for paid self-hosted license keys",
"billingCurrentKeys": "Current Keys",
"billingModifyCurrentPlan": "Modify Current Plan",
"billingManageLicenseSubscriptionDescription": "Manage your subscription for paid self-hosted license keys and download invoices.",
"billingConfirmUpgrade": "Confirm Upgrade",
"billingConfirmDowngrade": "Confirm Downgrade",
"billingConfirmUpgradeDescription": "You are about to upgrade your plan. Review the new limits and pricing below.",
@@ -1996,7 +2045,36 @@
"timeIsInSeconds": "Time is in seconds",
"requireDeviceApproval": "Require Device Approvals",
"requireDeviceApprovalDescription": "Users with this role need new devices approved by an admin before they can connect and access resources.",
"sshAccess": "SSH Access",
"sshSettings": "SSH Settings",
"rdpSettings": "RDP Settings",
"vncSettings": "VNC Settings",
"sshServer": "SSH Server",
"rdpServer": "RDP Server",
"vncServer": "VNC Server",
"sshServerDescription": "Set up the authentication method, daemon location, and server destination",
"rdpServerDescription": "Configure the destination and port of the RDP server",
"vncServerDescription": "Configure the destination and port of the VNC server",
"sshServerMode": "Mode",
"sshServerModeStandard": "Standard SSH Server",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Routes commands over network to an SSH server such as OpenSSH.",
"sshServerModeNative": "Native SSH Server",
"sshServerModeNativeDescription": "Executes commands directly on the host via the Site Connector. No network config required.",
"sshAuthenticationMethod": "Authentication Method",
"sshAuthMethodManual": "Manual Authentication",
"sshAuthMethodManualDescription": "Requires existing host credentials. Bypasses automatic provisioning.",
"sshAuthMethodAutomated": "Automated Provisioning",
"sshAuthMethodAutomatedDescription": "Automatically creates users, groups, and sudo permissions on host.",
"sshAuthDaemonLocation": "Auth Daemon Location",
"sshDaemonLocationSiteDescription": "Executes locally on the machine hosting the site connector.",
"sshDaemonLocationRemote": "On Remote Host",
"sshDaemonLocationRemoteDescription": "Executes on a separate target machine on the same network.",
"sshDaemonDisclaimer": "Ensure your target host is properly configured to run the auth daemon before completing this setup, or provisioning will fail.",
"sshDaemonPort": "Daemon Port",
"sshServerDestination": "Server Destination",
"sshServerDestinationDescription": "Configure the destination and port of the SSH server",
"destination": "Destination",
"bgTargetMultiSiteDisclaimer": "Selecting multiple sites enables resilient routing and failover for high availability.",
"roleAllowSsh": "Allow SSH",
"roleAllowSshAllow": "Allow",
"roleAllowSshDisallow": "Disallow",
@@ -2010,7 +2088,7 @@
"sshSudoModeCommandsDescription": "User can run only the specified commands with sudo.",
"sshSudo": "Allow sudo",
"sshSudoCommands": "Sudo Commands",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo. Absolute paths must be used.",
"sshCreateHomeDir": "Create Home Directory",
"sshUnixGroups": "Unix Groups",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
@@ -2102,6 +2180,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Scheme",
"editInternalResourceDialogEnableSsl": "Enable TLS",
"editInternalResourceDialogEnableSslDescription": "Enable SSL/TLS encryption for secure HTTPS connections to the destination.",
@@ -2151,6 +2230,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Scheme",
"createInternalResourceDialogScheme": "Scheme",
"createInternalResourceDialogEnableSsl": "Enable TLS",
@@ -2990,7 +3070,7 @@
"learnMore": "Learn more",
"backToHome": "Go back to home",
"needToSignInToOrg": "Need to use your organization's identity provider?",
"maintenanceMode": "Maintenance Mode",
"maintenanceMode": "Maintenance Page",
"maintenanceModeDescription": "Display a maintenance page to visitors",
"maintenanceModeType": "Maintenance Mode Type",
"showMaintenancePage": "Show a maintenance page to visitors",
@@ -3020,6 +3100,7 @@
"maintenanceScreenEstimatedCompletion": "Estimated Completion:",
"createInternalResourceDialogDestinationRequired": "Destination is required",
"available": "Available",
"disabledResourceDescription": "When disabled, the resource will be inaccessible by everyone.",
"archived": "Archived",
"noArchivedDevices": "No archived devices found",
"deviceArchived": "Device archived",
@@ -3265,6 +3346,8 @@
"idpUnassociateQuestion": "Are you sure you want to unassociate this identity provider from this organization?",
"idpUnassociateDescription": "All users associated with this identity provider will be removed from this organization, but the identity provider will still continue to exist for other associated organizations.",
"idpUnassociateConfirm": "Confirm Unassociate Identity Provider",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "This cannot be undone for this organization.",
"idpUnassociatedDescription": "Identity provider unassociated from this organization successfully",
"idpUnassociateMenu": "Unassociate",
@@ -3349,5 +3432,27 @@
"memberPortalResourceDisabled": "Resource Disabled",
"memberPortalShowingResources": "Showing {start}-{end} of {total} resources",
"memberPortalPrevious": "Previous",
"memberPortalNext": "Next"
"memberPortalNext": "Next",
"httpSettings": "HTTP Settings",
"tcpSettings": "TCP Settings",
"udpSettings": "UDP Settings",
"sshTitle": "SSH",
"sshConnectingDescription": "Establishing a secure connection…",
"sshConnecting": "Connecting…",
"sshInitializing": "Initializing…",
"sshSignInTitle": "Sign in to SSH",
"sshSignInDescription": "Enter your SSH credentials",
"sshPasswordTab": "Password",
"sshPrivateKeyTab": "Private Key",
"sshPrivateKeyField": "Private Key",
"sshPrivateKeyDisclaimer": "Your private key is not stored or visible to Pangolin. Alternatively, you can use short-lived certificates for seamless authentication using your existing Pangolin identity.",
"sshLearnMore": "Learn more",
"sshPrivateKeyFile": "Private Key File",
"sshAuthenticate": "Authenticate",
"sshTerminate": "Terminate",
"sshPoweredBy": "Powered by",
"sshErrorNoTarget": "No target specified",
"sshErrorWebSocket": "WebSocket connection failed",
"sshErrorAuthFailed": "Authentication failed",
"sshErrorConnectionClosed": "Connection closed before authentication completed"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Ver Recursos Privados",
"siteInstallNewt": "Instalar Newt",
"siteInstallNewtDescription": "Recibe Newt corriendo en tu sistema",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Configuración de Wirex Guard",
"WgConfigurationDescription": "Utilice la siguiente configuración para conectarse a la red",
"operatingSystem": "Sistema operativo",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Sólo podrás verlo una vez. Asegúrate de copiarlo a un lugar seguro.",
"siteInfo": "Información del sitio",
"status": "Estado",
"shareTitle": "Administrar Enlaces de Compartir",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Crear enlaces compartidos para conceder acceso temporal o permanente a recursos proxy",
"shareSearch": "Buscar enlaces compartidos...",
"shareCreate": "Crear enlace Compartir",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Error al eliminar el enlace",
"shareErrorDeleteMessage": "Se ha producido un error al eliminar el enlace",
"shareDeleted": "Enlace eliminado",
"shareDeletedDescription": "El enlace ha sido eliminado",
"shareDelete": "Borrar Enlace Compartido",
"shareDeleteConfirm": "Confirmar Borrado del Enlace Compartido",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "¿Está seguro de que desea borrar este enlace compartido?",
"shareMessageRemove": "Una vez borrado, el enlace dejará de funcionar y cualquier persona que lo use perderá acceso al recurso.",
"shareTokenDescription": "El token de acceso puede ser pasado de dos maneras: como parámetro de consulta o en las cabeceras de solicitud. Estos deben ser pasados del cliente en cada solicitud de acceso autenticado.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Se ha producido un error al crear el enlace compartido",
"shareCreateDescription": "Cualquiera con este enlace puede acceder al recurso",
"shareTitleOptional": "Título (opcional)",
"sharePathOptional": "Ruta (opcional)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Caduca en",
"neverExpire": "Nunca expirar",
"shareExpireDescription": "El tiempo de caducidad es cuánto tiempo el enlace será utilizable y proporcionará acceso al recurso. Después de este tiempo, el enlace ya no funcionará, y los usuarios que usaron este enlace perderán el acceso al recurso.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Por favor, seleccione un recurso",
"proxyResourceTitle": "Administrar recursos públicos",
"proxyResourceDescription": "Crear y administrar recursos que sean accesibles públicamente a través de un navegador web",
"proxyResourcesBannerTitle": "Acceso público basado en web",
"proxyResourcesBannerDescription": "Los recursos públicos son proxies HTTPS o TCP/UDP accesibles a cualquiera en Internet a través de un navegador web. A diferencia de los recursos privados, no requieren software del lado del cliente e incluye políticas de acceso basadas en identidad y contexto.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Administrar recursos privados",
"clientResourceDescription": "Crear y administrar recursos que sólo son accesibles a través de un cliente conectado",
"privateResourcesBannerTitle": "Acceso privado de confianza cero",
@@ -208,11 +212,36 @@
"resourcesSearch": "Buscar recursos...",
"resourceAdd": "Añadir Recurso",
"resourceErrorDelte": "Error al eliminar el recurso",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} recurso/s",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "sin recursos",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Buscar políticas...",
"resourcePoliciesAdd": "Agregar Política",
"resourcePoliciesDefaultBadgeText": "Política predeterminada",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Siga los pasos a continuación para crear una nueva política",
"resourcePolicyName": "Nombre de la política",
"resourcePolicyNameDescription": "Déle a esta política un nombre para identificarla en sus recursos",
"resourcePolicyNamePlaceholder": "por ejemplo, Política de Acceso Interno",
"resourcePoliciesSeeAll": "Ver todas las políticas",
"resourcePolicyAuthMethodAdd": "Agregar Método de Autenticación",
"resourcePolicyOtpEmailAdd": "Agregar correos electrónicos OTP",
"resourcePolicyRulesAdd": "Añadir reglas",
"resourcePolicyAuthMethodsDescription": "Permitir el acceso a los recursos a través de métodos de autenticación adicionales",
"resourcePolicyUsersRolesDescription": "Configure qué usuarios y roles pueden visitar los recursos asociados",
"rulesResourcePolicyDescription": "Configure reglas para controlar el acceso a los recursos asociados a esta política",
"authentication": "Autenticación",
"protected": "Protegido",
"notProtected": "No protegido",
"resourceMessageRemove": "Una vez eliminado, el recurso ya no será accesible. Todos los objetivos asociados con el recurso también serán eliminados.",
"resourceQuestionRemove": "¿Está seguro que desea eliminar el recurso de la organización?",
"resourcePolicyMessageRemove": "Una vez eliminada, la política de recursos ya no será accesible. Todos los recursos asociados al recurso serán desvinculados y quedarán sin autenticación.",
"resourcePolicyQuestionRemove": "¿Está seguro de que desea eliminar la política de recursos de la organización?",
"resourceHTTP": "HTTPS Recurso",
"resourceHTTPDescription": "Proxy proporciona solicitudes sobre HTTPS usando un nombre de dominio completamente calificado.",
"resourceRaw": "Recurso TCP/UDP sin procesar",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Las peticiones de proxy sobre TCP/UDP crudas usando un número de puerto. Requiere que los sitios se conecten a un nodo remoto.",
"resourceCreate": "Crear Recurso",
"resourceCreateDescription": "Siga los siguientes pasos para crear un nuevo recurso",
"resourceCreateGeneralDescription": "Configurar la configuración básica del recurso, incluido el nombre y el tipo",
"resourceSeeAll": "Ver todos los recursos",
"resourceInfo": "Información del recurso",
"resourceCreateGeneral": "General",
"resourceNameDescription": "Este es el nombre para mostrar el recurso.",
"siteSelect": "Seleccionar sitio",
"siteSearch": "Buscar sitio",
@@ -231,12 +261,15 @@
"noCountryFound": "Ningún país encontrado.",
"siteSelectionDescription": "Este sitio proporcionará conectividad al objetivo.",
"resourceType": "Tipo de recurso",
"resourceTypeDescription": "Determina cómo acceder al recurso",
"resourceTypeDescription": "Esto controla el protocolo del recurso y cómo se renderizará en el navegador. Esto no se puede cambiar más tarde.",
"resourceDomainDescription": "El recurso se servirá en este nombre de dominio completamente calificado.",
"resourceHTTPSSettings": "Configuración HTTPS",
"resourceHTTPSSettingsDescription": "Configurar cómo se accederá al recurso a través de HTTPS",
"resourcePortDescription": "El puerto externo en la instancia o nodo de Pangolin donde el recurso será accesible.",
"domainType": "Tipo de dominio",
"subdomain": "Subdominio",
"baseDomain": "Dominio base",
"configure": "Configurar",
"subdomnainDescription": "El subdominio al que el recurso será accesible.",
"resourceRawSettings": "Configuración TCP/UDP",
"resourceRawSettingsDescription": "Configurar cómo se accederá al recurso a través de TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Aprende cómo configurar los recursos TCP/UDP",
"resourceBack": "Volver a Recursos",
"resourceGoTo": "Ir a Recurso",
"resourcePolicyDelete": "Eliminar Política de Recursos",
"resourcePolicyDeleteConfirm": "Confirmar eliminación de la política de recursos",
"resourceDelete": "Eliminar Recurso",
"resourceDeleteConfirm": "Confirmar Borrar Recurso",
"labelDelete": "Eliminar etiqueta",
"labelAdd": "Agregar etiqueta",
"labelCreateSuccessMessage": "Etiqueta creada correctamente",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etiqueta modificada correctamente",
"labelNameField": "Nombre de la etiqueta",
"labelColorField": "Color de la etiqueta",
"labelPlaceholder": "Ej: homelab",
"labelCreate": "Crear etiqueta",
"createLabelDialogTitle": "Crear etiqueta",
"createLabelDialogDescription": "Cree una nueva etiqueta que se pueda adjuntar a esta organización",
"labelEdit": "Editar etiqueta",
"editLabelDialogTitle": "Actualizar etiqueta",
"editLabelDialogDescription": "Edite una nueva etiqueta que se pueda adjuntar a esta organización",
"labelDeleteConfirm": "Confirmar eliminación de etiqueta",
"labelErrorDelete": "Error al eliminar la etiqueta",
"labelMessageRemove": "Esta acción es permanente. Todos los sitios, recursos y clientes etiquetados con esta etiqueta serán des- etiquetados.",
"labelQuestionRemove": "¿Está seguro de que desea eliminar la etiqueta de la organización?",
"visibility": "Visibilidad",
"enabled": "Activado",
"disabled": "Deshabilitado",
@@ -265,6 +319,8 @@
"rules": "Reglas",
"resourceSettingDescription": "Configurar la configuración del recurso",
"resourceSetting": "Ajustes {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Configuración {policyName}",
"alwaysAllow": "Autorización Bypass",
"alwaysDeny": "Bloquear acceso",
"passToAuth": "Pasar a Autenticación",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Duplicar regla",
"rulesErrorDuplicateDescription": "Ya existe una regla con estos ajustes",
"rulesErrorInvalidIpAddressRange": "CIDR inválido",
"rulesErrorInvalidIpAddressRangeDescription": "Por favor, introduzca un valor CIDR válido",
"rulesErrorInvalidUrl": "Ruta URL inválida",
"rulesErrorInvalidUrlDescription": "Por favor, introduzca un valor de ruta de URL válido",
"rulesErrorInvalidIpAddress": "IP inválida",
"rulesErrorInvalidIpAddressDescription": "Por favor, introduzca una dirección IP válida",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Error al actualizar las reglas",
"rulesErrorUpdateDescription": "Se ha producido un error al actualizar las reglas",
"rulesUpdated": "Activar Reglas",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Introduzca una dirección en formato CIDR (por ejemplo, 103.21.244.0/22)",
"rulesMatchIpAddress": "Introduzca una dirección IP (por ejemplo, 103.21.244.12)",
"rulesMatchUrl": "Introduzca una ruta URL o patrón (por ej., /api/v1/todos o /api/v1/*)",
"rulesErrorInvalidPriority": "Prioridad inválida",
"rulesErrorInvalidPriorityDescription": "Por favor, introduzca una prioridad válida",
"rulesErrorDuplicatePriority": "Prioridades duplicadas",
"rulesErrorDuplicatePriorityDescription": "Por favor, introduzca prioridades únicas",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Reglas actualizadas",
"ruleUpdatedDescription": "Reglas actualizadas correctamente",
"ruleErrorUpdate": "Operación fallida",
"ruleErrorUpdateDescription": "Se ha producido un error durante la operación de guardado",
"rulesPriority": "Prioridad",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Accin",
"rulesMatchType": "Tipo de partida",
"value": "Valor",
@@ -744,9 +809,60 @@
"rulesResource": "Configuración de reglas de recursos",
"rulesResourceDescription": "Configurar reglas para controlar el acceso al recurso",
"ruleSubmit": "Añadir Regla",
"rulesNoOne": "No hay reglas. Agregue una regla usando el formulario.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Las reglas son evaluadas por prioridad en orden ascendente.",
"rulesSubmit": "Guardar Reglas",
"policyErrorCreate": "Error al crear la política",
"policyErrorCreateDescription": "Se ha producido un error al crear la política",
"policyErrorCreateMessageDescription": "Se ha producido un error inesperado",
"policyErrorUpdate": "Error al actualizar la política",
"policyErrorUpdateDescription": "Se ha producido un error al actualizar la política",
"policyErrorUpdateMessageDescription": "Se ha producido un error inesperado",
"policyCreatedSuccess": "Política de recursos creada con éxito",
"policyUpdatedSuccess": "Política de recursos actualizada con éxito",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Guardar reglas",
"resourceErrorCreate": "Error al crear recurso",
"resourceErrorCreateDescription": "Se ha producido un error al crear el recurso",
"resourceErrorCreateMessage": "Error al crear el recurso:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Se ha producido un error al actualizar el recurso",
"access": "Acceder",
"accessControl": "Control de acceso",
"shareLink": "{resource} Compartir Enlace",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Seleccionar recurso",
"shareLinks": "Compartir enlaces",
"shareLinks": "Shareable Links",
"share": "Enlaces compartibles",
"shareDescription2": "Crea enlaces compartidos a recursos. Los enlaces proporcionan acceso temporal o ilimitado a tu recurso. Puede configurar la duración de caducidad del enlace cuando cree uno.",
"shareEasyCreate": "Fácil de crear y compartir",
@@ -810,6 +926,17 @@
"pincodeAdd": "Añadir código PIN",
"pincodeRemove": "Eliminar código PIN",
"resourceAuthMethods": "Métodos de autenticación",
"resourcePolicyAuthMethodsEmpty": "No hay método de autenticación",
"resourcePolicyOtpEmpty": "Sin contraseña de un solo uso",
"resourcePolicyReadOnly": "Esta política es solo de lectura",
"resourcePolicyReadOnlyDescription": "Esta política de recursos se comparte entre varios recursos, no puede editarla en esta página.",
"editSharedPolicy": "Editar Política Compartida",
"resourcePolicyTypeSave": "Guardar tipo de recurso",
"resourcePolicySelect": "Seleccionar política de recursos",
"resourcePolicySelectError": "Seleccione una política de recursos",
"resourcePolicyNotFound": "Política no encontrada",
"resourcePolicySearch": "Buscar políticas",
"resourcePolicyRulesEmpty": "Sin reglas de autenticación",
"resourceAuthMethodsDescriptions": "Permitir el acceso al recurso a través de métodos de autenticación adicionales",
"resourceAuthSettingsSave": "Guardado correctamente",
"resourceAuthSettingsSaveDescription": "Se han guardado los ajustes de autenticación",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Definir Pincode",
"resourcePincodeSetupTitleDescription": "Establecer un pincode para proteger este recurso",
"resourceRoleDescription": "Los administradores siempre pueden acceder a este recurso.",
"resourcePolicySelectTitle": "Política de Acceso a Recursos",
"resourcePolicySelectDescription": "Seleccione el tipo de política de recursos para la autenticación",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Política de Recursos Integrada",
"resourcePolicyInlineDescription": "Política de Acceso solo destinada a este recurso",
"resourcePolicyShared": "Política de Recursos Compartida",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Controles de acceso",
"resourceUsersRolesDescription": "Configurar qué usuarios y roles pueden visitar este recurso",
"resourceUsersRolesSubmit": "Guardar controles de acceso",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Hubo un problema al conectar con {name}. Por favor, póngase en contacto con su administrador.",
"idpErrorNotFound": "IdP no encontrado",
"inviteInvalid": "Invitación inválida",
"labels": "Etiquetas",
"orgLabelsDescription": "Administrar etiquetas en esta organización.",
"addLabels": "Agregar etiquetas",
"siteLabelsTab": "Etiquetas",
"siteLabelsDescription": "Administrar las etiquetas asociadas con este sitio.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Buscar etiquetas",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# etiqueta} other {# etiquetas}}",
"labelOverflowCount": "+{count, plural, one {# etiqueta} other {# etiquetas}}",
"accessLabelFilterClear": "Borrar filtros de etiquetas",
"accessFilterClear": "Clear filters",
"selectColor": "Seleccionar color",
"createNewLabel": "Crear nueva etiqueta de organización \"{label}\"",
"inviteInvalidDescription": "El enlace de invitación no es válido.",
"inviteErrorWrongUser": "La invitación no es para este usuario",
"inviteErrorUserNotExists": "El usuario no existe. Por favor, cree una cuenta primero.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Recursos",
"sidebarProxyResources": "Público",
"sidebarClientResources": "Privado",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Control de acceso",
"sidebarLogsAndAnalytics": "Registros y análisis",
"sidebarTeam": "Equipo",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Admin",
"sidebarInvitations": "Invitaciones",
"sidebarRoles": "Roles",
"sidebarShareableLinks": "Enlaces",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "Claves API",
"sidebarProvisioning": "Aprovisionamiento",
"sidebarSettings": "Ajustes",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Sitio {id}",
"standaloneHcFilterResourceIdFallback": "Recurso {id}",
"blueprints": "Planos",
"blueprintsDescription": "Aplicar configuraciones declarativas y ver ejecuciones anteriores",
"blueprintsLog": "Registro de planos",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Añadir plano",
"blueprintGoBack": "Ver todos los Planos",
"blueprintCreate": "Crear Plano",
@@ -1575,7 +1732,17 @@
"contents": "Contenido",
"parsedContents": "Contenido analizado (Sólo lectura)",
"enableDockerSocket": "Habilitar Plano Docker",
"enableDockerSocketDescription": "Activar el raspado de etiquetas de Socket Docker para etiquetas de planos. La ruta del Socket debe proporcionarse a Newt.",
"enableDockerSocketDescription": "Activar el raspado de etiquetas del socket Docker para etiquetas de planos. La ruta del socket debe proporcionarse al conector del sitio. Lea sobre cómo funciona esto en <docsLink>la documentación</docsLink>.",
"newtAutoUpdate": "Habilitar actualización automática del sitio",
"newtAutoUpdateDescription": "Cuando está habilitado, los conectores del sitio se actualizarán automáticamente a la última versión cuando haya disponible una nueva versión.",
"siteAutoUpdate": "Actualización automática del sitio",
"siteAutoUpdateLabel": "Habilitar actualización automática",
"siteAutoUpdateDescription": "Controlar si el conector de este sitio descarga automáticamente la última versión.",
"siteAutoUpdateOrgDefault": "Predeterminado de la organización: {state}",
"siteAutoUpdateOverriding": "Configuración de anulación de la organización",
"siteAutoUpdateResetToOrg": "Restablecer al predeterminado de la organización",
"siteAutoUpdateEnabled": "activado",
"siteAutoUpdateDisabled": "deshabilitado",
"viewDockerContainers": "Ver contenedores Docker",
"containersIn": "Contenedores en {siteName}",
"selectContainerDescription": "Seleccione cualquier contenedor para usar como nombre de host para este objetivo. Haga clic en un puerto para usar un puerto.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certificado",
"certificateStatusAutoRefreshHint": "El estado se actualiza automáticamente.",
"loading": "Cargando",
"loadingEllipsis": "Cargando...",
"loadingAnalytics": "Cargando analíticas",
"restart": "Reiniciar",
"domains": "Dominios",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Administra tu suscripción para las claves de licencia autoalojadas pagadas",
"billingCurrentKeys": "Claves actuales",
"billingModifyCurrentPlan": "Modificar plan actual",
"billingManageLicenseSubscriptionDescription": "Administre su suscripción para claves de licencia autogestionadas pagas y descargue facturas.",
"billingConfirmUpgrade": "Confirmar actualización",
"billingConfirmDowngrade": "Confirmar descenso",
"billingConfirmUpgradeDescription": "Estás a punto de actualizar tu plan. Revisa los nuevos límites y precios a continuación.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Desconocido",
"healthCheck": "Chequeo de salud",
"configureHealthCheck": "Configurar Chequeo de Salud",
"configureHealthCheckDescription": "Configura la monitorización de salud para {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Activar Chequeos de Salud",
"healthCheckDisabledStateDescription": "Cuando está deshabilitado, el sitio no realizará comprobaciones de salud y el estado se considerará desconocido.",
"enableHealthChecksDescription": "Controlar la salud de este objetivo. Puedes supervisar un punto final diferente al objetivo si es necesario.",
"healthScheme": "Método",
"healthSelectScheme": "Seleccionar método",
"healthCheckPortInvalid": "El puerto de chequeo de salud debe estar entre 1 y 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Ruta",
"healthHostname": "IP / Nombre del host",
"healthPort": "Puerto",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "El tiempo está en segundos",
"requireDeviceApproval": "Requiere aprobaciones del dispositivo",
"requireDeviceApprovalDescription": "Los usuarios con este rol necesitan nuevos dispositivos aprobados por un administrador antes de poder conectarse y acceder a los recursos.",
"sshAccess": "Acceso a SSH",
"sshSettings": "Configuración SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Configuración RDP",
"vncSettings": "Configuración VNC",
"sshServer": "Servidor SSH",
"rdpServer": "Servidor RDP",
"vncServer": "Servidor VNC",
"sshServerDescription": "Configure el método de autenticación, la ubicación del daemon y el destino del servidor",
"rdpServerDescription": "Configure el destino y el puerto del servidor RDP",
"vncServerDescription": "Configure el destino y el puerto del servidor VNC",
"sshServerMode": "Modo",
"sshServerModeStandard": "Servidor SSH estándar",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Rutas de comandos a través de la red a un servidor SSH como OpenSSH.",
"sshServerModeNative": "Servidor SSH nativo",
"sshServerModeNativeDescription": "Ejecuta comandos directamente en el host a través del Conector de Sitio. No se requiere configuración de red.",
"sshAuthenticationMethod": "Método de autenticación",
"sshAuthMethodManual": "Autenticación manual",
"sshAuthMethodManualDescription": "Requiere credenciales de host existentes. Omite la provisión automática.",
"sshAuthMethodAutomated": "Provisión automatizada",
"sshAuthMethodAutomatedDescription": "Crea automáticamente usuarios, grupos y permisos de sudo en el host.",
"sshAuthDaemonLocation": "Ubicación del Daemon de Autenticación",
"sshDaemonLocationSiteDescription": "Ejecuta localmente en la máquina que aloja el conector de sitio.",
"sshDaemonLocationRemote": "En Host Remoto",
"sshDaemonLocationRemoteDescription": "Ejecuta en una máquina objetivo separada en la misma red.",
"sshDaemonDisclaimer": "Asegúrese de que su host objetivo esté correctamente configurado para ejecutar el daemon de autenticación antes de completar esta configuración, o la provisión fallará.",
"sshDaemonPort": "Puerto del Daemon",
"sshServerDestination": "Destino del Servidor",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Destino",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Seleccionar múltiples sitios permite el enrutamiento resiliente y el failover para alta disponibilidad.",
"roleAllowSsh": "Permitir SSH",
"roleAllowSshAllow": "Permitir",
"roleAllowSshDisallow": "Rechazar",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "El usuario sólo puede ejecutar los comandos especificados con sudo.",
"sshSudo": "Permitir sudo",
"sshSudoCommands": "Comandos Sudo",
"sshSudoCommandsDescription": "Lista separada por comas de comandos que el usuario puede ejecutar con sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Crear directorio principal",
"sshUnixGroups": "Grupos Unix",
"sshUnixGroupsDescription": "Grupos Unix separados por comas para agregar el usuario en el host de destino.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Intentos de Reintento",
"expectedResponseCodes": "Códigos de respuesta esperados",
"expectedResponseCodesDescription": "Código de estado HTTP que indica un estado saludable. Si se deja en blanco, se considera saludable de 200 a 300.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Esquema",
"editInternalResourceDialogEnableSsl": "Activar TLS",
"editInternalResourceDialogEnableSslDescription": "Habilitar cifrado SSL/TLS para conexiones HTTPS seguras al destino.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Esquema",
"createInternalResourceDialogScheme": "Esquema",
"createInternalResourceDialogEnableSsl": "Activar TLS",
@@ -2233,7 +2454,7 @@
"description": "Servidor Pangolin autoalojado más fiable y de bajo mantenimiento con campanas y silbidos extra",
"introTitle": "Pangolin autogestionado",
"introDescription": "es una opción de despliegue diseñada para personas que quieren simplicidad y fiabilidad extra mientras mantienen sus datos privados y autoalojados.",
"introDetail": "Con esta opción, todavía ejecuta su propio nodo Pangolin, sus túneles, terminación TLS y tráfico permanecen en su servidor. La diferencia es que la gestión y el control se gestionan a través de nuestro panel de control en la nube, que desbloquea una serie de ventajas:",
"introDetail": "Con esta opción, todavía ejecuta su propio nodo Pangolin, sus túneles, terminación del TLS y tráfico permanecen en su servidor. La diferencia es que la gestión y el monitoreo se manejan a través de nuestro panel de control en la nube, lo que desbloquea una serie de beneficios:",
"benefitSimplerOperations": {
"title": "Operaciones simples",
"description": "No necesitas ejecutar tu propio servidor de correo o configurar alertas complejas. Recibirás cheques de salud y alertas de tiempo de inactividad."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Ingresar confirmación",
"blueprintViewDetails": "Detalles",
"defaultIdentityProvider": "Proveedor de identidad predeterminado",
"defaultIdentityProviderDescription": "Cuando se selecciona un proveedor de identidad por defecto, el usuario será redirigido automáticamente al proveedor de autenticación.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Configuración de red",
"editInternalResourceDialogAccessPolicy": "Política de acceso",
"editInternalResourceDialogAddRoles": "Agregar roles",
@@ -2937,11 +3158,12 @@
"learnMore": "Más información",
"backToHome": "Volver a inicio",
"needToSignInToOrg": "¿Necesita usar el proveedor de identidad de su organización?",
"maintenanceMode": "Modo de mantenimiento",
"maintenanceMode": "Página de Mantenimiento",
"maintenanceModeDescription": "Muestra una página de mantenimiento a los visitantes",
"maintenanceModeType": "Tipo de modo de mantenimiento",
"showMaintenancePage": "Mostrar página de mantenimiento a los visitantes",
"enableMaintenanceMode": "Habilitar modo de mantenimiento",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automático",
"automaticModeDescription": "Mostrar página de mantenimiento solo cuando todos los objetivos de backend están caídos o no saludables. Su recurso continúa funcionando normalmente siempre que al menos un objetivo esté saludable.",
"forced": "Forzado",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Estimado completado:",
"createInternalResourceDialogDestinationRequired": "Se requiere destino",
"available": "Disponible",
"disabledResourceDescription": "Cuando está deshabilitado, el recurso será inaccesible para todos.",
"archived": "Archivado",
"noArchivedDevices": "No se encontraron dispositivos archivados",
"deviceArchived": "Dispositivo archivado",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "¿Está seguro de que desea desasociar este proveedor de identidad de esta organización?",
"idpUnassociateDescription": "Todos los usuarios asociados con este proveedor de identidad serán eliminados de esta organización, pero el proveedor de identidad continuará existiendo para otras organizaciones asociadas.",
"idpUnassociateConfirm": "Confirme Desasociar Proveedor de Identidad",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Esto no se puede deshacer para esta organización.",
"idpUnassociatedDescription": "Proveedor de identidad desasociado de esta organización con éxito",
"idpUnassociateMenu": "Desasociar",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Recurso Deshabilitado",
"memberPortalShowingResources": "Mostrando {start}-{end} de {total} recursos",
"memberPortalPrevious": "Anterior",
"memberPortalNext": "Siguiente"
"memberPortalNext": "Siguiente",
"httpSettings": "Configuración HTTP",
"tcpSettings": "Configuración TCP",
"udpSettings": "Configuración UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Estableciendo una conexión segura…",
"sshConnecting": "Conectando…",
"sshInitializing": "Inicializando…",
"sshSignInTitle": "Iniciar sesión en SSH",
"sshSignInDescription": "Ingrese sus credenciales SSH",
"sshPasswordTab": "Contraseña",
"sshPrivateKeyTab": "Clave Privada",
"sshPrivateKeyField": "Clave Privada",
"sshPrivateKeyDisclaimer": "Su clave privada no se almacena ni es visible para Pangolin. Alternativamente, puede usar certificados de corta duración para una autenticación sin interrupciones usando su identidad Pangolin existente.",
"sshLearnMore": "Más información",
"sshPrivateKeyFile": "Archivo de clave privada",
"sshAuthenticate": "Autenticarse",
"sshTerminate": "Terminar",
"sshPoweredBy": "Desarrollado por",
"sshErrorNoTarget": "No se especificó el objetivo",
"sshErrorWebSocket": "Conexión WebSocket fallida",
"sshErrorAuthFailed": "Falló la autenticación",
"sshErrorConnectionClosed": "La conexión se cerró antes de completar la autenticación",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Voir les ressources privées",
"siteInstallNewt": "Installer Newt",
"siteInstallNewtDescription": "Faites fonctionner Newt sur votre système",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Configuration WireGuard",
"WgConfigurationDescription": "Utilisez la configuration suivante pour vous connecter au réseau",
"operatingSystem": "Système d'exploitation",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Vous ne pourrez voir cela qu'une seule fois. Assurez-vous de l'enregistrer dans un endroit sécurisé.",
"siteInfo": "Informations du nœud",
"status": "Statut",
"shareTitle": "Gérer les liens partageables",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Créez des liens partageables pour accorder un accès temporaire ou permanent aux ressources de proxy",
"shareSearch": "Rechercher des liens partageables...",
"shareCreate": "Créer un lien partageable",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Impossible de supprimer le lien",
"shareErrorDeleteMessage": "Une erreur s'est produite lors de la suppression du lien",
"shareDeleted": "Lien supprimé",
"shareDeletedDescription": "Le lien a été supprimé",
"shareDelete": "Supprimer le lien de partage",
"shareDeleteConfirm": "Confirmer la suppression du lien de partage",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Êtes-vous sûr de vouloir supprimer ce lien de partage ?",
"shareMessageRemove": "Une fois supprimé, le lien ne fonctionnera plus et toute personne l'utilisant perdra l'accès à la ressource.",
"shareTokenDescription": "Le jeton d'accès peut être passé de deux façons : en tant que paramètre de requête ou dans les en-têtes de la requête. Elles doivent être transmises par le client à chaque demande d'accès authentifié.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Une erreur s'est produite lors de la création du lien partageable",
"shareCreateDescription": "N'importe qui avec ce lien peut accéder à la ressource",
"shareTitleOptional": "Titre (facultatif)",
"sharePathOptional": "Chemin (optionnel)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Expire dans",
"neverExpire": "N'expire jamais",
"shareExpireDescription": "Le délai d'expiration correspond à la période pendant laquelle le lien sera utilisable et permettra d'accéder à la ressource. Passé ce délai, le lien ne fonctionnera plus et les utilisateurs qui l'ont utilisé perdront l'accès à la ressource.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Veuillez sélectionner une ressource",
"proxyResourceTitle": "Gérer les ressources publiques",
"proxyResourceDescription": "Créer et gérer des ressources accessibles au public via un navigateur web",
"proxyResourcesBannerTitle": "Accès public basé sur le Web",
"proxyResourcesBannerDescription": "Les ressources publiques sont des proxys HTTPS ou TCP/UDP accessibles par tout le monde sur Internet via un navigateur Web. Contrairement aux ressources privées, elles n'exigent pas de logiciel côté client et peuvent inclure des politiques d'accès basées sur l'identité et le contexte.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Gérer les ressources privées",
"clientResourceDescription": "Créer et gérer des ressources qui ne sont accessibles que via un client connecté",
"privateResourcesBannerTitle": "Accès privé sans confiance",
@@ -208,11 +212,36 @@
"resourcesSearch": "Chercher des ressources...",
"resourceAdd": "Ajouter une ressource",
"resourceErrorDelte": "Erreur lors de la de suppression de la ressource",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} ressource(s)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "pas de ressources",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Chercher des politiques...",
"resourcePoliciesAdd": "Ajouter une politique",
"resourcePoliciesDefaultBadgeText": "Politique par défaut",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Suivez les étapes ci-dessous pour créer une nouvelle politique",
"resourcePolicyName": "Nom de la politique",
"resourcePolicyNameDescription": "Donnez à cette politique un nom pour l'identifier parmi vos ressources",
"resourcePolicyNamePlaceholder": "par exemple : Politique d'Accès Interne",
"resourcePoliciesSeeAll": "Voir toutes les politiques",
"resourcePolicyAuthMethodAdd": "Ajouter une méthode d'authentification",
"resourcePolicyOtpEmailAdd": "Ajouter des emails pour OTP",
"resourcePolicyRulesAdd": "Ajouter des règles",
"resourcePolicyAuthMethodsDescription": "Permettre l'accès aux ressources via des méthodes d'authentification supplémentaires",
"resourcePolicyUsersRolesDescription": "Configurer quels utilisateurs et rôles peuvent visiter les ressources associées",
"rulesResourcePolicyDescription": "Configurer les règles pour contrôler l'accès aux ressources associées à cette politique",
"authentication": "Authentification",
"protected": "Protégé",
"notProtected": "Non Protégé",
"resourceMessageRemove": "Une fois supprimée, la ressource ne sera plus accessible. Toutes les cibles associées à la ressource seront également supprimées.",
"resourceQuestionRemove": "Êtes-vous sûr de vouloir retirer la ressource de l'organisation ?",
"resourcePolicyMessageRemove": "Une fois supprimée, la politique de ressource ne sera plus accessible. Toutes les ressources associées seront détachées et laissées sans authentification.",
"resourcePolicyQuestionRemove": "Êtes-vous sûr de vouloir supprimer la politique de ressource de l'organisation ?",
"resourceHTTP": "Ressource HTTPS",
"resourceHTTPDescription": "Proxy les demandes sur HTTPS en utilisant un nom de domaine entièrement qualifié.",
"resourceRaw": "Ressource TCP/UDP brute",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Requêtes de proxy sur TCP/UDP brute en utilisant un numéro de port. Nécessite des sites pour se connecter à un noeud distant.",
"resourceCreate": "Créer une ressource",
"resourceCreateDescription": "Suivez les étapes ci-dessous pour créer une nouvelle ressource",
"resourceCreateGeneralDescription": "Configurer les paramètres de ressource de base, y compris le nom et le type",
"resourceSeeAll": "Voir toutes les ressources",
"resourceInfo": "Informations sur la ressource",
"resourceCreateGeneral": "Général",
"resourceNameDescription": "Ceci est le nom d'affichage de la ressource.",
"siteSelect": "Sélectionnez un nœud",
"siteSearch": "Chercher un nœud",
@@ -231,12 +261,15 @@
"noCountryFound": "Aucun pays trouvé.",
"siteSelectionDescription": "Ce site fournira la connectivité à la cible.",
"resourceType": "Type de ressource",
"resourceTypeDescription": "Déterminer comment accéder à la ressource",
"resourceTypeDescription": "Cela contrôle le protocole de la ressource et comment il sera rendu dans le navigateur. Cela ne peut pas être changé plus tard.",
"resourceDomainDescription": "La ressource sera servie à ce nom de domaine pleinement qualifié.",
"resourceHTTPSSettings": "Paramètres HTTPS",
"resourceHTTPSSettingsDescription": "Configurer comment la ressource sera accédée via HTTPS",
"resourcePortDescription": "Le port externe sur l'instance ou nœud Pangolin où la ressource sera accessible.",
"domainType": "Type de domaine",
"subdomain": "Sous-domaine",
"baseDomain": "Domaine racine",
"configure": "Configurer",
"subdomnainDescription": "Le sous-domaine où la ressource sera accessible.",
"resourceRawSettings": "Paramètres TCP/UDP",
"resourceRawSettingsDescription": "Configurer comment la ressource sera accédée via TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Apprenez à configurer les ressources TCP/UDP",
"resourceBack": "Retour aux ressources",
"resourceGoTo": "Aller à la ressource",
"resourcePolicyDelete": "Supprimer la politique de ressource",
"resourcePolicyDeleteConfirm": "Confirmer la suppression de la politique de ressource",
"resourceDelete": "Supprimer la ressource",
"resourceDeleteConfirm": "Confirmer la suppression de la ressource",
"labelDelete": "Supprimer Étiquette",
"labelAdd": "Ajouter Étiquette",
"labelCreateSuccessMessage": "Étiquette créée avec succès",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Étiquette modifiée avec succès",
"labelNameField": "Nom de l'étiquette",
"labelColorField": "Couleur de l'étiquette",
"labelPlaceholder": "Ex : homelab",
"labelCreate": "Créer Étiquette",
"createLabelDialogTitle": "Créer Étiquette",
"createLabelDialogDescription": "Créer une nouvelle étiquette qui peut être attachée à cette organisation",
"labelEdit": "Modifier Étiquette",
"editLabelDialogTitle": "Mettre à jour Étiquette",
"editLabelDialogDescription": "Modifier une nouvelle étiquette qui peut être attachée à cette organisation",
"labelDeleteConfirm": "Confirmer la suppression de l'étiquette",
"labelErrorDelete": "Échec de la suppression de l'étiquette",
"labelMessageRemove": "Cette action est permanente. Tous les sites, ressources et clients étiquetés avec cette étiquette seront détachés.",
"labelQuestionRemove": "Êtes-vous sûr de vouloir supprimer l'étiquette de l'organisation ?",
"visibility": "Visibilité",
"enabled": "Activé",
"disabled": "Désactivé",
@@ -265,6 +319,8 @@
"rules": "Règles",
"resourceSettingDescription": "Configurer les paramètres de la ressource",
"resourceSetting": "Réglages de {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Paramètres de {policyName}",
"alwaysAllow": "Outrepasser l'authentification",
"alwaysDeny": "Bloquer l'accès",
"passToAuth": "Passer à l'authentification",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Règle en double",
"rulesErrorDuplicateDescription": "Une règle avec ces paramètres existe déjà",
"rulesErrorInvalidIpAddressRange": "CIDR invalide",
"rulesErrorInvalidIpAddressRangeDescription": "Veuillez entrer une valeur CIDR valide",
"rulesErrorInvalidUrl": "Chemin URL invalide",
"rulesErrorInvalidUrlDescription": "Veuillez entrer un chemin URL valide",
"rulesErrorInvalidIpAddress": "IP invalide",
"rulesErrorInvalidIpAddressDescription": "Veuillez entrer une adresse IP valide",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Échec de la mise à jour des règles",
"rulesErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour des règles",
"rulesUpdated": "Activer les règles",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Entrez une adresse au format CIDR (ex: 103.21.244.0/22)",
"rulesMatchIpAddress": "Entrez une adresse IP (ex: 103.21.244.12)",
"rulesMatchUrl": "Entrez un chemin URL ou un motif (ex: /api/v1/todos ou /api/v1/*)",
"rulesErrorInvalidPriority": "Priorité invalide",
"rulesErrorInvalidPriorityDescription": "Veuillez entrer une priorité valide",
"rulesErrorDuplicatePriority": "Priorités en double",
"rulesErrorDuplicatePriorityDescription": "Veuillez entrer des priorités uniques",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Règles mises à jour",
"ruleUpdatedDescription": "Règles mises à jour avec succès",
"ruleErrorUpdate": "L'opération a échoué",
"ruleErrorUpdateDescription": "Une erreur s'est produite lors de l'enregistrement",
"rulesPriority": "Priorité",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Action",
"rulesMatchType": "Type de correspondance",
"value": "Valeur",
@@ -744,9 +809,60 @@
"rulesResource": "Configuration des règles de ressource",
"rulesResourceDescription": "Configurer les règles pour contrôler l'accès à la ressource",
"ruleSubmit": "Ajouter une règle",
"rulesNoOne": "Aucune règle. Ajoutez une règle en utilisant le formulaire.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Les règles sont évaluées par priorité dans l'ordre croissant.",
"rulesSubmit": "Enregistrer les règles",
"policyErrorCreate": "Erreur lors de la création de la politique",
"policyErrorCreateDescription": "Une erreur s'est produite lors de la création de la politique",
"policyErrorCreateMessageDescription": "Une erreur inattendue s'est produite",
"policyErrorUpdate": "Erreur lors de la mise à jour de la politique",
"policyErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour de la politique",
"policyErrorUpdateMessageDescription": "Une erreur inattendue s'est produite",
"policyCreatedSuccess": "Politique de ressource créée avec succès",
"policyUpdatedSuccess": "Politique de ressource mise à jour avec succès",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Enregistrer les règles",
"resourceErrorCreate": "Erreur lors de la création de la ressource",
"resourceErrorCreateDescription": "Une erreur s'est produite lors de la création de la ressource",
"resourceErrorCreateMessage": "Erreur lors de la création de la ressource :",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Une erreur s'est produite lors de la mise à jour de la ressource",
"access": "Accès",
"accessControl": "Contrôle d'accès",
"shareLink": "Lien de partage {resource}",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Sélectionner une ressource",
"shareLinks": "Liens de partage",
"shareLinks": "Shareable Links",
"share": "Liens partageables",
"shareDescription2": "Créez des liens partageables vers des ressources. Les liens fournissent un accès temporaire ou illimité à votre ressource. Vous pouvez configurer la durée d'expiration du lien lorsque vous en créez un.",
"shareEasyCreate": "Facile à créer et à partager",
@@ -810,6 +926,17 @@
"pincodeAdd": "Ajouter un code PIN",
"pincodeRemove": "Supprimer le code PIN",
"resourceAuthMethods": "Méthodes d'authentification",
"resourcePolicyAuthMethodsEmpty": "Pas de méthode d'authentification",
"resourcePolicyOtpEmpty": "Aucun mot de passe à usage unique",
"resourcePolicyReadOnly": "Cette politique est en lecture seule",
"resourcePolicyReadOnlyDescription": "Cette politique de ressource est partagée sur plusieurs ressources, vous ne pouvez pas l'éditer sur cette page.",
"editSharedPolicy": "Modifier la politique partagée",
"resourcePolicyTypeSave": "Enregistrer le type de ressource",
"resourcePolicySelect": "Sélectionner la politique de ressource",
"resourcePolicySelectError": "Sélectionner une politique de ressource",
"resourcePolicyNotFound": "Politique introuvable",
"resourcePolicySearch": "Chercher des politiques",
"resourcePolicyRulesEmpty": "Pas de règles d'authentification",
"resourceAuthMethodsDescriptions": "Permettre l'accès à la ressource via des méthodes d'authentification supplémentaires",
"resourceAuthSettingsSave": "Enregistré avec succès",
"resourceAuthSettingsSaveDescription": "Les paramètres d'authentification ont été enregistrés",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Définir le code PIN",
"resourcePincodeSetupTitleDescription": "Définir un code PIN pour protéger cette ressource",
"resourceRoleDescription": "Les administrateurs peuvent toujours accéder à cette ressource.",
"resourcePolicySelectTitle": "Politique d'accès à la ressource",
"resourcePolicySelectDescription": "Sélectionner le type de politique de ressource pour l'authentification",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Politique de ressource en ligne",
"resourcePolicyInlineDescription": "Politique d'accès limitée uniquement à cette ressource",
"resourcePolicyShared": "Politique de ressource partagée",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Contrôles d'accès",
"resourceUsersRolesDescription": "Configurer quels utilisateurs et rôles peuvent visiter cette ressource",
"resourceUsersRolesSubmit": "Enregistrer les contrôles d'accès",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Un problème est survenu lors de la connexion à {name}. Veuillez contacter votre administrateur.",
"idpErrorNotFound": "IdP introuvable",
"inviteInvalid": "Invitation invalide",
"labels": "Étiquettes",
"orgLabelsDescription": "Gérer les étiquettes dans cette organisation.",
"addLabels": "Ajouter des étiquettes",
"siteLabelsTab": "Étiquettes",
"siteLabelsDescription": "Gérer les étiquettes associées à ce site.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Chercher des étiquettes",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# étiquette} other {# étiquettes}}",
"labelOverflowCount": "+{count, plural, one {# étiquette} other {# étiquettes}}",
"accessLabelFilterClear": "Effacer les filtres d'étiquette",
"accessFilterClear": "Clear filters",
"selectColor": "Sélectionner la couleur",
"createNewLabel": "Créer une nouvelle étiquette d'organisation \"{label}\"",
"inviteInvalidDescription": "Le lien d'invitation n'est pas valide.",
"inviteErrorWrongUser": "L'invitation n'est pas pour cet utilisateur",
"inviteErrorUserNotExists": "L'utilisateur n'existe pas. Veuillez d'abord créer un compte.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Ressource",
"sidebarProxyResources": "Publique",
"sidebarClientResources": "Privé",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Contrôle d'accès",
"sidebarLogsAndAnalytics": "Journaux & Analytiques",
"sidebarTeam": "Equipe",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Administrateur",
"sidebarInvitations": "Invitations",
"sidebarRoles": "Rôles",
"sidebarShareableLinks": "Liens",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "Clés API",
"sidebarProvisioning": "Mise en place",
"sidebarSettings": "Réglages",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Site {id}",
"standaloneHcFilterResourceIdFallback": "Ressource {id}",
"blueprints": "Configs",
"blueprintsDescription": "Appliquer les configurations déclaratives et afficher les exécutions précédentes",
"blueprintsLog": "Journal des plans",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Ajouter une Config",
"blueprintGoBack": "Voir toutes les Configs",
"blueprintCreate": "Créer une Config",
@@ -1575,7 +1732,17 @@
"contents": "Contenus",
"parsedContents": "Contenu analysé (lecture seule)",
"enableDockerSocket": "Activer la Config Docker",
"enableDockerSocketDescription": "Activer le ramassage d'étiquettes de socket Docker pour les étiquettes de plan. Le chemin de socket doit être fourni à Newt.",
"enableDockerSocketDescription": "Activer le ramassage d'étiquettes de socket Docker pour les étiquettes de plan. Le chemin du socket doit être fourni au connecteur du site. Lisez plus à ce sujet dans <docsLink>la documentation</docsLink>.",
"newtAutoUpdate": "Activer la mise à jour automatique du site",
"newtAutoUpdateDescription": "Lorsqu'il est activé, les connecteurs de site se mettront automatiquement à jour vers la dernière version lorsqu'une nouvelle version sera disponible.",
"siteAutoUpdate": "Mise à jour automatique du site",
"siteAutoUpdateLabel": "Activer la mise à jour automatique",
"siteAutoUpdateDescription": "Contrôler si le connecteur de ce site télécharge automatiquement la dernière version.",
"siteAutoUpdateOrgDefault": "Valeur par défaut de l'organisation : {state}",
"siteAutoUpdateOverriding": "Substitution des paramètres de l'organisation",
"siteAutoUpdateResetToOrg": "Réinitialiser à la valeur par défaut de l'organisation",
"siteAutoUpdateEnabled": "activé",
"siteAutoUpdateDisabled": "désactivé",
"viewDockerContainers": "Voir les conteneurs Docker",
"containersIn": "Conteneurs en {siteName}",
"selectContainerDescription": "Sélectionnez n'importe quel conteneur à utiliser comme nom d'hôte pour cette cible. Cliquez sur un port pour utiliser un port.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certificat",
"certificateStatusAutoRefreshHint": "L'état se rafraîchit automatiquement.",
"loading": "Chargement",
"loadingEllipsis": "Chargement...",
"loadingAnalytics": "Chargement de l'analyse",
"restart": "Redémarrer",
"domains": "Domaines",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Gérer votre abonnement pour les clés de licence auto-hébergées payantes",
"billingCurrentKeys": "Clés actuelles",
"billingModifyCurrentPlan": "Modifier le plan actuel",
"billingManageLicenseSubscriptionDescription": "Gérez votre abonnement pour clés de licence auto-hébergées payantes et téléchargez les factures.",
"billingConfirmUpgrade": "Confirmer la mise à niveau",
"billingConfirmDowngrade": "Confirmer la rétrogradation",
"billingConfirmUpgradeDescription": "Vous êtes sur le point de mettre à niveau votre offre. Examinez les nouvelles limites et les nouveaux prix ci-dessous.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Inconnu",
"healthCheck": "Vérification de l'état de santé",
"configureHealthCheck": "Configurer la vérification de l'état de santé",
"configureHealthCheckDescription": "Configurer la surveillance de la santé pour {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Activer les vérifications de santé",
"healthCheckDisabledStateDescription": "Lorsqu'il est désactivé, le site ne procédera pas aux vérifications de santé et l'état sera considéré comme inconnu.",
"enableHealthChecksDescription": "Surveiller la vie de cette cible. Vous pouvez surveiller un point de terminaison différent de la cible si nécessaire.",
"healthScheme": "Méthode",
"healthSelectScheme": "Sélectionnez la méthode",
"healthCheckPortInvalid": "Le port du bilan de santé doit être compris entre 1 et 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Chemin d'accès",
"healthHostname": "IP / Hôte",
"healthPort": "Port",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Le temps est exprimé en secondes",
"requireDeviceApproval": "Exiger les autorisations de l'appareil",
"requireDeviceApprovalDescription": "Les utilisateurs ayant ce rôle ont besoin de nouveaux périphériques approuvés par un administrateur avant de pouvoir se connecter et accéder aux ressources.",
"sshAccess": "Accès SSH",
"sshSettings": "Paramètres SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Paramètres RDP",
"vncSettings": "Paramètres VNC",
"sshServer": "Serveur SSH",
"rdpServer": "Serveur RDP",
"vncServer": "Serveur VNC",
"sshServerDescription": "Configurer la méthode d'authentification, l'emplacement du démon et la destination du serveur",
"rdpServerDescription": "Configurer la destination et le port du serveur RDP",
"vncServerDescription": "Configurer la destination et le port du serveur VNC",
"sshServerMode": "Mode",
"sshServerModeStandard": "Serveur SSH Standard",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Relai les commandes sur le réseau vers un serveur SSH tel qu'OpenSSH.",
"sshServerModeNative": "Serveur SSH Natif",
"sshServerModeNativeDescription": "Exécute les commandes directement sur l'hôte via le Connecteur de Site. Aucune configuration réseau requise.",
"sshAuthenticationMethod": "Méthode d'authentification",
"sshAuthMethodManual": "Authentification Manuelle",
"sshAuthMethodManualDescription": "Nécessite des identifiants d'hôte existants. Évite l'approvisionnement automatique.",
"sshAuthMethodAutomated": "Approvisionnement Automatisé",
"sshAuthMethodAutomatedDescription": "Crée automatiquement des utilisateurs, groupes, et permissions sudo sur l'hôte.",
"sshAuthDaemonLocation": "Emplacement du Démon Auth",
"sshDaemonLocationSiteDescription": "Exécute localement sur la machine hébergeant le connecteur de site.",
"sshDaemonLocationRemote": "Sur hôte distant",
"sshDaemonLocationRemoteDescription": "S'exécute sur une machine cible séparée sur le même réseau.",
"sshDaemonDisclaimer": "Assurez-vous que votre hôte cible est correctement configuré pour exécuter le daemon auth avant de terminer cette configuration, ou l'approvisionnement échouera.",
"sshDaemonPort": "Port du Démon",
"sshServerDestination": "Destination du Serveur",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Destination",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "La sélection de plusieurs sites permet un routage résilient et une bascule pour une haute disponibilité.",
"roleAllowSsh": "Autoriser SSH",
"roleAllowSshAllow": "Autoriser",
"roleAllowSshDisallow": "Interdire",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "L'utilisateur ne peut exécuter que les commandes spécifiées avec sudo.",
"sshSudo": "Autoriser sudo",
"sshSudoCommands": "Commandes Sudo",
"sshSudoCommandsDescription": "Liste des commandes séparées par des virgules que l'utilisateur est autorisé à exécuter avec sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Créer un répertoire personnel",
"sshUnixGroups": "Groupes Unix",
"sshUnixGroupsDescription": "Groupes Unix séparés par des virgules pour ajouter l'utilisateur sur l'hôte cible.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Tentatives de réessai",
"expectedResponseCodes": "Codes de réponse attendus",
"expectedResponseCodesDescription": "Code de statut HTTP indiquant un état de santé satisfaisant. Si non renseigné, 200-300 est considéré comme satisfaisant.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Méthode HTTP",
"editInternalResourceDialogEnableSsl": "Activer TLS",
"editInternalResourceDialogEnableSslDescription": "Activer le cryptage SSL/TLS pour des connexions HTTPS sécurisées vers la destination.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Méthode HTTP",
"createInternalResourceDialogScheme": "Méthode HTTP",
"createInternalResourceDialogEnableSsl": "Activer TLS",
@@ -2233,7 +2454,7 @@
"description": "Serveur Pangolin auto-hébergé avec des cloches et des sifflets supplémentaires",
"introTitle": "Pangolin auto-hébergé géré",
"introDescription": "est une option de déploiement conçue pour les personnes qui veulent de la simplicité et de la fiabilité tout en gardant leurs données privées et auto-hébergées.",
"introDetail": "Avec cette option, vous exécutez toujours votre propre nœud Pangolin - vos tunnels, la terminaison TLS et le trafic restent sur votre serveur. La différence est que la gestion et la surveillance sont gérées via notre tableau de bord du cloud, qui déverrouille un certain nombre d'avantages :",
"introDetail": "Avec cette option, vous exécutez toujours votre propre nœud Pangolin - vos tunnels, la terminaison TLS et le trafic restent sur votre serveur. La différence est que la gestion et la surveillance sont gérées via notre tableau de bord du cloud, ce qui débloque un certain nombre d'avantages :",
"benefitSimplerOperations": {
"title": "Opérations plus simples",
"description": "Pas besoin de faire tourner votre propre serveur de messagerie ou de configurer des alertes complexes. Vous obtiendrez des contrôles de santé et des alertes de temps d'arrêt par la suite."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Entrez la confirmation",
"blueprintViewDetails": "Détails",
"defaultIdentityProvider": "Fournisseur d'identité par défaut",
"defaultIdentityProviderDescription": "Lorsqu'un fournisseur d'identité par défaut est sélectionné, l'utilisateur sera automatiquement redirigé vers le fournisseur pour authentification.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Paramètres réseau",
"editInternalResourceDialogAccessPolicy": "Politique d'accès",
"editInternalResourceDialogAddRoles": "Ajouter des rôles",
@@ -2937,11 +3158,12 @@
"learnMore": "En savoir plus",
"backToHome": "Retour à l'accueil",
"needToSignInToOrg": "Besoin d'utiliser le fournisseur d'identité de votre organisation ?",
"maintenanceMode": "Mode de maintenance",
"maintenanceMode": "Page de maintenance",
"maintenanceModeDescription": "Afficher une page de maintenance aux visiteurs",
"maintenanceModeType": "Type de mode de maintenance",
"showMaintenancePage": "Afficher une page de maintenance aux visiteurs",
"enableMaintenanceMode": "Activer le mode de maintenance",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatique",
"automaticModeDescription": "Afficher la page de maintenance uniquement lorsque toutes les cibles backend sont en panne ou dégradées. Votre ressource continue à fonctionner normalement tant qu'au moins une cible est en bonne santé.",
"forced": "Forcé",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Achèvement estimé :",
"createInternalResourceDialogDestinationRequired": "La destination est requise",
"available": "Disponible",
"disabledResourceDescription": "Lorsqu'il est désactivé, la ressource sera inaccessible pour tout le monde.",
"archived": "Archivé",
"noArchivedDevices": "Aucun périphérique archivé trouvé",
"deviceArchived": "Appareil archivé",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Êtes-vous sûr de vouloir dissocier ce fournisseur d'identités de cette organisation?",
"idpUnassociateDescription": "Tous les utilisateurs associés à ce fournisseur d'identités seront retirés de cette organisation, mais le fournisseur d'identités continuera d'exister pour d'autres organisations associées.",
"idpUnassociateConfirm": "Confirmer la dissociation du fournisseur d'identités",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Cela ne peut pas être annulé pour cette organisation.",
"idpUnassociatedDescription": "Fournisseur d'identités dissocié de cette organisation avec succès",
"idpUnassociateMenu": "Dissocier",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Ressource désactivée",
"memberPortalShowingResources": "Affichage de {start}-{end} sur {total} ressources",
"memberPortalPrevious": "Précédent",
"memberPortalNext": "Suivant"
"memberPortalNext": "Suivant",
"httpSettings": "Paramètres HTTP",
"tcpSettings": "Paramètres TCP",
"udpSettings": "Paramètres UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Établissement d'une connexion sécurisée…",
"sshConnecting": "Connexion…",
"sshInitializing": "Initialisation…",
"sshSignInTitle": "Se connecter à SSH",
"sshSignInDescription": "Entrez vos identifiants SSH",
"sshPasswordTab": "Mot de passe",
"sshPrivateKeyTab": "Clé Privée",
"sshPrivateKeyField": "Clé Privée",
"sshPrivateKeyDisclaimer": "Votre clé privée n'est pas stockée ou visible par Pangolin. Alternativement, vous pouvez utiliser des certificats de courte durée pour une authentification transparente utilisant votre identité Pangolin existante.",
"sshLearnMore": "En savoir plus",
"sshPrivateKeyFile": "Fichier de Clé Privée",
"sshAuthenticate": "Authentifier",
"sshTerminate": "Terminer",
"sshPoweredBy": "Propulsé par",
"sshErrorNoTarget": "Aucune cible spécifiée",
"sshErrorWebSocket": "Échec de la connexion WebSocket",
"sshErrorAuthFailed": "Échec de l'authentification",
"sshErrorConnectionClosed": "Connexion fermée avant que l'authentification soit terminée",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Visualizza Risorse Private",
"siteInstallNewt": "Installa Newt",
"siteInstallNewtDescription": "Esegui Newt sul tuo sistema",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Configurazione WireGuard",
"WgConfigurationDescription": "Utilizzare la seguente configurazione per connettersi alla rete",
"operatingSystem": "Sistema Operativo",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Potrai vederlo solo una volta. Assicurati di copiarlo in un luogo sicuro.",
"siteInfo": "Informazioni Sito",
"status": "Stato",
"shareTitle": "Gestisci Collegamenti Di Condivisione",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Crea link condivisibili per concedere accesso temporaneo o permanente alle risorse proxy",
"shareSearch": "Cerca link condivisi...",
"shareCreate": "Crea Link Di Condivisione",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Impossibile eliminare il link",
"shareErrorDeleteMessage": "Si è verificato un errore durante l'eliminazione del link",
"shareDeleted": "Link eliminato",
"shareDeletedDescription": "Il link è stato eliminato",
"shareDelete": "Elimina Link di Condivisione",
"shareDeleteConfirm": "Conferma Eliminazione Link di Condivisione",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Sei sicuro di voler eliminare questo link di condivisione?",
"shareMessageRemove": "Una volta eliminato, il link non funzionerà più e chiunque lo utilizzi perderà l'accesso alla risorsa.",
"shareTokenDescription": "Il token di accesso può essere passato in due modi: come parametro di interrogazione o nelle intestazioni della richiesta. Questi devono essere passati dal client su ogni richiesta di accesso autenticato.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Si è verificato un errore durante la creazione del link di condivisione",
"shareCreateDescription": "Chiunque con questo link può accedere alla risorsa",
"shareTitleOptional": "Titolo (facoltativo)",
"sharePathOptional": "Percorso (opzionale)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Scadenza In",
"neverExpire": "Nessuna scadenza",
"shareExpireDescription": "Il tempo di scadenza indica per quanto tempo il link sarà utilizzabile e fornirà accesso alla risorsa. Dopo questo tempo, il link non funzionerà più e gli utenti che hanno utilizzato questo link perderanno l'accesso alla risorsa.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Seleziona una risorsa",
"proxyResourceTitle": "Gestisci Risorse Pubbliche",
"proxyResourceDescription": "Creare e gestire risorse pubbliche accessibili tramite un browser web",
"proxyResourcesBannerTitle": "Accesso Pubblico Basato sul Web",
"proxyResourcesBannerDescription": "Le risorse pubbliche sono proxy HTTPS o TCP/UDP accessibili da chiunque tramite Internet da un browser web. A differenza delle risorse private non richiedono software lato client e possono includere politiche di accesso basate su identità e contesto.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Gestisci Risorse Private",
"clientResourceDescription": "Crea e gestisci risorse accessibili solo tramite un client connesso",
"privateResourcesBannerTitle": "Accesso Privato Zero-Trust",
@@ -208,11 +212,36 @@
"resourcesSearch": "Cerca risorse...",
"resourceAdd": "Aggiungi Risorsa",
"resourceErrorDelte": "Errore nell'eliminare la risorsa",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} risorsa(e)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "nessuna risorsa",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Cerca politiche...",
"resourcePoliciesAdd": "Aggiungi Politica",
"resourcePoliciesDefaultBadgeText": "Politica Predefinita",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Segui i passaggi seguenti per creare una nuova politica",
"resourcePolicyName": "Nome Politica",
"resourcePolicyNameDescription": "Dai un nome a questa politica per identificarla tra le tue risorse",
"resourcePolicyNamePlaceholder": "es. Politica di Accesso Interno",
"resourcePoliciesSeeAll": "Vedi Tutte le Politiche",
"resourcePolicyAuthMethodAdd": "Aggiungi Metodo di Autenticazione",
"resourcePolicyOtpEmailAdd": "Aggiungi email OTP",
"resourcePolicyRulesAdd": "Aggiungi Regole",
"resourcePolicyAuthMethodsDescription": "Consenti l'accesso alle risorse tramite metodi di autenticazione aggiuntivi",
"resourcePolicyUsersRolesDescription": "Configura quali utenti e ruoli possono visitare le risorse associate",
"rulesResourcePolicyDescription": "Configura regole per controllare l'accesso alle risorse associate a questa politica",
"authentication": "Autenticazione",
"protected": "Protetto",
"notProtected": "Non Protetto",
"resourceMessageRemove": "Una volta rimossa la risorsa non sarà più accessibile. Tutti gli oggetti target associati alla risorsa saranno rimossi.",
"resourceQuestionRemove": "Sei sicuro di voler rimuovere la risorsa dall'organizzazione?",
"resourcePolicyMessageRemove": "Una volta rimossa, la politica delle risorse non sarà più accessibile. Tutte le risorse associate saranno dissociate e rimarranno senza autenticazione.",
"resourcePolicyQuestionRemove": "Sei sicuro di voler rimuovere la politica delle risorse dall'organizzazione?",
"resourceHTTP": "Risorsa HTTPS",
"resourceHTTPDescription": "Richieste proxy su HTTPS usando un nome di dominio completo.",
"resourceRaw": "Risorsa Raw TCP/UDP",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Richiesta proxy su TCP/UDP grezzo utilizzando un numero di porta. Richiede siti per connettersi a un nodo remoto.",
"resourceCreate": "Crea Risorsa",
"resourceCreateDescription": "Segui i passaggi seguenti per creare una nuova risorsa",
"resourceCreateGeneralDescription": "Configura le impostazioni generali delle risorse, inclusi il nome e il tipo",
"resourceSeeAll": "Vedi Tutte Le Risorse",
"resourceInfo": "Informazioni Risorsa",
"resourceCreateGeneral": "Generale",
"resourceNameDescription": "Questo è il nome visualizzato per la risorsa.",
"siteSelect": "Seleziona sito",
"siteSearch": "Cerca sito",
@@ -231,12 +261,15 @@
"noCountryFound": "Nessun paese trovato.",
"siteSelectionDescription": "Questo sito fornirà connettività all'oggetto target.",
"resourceType": "Tipo Di Risorsa",
"resourceTypeDescription": "Determinare come accedere alla risorsa",
"resourceTypeDescription": "Questo controlla il protocollo delle risorse e come verrà reso nel browser. Questo non può essere modificato in seguito.",
"resourceDomainDescription": "La risorsa sarà servita su questo dominio completamente qualificato.",
"resourceHTTPSSettings": "Impostazioni HTTPS",
"resourceHTTPSSettingsDescription": "Configura come sarà possibile accedere alla risorsa su HTTPS",
"resourcePortDescription": "La porta esterna sull'istanza o nodo Pangolin dove la risorsa sarà accessibile.",
"domainType": "Tipo Di Dominio",
"subdomain": "Sottodominio",
"baseDomain": "Dominio Base",
"configure": "Configura",
"subdomnainDescription": "Il sottodominio in cui la risorsa sarà accessibile.",
"resourceRawSettings": "Impostazioni TCP/UDP",
"resourceRawSettingsDescription": "Configura come accedere alla risorsa tramite TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Scopri come configurare le risorse TCP/UDP",
"resourceBack": "Torna alle risorse",
"resourceGoTo": "Vai alla Risorsa",
"resourcePolicyDelete": "Elimina Politica Risorse",
"resourcePolicyDeleteConfirm": "Conferma Eliminazione Politica Risorse",
"resourceDelete": "Elimina Risorsa",
"resourceDeleteConfirm": "Conferma Eliminazione Risorsa",
"labelDelete": "Elimina Etichetta",
"labelAdd": "Aggiungi Etichetta",
"labelCreateSuccessMessage": "Etichetta Creata con Successo",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etichetta Modificata con Successo",
"labelNameField": "Nome Etichetta",
"labelColorField": "Colore Etichetta",
"labelPlaceholder": "Es: homelab",
"labelCreate": "Crea Etichetta",
"createLabelDialogTitle": "Crea Etichetta",
"createLabelDialogDescription": "Crea una nuova etichetta che può essere allegata a questa organizzazione",
"labelEdit": "Modifica Etichetta",
"editLabelDialogTitle": "Aggiorna Etichetta",
"editLabelDialogDescription": "Modifica una nuova etichetta che può essere allegata a questa organizzazione",
"labelDeleteConfirm": "Conferma Eliminazione Etichetta",
"labelErrorDelete": "Impossibile eliminare l'etichetta",
"labelMessageRemove": "Questa azione è permanente. Tutti i siti, le risorse e i clienti associati a questa etichetta verranno dissociati.",
"labelQuestionRemove": "Sei sicuro di voler rimuovere l'etichetta dall'organizzazione?",
"visibility": "Visibilità",
"enabled": "Abilitato",
"disabled": "Disabilitato",
@@ -265,6 +319,8 @@
"rules": "Regole",
"resourceSettingDescription": "Configura le impostazioni sulla risorsa",
"resourceSetting": "Impostazioni {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Impostazioni del sito {policyName}",
"alwaysAllow": "Bypass Autenticazione",
"alwaysDeny": "Blocca Accesso",
"passToAuth": "Passa all'autenticazione",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Regola duplicata",
"rulesErrorDuplicateDescription": "Esiste già una regola con queste impostazioni",
"rulesErrorInvalidIpAddressRange": "CIDR non valido",
"rulesErrorInvalidIpAddressRangeDescription": "Inserisci un valore CIDR valido",
"rulesErrorInvalidUrl": "Percorso URL non valido",
"rulesErrorInvalidUrlDescription": "Inserisci un valore di percorso URL valido",
"rulesErrorInvalidIpAddress": "IP non valido",
"rulesErrorInvalidIpAddressDescription": "Inserisci un indirizzo IP valido",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Impossibile aggiornare le regole",
"rulesErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento delle regole",
"rulesUpdated": "Abilita Regole",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Inserisci un indirizzo in formato CIDR (es. 103.21.244.0/22)",
"rulesMatchIpAddress": "Inserisci un indirizzo IP (es. 103.21.244.12)",
"rulesMatchUrl": "Inserisci un percorso URL o pattern (es. /api/v1/todos o /api/v1/*)",
"rulesErrorInvalidPriority": "Priorità Non Valida",
"rulesErrorInvalidPriorityDescription": "Inserisci una priorità valida",
"rulesErrorDuplicatePriority": "Priorità Duplicate",
"rulesErrorDuplicatePriorityDescription": "Inserisci priorità uniche",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Regole aggiornate",
"ruleUpdatedDescription": "Regole aggiornate con successo",
"ruleErrorUpdate": "Operazione fallita",
"ruleErrorUpdateDescription": "Si è verificato un errore durante il salvataggio",
"rulesPriority": "Priorità",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Azione",
"rulesMatchType": "Tipo di Corrispondenza",
"value": "Valore",
@@ -744,9 +809,60 @@
"rulesResource": "Configurazione Regole Risorsa",
"rulesResourceDescription": "Configura le regole per controllare l'accesso alla risorsa",
"ruleSubmit": "Aggiungi Regola",
"rulesNoOne": "Nessuna regola. Aggiungi una regola usando il modulo.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Le regole sono valutate per priorità in ordine crescente.",
"rulesSubmit": "Salva Regole",
"policyErrorCreate": "Errore nella creazione della politica",
"policyErrorCreateDescription": "Si è verificato un errore durante la creazione della politica",
"policyErrorCreateMessageDescription": "Si è verificato un errore imprevisto",
"policyErrorUpdate": "Errore nell'aggiornamento della politica",
"policyErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento della politica",
"policyErrorUpdateMessageDescription": "Si è verificato un errore imprevisto",
"policyCreatedSuccess": "Politica risorse creata con successo",
"policyUpdatedSuccess": "Politica risorse aggiornata con successo",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Salva Regole",
"resourceErrorCreate": "Errore nella creazione della risorsa",
"resourceErrorCreateDescription": "Si è verificato un errore durante la creazione della risorsa",
"resourceErrorCreateMessage": "Errore nella creazione della risorsa:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Si è verificato un errore durante l'aggiornamento della risorsa",
"access": "Accesso",
"accessControl": "Controllo Accessi",
"shareLink": "Link di Condivisione {resource}",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Seleziona risorsa",
"shareLinks": "Link di Condivisione",
"shareLinks": "Shareable Links",
"share": "Link Condivisibili",
"shareDescription2": "Crea link condivisibili alle risorse. I link forniscono un accesso temporaneo o illimitato alla tua risorsa. È possibile configurare la durata di scadenza del collegamento quando ne viene creato uno.",
"shareEasyCreate": "Facile da creare e condividere",
@@ -810,6 +926,17 @@
"pincodeAdd": "Aggiungi Codice PIN",
"pincodeRemove": "Rimuovi Codice PIN",
"resourceAuthMethods": "Metodi di Autenticazione",
"resourcePolicyAuthMethodsEmpty": "Nessun metodo di autenticazione",
"resourcePolicyOtpEmpty": "Nessuna password monouso",
"resourcePolicyReadOnly": "Questa politica è sola lettura",
"resourcePolicyReadOnlyDescription": "Questa politica delle risorse è condivisa su più risorse, non puoi modificarla in questa pagina.",
"editSharedPolicy": "Modifica Politica Condivisa",
"resourcePolicyTypeSave": "Salva tipo di risorsa",
"resourcePolicySelect": "Seleziona politica delle risorse",
"resourcePolicySelectError": "Seleziona una politica delle risorse",
"resourcePolicyNotFound": "Politica non trovata",
"resourcePolicySearch": "Cerca politiche",
"resourcePolicyRulesEmpty": "Nessuna regola di autenticazione",
"resourceAuthMethodsDescriptions": "Consenti l'accesso alla risorsa tramite metodi di autenticazione aggiuntivi",
"resourceAuthSettingsSave": "Salvato con successo",
"resourceAuthSettingsSaveDescription": "Le impostazioni di autenticazione sono state salvate",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Imposta Codice PIN",
"resourcePincodeSetupTitleDescription": "Imposta un codice PIN per proteggere questa risorsa",
"resourceRoleDescription": "Gli amministratori possono sempre accedere a questa risorsa.",
"resourcePolicySelectTitle": "Politica di Accesso Risorse",
"resourcePolicySelectDescription": "Seleziona il tipo di politica delle risorse per l'autenticazione",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Politica Inline delle Risorse",
"resourcePolicyInlineDescription": "Politica di Accesso limitata solo a questa risorsa",
"resourcePolicyShared": "Politica Condivisa delle Risorse",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Controlli di Accesso",
"resourceUsersRolesDescription": "Configura quali utenti e ruoli possono visitare questa risorsa",
"resourceUsersRolesSubmit": "Salva Controlli di Accesso",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Si è verificato un problema durante la connessione a {name}. Contatta il tuo amministratore.",
"idpErrorNotFound": "IdP non trovato",
"inviteInvalid": "Invito Non Valido",
"labels": "Etichette",
"orgLabelsDescription": "Gestisci le etichette in questa organizzazione.",
"addLabels": "Aggiungi etichette",
"siteLabelsTab": "Etichette",
"siteLabelsDescription": "Gestisci le etichette associate a questo sito.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Cerca etichette",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# etichetta} other {# etichette}}",
"labelOverflowCount": "+{count, plural, one {# etichetta} other {# etichette}}",
"accessLabelFilterClear": "Cancella filtri etichette",
"accessFilterClear": "Clear filters",
"selectColor": "Seleziona colore",
"createNewLabel": "Crea nuova etichetta dell'organizzazione \"{label}\"",
"inviteInvalidDescription": "Il link di invito non è valido.",
"inviteErrorWrongUser": "L'invito non è per questo utente",
"inviteErrorUserNotExists": "L'utente non esiste. Si prega di creare prima un account.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Risorse",
"sidebarProxyResources": "Pubblico",
"sidebarClientResources": "Privato",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Controllo Accesso",
"sidebarLogsAndAnalytics": "Registri E Analisi",
"sidebarTeam": "Squadra",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Amministratore",
"sidebarInvitations": "Inviti",
"sidebarRoles": "Ruoli",
"sidebarShareableLinks": "Collegamenti",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "Chiavi API",
"sidebarProvisioning": "Accantonamento",
"sidebarSettings": "Impostazioni",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Sito {id}",
"standaloneHcFilterResourceIdFallback": "Risorsa {id}",
"blueprints": "Progetti",
"blueprintsDescription": "Applica le configurazioni dichiarative e visualizza le partite precedenti",
"blueprintsLog": "Registro Progetti",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Aggiungi Progetto",
"blueprintGoBack": "Vedi tutti i progetti",
"blueprintCreate": "Crea Progetto",
@@ -1575,7 +1732,17 @@
"contents": "Contenuti",
"parsedContents": "Sommario Analizzato (Solo Lettura)",
"enableDockerSocket": "Abilita Progetto Docker",
"enableDockerSocketDescription": "Abilita la raschiatura dell'etichetta Docker Socket per le etichette dei progetti. Il percorso del socket deve essere fornito a Newt.",
"enableDockerSocketDescription": "Abilita lo scraping delle etichette Docker Socket per le etichette dei progetti. Il percorso del socket deve essere fornito al connettore del sito. Leggi come funziona nel <docsLink>documentazione</docsLink>.",
"newtAutoUpdate": "Abilita Aggiornamento Automatico del Sito",
"newtAutoUpdateDescription": "Quando abilitato, i connettori di sito si aggiorneranno automaticamente all'ultima versione quando è disponibile un nuovo rilascio.",
"siteAutoUpdate": "Aggiornamento Automatico del Sito",
"siteAutoUpdateLabel": "Abilita Aggiornamento Automatico",
"siteAutoUpdateDescription": "Controlla se il connettore di questo sito scarica automaticamente l'ultima versione.",
"siteAutoUpdateOrgDefault": "Predefinito dell'organizzazione: {state}",
"siteAutoUpdateOverriding": "Sovrascrivere le impostazioni dell'organizzazione",
"siteAutoUpdateResetToOrg": "Reimposta al Predefinito dell'Organizzazione",
"siteAutoUpdateEnabled": "abilitato",
"siteAutoUpdateDisabled": "disabilitato",
"viewDockerContainers": "Visualizza Contenitori Docker",
"containersIn": "Contenitori in {siteName}",
"selectContainerDescription": "Seleziona qualsiasi contenitore da usare come hostname per questo obiettivo. Fai clic su una porta per usare una porta.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certificato",
"certificateStatusAutoRefreshHint": "Lo stato si aggiorna automaticamente.",
"loading": "Caricamento",
"loadingEllipsis": "Caricamento...",
"loadingAnalytics": "Caricamento Delle Analisi",
"restart": "Riavvia",
"domains": "Domini",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Gestisci il tuo abbonamento per le chiavi di licenza self-hosted a pagamento",
"billingCurrentKeys": "Tasti Attuali",
"billingModifyCurrentPlan": "Modifica Il Piano Corrente",
"billingManageLicenseSubscriptionDescription": "Gestisci il tuo abbonamento per le chiavi di licenza autogestite a pagamento e scarica le fatture.",
"billingConfirmUpgrade": "Conferma Aggiornamento",
"billingConfirmDowngrade": "Conferma Downgrade",
"billingConfirmUpgradeDescription": "Stai per aggiornare il tuo piano. Controlla i nuovi limiti e prezzi qui sotto.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Sconosciuto",
"healthCheck": "Controllo Salute",
"configureHealthCheck": "Configura Controllo Salute",
"configureHealthCheckDescription": "Imposta il monitoraggio della salute per {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Abilita i Controlli di Salute",
"healthCheckDisabledStateDescription": "Quando disabilitato, il sito non eseguirà controlli di integrità e lo stato sarà considerato sconosciuto.",
"enableHealthChecksDescription": "Monitorare lo stato di salute di questo obiettivo. Se necessario, è possibile monitorare un endpoint diverso da quello del bersaglio.",
"healthScheme": "Metodo",
"healthSelectScheme": "Seleziona Metodo",
"healthCheckPortInvalid": "La porta di controllo dello stato di salute deve essere compresa tra 1 e 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Percorso",
"healthHostname": "IP / Nome host",
"healthPort": "Porta",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Il tempo è in secondi",
"requireDeviceApproval": "Richiede Approvazioni Dispositivo",
"requireDeviceApprovalDescription": "Gli utenti con questo ruolo hanno bisogno di nuovi dispositivi approvati da un amministratore prima di poter connettersi e accedere alle risorse.",
"sshAccess": "Accesso SSH",
"sshSettings": "Impostazioni SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Impostazioni RDP",
"vncSettings": "Impostazioni VNC",
"sshServer": "Server SSH",
"rdpServer": "Server RDP",
"vncServer": "Server VNC",
"sshServerDescription": "Configura il metodo di autenticazione, la posizione del demone e la destinazione del server",
"rdpServerDescription": "Configura la destinazione e la porta del server RDP",
"vncServerDescription": "Configura la destinazione e la porta del server VNC",
"sshServerMode": "Modalità",
"sshServerModeStandard": "Server SSH Standard",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Instrada comandi sulla rete a un server SSH come OpenSSH.",
"sshServerModeNative": "Server SSH Nativo",
"sshServerModeNativeDescription": "Esegue comandi direttamente sull'host tramite il connettore del sito. Non è richiesta la configurazione di rete.",
"sshAuthenticationMethod": "Metodo di Autenticazione",
"sshAuthMethodManual": "Autenticazione Manuale",
"sshAuthMethodManualDescription": "Richiede credenziali host esistenti. Bypassa il provisioning automatico.",
"sshAuthMethodAutomated": "Provisioning Automatico",
"sshAuthMethodAutomatedDescription": "Crea automaticamente utenti, gruppi e permessi sudo sull'host.",
"sshAuthDaemonLocation": "Posizione Daemon Autenticazione",
"sshDaemonLocationSiteDescription": "Eseguito localmente sulla macchina che ospita il connettore del sito.",
"sshDaemonLocationRemote": "Su Host Remoto",
"sshDaemonLocationRemoteDescription": "Eseguito su una macchina target separata nella stessa rete.",
"sshDaemonDisclaimer": "Assicurati che l'host target sia correttamente configurato per eseguire il demone di autenticazione prima di completare questa configurazione, altrimenti il provisioning fallirà.",
"sshDaemonPort": "Porta Daemon",
"sshServerDestination": "Destinazione Server",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Destinazione",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Selezionare più siti abilita instradamento resiliente e failover per alta disponibilità.",
"roleAllowSsh": "Consenti SSH",
"roleAllowSshAllow": "Consenti",
"roleAllowSshDisallow": "Non Consentire",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "L'utente può eseguire solo i comandi specificati con sudo.",
"sshSudo": "Consenti sudo",
"sshSudoCommands": "Comandi Sudo",
"sshSudoCommandsDescription": "Elenco di comandi separati da virgole che l'utente può eseguire con sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Crea Cartella Home",
"sshUnixGroups": "Gruppi Unix",
"sshUnixGroupsDescription": "Gruppi Unix separati da virgole per aggiungere l'utente sull'host di destinazione.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Tentativi di Riprova",
"expectedResponseCodes": "Codici di Risposta Attesi",
"expectedResponseCodesDescription": "Codice di stato HTTP che indica lo stato di salute. Se lasciato vuoto, considerato sano è compreso tra 200-300.",
@@ -2049,8 +2268,9 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Metodo HTTP",
"editInternalResourceDialogEnableSsl": "Abilitare TLS",
"editInternalResourceDialogEnableSsl": "Abilita TLS",
"editInternalResourceDialogEnableSslDescription": "Abilita la crittografia SSL/TLS per connessioni HTTPS sicure alla destinazione.",
"editInternalResourceDialogDestination": "Destinazione",
"editInternalResourceDialogDestinationHostDescription": "L'indirizzo IP o il nome host della risorsa nella rete del sito.",
@@ -2098,9 +2318,10 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Metodo HTTP",
"createInternalResourceDialogScheme": "Metodo HTTP",
"createInternalResourceDialogEnableSsl": "Abilitare TLS",
"createInternalResourceDialogEnableSsl": "Abilita TLS",
"createInternalResourceDialogEnableSslDescription": "Abilita la crittografia SSL/TLS per connessioni HTTPS sicure alla destinazione.",
"createInternalResourceDialogDestination": "Destinazione",
"createInternalResourceDialogDestinationHostDescription": "L'indirizzo IP o il nome host della risorsa nella rete del sito.",
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Inserisci conferma",
"blueprintViewDetails": "Dettagli",
"defaultIdentityProvider": "Provider di Identità Predefinito",
"defaultIdentityProviderDescription": "Quando viene selezionato un provider di identità predefinito, l'utente verrà automaticamente reindirizzato al provider per l'autenticazione.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Impostazioni di Rete",
"editInternalResourceDialogAccessPolicy": "Politica di Accesso",
"editInternalResourceDialogAddRoles": "Aggiungi Ruoli",
@@ -2937,11 +3158,12 @@
"learnMore": "Scopri di più",
"backToHome": "Torna alla home",
"needToSignInToOrg": "Hai bisogno di utilizzare il provider di identità della tua organizzazione?",
"maintenanceMode": "Modalità di Manutenzione",
"maintenanceMode": "Pagina di Manutenzione",
"maintenanceModeDescription": "Visualizza una pagina di manutenzione ai visitatori",
"maintenanceModeType": "Tipo di Modalità di Manutenzione",
"showMaintenancePage": "Mostra una pagina di manutenzione ai visitatori",
"enableMaintenanceMode": "Abilita Modalità di Manutenzione",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatico",
"automaticModeDescription": "Mostra pagina di manutenzione solo quando tutti i target del backend sono inattivi o non in salute. La tua risorsa continua a funzionare normalmente finché almeno un target è in salute.",
"forced": "Forzato",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Completamento Stimato:",
"createInternalResourceDialogDestinationRequired": "Destinazione richiesta",
"available": "Disponibile",
"disabledResourceDescription": "Quando disabilitato, la risorsa sarà inaccessibile a tutti.",
"archived": "Archiviato",
"noArchivedDevices": "Nessun dispositivo archiviato trovato",
"deviceArchived": "Dispositivo archiviato",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Sei sicuro di voler disassociare questo provider di identità da questa organizzazione?",
"idpUnassociateDescription": "Tutti gli utenti associati a questo provider di identità verranno rimossi da questa organizzazione, ma il provider di identità continuerà ad esistere per altre organizzazioni associate.",
"idpUnassociateConfirm": "Conferma Disassociazione Provider di Identità",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Questo non può essere annullato per questa organizzazione.",
"idpUnassociatedDescription": "Provider di identità disassociato con successo da questa organizzazione",
"idpUnassociateMenu": "Disassocia",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Risorsa Disabilitata",
"memberPortalShowingResources": "Mostrando {start}-{end} di {total} risorse",
"memberPortalPrevious": "Precedente",
"memberPortalNext": "Successivo"
"memberPortalNext": "Successivo",
"httpSettings": "Impostazioni HTTP",
"tcpSettings": "Impostazioni TCP",
"udpSettings": "Impostazioni UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Stabilire una connessione sicura…",
"sshConnecting": "Connessione…",
"sshInitializing": "Inizializzazione…",
"sshSignInTitle": "Accedi a SSH",
"sshSignInDescription": "Inserisci le tue credenziali SSH",
"sshPasswordTab": "Password",
"sshPrivateKeyTab": "Chiave Privata",
"sshPrivateKeyField": "Chiave Privata",
"sshPrivateKeyDisclaimer": "La tua chiave privata non è memorizzata o visibile a Pangolin. In alternativa, puoi utilizzare certificati a vita breve per un'autenticazione continua utilizzando la tua identità Pangolin esistente.",
"sshLearnMore": "Scopri di più",
"sshPrivateKeyFile": "File Chiave Privata",
"sshAuthenticate": "Autentica",
"sshTerminate": "Termina",
"sshPoweredBy": "Offerto da",
"sshErrorNoTarget": "Nessun obiettivo specificato",
"sshErrorWebSocket": "Connessione WebSocket fallita",
"sshErrorAuthFailed": "Autenticazione fallita",
"sshErrorConnectionClosed": "Connessione chiusa prima del completamento dell'autenticazione",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "개인 리소스 보기",
"siteInstallNewt": "Newt 설치",
"siteInstallNewtDescription": "시스템에서 Newt 실행하기",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard 구성",
"WgConfigurationDescription": "네트워크에 연결하기 위한 다음 구성을 사용하세요.",
"operatingSystem": "운영 체제",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "이것은 한 번만 볼 수 있습니다. 안전한 장소에 복사해 두세요.",
"siteInfo": "사이트 정보",
"status": "상태",
"shareTitle": "공유 링크 관리",
"shareTitle": "Manage Shareable Links",
"shareDescription": "공유 가능한 링크를 생성하여 프록시 리소스에 임시 또는 영구적으로 액세스하세요.",
"shareSearch": "공유 링크 검색...",
"shareCreate": "공유 링크 생성",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "링크 삭제에 실패했습니다.",
"shareErrorDeleteMessage": "링크 삭제 중 오류가 발생했습니다.",
"shareDeleted": "링크가 삭제되었습니다.",
"shareDeletedDescription": "링크가 삭제되었습니다.",
"shareDelete": "공유 링크 삭제",
"shareDeleteConfirm": "공유 링크 삭제 확인",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "이 공유 링크를 삭제하시겠습니까?",
"shareMessageRemove": "삭제되면 링크가 더 이상 작동하지 않으며, 이를 사용하는 모든 사용자는 자원에 대한 접근을 잃게 됩니다.",
"shareTokenDescription": "액세스 토큰은 쿼리 매개변수 또는 요청 헤더의 두 가지 방법으로 전달될 수 있습니다. 이는 인증된 액세스를 위해 클라이언트에서 모든 요청마다 전달되어야 합니다.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "공유 링크를 생성하는 동안 오류가 발생했습니다",
"shareCreateDescription": "이 링크가 있는 누구나 리소스에 접근할 수 있습니다.",
"shareTitleOptional": "제목 (선택 사항)",
"sharePathOptional": "경로 (선택 사항)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "만료됨",
"neverExpire": "만료되지 않음",
"shareExpireDescription": "만료 시간은 링크가 사용 가능하고 리소스에 접근할 수 있는 기간입니다. 이 시간이 지나면 링크는 더 이상 작동하지 않으며, 이 링크를 사용한 사용자는 리소스에 대한 접근 권한을 잃게 됩니다.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "리소스를 선택하세요",
"proxyResourceTitle": "공개 리소스 관리",
"proxyResourceDescription": "웹 브라우저를 통해 공용으로 접근할 수 있는 리소스를 생성하고 관리하세요.",
"proxyResourcesBannerTitle": "웹 기반 공공 접근",
"proxyResourcesBannerDescription": "공공 자원은 누구나 웹 브라우저를 통해 접근 가능한 HTTPS 또는 TCP/UDP 프록시입니다. 개인 자원과 달리 클라이언트 측 소프트웨어가 필요하지 않으며, 아이덴티티 및 컨텍스트 인지 접근 정책을 포함할 수 있습니다.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "개인 리소스 관리",
"clientResourceDescription": "연결된 클라이언트를 통해서만 접근할 수 있는 리소스를 생성하고 관리하세요.",
"privateResourcesBannerTitle": "제로 트러스트 개인 접근",
@@ -208,11 +212,36 @@
"resourcesSearch": "리소스 검색...",
"resourceAdd": "리소스 추가",
"resourceErrorDelte": "리소스 삭제 중 오류 발생",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} 리소스",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "리소스 없음",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "정책 검색...",
"resourcePoliciesAdd": "정책 추가",
"resourcePoliciesDefaultBadgeText": "기본 정책",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "새로운 정책을 생성하려면 아래 단계들을 따르세요",
"resourcePolicyName": "정책 이름",
"resourcePolicyNameDescription": "이 정책에 리소스 간에 식별할 이름을 지정합니다",
"resourcePolicyNamePlaceholder": "예: 내부 접근 정책",
"resourcePoliciesSeeAll": "모든 정책 보기",
"resourcePolicyAuthMethodAdd": "인증 방법 추가",
"resourcePolicyOtpEmailAdd": "OTP 이메일 추가",
"resourcePolicyRulesAdd": "규칙 추가",
"resourcePolicyAuthMethodsDescription": "추가 인증 방법을 통해 리소스에 대한 접근을 허용합니다",
"resourcePolicyUsersRolesDescription": "어떤 사용자와 역할이 관련된 리소스를 방문할 수 있는지 구성합니다",
"rulesResourcePolicyDescription": "이 정책에 연결된 접근 리소스를 제어할 규칙을 구성하세요",
"authentication": "인증",
"protected": "보호됨",
"notProtected": "보호되지 않음",
"resourceMessageRemove": "제거되면 리소스에 더 이상 접근할 수 없습니다. 리소스와 연결된 모든 대상도 제거됩니다.",
"resourceQuestionRemove": "조직에서 리소스를 제거하시겠습니까?",
"resourcePolicyMessageRemove": "제거되면 리소스 정책에 접근할 수 없습니다. 리소스와 관련된 모든 리소스가 연동되지 않으며 인증 없이 남겨집니다.",
"resourcePolicyQuestionRemove": "정말로 조직에서 리소스 정책을 제거하시겠습니까?",
"resourceHTTP": "HTTPS 리소스",
"resourceHTTPDescription": "완전한 도메인 이름을 사용해 RAW 또는 HTTPS로 프록시 요청을 수행합니다.",
"resourceRaw": "원시 TCP/UDP 리소스",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "포트 번호를 사용하여 원격 노드에 연결해야 합니다. 원격 노드에서 리소스를 사용하려면 사용자 지정 도메인을 사용하십시오.",
"resourceCreate": "리소스 생성",
"resourceCreateDescription": "아래 단계를 따라 새 리소스를 생성하세요.",
"resourceCreateGeneralDescription": "이름 및 유형을 포함한 기본 리소스 설정 구성",
"resourceSeeAll": "모든 리소스 보기",
"resourceInfo": "리소스 정보",
"resourceCreateGeneral": "일반",
"resourceNameDescription": "이것은 리소스의 표시 이름입니다.",
"siteSelect": "사이트 선택",
"siteSearch": "사이트 검색",
@@ -231,12 +261,15 @@
"noCountryFound": "국가를 찾을 수 없습니다.",
"siteSelectionDescription": "이 사이트는 대상에 대한 연결을 제공합니다.",
"resourceType": "리소스 유형",
"resourceTypeDescription": "리소스에 액세스하는 방법을 결정하세요.",
"resourceTypeDescription": "이것은 리소스 프로토콜 및 브라우저에서 렌더링되는 방식에 영향을 줍니다. 나중에 변경할 수 없습니다.",
"resourceDomainDescription": "리소스는 숙주 네임에서 제공됩니다.",
"resourceHTTPSSettings": "HTTPS 설정",
"resourceHTTPSSettingsDescription": "리소스가 HTTPS로 접근할 수 있는 방식을 구성합니다.",
"resourcePortDescription": "리소스에 접근할 수 있는 Pangolin 인스턴스나 노드의 외부 포트입니다.",
"domainType": "도메인 유형",
"subdomain": "서브도메인",
"baseDomain": "기본 도메인",
"configure": "구성",
"subdomnainDescription": "리소스에 접근할 수 있는 하위 도메인입니다.",
"resourceRawSettings": "TCP/UDP 설정",
"resourceRawSettingsDescription": "TCP/UDP를 통해 리소스에 접근하는 방법을 구성하세요.",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "TCP/UDP 리소스 구성 방법 알아보기",
"resourceBack": "리소스로 돌아가기",
"resourceGoTo": "리소스로 이동",
"resourcePolicyDelete": "리소스 정책 삭제",
"resourcePolicyDeleteConfirm": "리소스 정책 삭제 확인",
"resourceDelete": "리소스 삭제",
"resourceDeleteConfirm": "리소스 삭제 확인",
"labelDelete": "레이블 삭제",
"labelAdd": "레이블 추가",
"labelCreateSuccessMessage": "레이블이 성공적으로 생성되었습니다",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "레이블이 성공적으로 수정되었습니다",
"labelNameField": "레이블 이름",
"labelColorField": "레이블 색상",
"labelPlaceholder": "예: homelab",
"labelCreate": "레이블 만들기",
"createLabelDialogTitle": "레이블 만들기",
"createLabelDialogDescription": "이 조직에 연결할 수 있는 새 레이블을 만듭니다",
"labelEdit": "레이블 편집",
"editLabelDialogTitle": "레이블 업데이트",
"editLabelDialogDescription": "이 조직에 연결할 수 있는 새 레이블을 편집합니다",
"labelDeleteConfirm": "레이블 삭제 확인",
"labelErrorDelete": "레이블 삭제 실패",
"labelMessageRemove": "이 작업은 영구적입니다. 이 레이블과 태그된 모든 사이트, 리소스, 클라이언트의 태그가 제거됩니다.",
"labelQuestionRemove": "정말로 조직에서 레이블을 제거하시겠습니까?",
"visibility": "가시성",
"enabled": "활성화됨",
"disabled": "비활성화됨",
@@ -265,6 +319,8 @@
"rules": "규칙",
"resourceSettingDescription": "리소스의 설정을 구성하세요.",
"resourceSetting": "{resourceName} 설정",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} 설정",
"alwaysAllow": "인증 우회",
"alwaysDeny": "접근 차단",
"passToAuth": "인증으로 전달",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "중복 규칙",
"rulesErrorDuplicateDescription": "이 설정을 가진 규칙이 이미 존재합니다.",
"rulesErrorInvalidIpAddressRange": "유효하지 않은 CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "유효한 CIDR 값을 입력하십시오.",
"rulesErrorInvalidUrl": "유효하지 않은 URL 경로",
"rulesErrorInvalidUrlDescription": "유효한 URL 경로 값을 입력해 주세요.",
"rulesErrorInvalidIpAddress": "유효하지 않은 IP",
"rulesErrorInvalidIpAddressDescription": "유효한 IP 주소를 입력하세요",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "규칙 업데이트에 실패했습니다.",
"rulesErrorUpdateDescription": "규칙 업데이트 중 오류가 발생했습니다.",
"rulesUpdated": "규칙 활성화",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "CIDR 형식으로 주소를 입력하세요 (예: 103.21.244.0/22)",
"rulesMatchIpAddress": "IP 주소를 입력하세요 (예: 103.21.244.12)",
"rulesMatchUrl": "URL 경로 또는 패턴을 입력하세요 (예: /api/v1/todos 또는 /api/v1/*)",
"rulesErrorInvalidPriority": "유효하지 않은 우선순위",
"rulesErrorInvalidPriorityDescription": "유효한 우선 순위를 입력하세요.",
"rulesErrorDuplicatePriority": "중복 우선순위",
"rulesErrorDuplicatePriorityDescription": "고유한 우선 순위를 입력하십시오.",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "규칙이 업데이트되었습니다",
"ruleUpdatedDescription": "규칙이 성공적으로 업데이트되었습니다",
"ruleErrorUpdate": "작업 실패",
"ruleErrorUpdateDescription": "저장 작업 중 오류가 발생했습니다.",
"rulesPriority": "우선순위",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "작업",
"rulesMatchType": "일치 유형",
"value": "값",
@@ -744,9 +809,60 @@
"rulesResource": "리소스 규칙 구성",
"rulesResourceDescription": "리소스에 대한 접근을 제어하는 규칙 구성",
"ruleSubmit": "규칙 추가",
"rulesNoOne": "규칙이 없습니다. 양식을 사용하여 규칙을 추가하십시오.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "규칙은 우선 순위에 따라 오름차순으로 평가됩니다.",
"rulesSubmit": "규칙 저장",
"policyErrorCreate": "정책 생성 오류",
"policyErrorCreateDescription": "정책 생성 중 오류가 발생했습니다",
"policyErrorCreateMessageDescription": "예기치 않은 오류가 발생했습니다",
"policyErrorUpdate": "정책 업데이트 오류",
"policyErrorUpdateDescription": "정책 업데이트 중 오류가 발생했습니다",
"policyErrorUpdateMessageDescription": "예기치 않은 오류가 발생했습니다",
"policyCreatedSuccess": "리소스 정책이 성공적으로 생성되었습니다",
"policyUpdatedSuccess": "리소스 정책이 성공적으로 업데이트되었습니다",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "규칙 저장",
"resourceErrorCreate": "리소스 생성 오류",
"resourceErrorCreateDescription": "리소스를 생성하는 중 오류가 발생했습니다.",
"resourceErrorCreateMessage": "리소스 생성 오류:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "리소스를 업데이트하는 동안 오류가 발생했습니다.",
"access": "접속",
"accessControl": "액세스 제어",
"shareLink": "{resource} 공유 링크",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "리소스 선택",
"shareLinks": "공유 링크",
"shareLinks": "Shareable Links",
"share": "공유 가능한 링크",
"shareDescription2": "리소스에 대한 공유 가능한 링크를 생성하세요. 링크는 리소스에 대한 임시 또는 무제한 액세스를 제공합니다. 링크를 생성할 때 만료 기간을 설정할 수 있습니다.",
"shareEasyCreate": "생성하고 공유하기 쉬움",
@@ -810,6 +926,17 @@
"pincodeAdd": "PIN 코드 추가",
"pincodeRemove": "PIN 코드 제거",
"resourceAuthMethods": "인증 방법",
"resourcePolicyAuthMethodsEmpty": "인증 방법 없음",
"resourcePolicyOtpEmpty": "일회용 비밀번호 없음",
"resourcePolicyReadOnly": "이 정책은 읽기 전용입니다",
"resourcePolicyReadOnlyDescription": "이 리소스 정책은 여러 리소스에 걸쳐 공유됩니다. 이 페이지에서는 수정할 수 없습니다.",
"editSharedPolicy": "공유 정책 편집",
"resourcePolicyTypeSave": "리소스 유형 저장",
"resourcePolicySelect": "리소스 정책 선택",
"resourcePolicySelectError": "리소스 정책 선택 오류",
"resourcePolicyNotFound": "정책을 찾을 수 없습니다",
"resourcePolicySearch": "정책 검색",
"resourcePolicyRulesEmpty": "인증 규칙 없음",
"resourceAuthMethodsDescriptions": "추가 인증 방법을 통해 리소스에 대한 액세스 허용",
"resourceAuthSettingsSave": "성공적으로 저장되었습니다.",
"resourceAuthSettingsSaveDescription": "인증 설정이 저장되었습니다",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "핀코드 설정",
"resourcePincodeSetupTitleDescription": "이 리소스를 보호하기 위해 핀 코드를 설정하십시오.",
"resourceRoleDescription": "관리자는 항상 이 리소스에 접근할 수 있습니다.",
"resourcePolicySelectTitle": "리소스 액세스 정책",
"resourcePolicySelectDescription": "인증을 위한 리소스 정책 유형을 선택하세요",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "인라인 리소스 정책",
"resourcePolicyInlineDescription": "이 리소스에만 범위가 있는 액세스 정책",
"resourcePolicyShared": "공유 리소스 정책",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "접근 제어",
"resourceUsersRolesDescription": "이 리소스를 방문할 수 있는 사용자 및 역할을 구성하십시오",
"resourceUsersRolesSubmit": "접근 제어 저장",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "{name}에 연결하는 데 문제가 발생했습니다. 관리자에게 문의하십시오.",
"idpErrorNotFound": "IdP를 찾을 수 없습니다.",
"inviteInvalid": "유효하지 않은 초대",
"labels": "레이블",
"orgLabelsDescription": "이 조직의 레이블을 관리합니다.",
"addLabels": "레이블 추가",
"siteLabelsTab": "레이블",
"siteLabelsDescription": "이 사이트와 연결된 레이블을 관리합니다.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "레이블 검색",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, other {# 레이블}}",
"labelOverflowCount": " +{count, plural, other {# 레이블}}",
"accessLabelFilterClear": "레이블 필터 초기화",
"accessFilterClear": "Clear filters",
"selectColor": "색상 선택",
"createNewLabel": "새 조직 레이블 \"{label}\" 만들기",
"inviteInvalidDescription": "초대 링크가 유효하지 않습니다.",
"inviteErrorWrongUser": "이 초대는 이 사용자에게 해당되지 않습니다",
"inviteErrorUserNotExists": "사용자가 존재하지 않습니다. 먼저 계정을 생성해 주세요.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "리소스",
"sidebarProxyResources": "공유",
"sidebarClientResources": "비공개",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "액세스 제어",
"sidebarLogsAndAnalytics": "로그 및 분석",
"sidebarTeam": "팀",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "관리자",
"sidebarInvitations": "초대",
"sidebarRoles": "역할",
"sidebarShareableLinks": "링크",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API 키",
"sidebarProvisioning": "프로비저닝",
"sidebarSettings": "설정",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "사이트 {id}",
"standaloneHcFilterResourceIdFallback": "리소스 {id}",
"blueprints": "청사진",
"blueprintsDescription": "선언적 구성을 적용하고 이전 실행을 봅니다",
"blueprintsLog": "블루프린트 로그",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "청사진 추가",
"blueprintGoBack": "모든 청사진 보기",
"blueprintCreate": "청사진 생성",
@@ -1575,7 +1732,17 @@
"contents": "콘텐츠",
"parsedContents": "구문 분석된 콘텐츠 (읽기 전용)",
"enableDockerSocket": "Docker 청사진 활성화",
"enableDockerSocketDescription": "블루프린트 레이블을 위한 Docker 소켓 레이블 수집을 활성화합니다. 소켓 경로는 Newt에 제공되어야 합니다.",
"enableDockerSocketDescription": "블루프린트 레이블을 위한 Docker 소켓 레이블 스크래핑을 활성화합니다. 소켓 경로는 사이트 커넥터에 제공되어야 합니다. 동작 방법에 대한 자세한 정보는 <docsLink>문서</docsLink>에서 확인하세요.",
"newtAutoUpdate": "사이트 자동 업데이트 활성화",
"newtAutoUpdateDescription": "활성화되면, 사이트 커넥터는 새 릴리스가 출시될 때 자동으로 최신 버전으로 업데이트됩니다.",
"siteAutoUpdate": "사이트 자동 업데이트",
"siteAutoUpdateLabel": "자동 업데이트 활성화",
"siteAutoUpdateDescription": "이 사이트의 커넥터가 최신 버전을 자동으로 다운로드할지 여부를 제어합니다.",
"siteAutoUpdateOrgDefault": "조직 기본값: {state}",
"siteAutoUpdateOverriding": "조직 설정 재정의",
"siteAutoUpdateResetToOrg": "조직 기본값으로 재설정",
"siteAutoUpdateEnabled": "활성화됨",
"siteAutoUpdateDisabled": "비활성화됨",
"viewDockerContainers": "도커 컨테이너 보기",
"containersIn": "{siteName}의 컨테이너",
"selectContainerDescription": "이 대상을 위한 호스트 이름으로 사용할 컨테이너를 선택하세요. 포트를 사용하려면 포트를 클릭하세요.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "인증서",
"certificateStatusAutoRefreshHint": "상태가 자동으로 새로 고쳐집니다.",
"loading": "로딩 중",
"loadingEllipsis": "로딩 중...",
"loadingAnalytics": "분석 로딩 중",
"restart": "재시작",
"domains": "도메인",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "유료 독립 호스트 라이센스 키를 위한 구독 관리",
"billingCurrentKeys": "현재 키",
"billingModifyCurrentPlan": "현재 계획 수정",
"billingManageLicenseSubscriptionDescription": "유료 셀프호스티드 라이선스 키에 대한 구독을 관리하고 송장을 다운로드합니다.",
"billingConfirmUpgrade": "업그레이드 확인",
"billingConfirmDowngrade": "다운그레이드 확인",
"billingConfirmUpgradeDescription": "계획을 업그레이드하려고 합니다. 아래의 새로운 제한 및 가격을 검토하세요.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "알 수 없음",
"healthCheck": "상태 확인",
"configureHealthCheck": "상태 확인 설정",
"configureHealthCheckDescription": "{target}에 대한 상태 모니터링 설정",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "상태 확인 활성화",
"healthCheckDisabledStateDescription": "비활성화되면 이 사이트가 상태 확인을 수행하지 않으며 상태가 알 수 없는 것으로 간주됩니다.",
"enableHealthChecksDescription": "이 대상을 모니터링하여 건강 상태를 확인하세요. 필요에 따라 대상과 다른 엔드포인트를 모니터링할 수 있습니다.",
"healthScheme": "방법",
"healthSelectScheme": "방법 선택",
"healthCheckPortInvalid": "올바르지 않은 서브넷 마스크입니다. 1에서 65535 사이여야 합니다",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "경로",
"healthHostname": "IP / 호스트",
"healthPort": "포트",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "시간은 초 단위입니다",
"requireDeviceApproval": "장치 승인 요구",
"requireDeviceApprovalDescription": "이 역할을 가진 사용자는 장치가 연결되기 전에 관리자의 승인이 필요합니다.",
"sshAccess": "SSH 접속",
"sshSettings": "SSH 설정",
"sshAccess": "SSH Access",
"rdpSettings": "RDP 설정",
"vncSettings": "VNC 설정",
"sshServer": "SSH 서버",
"rdpServer": "RDP 서버",
"vncServer": "VNC 서버",
"sshServerDescription": "인증 방법, 데몬 위치 및 서버 목적지를 설정합니다",
"rdpServerDescription": "RDP 서버의 목적지 및 포트를 구성합니다",
"vncServerDescription": "VNC 서버의 목적지 및 포트를 구성합니다",
"sshServerMode": "모드",
"sshServerModeStandard": "표준 SSH 서버",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "네트워크를 통해 OpenSSH와 같은 SSH 서버로 명령을 전달합니다.",
"sshServerModeNative": "네이티브 SSH 서버",
"sshServerModeNativeDescription": "사이트 커넥터를 통해 호스트에서 직접 명령을 실행합니다. 네트워크 구성이 필요 없습니다.",
"sshAuthenticationMethod": "인증 방법",
"sshAuthMethodManual": "수동 인증",
"sshAuthMethodManualDescription": "기존 호스트 자격 증명이 필요합니다. 자동 프로비저닝을 우회합니다.",
"sshAuthMethodAutomated": "자동 프로비저닝",
"sshAuthMethodAutomatedDescription": "호스트에 사용자, 그룹 및 sudo 권한을 자동으로 생성합니다.",
"sshAuthDaemonLocation": "인증 데몬 위치",
"sshDaemonLocationSiteDescription": "사이트 커넥터를 호스팅하는 기계에서 로컬로 실행됩니다.",
"sshDaemonLocationRemote": "원격 호스트에서",
"sshDaemonLocationRemoteDescription": "같은 네트워크의 별도의 대상 기계에서 실행됩니다.",
"sshDaemonDisclaimer": "이 설정을 완료하기 전에 인증 데몬을 실행할 대상 호스트가 적절히 구성되었는지 확인하십시오. 그렇지 않으면 프로비저닝이 실패할 수 있습니다.",
"sshDaemonPort": "데몬 포트",
"sshServerDestination": "서버 목적지",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "대상지",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "여러 사이트를 선택하면 고가용성을 위한 내구성 있는 라우팅 및 장애 조치를 활성화합니다.",
"roleAllowSsh": "SSH 허용",
"roleAllowSshAllow": "허용",
"roleAllowSshDisallow": "허용 안 함",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "사용자는 sudo로 지정된 명령만 실행할 수 있습니다.",
"sshSudo": "Sudo 허용",
"sshSudoCommands": "Sudo 명령",
"sshSudoCommandsDescription": "사용자가 sudo로 실행할 수 있는 명령어의 쉼표로 구분된 목록입니다.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "홈 디렉터리 생성",
"sshUnixGroups": "유닉스 그룹",
"sshUnixGroupsDescription": "대상 호스트에서 사용자에게 추가할 유닉스 그룹의 쉼표로 구분된 목록입니다.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "재시도 횟수",
"expectedResponseCodes": "예상 응답 코드",
"expectedResponseCodesDescription": "정상 상태를 나타내는 HTTP 상태 코드입니다. 비워 두면 200-300이 정상으로 간주됩니다.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "스킴",
"editInternalResourceDialogEnableSsl": "TLS 활성화",
"editInternalResourceDialogEnableSslDescription": "목적지로의 안전한 HTTPS 연결을 위한 SSL/TLS 암호화 활성화.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "스킴",
"createInternalResourceDialogScheme": "스킴",
"createInternalResourceDialogEnableSsl": "TLS 활성화",
@@ -2233,7 +2454,7 @@
"description": "더 신뢰할 수 있고 낮은 유지보수의 자체 호스팅 팡골린 서버, 추가 기능 포함",
"introTitle": "관리 자체 호스팅 팡골린",
"introDescription": "는 자신의 데이터를 프라이빗하고 자체 호스팅을 유지하면서 더 간단하고 추가적인 신뢰성을 원하는 사람들을 위한 배포 옵션입니다.",
"introDetail": "이 옵션을 사용하면 여전히 자신의 팡골린 노드를 운영하고 - 터널, TLS 종료 트래픽 모두 서버에 유지됩니다. 차이점은 관리 및 모니터링이 클라우드 대시보드를 통해 처리되어 여러 혜택을 제공합니다.",
"introDetail": "이 옵션을 사용하면 여전히 자신의 Pangolin 노드를 운영하고 - 터널, TLS 종료, 트래픽 모두 서버에 유지됩니다. 차이점은 관리 및 모니터링이 클라우드 대시보드를 통해 처리되어 여러 혜택을 제공합니다:",
"benefitSimplerOperations": {
"title": "더 간단한 운영",
"description": "자체 메일 서버를 운영하거나 복잡한 경고를 설정할 필요가 없습니다. 기본적으로 상태 점검 및 다운타임 경고를 받을 수 있습니다."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "확인 입력",
"blueprintViewDetails": "세부 정보",
"defaultIdentityProvider": "기본 아이덴티티 공급자",
"defaultIdentityProviderDescription": "기본 ID 공급자가 선택되면, 사용자는 인증을 위해 자동으로 해당 공급자로 리디렉션됩니다.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "네트워크 설정",
"editInternalResourceDialogAccessPolicy": "액세스 정책",
"editInternalResourceDialogAddRoles": "역할 추가",
@@ -2937,11 +3158,12 @@
"learnMore": "자세히 알아보기",
"backToHome": "홈으로 돌아가기",
"needToSignInToOrg": "조직의 아이덴티티 공급자를 사용해야 합니까?",
"maintenanceMode": "유지보수 모드",
"maintenanceMode": "유지 관리 페이지",
"maintenanceModeDescription": "방문자에게 유지보수 페이지 표시",
"maintenanceModeType": "유지보수 모드 유형",
"showMaintenancePage": "방문자에게 유지보수 페이지 표시",
"enableMaintenanceMode": "유지보수 모드 활성화",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "자동",
"automaticModeDescription": "백엔드 타깃이 모두 다운되거나 건강하지 않을 때만 유지보수 페이지를 표시합니다. 적어도 하나의 타깃이 건강한 한 리소스는 정상 작동합니다.",
"forced": "강제",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "예상 완료:",
"createInternalResourceDialogDestinationRequired": "목적지가 필요합니다.",
"available": "사용 가능",
"disabledResourceDescription": "비활성화되면 리소스에 모든 사람이 접근할 수 없습니다.",
"archived": "보관된",
"noArchivedDevices": "보관된 장치가 없습니다.",
"deviceArchived": "장치가 보관되었습니다.",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "정말로 이 조직에서 이 아이덴티티 공급자의 연관을 해제하시겠습니까?",
"idpUnassociateDescription": "이 아이덴티티 공급자와 연관된 모든 사용자는 이 조직에서 제거될 것이지만, 아이덴티티 공급자는 다른 연관된 조직에 계속해서 존재할 것입니다.",
"idpUnassociateConfirm": "아이덴티티 공급자 연관 해제 확인",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "이 조직에서 이것은 되돌릴 수 없습니다.",
"idpUnassociatedDescription": "아이덴티티 공급자가 이 조직에서 성공적으로 연관 해제되었습니다",
"idpUnassociateMenu": "연관 해제",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "리소스 비활성화됨",
"memberPortalShowingResources": "{start}-{end} 중 {total}개의 리소스를 표시 중",
"memberPortalPrevious": "이전",
"memberPortalNext": "다음"
"memberPortalNext": "다음",
"httpSettings": "HTTP 설정",
"tcpSettings": "TCP 설정",
"udpSettings": "UDP 설정",
"sshTitle": "SSH",
"sshConnectingDescription": "보안 연결 설정 중…",
"sshConnecting": "연결 중…",
"sshInitializing": "초기화 중…",
"sshSignInTitle": "SSH에 로그인",
"sshSignInDescription": "SSH 자격 증명을 입력하세요",
"sshPasswordTab": "비밀번호",
"sshPrivateKeyTab": "개인 키",
"sshPrivateKeyField": "개인 키",
"sshPrivateKeyDisclaimer": "당신의 개인 키는 Pangolin에 저장되거나 보이지 않습니다. 대신, 기존 Pangolin 신원을 사용하여 매끄러운 인증을 제공하는 단기 인증서를 사용할 수 있습니다.",
"sshLearnMore": "자세히 알아보기",
"sshPrivateKeyFile": "개인 키 파일",
"sshAuthenticate": "인증",
"sshTerminate": "종료",
"sshPoweredBy": "제공자",
"sshErrorNoTarget": "지정된 대상이 없습니다",
"sshErrorWebSocket": "WebSocket 연결 실패",
"sshErrorAuthFailed": "인증 실패",
"sshErrorConnectionClosed": "인증이 완료되기 전에 연결이 닫혔습니다",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Vis private ressurser",
"siteInstallNewt": "Installer Newt",
"siteInstallNewtDescription": "Få Newt til å kjøre på systemet ditt",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard Konfigurasjon",
"WgConfigurationDescription": "Bruk følgende konfigurasjon for å koble til nettverket",
"operatingSystem": "Operativsystem",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Du vil kun kunne se dette én gang. Sørg for å kopiere det til et sikkert sted.",
"siteInfo": "Områdeinformasjon",
"status": "Status",
"shareTitle": "Administrer delingslenker",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Opprett delbare lenker for å gi midlertidige eller permanent tilgang til proxyressurser",
"shareSearch": "Søk delingslenker...",
"shareCreate": "Opprett delingslenke",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Klarte ikke å slette lenke",
"shareErrorDeleteMessage": "En feil oppstod ved sletting av lenke",
"shareDeleted": "Lenke slettet",
"shareDeletedDescription": "Lenken har blitt slettet",
"shareDelete": "Slett delingslenke",
"shareDeleteConfirm": "Bekreft sletting av delingslenke",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Er du sikker på at du vil slette denne delingslenken?",
"shareMessageRemove": "Når slettet, vil lenken ikke lenger fungere, og alle som bruker den vil miste tilgang til ressursen.",
"shareTokenDescription": "Adgangstoken kan sendes på to måter: som en spørringsparameter eller i forespørselsoverskriftene. Disse må sendes fra klienten på hver forespørsel om autentisert tilgang.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Det oppsto en feil ved opprettelse av delingslenken",
"shareCreateDescription": "Alle med denne lenken får tilgang til ressursen",
"shareTitleOptional": "Tittel (valgfritt)",
"sharePathOptional": "Bane (valgfritt)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Utløper om",
"neverExpire": "Utløper aldri",
"shareExpireDescription": "Utløpstid er hvor lenge lenken vil være brukbar og gi tilgang til ressursen. Etter denne tiden vil lenken ikke lenger fungere, og brukere som brukte denne lenken vil miste tilgangen til ressursen.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Vennligst velg en ressurs",
"proxyResourceTitle": "Administrere offentlige ressurser",
"proxyResourceDescription": "Opprett og administrer ressurser som er offentlig tilgjengelige via en nettleser",
"proxyResourcesBannerTitle": "Nettbasert offentlig tilgang",
"proxyResourcesBannerDescription": "Offentlige ressurser er HTTPS- eller TCP/UDP-proxyer tilgjengelige for alle på internett via en nettleser. I motsetning til private ressurser, krever de ikke klient-basert programvare og kan inkludere identitets- og kontekstbevisste tilgangspolicyer.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Administrer private ressurser",
"clientResourceDescription": "Opprette og administrere ressurser som bare er tilgjengelige via en tilkoblet klient",
"privateResourcesBannerTitle": "Zero-Trust privat tilgang",
@@ -208,11 +212,36 @@
"resourcesSearch": "Søk i ressurser...",
"resourceAdd": "Legg til ressurs",
"resourceErrorDelte": "Feil ved sletting av ressurs",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} ressurs(er)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "ingen ressurser",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Søk etter regler...",
"resourcePoliciesAdd": "Legg til policy",
"resourcePoliciesDefaultBadgeText": "Standard politisk",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Følg trinnene nedenfor for å lage en ny policy",
"resourcePolicyName": "Polisnavn",
"resourcePolicyNameDescription": "Gi denne policynavnet for å identifisere den på tvers av dine ressurser",
"resourcePolicyNamePlaceholder": "f.eks. Intern Tilgangspolicy",
"resourcePoliciesSeeAll": "Se Alle Policies",
"resourcePolicyAuthMethodAdd": "Legg til Autentiseringsmetode",
"resourcePolicyOtpEmailAdd": "Legg til OTP e-poster",
"resourcePolicyRulesAdd": "Legg til Regler",
"resourcePolicyAuthMethodsDescription": "Tillat tilgang til ressurser via tilleggsauthentiseringsmetoder",
"resourcePolicyUsersRolesDescription": "Konfigurer hvilke brukere og roller som kan besøke tilknyttede ressurser",
"rulesResourcePolicyDescription": "Konfigurer regler for å kontrollere tilgangen til ressurser som er knyttet til denne policyen",
"authentication": "Autentisering",
"protected": "Beskyttet",
"notProtected": "Ikke beskyttet",
"resourceMessageRemove": "Når den er fjernet, vil ressursen ikke lenger være tilgjengelig. Alle mål knyttet til ressursen vil også bli fjernet.",
"resourceQuestionRemove": "Er du sikker på at du vil fjerne ressursen fra organisasjonen?",
"resourcePolicyMessageRemove": "Når den er fjernet, vil ressursen ikke lenger være tilgjengelig. Alle ressurser knyttet til ressursen vil bli frakoblet og stå uten autentisering.",
"resourcePolicyQuestionRemove": "Er du sikker på at du vil fjerne ressurspolitikken fra organisasjonen?",
"resourceHTTP": "HTTPS-ressurs",
"resourceHTTPDescription": "Proxy forespørsler over HTTPS ved å bruke et fullstendig kvalifisert domenenavn.",
"resourceRaw": "Rå TCP/UDP-ressurs",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy forespørsler om rå TCP/UDP ved hjelp av et portnummer. Krever sider for å koble til en ekstern node.",
"resourceCreate": "Opprett ressurs",
"resourceCreateDescription": "Følg trinnene nedenfor for å opprette en ny ressurs",
"resourceCreateGeneralDescription": "Konfigurer de grunnleggende ressursinnstillingene inkludert navnet og typen",
"resourceSeeAll": "Se alle ressurser",
"resourceInfo": "Ressursinformasjon",
"resourceCreateGeneral": "Generelt",
"resourceNameDescription": "Dette er visningsnavnet for ressursen.",
"siteSelect": "Velg område",
"siteSearch": "Søk i område",
@@ -231,12 +261,15 @@
"noCountryFound": "Ingen land funnet.",
"siteSelectionDescription": "Dette området vil gi tilkobling til mål.",
"resourceType": "Ressurstype",
"resourceTypeDescription": "Bestemme hvordan denne ressursen skal brukes",
"resourceTypeDescription": "Dette kontrollerer ressursprotokollen og hvordan den vil vises i nettleseren. Dette kan ikke endres senere.",
"resourceDomainDescription": "Ressursen vil bli servert på dette fullstendig kvalifiserte domenenavnet.",
"resourceHTTPSSettings": "HTTPS-innstillinger",
"resourceHTTPSSettingsDescription": "Konfigurer hvordan ressursen skal nås over HTTPS",
"resourcePortDescription": "Den eksterne porten på Pangolin-instansen eller noden der ressursen vil være tilgjengelig.",
"domainType": "Domenetype",
"subdomain": "Underdomene",
"baseDomain": "Grunndomene",
"configure": "Konfigurer",
"subdomnainDescription": "Underdomenet hvor ressursen vil være tilgjengelig.",
"resourceRawSettings": "TCP/UDP-innstillinger",
"resourceRawSettingsDescription": "Konfigurer hvordan ressursen vil bli tilgjengelig over TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Lær hvordan å konfigurere TCP/UDP-ressurser",
"resourceBack": "Tilbake til ressurser",
"resourceGoTo": "Gå til ressurs",
"resourcePolicyDelete": "Slett Ressurspolitikk",
"resourcePolicyDeleteConfirm": "Bekreft sletting av ressurspolitikk",
"resourceDelete": "Slett ressurs",
"resourceDeleteConfirm": "Bekreft sletting av ressurs",
"labelDelete": "Slett etikett",
"labelAdd": "Legg til etikett",
"labelCreateSuccessMessage": "Etikett opprettet vellykket",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etikett endret vellykket",
"labelNameField": "Etikettnavn",
"labelColorField": "Etikettfarge",
"labelPlaceholder": "Eksempel: homelab",
"labelCreate": "Opprett etikett",
"createLabelDialogTitle": "Opprett etikett",
"createLabelDialogDescription": "Opprett en ny etikett som kan knyttes til denne organisasjonen",
"labelEdit": "Rediger etikett",
"editLabelDialogTitle": "Oppdater etikett",
"editLabelDialogDescription": "Rediger en ny etikett som kan knyttes til denne organisasjonen",
"labelDeleteConfirm": "Bekreft sletting av etikett",
"labelErrorDelete": "Kunne ikke slette etikett",
"labelMessageRemove": "Denne handlingen er permanent. Alle steder, ressurser, og klienter tagget med denne etiketten vil bli umerket.",
"labelQuestionRemove": "Er du sikker på at du vil fjerne etiketten fra organisasjonen?",
"visibility": "Synlighet",
"enabled": "Aktivert",
"disabled": "Deaktivert",
@@ -265,6 +319,8 @@
"rules": "Regler",
"resourceSettingDescription": "Konfigurere innstillingene på ressursen",
"resourceSetting": "{resourceName} Innstillinger",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} Innstillinger",
"alwaysAllow": "Omgå Auth",
"alwaysDeny": "Blokker tilgang",
"passToAuth": "Pass til Autentisering",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Duplisert regel",
"rulesErrorDuplicateDescription": "En regel med disse innstillingene finnes allerede",
"rulesErrorInvalidIpAddressRange": "Ugyldig CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Vennligst skriv inn en gyldig CIDR-verdi",
"rulesErrorInvalidUrl": "Ugyldig URL-sti",
"rulesErrorInvalidUrlDescription": "Skriv inn en gyldig verdi for URL-sti",
"rulesErrorInvalidIpAddress": "Ugyldig IP",
"rulesErrorInvalidIpAddressDescription": "Skriv inn en gyldig IP-adresse",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Kunne ikke oppdatere regler",
"rulesErrorUpdateDescription": "Det oppsto en feil under oppdatering av regler",
"rulesUpdated": "Aktiver Regler",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Angi en adresse i CIDR-format (f.eks., 103.21.244.0/22)",
"rulesMatchIpAddress": "Angi en IP-adresse (f.eks. 103.21.244.12)",
"rulesMatchUrl": "Skriv inn en URL-sti eller et mønster (f.eks. /api/v1/todos eller /api/v1/*)",
"rulesErrorInvalidPriority": "Ugyldig prioritet",
"rulesErrorInvalidPriorityDescription": "Vennligst skriv inn en gyldig prioritet",
"rulesErrorDuplicatePriority": "Dupliserte prioriteringer",
"rulesErrorDuplicatePriorityDescription": "Vennligst angi unike prioriteringer",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Regler oppdatert",
"ruleUpdatedDescription": "Reglene er oppdatert",
"ruleErrorUpdate": "Operasjon mislyktes",
"ruleErrorUpdateDescription": "En feil oppsto under lagringsoperasjonen",
"rulesPriority": "Prioritet",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Handling",
"rulesMatchType": "Trefftype",
"value": "Verdi",
@@ -744,9 +809,60 @@
"rulesResource": "Konfigurasjon av ressursregler",
"rulesResourceDescription": "Konfigurer regler for å kontrollere tilgang til ressursen",
"ruleSubmit": "Legg til regel",
"rulesNoOne": "Ingen regler. Legg til en regel ved å bruke skjemaet.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Regler evalueres etter prioritet i stigende rekkefølge.",
"rulesSubmit": "Lagre regler",
"policyErrorCreate": "Feil ved opprettelse av policy",
"policyErrorCreateDescription": "Det oppstod en feil under opprettelse av policyen",
"policyErrorCreateMessageDescription": "En uventet feil oppstod",
"policyErrorUpdate": "Feil ved oppdatering av policy",
"policyErrorUpdateDescription": "Det oppstod en feil ved oppdatering av policyen",
"policyErrorUpdateMessageDescription": "En uventet feil oppstod",
"policyCreatedSuccess": "Ressurspolitikken ble opprettet vellykket",
"policyUpdatedSuccess": "Ressurspolitikken ble oppdatert vellykket",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Lagre Regler",
"resourceErrorCreate": "Feil under oppretting av ressurs",
"resourceErrorCreateDescription": "Det oppstod en feil under oppretting av ressursen",
"resourceErrorCreateMessage": "Feil ved oppretting av ressurs:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "En feil oppstod under oppdatering av ressursen",
"access": "Tilgang",
"accessControl": "Tilgangskontroll",
"shareLink": "{resource} Del Lenke",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Velg ressurs",
"shareLinks": "Del lenker",
"shareLinks": "Shareable Links",
"share": "Delbare lenker",
"shareDescription2": "Opprett delbare lenker til ressurser. Lenker gir midlertidig eller ubegrenset tilgang til din ressurs. Du kan konfigurere utløpsvarigheten på lenken når du oppretter en.",
"shareEasyCreate": "Enkelt å lage og dele",
@@ -810,6 +926,17 @@
"pincodeAdd": "Legg til PIN-kode",
"pincodeRemove": "Fjern PIN-kode",
"resourceAuthMethods": "Autentiseringsmetoder",
"resourcePolicyAuthMethodsEmpty": "Ingen autentiseringsmetode",
"resourcePolicyOtpEmpty": "Ingen engangspassord",
"resourcePolicyReadOnly": "Denne policyen er kun lesbar",
"resourcePolicyReadOnlyDescription": "Denne ressursreglen deles på tvers av flere ressurser, du kan ikke redigere den på denne siden.",
"editSharedPolicy": "Rediger Delte Rekvireringer",
"resourcePolicyTypeSave": "Lagre Ressurstype",
"resourcePolicySelect": "Velg ressurspolitikk",
"resourcePolicySelectError": "Velg en ressursregel",
"resourcePolicyNotFound": "Policy ikke funnet",
"resourcePolicySearch": "Søk etter regler",
"resourcePolicyRulesEmpty": "Ingen autentiseringsregler",
"resourceAuthMethodsDescriptions": "Tillat tilgang til ressursen via ytterligere autentiseringsmetoder",
"resourceAuthSettingsSave": "Lagret vellykket",
"resourceAuthSettingsSaveDescription": "Autentiseringsinnstillinger er lagret",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Angi PIN-kode",
"resourcePincodeSetupTitleDescription": "Sett en pinkode for å beskytte denne ressursen",
"resourceRoleDescription": "Administratorer har alltid tilgang til denne ressursen.",
"resourcePolicySelectTitle": "Ressurstilgangspolitikk",
"resourcePolicySelectDescription": "Velg policytype for autentisering",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Inline Ressursregler",
"resourcePolicyInlineDescription": "Tilgangspolitikk som kun er gyldig for denne ressursen",
"resourcePolicyShared": "Delte Ressursregler",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Tilgangskontroller",
"resourceUsersRolesDescription": "Konfigurer hvilke brukere og roller som har tilgang til denne ressursen",
"resourceUsersRolesSubmit": "Lagre tilgangskontroller",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Det oppstod et problem med å koble til {name}. Vennligst kontakt din administrator.",
"idpErrorNotFound": "IdP ikke funnet",
"inviteInvalid": "Ugyldig invitasjon",
"labels": "Etiketter",
"orgLabelsDescription": "Administrer etiketter i denne organisasjonen.",
"addLabels": "Legg til etiketter",
"siteLabelsTab": "Etiketter",
"siteLabelsDescription": "Administrer etiketter knyttet til dette nettstedet.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Søk etter etiketter",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {en etikett} other {# etiketter}}",
"labelOverflowCount": "+{count, plural, one {en etikett} other {# etiketter}}",
"accessLabelFilterClear": "Fjern etikettfiltre",
"accessFilterClear": "Clear filters",
"selectColor": "Velg farge",
"createNewLabel": "Opprett ny org-etikett \"{label}\"",
"inviteInvalidDescription": "Invitasjonslenken er ugyldig.",
"inviteErrorWrongUser": "Invitasjonen er ikke for denne brukeren",
"inviteErrorUserNotExists": "Brukeren eksisterer ikke. Vennligst opprett en konto først.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Ressurser",
"sidebarProxyResources": "Offentlig",
"sidebarClientResources": "Privat",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Tilgangskontroll",
"sidebarLogsAndAnalytics": "Logger og analyser",
"sidebarTeam": "Lag",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Administrator",
"sidebarInvitations": "Invitasjoner",
"sidebarRoles": "Roller",
"sidebarShareableLinks": "Lenker",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API-nøkler",
"sidebarProvisioning": "Levering",
"sidebarSettings": "Innstillinger",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Område {id}",
"standaloneHcFilterResourceIdFallback": "Ressurs {id}",
"blueprints": "Tegninger",
"blueprintsDescription": "Bruk deklarative konfigurasjoner og vis tidligere kjøringer",
"blueprintsLog": "Blåkopieringslogg",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Legg til blåkopi",
"blueprintGoBack": "Se alle blåkopier",
"blueprintCreate": "Opprette mal",
@@ -1575,7 +1732,17 @@
"contents": "Innhold",
"parsedContents": "Parastinnhold (kun lese)",
"enableDockerSocket": "Aktiver Docker blåkopi",
"enableDockerSocketDescription": "Aktiver skraping av Docker Socket for blueprint Etiketter. Socket bane må brukes for nye.",
"enableDockerSocketDescription": "Aktiver Docker Socket etikett skrubbing for blueprint etiketter. Socket bane må oppgis til nettstedkobleren. Les om hvordan dette fungerer i <docsLink>dokumentasjonen</docsLink>.",
"newtAutoUpdate": "Aktiver Automatisk Oppdatering av Nettsted",
"newtAutoUpdateDescription": "Når aktivert, vil nettstedskoblere automatisk oppdatere til nyeste versjon når en ny utgave er tilgjengelig.",
"siteAutoUpdate": "Automatisk Oppdatering av Nettsted",
"siteAutoUpdateLabel": "Aktiver Automatisk Oppdatering",
"siteAutoUpdateDescription": "Kontroller om denne sidens kobler automatisk laster ned den nyeste versjonen.",
"siteAutoUpdateOrgDefault": "Organisasjon standard: {state}",
"siteAutoUpdateOverriding": "Overstyrer organisasjonens innstilling",
"siteAutoUpdateResetToOrg": "Tilbakestill til Organisasjonsstandard",
"siteAutoUpdateEnabled": "aktivert",
"siteAutoUpdateDisabled": "deaktivert",
"viewDockerContainers": "Vis Docker-containere",
"containersIn": "Containere i {siteName}",
"selectContainerDescription": "Velg en hvilken som helst container for å bruke som vertsnavn for dette målet. Klikk på en port for å bruke en port.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Sertifikat",
"certificateStatusAutoRefreshHint": "Status oppdateres automatisk.",
"loading": "Laster inn",
"loadingEllipsis": "Laster inn...",
"loadingAnalytics": "Laster inn analyser",
"restart": "Start på nytt",
"domains": "Domener",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Administrer abonnementet for betalte lisensnøkler selv hostet",
"billingCurrentKeys": "Nåværende nøkler",
"billingModifyCurrentPlan": "Endre gjeldende plan",
"billingManageLicenseSubscriptionDescription": "Administrer ditt abonnement for betalte egenvertslisensnøkler og last ned fakturaer.",
"billingConfirmUpgrade": "Bekreft oppgradering",
"billingConfirmDowngrade": "Bekreft nedgradering",
"billingConfirmUpgradeDescription": "Du er i ferd med å oppgradere abonnementet ditt. Gå gjennom de nye grensene og pris nedenfor.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Ukjent",
"healthCheck": "Helsekontroll",
"configureHealthCheck": "Konfigurer Helsekontroll",
"configureHealthCheckDescription": "Sett opp helsekontroll for {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Aktiver Helsekontroller",
"healthCheckDisabledStateDescription": "Når deaktivert, vil ikke nettstedet utføre helsekontroller, og tilstanden vil anses som ukjent.",
"enableHealthChecksDescription": "Overvåk helsen til dette målet. Du kan overvåke et annet endepunkt enn målet hvis nødvendig.",
"healthScheme": "Metode",
"healthSelectScheme": "Velg metode",
"healthCheckPortInvalid": "Helsekontrollporten må være mellom 1 og 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Sti",
"healthHostname": "IP / Vert",
"healthPort": "Port",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Tid er i sekunder",
"requireDeviceApproval": "Krev enhetsgodkjenning",
"requireDeviceApprovalDescription": "Brukere med denne rollen trenger nye enheter godkjent av en admin før de kan koble seg og få tilgang til ressurser.",
"sshAccess": "SSH tilgang",
"sshSettings": "SSH Innstillinger",
"sshAccess": "SSH Access",
"rdpSettings": "RDP Innstillinger",
"vncSettings": "VNC Innstillinger",
"sshServer": "SSH-server",
"rdpServer": "RDP-server",
"vncServer": "VNC-server",
"sshServerDescription": "Sett opp autentiseringsmetoden, daemonplasseringen, og serverens destinasjon",
"rdpServerDescription": "Konfigurer destinasjonen og porten til RDP-serveren",
"vncServerDescription": "Konfigurer destinasjonen og porten til VNC-serveren",
"sshServerMode": "Modus",
"sshServerModeStandard": "Standard SSH-server",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Ruter kommandoer over nettverk til en SSH-server som OpenSSH.",
"sshServerModeNative": "Innfødt SSH Server",
"sshServerModeNativeDescription": "Utfører kommandoer direkte på verten via Nettsted-kobleren. Ingen nettverkskonfigurasjon kreves.",
"sshAuthenticationMethod": "Autentiseringsmetode",
"sshAuthMethodManual": "Manuell Autentisering",
"sshAuthMethodManualDescription": "Krever eksisterende vertlegitimasjon. Omgår automatisk klargjøring.",
"sshAuthMethodAutomated": "Automatisk Klargjøring",
"sshAuthMethodAutomatedDescription": "Oppretter automatisk brukere, grupper og sudo-tillatelser på verten.",
"sshAuthDaemonLocation": "Autentisering Daemon-plassering",
"sshDaemonLocationSiteDescription": "Utføres lokalt på maskinen som er vert for nettstedkobleren.",
"sshDaemonLocationRemote": "På Ekstern Vert",
"sshDaemonLocationRemoteDescription": "Utføres på en separat målenhet på samme nettverk.",
"sshDaemonDisclaimer": "Sørg for at målenheten din er riktig konfigurert for å kjøre autentiseringsdaemon før du fullfører denne oppsettet, eller klargjøring vil mislykkes.",
"sshDaemonPort": "Daemon-port",
"sshServerDestination": "Serverens Destinasjon",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Destinasjon",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Ved å velge flere nettsteder aktiveres robust ruting og feilaktig avbrudd for høy tilgjengelighet.",
"roleAllowSsh": "Tillat SSH",
"roleAllowSshAllow": "Tillat",
"roleAllowSshDisallow": "Forby",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Brukeren kan bare kjøre de angitte kommandoene med sudo.",
"sshSudo": "Tillat sudo",
"sshSudoCommands": "Sudo kommandoer",
"sshSudoCommandsDescription": "Kommaseparert liste med kommandoer brukeren kan kjøre med sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Opprett hjemmappe",
"sshUnixGroups": "Unix grupper",
"sshUnixGroupsDescription": "Kommaseparerte Unix grupper for å legge brukeren til på mål-verten.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Forsøk på nytt",
"expectedResponseCodes": "Forventede svarkoder",
"expectedResponseCodesDescription": "HTTP-statuskode som indikerer sunn status. Hvis den blir stående tom, regnes 200-300 som sunn.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Skjema",
"editInternalResourceDialogEnableSsl": "Aktiver TLS",
"editInternalResourceDialogEnableSslDescription": "Aktiver SSL/TLS-kryptering for sikre HTTPS-tilkoblinger til destinasjonen.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Skjema",
"createInternalResourceDialogScheme": "Skjema",
"createInternalResourceDialogEnableSsl": "Aktiver TLS",
@@ -2233,7 +2454,7 @@
"description": "Sikre og lavvedlikeholdsservere, selvbetjente Pangolin med ekstra klokker, og understell",
"introTitle": "Administrert Self-Hosted Pangolin",
"introDescription": "er et alternativ for bruk utviklet for personer som ønsker enkel og ekstra pålitelighet mens de fortsatt holder sine data privat og selvdrevne.",
"introDetail": "Med dette valget kjører du fortsatt din egen Pangolin-node - tunneler, TLS-terminering og trafikken ligger på serveren din. Forskjellen er at behandling og overvåking håndteres gjennom vårt skydashbord, som låser opp en rekke fordeler:",
"introDetail": "Med dette valget kjører du fortsatt din egen Pangolin-node - tunneler, TLS-terminering, og trafikken ligger på serveren din. Forskjellen er at behandling og overvåking håndteres gjennom vårt sky-dashbord, som låser opp en rekke fordeler:",
"benefitSimplerOperations": {
"title": "Enklere operasjoner",
"description": "Ingen grunn til å kjøre din egen e-postserver eller sette opp kompleks varsling. Du vil få helsesjekk og nedetid varsler ut av boksen."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Skriv inn bekreftelse",
"blueprintViewDetails": "Detaljer",
"defaultIdentityProvider": "Standard identitetsleverandør",
"defaultIdentityProviderDescription": "Når en standard identitetsleverandør er valgt, vil brukeren automatisk bli omdirigert til leverandøren for autentisering.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Nettverksinnstillinger",
"editInternalResourceDialogAccessPolicy": "Tilgangsregler for tilgang",
"editInternalResourceDialogAddRoles": "Legg til roller",
@@ -2937,11 +3158,12 @@
"learnMore": "Lær mer",
"backToHome": "Gå tilbake til start",
"needToSignInToOrg": "Trenger du å bruke organisasjonens identitetsleverandør?",
"maintenanceMode": "Vedlikeholdsmodus",
"maintenanceMode": "Vedlikeholdsside",
"maintenanceModeDescription": "Vis en vedlikeholdsside til besøkende",
"maintenanceModeType": "Vedlikeholdsmodus type",
"showMaintenancePage": "Vis en vedlikeholdsside til besøkende",
"enableMaintenanceMode": "Aktiver vedlikeholdsmodus",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatisk",
"automaticModeDescription": "Vis vedlikeholdsside kun når alle serverens mål er nede eller usunne. Ressursen din fortsetter å fungere normalt så lenge minst ett mål er sunt.",
"forced": "Tvunget",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Estimert ferdigstillelse:",
"createInternalResourceDialogDestinationRequired": "Destinasjonen er nødvendig",
"available": "Tilgjengelig",
"disabledResourceDescription": "Når deaktivert, vil ressursen være utilgjengelig for alle.",
"archived": "Arkivert",
"noArchivedDevices": "Ingen arkiverte enheter funnet",
"deviceArchived": "Enhet arkivert",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Er du sikker på at du vil frakoble denne identitetsleverandøren fra denne organisasjonen?",
"idpUnassociateDescription": "Alle brukere knyttet til denne identitetsleverandøren vil bli fjernet fra denne organisasjonen, men identitetsleverandøren vil fortsatt eksistere for andre tilknyttede organisasjoner.",
"idpUnassociateConfirm": "Bekreft frakobling av identitetsleverandør",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Dette kan ikke angres for denne organisasjonen.",
"idpUnassociatedDescription": "Identitetsleverandør er vellykket frakoblet fra denne organisasjonen",
"idpUnassociateMenu": "Frakoble",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Ressurs deaktivert",
"memberPortalShowingResources": "Viser {start}-{end} av {total} ressurser",
"memberPortalPrevious": "Forrige",
"memberPortalNext": "Neste"
"memberPortalNext": "Neste",
"httpSettings": "HTTP Innstillinger",
"tcpSettings": "TCP Innstillinger",
"udpSettings": "UDP Innstillinger",
"sshTitle": "SSH",
"sshConnectingDescription": "Opprette en sikker tilkobling…",
"sshConnecting": "Kobler til…",
"sshInitializing": "Initialiserer…",
"sshSignInTitle": "Logg inn på SSH",
"sshSignInDescription": "Oppgi dine SSH-legitimasjoner",
"sshPasswordTab": "Passord",
"sshPrivateKeyTab": "Privat Nøkkel",
"sshPrivateKeyField": "Privat Nøkkel",
"sshPrivateKeyDisclaimer": "Din private nøkkel er ikke lagret eller synlig for Pangolin. Alternativt kan du bruke kortevaliderte sertifikater for sømløs autentisering ved å bruke din eksisterende Pangolin-identitet.",
"sshLearnMore": "Lær mer",
"sshPrivateKeyFile": "Privat Nøkkelfil",
"sshAuthenticate": "Autentiser",
"sshTerminate": "Avslutt",
"sshPoweredBy": "Drevet av",
"sshErrorNoTarget": "Ingen mål spesifisert",
"sshErrorWebSocket": "WebSocket-tilkobling mislyktes",
"sshErrorAuthFailed": "Autentisering mislyktes",
"sshErrorConnectionClosed": "Tilkobling avsluttet før autentisering ble fullført",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Privébronnen bekijken",
"siteInstallNewt": "Installeer Newt",
"siteInstallNewtDescription": "Laat Newt draaien op uw systeem",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard Configuratie",
"WgConfigurationDescription": "Gebruik de volgende configuratie om verbinding te maken met het netwerk",
"operatingSystem": "Operating systeem",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Je kunt dit slechts één keer zien. Kopieer het naar een beveiligde plek.",
"siteInfo": "Site informatie",
"status": "Status",
"shareTitle": "Beheer deellinks",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Maak deelbare links aan om tijdelijke of permanente toegang tot proxybronnen te verlenen",
"shareSearch": "Zoek share links...",
"shareCreate": "Maak Share link",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Kan link niet verwijderen",
"shareErrorDeleteMessage": "Fout opgetreden tijdens het verwijderen link",
"shareDeleted": "Link verwijderd",
"shareDeletedDescription": "De link is verwijderd",
"shareDelete": "Verwijder Deel Link",
"shareDeleteConfirm": "Bevestig verwijdering van Deel Link",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Weet u zeker dat u deze deel link wilt verwijderen?",
"shareMessageRemove": "Zodra verwijderd, zal de link niet meer werken en zal iedereen die het gebruikt de toegang tot de bron verliezen.",
"shareTokenDescription": "De toegangstoken kan op twee manieren worden doorgegeven: als queryparameter of in de aanvraagheaders. Deze moeten worden doorgegeven van de client op elk verzoek voor geverifieerde toegang.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Fout opgetreden tijdens het maken van de share link",
"shareCreateDescription": "Iedereen met deze link heeft toegang tot de pagina",
"shareTitleOptional": "Titel (optioneel)",
"sharePathOptional": "Pad (optioneel)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Vervalt in",
"neverExpire": "Nooit verlopen",
"shareExpireDescription": "Vervaltijd is hoe lang de link bruikbaar is en geeft toegang tot de bron. Na deze tijd zal de link niet meer werken en zullen gebruikers die deze link hebben gebruikt de toegang tot de pagina verliezen.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Selecteer een bron",
"proxyResourceTitle": "Openbare bronnen beheren",
"proxyResourceDescription": "Creëer en beheer bronnen die openbaar toegankelijk zijn via een webbrowser",
"proxyResourcesBannerTitle": "Webgebaseerde openbare toegang",
"proxyResourcesBannerDescription": "Openbare bronnen zijn HTTPS of TCP/UDP-proxies die toegankelijk zijn voor iedereen op het internet via een webbrowser. In tegenstelling tot priv<69><76>bronnen vereisen ze geen client-side software maar kunnen ze identiteits- en context-bewuste toegangsrichtlijnen bevatten.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Privébronnen beheren",
"clientResourceDescription": "Creëer en beheer bronnen die alleen toegankelijk zijn via een verbonden client",
"privateResourcesBannerTitle": "Zero-Trust Private Access",
@@ -208,11 +212,36 @@
"resourcesSearch": "Zoek bronnen...",
"resourceAdd": "Bron toevoegen",
"resourceErrorDelte": "Fout bij verwijderen document",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} bron(nen)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "geen bronnen",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Beleidsregels zoeken...",
"resourcePoliciesAdd": "Beleid toevoegen",
"resourcePoliciesDefaultBadgeText": "Standaard beleidsregel",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Volg de onderstaande stappen om een nieuw beleid aan te maken",
"resourcePolicyName": "Beleidsregelnaam",
"resourcePolicyNameDescription": "Geef deze beleidsregel een naam om deze te identificeren in uw bronnen",
"resourcePolicyNamePlaceholder": "bijv. Intern Toegangsbeleid",
"resourcePoliciesSeeAll": "Zie Alle Beleid",
"resourcePolicyAuthMethodAdd": "Authenticatiemethode toevoegen",
"resourcePolicyOtpEmailAdd": "OTP e-mails toevoegen",
"resourcePolicyRulesAdd": "Regels toevoegen",
"resourcePolicyAuthMethodsDescription": "Sta toegang tot bronnen toe via aanvullende authenticatiemethoden",
"resourcePolicyUsersRolesDescription": "Bepaal welke gebruikers en rollen geassocieerde bronnen kunnen bezoeken",
"rulesResourcePolicyDescription": "Stel regels in om toegang te regelen tot bronnen die zijn gekoppeld aan dit beleid",
"authentication": "Authenticatie",
"protected": "Beschermd",
"notProtected": "Niet beveiligd",
"resourceMessageRemove": "Eenmaal verwijderd, zal het bestand niet langer toegankelijk zijn. Alle doelen die gekoppeld zijn aan het hulpbron, zullen ook verwijderd worden.",
"resourceQuestionRemove": "Weet u zeker dat u het document van de organisatie wilt verwijderen?",
"resourcePolicyMessageRemove": "Zodra verwijderd, zal het bronbeleid niet langer toegankelijk zijn. Alle met de bron geassocieerde bronnen worden ontkoppeld en zonder authenticatie achtergelaten.",
"resourcePolicyQuestionRemove": "Weet u zeker dat u het bronbeleid uit de organisatie wilt verwijderen?",
"resourceHTTP": "HTTPS bron",
"resourceHTTPDescription": "Proxyverzoeken via HTTPS met een volledig gekwalificeerde domeinnaam.",
"resourceRaw": "TCP/UDP bron",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy verzoeken over rauwe TCP/UDP met behulp van een poortnummer. Vereist sites om verbinding te maken met een remote node.",
"resourceCreate": "Bron maken",
"resourceCreateDescription": "Volg de onderstaande stappen om een nieuwe bron te maken",
"resourceCreateGeneralDescription": "Configureer de basisinstellingen van de bron, inclusief de naam en het type",
"resourceSeeAll": "Alle bronnen bekijken",
"resourceInfo": "Bron informatie",
"resourceCreateGeneral": "Algemeen",
"resourceNameDescription": "Dit is de weergavenaam voor het document.",
"siteSelect": "Selecteer site",
"siteSearch": "Zoek site",
@@ -231,12 +261,15 @@
"noCountryFound": "Geen land gevonden.",
"siteSelectionDescription": "Deze site zal connectiviteit met het doelwit bieden.",
"resourceType": "Type bron",
"resourceTypeDescription": "Bepaal hoe u toegang wilt tot de bron",
"resourceTypeDescription": "Dit bepaalt het bronprotocol en hoe het in de browser wordt weergegeven. Dit kan later niet gewijzigd worden.",
"resourceDomainDescription": "De bron zal worden bediend onder deze volledig gekwalificeerde domeinnaam.",
"resourceHTTPSSettings": "HTTPS instellingen",
"resourceHTTPSSettingsDescription": "Stel in hoe de bron wordt benaderd via HTTPS",
"resourcePortDescription": "De externe poort op de Pangolin-instantie of -node waar de bron toegankelijk zal zijn.",
"domainType": "Domein type",
"subdomain": "Subdomein",
"baseDomain": "Basis domein",
"configure": "Configureren",
"subdomnainDescription": "Het subdomein waar de bron toegankelijk zal zijn.",
"resourceRawSettings": "TCP/UDP instellingen",
"resourceRawSettingsDescription": "Stel in hoe de bron wordt benaderd via TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Leer hoe je TCP/UDP bronnen kunt configureren",
"resourceBack": "Terug naar bronnen",
"resourceGoTo": "Ga naar Resource",
"resourcePolicyDelete": "Verwijder Bronbeleid",
"resourcePolicyDeleteConfirm": "Bevestig Verwijderen Bronbeleid",
"resourceDelete": "Document verwijderen",
"resourceDeleteConfirm": "Bevestig Verwijderen Document",
"labelDelete": "Label verwijderen",
"labelAdd": "Label toevoegen",
"labelCreateSuccessMessage": "Label succesvol aangemaakt",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Label succesvol gewijzigd",
"labelNameField": "Labelnaam",
"labelColorField": "Label kleur",
"labelPlaceholder": "Bijv.: homelab",
"labelCreate": "Label aanmaken",
"createLabelDialogTitle": "Label aanmaken",
"createLabelDialogDescription": "Maak een nieuw label aan dat aan deze organisatie kan worden gekoppeld",
"labelEdit": "Label bewerken",
"editLabelDialogTitle": "Label bijwerken",
"editLabelDialogDescription": "Bewerk een nieuw label dat aan deze organisatie kan worden gekoppeld",
"labelDeleteConfirm": "Bevestigen Verwijderen Label",
"labelErrorDelete": "Kan label niet verwijderen",
"labelMessageRemove": "Deze handeling is definitief. Alle sites, bronnen en klanten met dit label zullen worden onttakeld.",
"labelQuestionRemove": "Weet u zeker dat u het label uit de organisatie wilt verwijderen?",
"visibility": "Zichtbaarheid",
"enabled": "Ingeschakeld",
"disabled": "Uitgeschakeld",
@@ -265,6 +319,8 @@
"rules": "Regels",
"resourceSettingDescription": "Configureer de instellingen in de bron",
"resourceSetting": "{resourceName} instellingen",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} instellingen",
"alwaysAllow": "Authenticatie omzeilen",
"alwaysDeny": "Blokkeer toegang",
"passToAuth": "Passeren naar Auth",
@@ -630,7 +686,7 @@
"createdAt": "Aangemaakt op",
"proxyErrorInvalidHeader": "Ongeldige aangepaste Header waarde. Gebruik het domeinnaam formaat, of sla leeg op om de aangepaste Host header ongedaan te maken.",
"proxyErrorTls": "Ongeldige TLS servernaam. Gebruik de domeinnaam of sla leeg op om de TLS servernaam te verwijderen.",
"proxyEnableSSL": "TLS inschakelen",
"proxyEnableSSL": "Schakel TLS in",
"proxyEnableSSLDescription": "SSL/TLS-versleuteling inschakelen voor beveiligde HTTPS-verbindingen naar de doelen.",
"target": "Target",
"configureTarget": "Doelstellingen configureren",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Dupliceer regel",
"rulesErrorDuplicateDescription": "Een regel met deze instellingen bestaat al",
"rulesErrorInvalidIpAddressRange": "Ongeldige CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Voer een geldige CIDR waarde in",
"rulesErrorInvalidUrl": "Ongeldige URL pad",
"rulesErrorInvalidUrlDescription": "Voer een geldige URL padwaarde in",
"rulesErrorInvalidIpAddress": "Ongeldig IP",
"rulesErrorInvalidIpAddressDescription": "Voer een geldig IP-adres in",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Regels bijwerken mislukt",
"rulesErrorUpdateDescription": "Fout opgetreden tijdens het bijwerken van de regels",
"rulesUpdated": "Regels inschakelen",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Voer een adres in in het CIDR-formaat (bijv. 103.21.244.0/22)",
"rulesMatchIpAddress": "Voer een IP-adres in (bijv. 103.21.244.12)",
"rulesMatchUrl": "Voer een URL-pad of patroon in (bijv. /api/v1/todos of /api/v1/*)",
"rulesErrorInvalidPriority": "Ongeldige prioriteit",
"rulesErrorInvalidPriorityDescription": "Voer een geldige prioriteit in",
"rulesErrorDuplicatePriority": "Dubbele prioriteiten",
"rulesErrorDuplicatePriorityDescription": "Voer unieke prioriteiten in",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Regels bijgewerkt",
"ruleUpdatedDescription": "Regels met succes bijgewerkt",
"ruleErrorUpdate": "Bewerking mislukt",
"ruleErrorUpdateDescription": "Er is een fout opgetreden tijdens het opslaan",
"rulesPriority": "Prioriteit",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "actie",
"rulesMatchType": "Wedstrijd Type",
"value": "Waarde",
@@ -744,9 +809,60 @@
"rulesResource": "Configuratie Resource Regels",
"rulesResourceDescription": "Regels instellen om toegang tot de bron te beheren",
"ruleSubmit": "Regel toevoegen",
"rulesNoOne": "Geen regels. Voeg een regel toe via het formulier.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Regels worden in oplopende volgorde volgens prioriteit beoordeeld.",
"rulesSubmit": "Regels opslaan",
"policyErrorCreate": "Fout bij het maken van beleid",
"policyErrorCreateDescription": "Er is een fout opgetreden bij het maken van het beleid",
"policyErrorCreateMessageDescription": "Er is een onverwachte fout opgetreden",
"policyErrorUpdate": "Fout bij het bijwerken van beleid",
"policyErrorUpdateDescription": "Er is een fout opgetreden bij het bijwerken van het beleid",
"policyErrorUpdateMessageDescription": "Er is een onverwachte fout opgetreden",
"policyCreatedSuccess": "Bronbeleid met succes aangemaakt",
"policyUpdatedSuccess": "Bronbeleid succesvol bijgewerkt",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Regels opslaan",
"resourceErrorCreate": "Fout bij maken document",
"resourceErrorCreateDescription": "Er is een fout opgetreden bij het maken van het document",
"resourceErrorCreateMessage": "Fout bij maken bron:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Er is een fout opgetreden tijdens het bijwerken van het document",
"access": "Toegangsrechten",
"accessControl": "Toegangs controle",
"shareLink": "{resource} Share link",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Selecteer resource",
"shareLinks": "Links delen",
"shareLinks": "Shareable Links",
"share": "Deelbare links",
"shareDescription2": "Maak deelbare links naar bronnen. Links bieden tijdelijke of onbeperkte toegang tot je bestand. U kunt de vervalduur van de link configureren wanneer u er een aanmaakt.",
"shareEasyCreate": "Makkelijk te maken en te delen",
@@ -810,6 +926,17 @@
"pincodeAdd": "PIN-code toevoegen",
"pincodeRemove": "PIN-code verwijderen",
"resourceAuthMethods": "Authenticatie methoden",
"resourcePolicyAuthMethodsEmpty": "Geen authenticatiemethode",
"resourcePolicyOtpEmpty": "Geen eenmalig wachtwoord",
"resourcePolicyReadOnly": "Dit beleid is alleen-lezen",
"resourcePolicyReadOnlyDescription": "Dit bronbeleid wordt gedeeld over meerdere bronnen, u kunt het niet op deze pagina bewerken.",
"editSharedPolicy": "Gedeeld Beleid Bewerken",
"resourcePolicyTypeSave": "Bewaar brontype",
"resourcePolicySelect": "Selecteer bronbeleid",
"resourcePolicySelectError": "Selecteer een bronbeleid",
"resourcePolicyNotFound": "Beleid niet gevonden",
"resourcePolicySearch": "Beleidsregels zoeken",
"resourcePolicyRulesEmpty": "Geen authenticatieregels",
"resourceAuthMethodsDescriptions": "Sta toegang tot de bron toe via extra autorisatiemethoden",
"resourceAuthSettingsSave": "Succesvol opgeslagen",
"resourceAuthSettingsSaveDescription": "Verificatie-instellingen zijn opgeslagen",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Pincode instellen",
"resourcePincodeSetupTitleDescription": "Stel een pincode in om deze hulpbron te beschermen",
"resourceRoleDescription": "Beheerders hebben altijd toegang tot deze bron.",
"resourcePolicySelectTitle": "Toegangsbeleid voor bronnen",
"resourcePolicySelectDescription": "Selecteer het bronbeleidstype voor authenticatie",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Inline bronbeleid",
"resourcePolicyInlineDescription": "Toegangsbeleid alleen gericht op deze bron",
"resourcePolicyShared": "Gedeeld bronbeleid",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Toegang Bediening",
"resourceUsersRolesDescription": "Configureer welke gebruikers en rollen deze pagina kunnen bezoeken",
"resourceUsersRolesSubmit": "Bewaar Toegangsbesturing",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Er was een probleem bij het verbinden met {name}. Neem contact op met uw beheerder.",
"idpErrorNotFound": "IdP niet gevonden",
"inviteInvalid": "Ongeldige uitnodiging",
"labels": "Labels",
"orgLabelsDescription": "Beheer labels in deze organisatie.",
"addLabels": "Labels toevoegen",
"siteLabelsTab": "Labels",
"siteLabelsDescription": "Beheer labels geassocieerd met deze site.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Labels zoeken",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# label} other {# labels}}",
"labelOverflowCount": "+{count, plural, one {# label} other {# labels}}",
"accessLabelFilterClear": "Labelfilters wissen",
"accessFilterClear": "Clear filters",
"selectColor": "Kleur selecteren",
"createNewLabel": "Nieuw org-label \"{label}\" aanmaken",
"inviteInvalidDescription": "Uitnodigingslink is ongeldig.",
"inviteErrorWrongUser": "Uitnodiging is niet voor deze gebruiker",
"inviteErrorUserNotExists": "Gebruiker bestaat niet. Maak eerst een account aan.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Bronnen",
"sidebarProxyResources": "Openbaar",
"sidebarClientResources": "Privé",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Toegangs controle",
"sidebarLogsAndAnalytics": "Logs & Analytics",
"sidebarTeam": "Team",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Beheerder",
"sidebarInvitations": "Uitnodigingen",
"sidebarRoles": "Rollen",
"sidebarShareableLinks": "Koppelingen",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API sleutels",
"sidebarProvisioning": "Provisie",
"sidebarSettings": "Instellingen",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Site {id}",
"standaloneHcFilterResourceIdFallback": "Bron {id}",
"blueprints": "Blauwdrukken",
"blueprintsDescription": "Gebruik declaratieve configuraties en bekijk vorige uitvoeringen.",
"blueprintsLog": "Log Blueprints",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Blauwdruk toevoegen",
"blueprintGoBack": "Bekijk alle Blauwdrukken",
"blueprintCreate": "Creëer blauwdruk",
@@ -1575,7 +1732,17 @@
"contents": "Inhoud",
"parsedContents": "Geparseerde inhoud (alleen lezen)",
"enableDockerSocket": "Schakel Docker Blauwdruk in",
"enableDockerSocketDescription": "Schakel Docker Socket label in voor blauwdruk labels. Pad naar Nieuw.",
"enableDockerSocketDescription": "Schakel Docker Socket-label in voor blueprint-labels. Socket-pad moet worden opgegeven aan de siteconnector. Lees meer over hoe dit werkt in <docsLink>de documentatie</docsLink>.",
"newtAutoUpdate": "Automatische site-update inschakelen",
"newtAutoUpdateDescription": "Wanneer ingeschakeld, zullen site-connectors automatisch updaten naar de nieuwste versie wanneer een nieuwe release beschikbaar is.",
"siteAutoUpdate": "Automatische site-update",
"siteAutoUpdateLabel": "Automatische update inschakelen",
"siteAutoUpdateDescription": "Controleer of de siteconnector automatisch de laatste versie downloadt.",
"siteAutoUpdateOrgDefault": "Standaard van organisatie: {state}",
"siteAutoUpdateOverriding": "Overschrijving van organisatiestandaardinstelling",
"siteAutoUpdateResetToOrg": "Terugzetten naar standaard van organisatie",
"siteAutoUpdateEnabled": "ingeschakeld",
"siteAutoUpdateDisabled": "uitgeschakeld",
"viewDockerContainers": "Bekijk Docker containers",
"containersIn": "Containers in {siteName}",
"selectContainerDescription": "Selecteer een container om als hostnaam voor dit doel te gebruiken. Klik op een poort om een poort te gebruiken.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certificaat",
"certificateStatusAutoRefreshHint": "Status ververst automatisch.",
"loading": "Bezig met laden",
"loadingEllipsis": "Bezig met laden...",
"loadingAnalytics": "Laden van Analytics",
"restart": "Herstarten",
"domains": "Domeinen",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Beheer je abonnement voor betaalde zelf gehoste licentiesleutels",
"billingCurrentKeys": "Huidige toetsen",
"billingModifyCurrentPlan": "Huidig plan wijzigen",
"billingManageLicenseSubscriptionDescription": "Beheer uw abonnement voor betaalde zelf-gehoste licentiesleutels en download facturen.",
"billingConfirmUpgrade": "Bevestig Upgrade",
"billingConfirmDowngrade": "Downgraden bevestigen",
"billingConfirmUpgradeDescription": "U staat op het punt uw abonnement te upgraden. Controleer de nieuwe limieten en prijzen hieronder.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Onbekend",
"healthCheck": "Gezondheidscontrole",
"configureHealthCheck": "Configureer Gezondheidscontrole",
"configureHealthCheckDescription": "Stel gezondheid monitor voor {target} in",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Inschakelen Gezondheidscontroles",
"healthCheckDisabledStateDescription": "Wanneer uitgeschakeld, zal de site geen gezondheidscontroles uitvoeren en wordt de staat als onbekend beschouwd.",
"enableHealthChecksDescription": "Controleer de gezondheid van dit doel. U kunt een ander eindpunt monitoren dan het doel indien vereist.",
"healthScheme": "Methode",
"healthSelectScheme": "Selecteer methode",
"healthCheckPortInvalid": "Health check poort moet tussen 1 en 65535 zijn",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Pad",
"healthHostname": "IP / Hostnaam",
"healthPort": "Poort",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Tijd is in seconden",
"requireDeviceApproval": "Vereist goedkeuring van apparaat",
"requireDeviceApprovalDescription": "Gebruikers met deze rol hebben nieuwe apparaten nodig die door een beheerder zijn goedgekeurd voordat ze verbinding kunnen maken met bronnen en deze kunnen gebruiken.",
"sshAccess": "SSH toegang",
"sshSettings": "SSH-instellingen",
"sshAccess": "SSH Access",
"rdpSettings": "RDP-instellingen",
"vncSettings": "VNC-instellingen",
"sshServer": "SSH-server",
"rdpServer": "RDP-server",
"vncServer": "VNC-server",
"sshServerDescription": "Stel de authenticatiemethode, demoonlocatie en serverbestemming in",
"rdpServerDescription": "Configureer de bestemming en poort van de RDP-server",
"vncServerDescription": "Configureer de bestemming en poort van de VNC-server",
"sshServerMode": "Modus",
"sshServerModeStandard": "Standaard SSH-server",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Opdrachten over netwerk routeren naar een SSH-server zoals OpenSSH.",
"sshServerModeNative": "Natuurlijke SSH-server",
"sshServerModeNativeDescription": "Voert rechtstreeks opdrachten uit op de host via de Siteconnector. Geen netwerkconfiguratie vereist.",
"sshAuthenticationMethod": "Authenticatiemethode",
"sshAuthMethodManual": "Handmatige authenticatie",
"sshAuthMethodManualDescription": "Vereist bestaande hostreferenties. Omzeilt automatische voorziening.",
"sshAuthMethodAutomated": "Automatische voorziening",
"sshAuthMethodAutomatedDescription": "Creëert automatisch gebruikers, groepen en sudo-rechten op host.",
"sshAuthDaemonLocation": "Auth Daemon Locatie",
"sshDaemonLocationSiteDescription": "Wordt lokaal uitgevoerd op de machine die de siteconnector host.",
"sshDaemonLocationRemote": "Op Remote Host",
"sshDaemonLocationRemoteDescription": "Wordt uitgevoerd op een aparte doelmachine in hetzelfde netwerk.",
"sshDaemonDisclaimer": "Zorg ervoor dat uw doelhost goed is geconfigureerd om de auth daemon uit te voeren voordat u deze configuratie voltooit, anders zal de voorziening mislukken.",
"sshDaemonPort": "Demonpoort",
"sshServerDestination": "Serverbestemming",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Bestemming",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Het selecteren van meerdere sites maakt veerkrachtige routering mogelijk en failover voor hoge beschikbaarheid.",
"roleAllowSsh": "SSH toestaan",
"roleAllowSshAllow": "Toestaan",
"roleAllowSshDisallow": "Weigeren",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Gebruiker kan alleen de opgegeven commando's uitvoeren met de sudo.",
"sshSudo": "sudo toestaan",
"sshSudoCommands": "Sudo Commando's",
"sshSudoCommandsDescription": "Komma's gescheiden lijst van commando's waar de gebruiker een sudo mee mag uitvoeren.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Maak Home Directory",
"sshUnixGroups": "Unix groepen",
"sshUnixGroupsDescription": "Door komma's gescheiden Unix-groepen om de gebruiker toe te voegen aan de doelhost.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Herhaal Pogingen",
"expectedResponseCodes": "Verwachte Reactiecodes",
"expectedResponseCodesDescription": "HTTP-statuscode die gezonde status aangeeft. Indien leeg wordt 200-300 als gezond beschouwd.",
@@ -2049,8 +2268,9 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Schema",
"editInternalResourceDialogEnableSsl": "TLS inschakelen",
"editInternalResourceDialogEnableSsl": "Schakel TLS in",
"editInternalResourceDialogEnableSslDescription": "Schakel SSL/TLS-encryptie in voor beveiligde HTTPS-verbindingen met de bestemming.",
"editInternalResourceDialogDestination": "Bestemming",
"editInternalResourceDialogDestinationHostDescription": "Het IP-adres of de hostnaam van de bron op het netwerk van de site.",
@@ -2098,9 +2318,10 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Schema",
"createInternalResourceDialogScheme": "Schema",
"createInternalResourceDialogEnableSsl": "TLS inschakelen",
"createInternalResourceDialogEnableSsl": "Schakel TLS in",
"createInternalResourceDialogEnableSslDescription": "Schakel SSL/TLS-encryptie in voor beveiligde HTTPS-verbindingen met de bestemming.",
"createInternalResourceDialogDestination": "Bestemming",
"createInternalResourceDialogDestinationHostDescription": "Het IP-adres of de hostnaam van de bron op het netwerk van de site.",
@@ -2233,7 +2454,7 @@
"description": "betrouwbaardere en slecht onderhouden Pangolin server met extra klokken en klokkenluiders",
"introTitle": "Beheerde zelfgehoste pangolin",
"introDescription": "is een implementatieoptie ontworpen voor mensen die eenvoud en extra betrouwbaarheid willen, terwijl hun gegevens privé en zelf georganiseerd blijven.",
"introDetail": "Met deze optie beheert u nog steeds uw eigen Pangolin node - uw tunnels, TLS-verbinding en verkeer alles op uw server. Het verschil is dat beheer en monitoring worden behandeld via onze cloud dashboard, wat een aantal voordelen oplevert:",
"introDetail": "Met deze optie beheert u nog steeds uw eigen Pangolin-node - uw tunnels, TLS-terminatie en verkeer blijven allemaal op uw server. Het verschil is dat beheer en monitoring worden afgehandeld via ons cloud-dashboard, wat een aantal voordelen oplevert:",
"benefitSimplerOperations": {
"title": "Simpler operaties",
"description": "Je hoeft geen eigen mailserver te draaien of complexe waarschuwingen in te stellen. Je krijgt gezondheidscontroles en downtime meldingen uit de box."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Bevestiging invoeren",
"blueprintViewDetails": "Details",
"defaultIdentityProvider": "Standaard Identiteitsprovider",
"defaultIdentityProviderDescription": "Wanneer een standaard identity provider is geselecteerd, zal de gebruiker automatisch worden doorgestuurd naar de provider voor authenticatie.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Netwerkinstellingen",
"editInternalResourceDialogAccessPolicy": "Toegangsbeleid",
"editInternalResourceDialogAddRoles": "Rollen toevoegen",
@@ -2937,11 +3158,12 @@
"learnMore": "Meer informatie",
"backToHome": "Ga terug naar startpagina",
"needToSignInToOrg": "Moet u de identiteit provider van uw organisatie gebruiken?",
"maintenanceMode": "Onderhoudsmodus",
"maintenanceMode": "Onderhoudspagina",
"maintenanceModeDescription": "Toon een onderhoudspagina aan bezoekers",
"maintenanceModeType": "Type onderhoudsmodus",
"showMaintenancePage": "Toon een onderhoudspagina aan bezoekers",
"enableMaintenanceMode": "Onderhoudsmodus inschakelen",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatisch",
"automaticModeDescription": " Toon onderhoudspagina alleen wanneer alle back-enddoelen niet beschikbaar zijn of ongezond zijn. Jouw bron blijft normaal functioneren zolang er tenminste één doel gezond is.",
"forced": "Geforceerd",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Geschatte voltooiing:",
"createInternalResourceDialogDestinationRequired": "Bestemming is vereist",
"available": "Beschikbaar",
"disabledResourceDescription": "Wanneer uitgeschakeld, zal de bron voor iedereen ontoegankelijk zijn.",
"archived": "Gearchiveerd",
"noArchivedDevices": "Geen gearchiveerde apparaten gevonden",
"deviceArchived": "Apparaat gearchiveerd",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Weet u zeker dat u deze identiteitsprovider van deze organisatie wilt loskoppelen?",
"idpUnassociateDescription": "Alle gebruikers die aan deze identiteitsprovider zijn gekoppeld, worden uit deze organisatie verwijderd, maar de identiteitsprovider blijft bestaan voor andere gerelateerde organisaties.",
"idpUnassociateConfirm": "Bevestig ontkoppelen identiteitsprovider",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Dit kan niet ongedaan worden gemaakt voor deze organisatie.",
"idpUnassociatedDescription": "Identiteitsprovider succesvol losgekoppeld van deze organisatie",
"idpUnassociateMenu": "Ontkoppelen",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Bron Uitgeschakeld",
"memberPortalShowingResources": "Toont {start}-{end} van {total} bronnen",
"memberPortalPrevious": "Vorige",
"memberPortalNext": "Volgende"
"memberPortalNext": "Volgende",
"httpSettings": "HTTP-instellingen",
"tcpSettings": "TCP-instellingen",
"udpSettings": "UDP-instellingen",
"sshTitle": "SSH",
"sshConnectingDescription": "Veilige verbinding tot stand brengen…",
"sshConnecting": "Verbinding maken…",
"sshInitializing": "Initialiseren…",
"sshSignInTitle": "Meld u aan bij SSH",
"sshSignInDescription": "Voer uw SSH-referenties in",
"sshPasswordTab": "Wachtwoord",
"sshPrivateKeyTab": "Privésleutel",
"sshPrivateKeyField": "Privésleutel",
"sshPrivateKeyDisclaimer": "Uw privésleutel wordt niet opgeslagen of zichtbaar gemaakt voor Pangolin. U kunt ook gebruik maken van kortlopende certificaten voor naadloze authenticatie met uw bestaande Pangolin-identiteit.",
"sshLearnMore": "Meer informatie",
"sshPrivateKeyFile": "Bestand met privésleutel",
"sshAuthenticate": "Authenticeren",
"sshTerminate": "Beëindigen",
"sshPoweredBy": "Aangeboden door",
"sshErrorNoTarget": "Geen doelwit gespecificeerd",
"sshErrorWebSocket": "WebSocket-verbinding is mislukt",
"sshErrorAuthFailed": "Authenticatie mislukt",
"sshErrorConnectionClosed": "Verbinding gesloten voordat authenticatie was voltooid",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Zobacz zasoby prywatne",
"siteInstallNewt": "Zainstaluj Newt",
"siteInstallNewtDescription": "Uruchom Newt w swoim systemie",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Konfiguracja WireGuard",
"WgConfigurationDescription": "Użyj następującej konfiguracji, aby połączyć się z siecią",
"operatingSystem": "System operacyjny",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Możesz to zobaczyć tylko raz. Upewnij się, że skopiuj je do bezpiecznego miejsca.",
"siteInfo": "Informacje o witrynie",
"status": "Status",
"shareTitle": "Zarządzaj linkami udostępniania",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Utwórz linki do współdzielenia, aby przyznać tymczasowy lub stały dostęp do zasobów proxy",
"shareSearch": "Szukaj linków udostępnienia...",
"shareCreate": "Utwórz link udostępniania",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Nie udało się usunąć linku",
"shareErrorDeleteMessage": "Wystąpił błąd podczas usuwania linku",
"shareDeleted": "Link usunięty",
"shareDeletedDescription": "Link został usunięty",
"shareDelete": "Usuń link udostępniania",
"shareDeleteConfirm": "Potwierdź usunięcie linku udostępniania",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Czy na pewno chcesz usunąć ten link udostępniania?",
"shareMessageRemove": "Po usunięciu, link przestanie działać i wszyscy korzystający z niego stracą dostęp do zasobu.",
"shareTokenDescription": "Token dostępu może być przekazywany na dwa sposoby: jako parametr zapytania lub w nagłówkach żądania. Muszą być przekazywane z klienta na każde żądanie uwierzytelnionego dostępu.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Wystąpił błąd podczas tworzenia linku udostępniania",
"shareCreateDescription": "Każdy z tym linkiem może uzyskać dostęp do zasobu",
"shareTitleOptional": "Tytuł (opcjonalnie)",
"sharePathOptional": "Ścieżka (opcjonalnie)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Wygasa za",
"neverExpire": "Nigdy nie wygasa",
"shareExpireDescription": "Czas wygaśnięcia to jak długo link będzie mógł być użyty i zapewni dostęp do zasobu. Po tym czasie link nie będzie już działał, a użytkownicy, którzy użyli tego linku, utracą dostęp do zasobu.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Wybierz zasób",
"proxyResourceTitle": "Zarządzaj zasobami publicznymi",
"proxyResourceDescription": "Twórz i zarządzaj zasobami, które są publicznie dostępne w przeglądarce internetowej",
"proxyResourcesBannerTitle": "Publiczny dostęp za pośrednictwem sieci Web",
"proxyResourcesBannerDescription": "Zasoby publiczne to proxy HTTPS lub TCP/UDP dostępne dla każdego w internecie za pośrednictwem przeglądarki internetowej. W przeciwieństwie do zasobów prywatnych, nie wymagają oprogramowania po stronie klienta i mogą obejmować polityki dostępu świadome tożsamości i kontekstu.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Zarządzaj zasobami prywatnymi",
"clientResourceDescription": "Twórz i zarządzaj zasobami, które są dostępne tylko za pośrednictwem połączonego klienta",
"privateResourcesBannerTitle": "Zero zaufania do prywatnego dostępu",
@@ -208,11 +212,36 @@
"resourcesSearch": "Szukaj zasobów...",
"resourceAdd": "Dodaj zasób",
"resourceErrorDelte": "Błąd podczas usuwania zasobu",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} zasób(y)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "brak zasobów",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Szukaj polityk...",
"resourcePoliciesAdd": "Dodaj politykę",
"resourcePoliciesDefaultBadgeText": "Domyślna polityka",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Wykonaj poniższe kroki, aby utworzyć nową politykę",
"resourcePolicyName": "Nazwa polityki",
"resourcePolicyNameDescription": "Nadaj tej polityce nazwę, aby można ją było zidentyfikować w całych zasobach",
"resourcePolicyNamePlaceholder": "np. Polityka Dostępu Wewnętrznego",
"resourcePoliciesSeeAll": "Zobacz wszystkie polityki",
"resourcePolicyAuthMethodAdd": "Dodaj metodę uwierzytelniania",
"resourcePolicyOtpEmailAdd": "Dodaj OTP e-maile",
"resourcePolicyRulesAdd": "Dodaj zasady",
"resourcePolicyAuthMethodsDescription": "Zezwól na dostęp do zasobu poprzez dodatkowe metody uwierzytelniania",
"resourcePolicyUsersRolesDescription": "Skonfiguruj, którzy użytkownicy i role mogą odwiedzać powiązane zasoby",
"rulesResourcePolicyDescription": "Skonfiguruj zasady, aby kontrolować zasoby dostępne w ramach tej polityki",
"authentication": "Uwierzytelnianie",
"protected": "Chronione",
"notProtected": "Niechronione",
"resourceMessageRemove": "Po usunięciu zasób nie będzie już dostępny. Wszystkie cele związane z zasobem zostaną również usunięte.",
"resourceQuestionRemove": "Czy na pewno chcesz usunąć zasób z organizacji?",
"resourcePolicyMessageRemove": "Po usunięciu polityka zasobów nie będzie już dostępna. Wszystkie zasoby połączone z zasobem zostaną odłączone i pozostawione bez uwierzytelniania.",
"resourcePolicyQuestionRemove": "Czy na pewno chcesz usunąć politykę zasobu z organizacji?",
"resourceHTTP": "Zasób HTTPS",
"resourceHTTPDescription": "Proxy zapytań przez HTTPS przy użyciu w pełni kwalifikowanej nazwy domeny.",
"resourceRaw": "Surowy zasób TCP/UDP",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Żądania proxy nad surowym TCP/UDP przy użyciu numeru portu. Wymaga stron aby połączyć się ze zdalnym węzłem.",
"resourceCreate": "Utwórz zasób",
"resourceCreateDescription": "Wykonaj poniższe kroki, aby utworzyć nowy zasób",
"resourceCreateGeneralDescription": "Skonfiguruj podstawowe ustawienia zasobu, w tym nazwę i typ",
"resourceSeeAll": "Zobacz wszystkie zasoby",
"resourceInfo": "Informacje o zasobach",
"resourceCreateGeneral": "Ogólny",
"resourceNameDescription": "To jest wyświetlana nazwa zasobu.",
"siteSelect": "Wybierz witrynę",
"siteSearch": "Szukaj witryny",
@@ -231,12 +261,15 @@
"noCountryFound": "Nie znaleziono kraju.",
"siteSelectionDescription": "Ta strona zapewni połączenie z celem.",
"resourceType": "Typ zasobu",
"resourceTypeDescription": "Określ jak uzyskać dostęp do zasobu",
"resourceTypeDescription": "To kontroluje protokół zasobu i sposób jego renderowania w przeglądarce. Później nie można tego zmienić.",
"resourceDomainDescription": "Zasób będzie udostępniany pod tym w pełni kwalifikowanym adresem domenowym.",
"resourceHTTPSSettings": "Ustawienia HTTPS",
"resourceHTTPSSettingsDescription": "Skonfiguruj jak zasób będzie dostępny przez HTTPS",
"resourcePortDescription": "Zewnętrzny port na instancji lub węźle Pangolina, gdzie zasób będzie dostępny.",
"domainType": "Typ domeny",
"subdomain": "Poddomena",
"baseDomain": "Bazowa domena",
"configure": "Konfiguracja",
"subdomnainDescription": "Poddomena, w której zasób będzie dostępny.",
"resourceRawSettings": "Ustawienia TCP/UDP",
"resourceRawSettingsDescription": "Skonfiguruj jak zasób będzie dostępny przez TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Dowiedz się, jak skonfigurować zasoby TCP/UDP",
"resourceBack": "Powrót do zasobów",
"resourceGoTo": "Przejdź do zasobu",
"resourcePolicyDelete": "Usuń politykę zasobu",
"resourcePolicyDeleteConfirm": "Potwierdź usunięcie polityki zasobu",
"resourceDelete": "Usuń zasób",
"resourceDeleteConfirm": "Potwierdź usunięcie zasobu",
"labelDelete": "Usuń etykietę",
"labelAdd": "Dodaj etykietę",
"labelCreateSuccessMessage": "Etykieta została utworzona pomyślnie",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etykieta została pomyślnie zmodyfikowana",
"labelNameField": "Nazwa etykiety",
"labelColorField": "Kolor etykiety",
"labelPlaceholder": "Np.: homelab",
"labelCreate": "Utwórz etykietę",
"createLabelDialogTitle": "Utwórz etykietę",
"createLabelDialogDescription": "Utwórz nową etykietę, która może być przypisana do tej organizacji",
"labelEdit": "Edytuj etykietę",
"editLabelDialogTitle": "Aktualizuj etykietę",
"editLabelDialogDescription": "Edytuj nową etykietę, która może być przypisana do tej organizacji",
"labelDeleteConfirm": "Potwierdź usunięcie etykiety",
"labelErrorDelete": "Nie udało się usunąć etykiety",
"labelMessageRemove": "To działanie jest nieodwracalne. Wszystkie strony, zasoby i klienci oznaczeni tą etykietą zostaną odznaczeni.",
"labelQuestionRemove": "Czy na pewno chcesz usunąć etykietę z organizacji?",
"visibility": "Widoczność",
"enabled": "Włączone",
"disabled": "Wyłączone",
@@ -265,6 +319,8 @@
"rules": "Regulamin",
"resourceSettingDescription": "Skonfiguruj ustawienia zasobu",
"resourceSetting": "Ustawienia {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Ustawienia {policyName}",
"alwaysAllow": "Omijanie uwierzytelniania",
"alwaysDeny": "Blokuj dostęp",
"passToAuth": "Przekaż do Autoryzacji",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Duplikat reguły",
"rulesErrorDuplicateDescription": "Reguła o tych ustawieniach już istnieje",
"rulesErrorInvalidIpAddressRange": "Nieprawidłowy CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Wprowadź prawidłową wartość CIDR",
"rulesErrorInvalidUrl": "Nieprawidłowa ścieżka URL",
"rulesErrorInvalidUrlDescription": "Wprowadź prawidłową wartość ścieżki URL",
"rulesErrorInvalidIpAddress": "Nieprawidłowe IP",
"rulesErrorInvalidIpAddressDescription": "Wprowadź prawidłowy adres IP",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Nie udało się zaktualizować reguł",
"rulesErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji reguł",
"rulesUpdated": "Włącz reguły",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Wprowadź adres w formacie CIDR (np. 103.21.244.0/22)",
"rulesMatchIpAddress": "Wprowadź adres IP (np. 103.21.244.12)",
"rulesMatchUrl": "Wprowadź ścieżkę URL lub wzorzec (np. /api/v1/todos lub /api/v1/*)",
"rulesErrorInvalidPriority": "Nieprawidłowy priorytet",
"rulesErrorInvalidPriorityDescription": "Wprowadź prawidłowy priorytet",
"rulesErrorDuplicatePriority": "Zduplikowane priorytety",
"rulesErrorDuplicatePriorityDescription": "Wprowadź unikalne priorytety",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Reguły zaktualizowane",
"ruleUpdatedDescription": "Reguły zostały pomyślnie zaktualizowane",
"ruleErrorUpdate": "Operacja nie powiodła się",
"ruleErrorUpdateDescription": "Wystąpił błąd podczas operacji zapisu",
"rulesPriority": "Priorytet",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Akcja",
"rulesMatchType": "Typ dopasowania",
"value": "Wartość",
@@ -744,9 +809,60 @@
"rulesResource": "Konfiguracja reguł zasobu",
"rulesResourceDescription": "Skonfiguruj reguły, aby kontrolować dostęp do zasobu",
"ruleSubmit": "Dodaj regułę",
"rulesNoOne": "Brak reguł. Dodaj regułę używając formularza.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Reguły są oceniane według priorytetu w kolejności rosnącej.",
"rulesSubmit": "Zapisz reguły",
"policyErrorCreate": "Błąd przy tworzeniu polityki",
"policyErrorCreateDescription": "Wystąpił błąd podczas tworzenia polityki",
"policyErrorCreateMessageDescription": "Wystąpił nieoczekiwany błąd",
"policyErrorUpdate": "Błąd przy aktualizacji polityki",
"policyErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji polityki",
"policyErrorUpdateMessageDescription": "Wystąpił nieoczekiwany błąd",
"policyCreatedSuccess": "Polityka zasobów została pomyślnie utworzona",
"policyUpdatedSuccess": "Polityka zasobów została pomyślnie zaktualizowana",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Zapisz zasady",
"resourceErrorCreate": "Błąd podczas tworzenia zasobu",
"resourceErrorCreateDescription": "Wystąpił błąd podczas tworzenia zasobu",
"resourceErrorCreateMessage": "Błąd podczas tworzenia zasobu:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Wystąpił błąd podczas aktualizacji zasobu",
"access": "Dostęp",
"accessControl": "Kontrola dostępu",
"shareLink": "Link udostępniania {resource}",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Wybierz zasób",
"shareLinks": "Linki udostępniania",
"shareLinks": "Shareable Links",
"share": "Linki do udostępniania",
"shareDescription2": "Utwórz linki do zasobów, które można współdzielić. Linki zapewniają tymczasowy lub nieograniczony dostęp do twojego zasobu. Możesz skonfigurować czas ważności linku, gdy go utworzysz.",
"shareEasyCreate": "Łatwe tworzenie i udostępnianie",
@@ -810,6 +926,17 @@
"pincodeAdd": "Dodaj kod PIN",
"pincodeRemove": "Usuń kod PIN",
"resourceAuthMethods": "Metody uwierzytelniania",
"resourcePolicyAuthMethodsEmpty": "Brak metody uwierzytelniania",
"resourcePolicyOtpEmpty": "Brak jednorazowego hasła",
"resourcePolicyReadOnly": "Ta polityka jest tylko do odczytu",
"resourcePolicyReadOnlyDescription": "Ta polityka zasobów jest dzielona pomiędzy wieloma zasobami, nie możesz jej edytować na tej stronie.",
"editSharedPolicy": "Edytuj Dzieleną Politykę",
"resourcePolicyTypeSave": "Zapisz typ zasobu",
"resourcePolicySelect": "Wybierz politykę zasobów",
"resourcePolicySelectError": "Wybierz politykę zasobów",
"resourcePolicyNotFound": "Nie znaleziono polityki",
"resourcePolicySearch": "Szukaj polityki",
"resourcePolicyRulesEmpty": "Brak zasad uwierzytelniania",
"resourceAuthMethodsDescriptions": "Zezwól na dostęp do zasobu przez dodatkowe metody uwierzytelniania",
"resourceAuthSettingsSave": "Zapisano pomyślnie",
"resourceAuthSettingsSaveDescription": "Ustawienia uwierzytelniania zostały zapisane",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Ustaw kod PIN",
"resourcePincodeSetupTitleDescription": "Ustaw kod PIN, aby chronić ten zasób",
"resourceRoleDescription": "Administratorzy zawsze mają dostęp do tego zasobu.",
"resourcePolicySelectTitle": "Polityka dostępu do zasobów",
"resourcePolicySelectDescription": "Wybierz typ polityki zasobów do uwierzytelniania",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Warunkowa polityka zasobów",
"resourcePolicyInlineDescription": "Polityka dostępu tylko do tego zasobu",
"resourcePolicyShared": "Dzielona polityka zasobów",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Kontrola dostępu",
"resourceUsersRolesDescription": "Skonfiguruj, którzy użytkownicy i role mogą odwiedzać ten zasób",
"resourceUsersRolesSubmit": "Zapisz kontrole dostępu",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Wystąpił problem z połączeniem z {name}. Skontaktuj się z administratorem.",
"idpErrorNotFound": "Nie znaleziono IdP",
"inviteInvalid": "Nieprawidłowe zaproszenie",
"labels": "Etykiety",
"orgLabelsDescription": "Zarządzaj etykietami w tej organizacji.",
"addLabels": "Dodaj etykiety",
"siteLabelsTab": "Etykiety",
"siteLabelsDescription": "Zarządzaj etykietami powiązanymi z tą stroną.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Szukaj etykiet",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# etykieta} few {# etykiety} many {# etykiet} other {# etykiet}}",
"labelOverflowCount": "+{count, plural, one {# etykieta} few {# etykiety} many {# etykiet} other {# etykiet}}",
"accessLabelFilterClear": "Wyczyść filtry etykiet",
"accessFilterClear": "Clear filters",
"selectColor": "Wybierz kolor",
"createNewLabel": "Utwórz nową etykietę org \"{label}\"",
"inviteInvalidDescription": "Link zapraszający jest nieprawidłowy.",
"inviteErrorWrongUser": "Zaproszenie nie jest dla tego użytkownika",
"inviteErrorUserNotExists": "Użytkownik nie istnieje. Najpierw utwórz konto.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Zasoby",
"sidebarProxyResources": "Publiczne",
"sidebarClientResources": "Prywatny",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Kontrola dostępu",
"sidebarLogsAndAnalytics": "Logi i Analityki",
"sidebarTeam": "Drużyna",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Administrator",
"sidebarInvitations": "Zaproszenia",
"sidebarRoles": "Role",
"sidebarShareableLinks": "Linki",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "Klucze API",
"sidebarProvisioning": "Dostarczanie",
"sidebarSettings": "Ustawienia",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Witryna {id}",
"standaloneHcFilterResourceIdFallback": "Zasób {id}",
"blueprints": "Schematy",
"blueprintsDescription": "Zastosuj konfiguracje deklaracyjne i wyświetl poprzednie operacje",
"blueprintsLog": "Dziennik szablonów",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Dodaj schemat",
"blueprintGoBack": "Zobacz wszystkie schematy",
"blueprintCreate": "Utwórz schemat",
@@ -1575,7 +1732,17 @@
"contents": "Treść",
"parsedContents": "Przetworzona zawartość (tylko do odczytu)",
"enableDockerSocket": "Włącz schemat dokera",
"enableDockerSocketDescription": "Włącz etykietowanie kieszeni dokującej dla etykiet schematów. Ścieżka do gniazda musi być dostarczona do Newt.",
"enableDockerSocketDescription": "Włącz etykietowanie gniazda dokera dla etykiet szablonów. Ścieżka do gniazda musi być dostarczona do łącznika strony. Przeczytaj zarówno jak to działa w <docsLink>dokumentacji</docsLink>.",
"newtAutoUpdate": "Włącz automatyczną aktualizację witryny",
"newtAutoUpdateDescription": "Kiedy włączone, łączniki witryn będą się automatycznie aktualizować do najnowszej wersji, gdy dostępne będzie nowe wydanie.",
"siteAutoUpdate": "Automatyczna aktualizacja strony",
"siteAutoUpdateLabel": "Włącz aktualizacje automatyczne",
"siteAutoUpdateDescription": "Kontroluj czy łącznik tej strony automatycznie pobiera najnowszą wersję.",
"siteAutoUpdateOrgDefault": "Domyślnie dla organizacji: {state}",
"siteAutoUpdateOverriding": "Nadpisywanie ustawień organizacji",
"siteAutoUpdateResetToOrg": "Zresetuj do domyślnych ustawień organizacji",
"siteAutoUpdateEnabled": "włączone",
"siteAutoUpdateDisabled": "wyłączone",
"viewDockerContainers": "Zobacz kontenery dokujące",
"containersIn": "Pojemniki w {siteName}",
"selectContainerDescription": "Wybierz dowolny kontener do użycia jako nazwa hosta dla tego celu. Kliknij port, aby użyć portu.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certyfikat",
"certificateStatusAutoRefreshHint": "Status odświeża się automatycznie.",
"loading": "Ładowanie",
"loadingEllipsis": "Ładowanie...",
"loadingAnalytics": "Ładowanie Analityki",
"restart": "Uruchom ponownie",
"domains": "Domeny",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Zarządzaj subskrypcją płatnych własnych kluczy licencyjnych",
"billingCurrentKeys": "Bieżące klucze",
"billingModifyCurrentPlan": "Modyfikuj bieżący plan",
"billingManageLicenseSubscriptionDescription": "Zarządzaj swoją subskrypcją dla płatnych kluczy licencyjnych na samoobsługowy hosting i pobieraj faktury.",
"billingConfirmUpgrade": "Potwierdź aktualizację",
"billingConfirmDowngrade": "Potwierdź obniżenie",
"billingConfirmUpgradeDescription": "Zamierzasz ulepszyć swój plan. Przejrzyj nowe limity i ceny poniżej.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Nieznany",
"healthCheck": "Kontrola Zdrowia",
"configureHealthCheck": "Skonfiguruj Kontrolę Zdrowia",
"configureHealthCheckDescription": "Skonfiguruj monitorowanie zdrowia dla {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Włącz Kontrole Zdrowia",
"healthCheckDisabledStateDescription": "Gdy wyłączone, strona nie będzie wykonywać kontroli zdrowia, a stan zostanie uznany za nieznany.",
"enableHealthChecksDescription": "Monitoruj zdrowie tego celu. Możesz monitorować inny punkt końcowy niż docelowy w razie potrzeby.",
"healthScheme": "Metoda",
"healthSelectScheme": "Wybierz metodę",
"healthCheckPortInvalid": "Port oceny stanu musi znajdować się między 1 a 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Ścieżka",
"healthHostname": "IP / Nazwa hosta",
"healthPort": "Port",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Czas w sekundach",
"requireDeviceApproval": "Wymagaj zatwierdzenia urządzenia",
"requireDeviceApprovalDescription": "Użytkownicy o tej roli potrzebują nowych urządzeń zatwierdzonych przez administratora, zanim będą mogli połączyć się i uzyskać dostęp do zasobów.",
"sshAccess": "Dostęp SSH",
"sshSettings": "Ustawienia SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Ustawienia RDP",
"vncSettings": "Ustawienia VNC",
"sshServer": "Serwer SSH",
"rdpServer": "Serwer RDP",
"vncServer": "Serwer VNC",
"sshServerDescription": "Skonfiguruj metodę uwierzytelniania, lokalizację demona i miejsce docelowe serwera",
"rdpServerDescription": "Skonfiguruj miejsce docelowe i port serwera RDP",
"vncServerDescription": "Skonfiguruj miejsce docelowe i port serwera VNC",
"sshServerMode": "Tryb",
"sshServerModeStandard": "Standardowy Serwer SSH",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Przesyła polecenia przez sieć do serwera SSH takiego jak OpenSSH.",
"sshServerModeNative": "Natywny Serwer SSH",
"sshServerModeNativeDescription": "Wykonuje polecenia bezpośrednio na hoście za pomocą łącznika strony. Nie wymaga konfiguracji sieci.",
"sshAuthenticationMethod": "Metoda uwierzytelniania",
"sshAuthMethodManual": "Ręczne uwierzytelnianie",
"sshAuthMethodManualDescription": "Wymaga istniejących poświadczeń hosta. Omiija automatyczne provisioning.",
"sshAuthMethodAutomated": "Automatyczne Provisioning",
"sshAuthMethodAutomatedDescription": "Automatycznie tworzy użytkowników, grupy i uprawnienia sudo na hoście.",
"sshAuthDaemonLocation": "Lokalizacja Demona Uwierzytelniania",
"sshDaemonLocationSiteDescription": "Wykonuje lokalnie na maszynie hostującej łącznik strony.",
"sshDaemonLocationRemote": "Na Zdalnym Hoście",
"sshDaemonLocationRemoteDescription": "Wykonuje się na innej maszynie docelowej w tej samej sieci.",
"sshDaemonDisclaimer": "Upewnij się, że Twoja maszyna docelowa jest poprawnie skonfigurowana do uruchamiania demona uwierzytelniania zanim ukończysz tę konfigurację, w przeciwnym razie provisioning zakończy się niepowodzeniem.",
"sshDaemonPort": "Port Demona",
"sshServerDestination": "Miejsce docelowe serwera",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Miejsce docelowe",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Wybór wielu stron umożliwia odporność trasowania i zmienioność dla wysokiej dostępności.",
"roleAllowSsh": "Zezwalaj na SSH",
"roleAllowSshAllow": "Zezwól",
"roleAllowSshDisallow": "Nie zezwalaj",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Użytkownik może uruchamiać tylko określone polecenia z sudo.",
"sshSudo": "Zezwól na sudo",
"sshSudoCommands": "Komendy Sudo",
"sshSudoCommandsDescription": "Lista poleceń oddzielonych przecinkami, które użytkownik może uruchamiać z sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Utwórz katalog domowy",
"sshUnixGroups": "Grupy Unix",
"sshUnixGroupsDescription": "Oddzielone przecinkami grupy Unix, aby dodać użytkownika do docelowego hosta.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Próby Ponowienia",
"expectedResponseCodes": "Oczekiwane Kody Odpowiedzi",
"expectedResponseCodesDescription": "Kod statusu HTTP, który wskazuje zdrowy status. Jeśli pozostanie pusty, uznaje się 200-300 za zdrowy.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Schemat",
"editInternalResourceDialogEnableSsl": "Włącz TLS",
"editInternalResourceDialogEnableSslDescription": "Włącz szyfrowanie SSL/TLS dla bezpiecznych połączeń HTTPS z miejscem docelowym.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Schemat",
"createInternalResourceDialogScheme": "Schemat",
"createInternalResourceDialogEnableSsl": "Włącz TLS",
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Wprowadź potwierdzenie",
"blueprintViewDetails": "Szczegóły",
"defaultIdentityProvider": "Domyślny dostawca tożsamości",
"defaultIdentityProviderDescription": "Gdy zostanie wybrany domyślny dostawca tożsamości, użytkownik zostanie automatycznie przekierowany do dostawcy w celu uwierzytelnienia.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Ustawienia sieci",
"editInternalResourceDialogAccessPolicy": "Polityka dostępowa",
"editInternalResourceDialogAddRoles": "Dodaj role",
@@ -2937,11 +3158,12 @@
"learnMore": "Dowiedz się więcej",
"backToHome": "Wróć do strony głównej",
"needToSignInToOrg": "Czy potrzebujesz użyć dostawcy tożsamości organizacji?",
"maintenanceMode": "Tryb konserwacji",
"maintenanceMode": "Strona konserwacji",
"maintenanceModeDescription": "Wyświetl stronę konserwacyjną odwiedzającym",
"maintenanceModeType": "Typ trybu konserwacji",
"showMaintenancePage": "Pokaż odwiedzającym stronę konserwacji",
"enableMaintenanceMode": "Włącz tryb konserwacji",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automatycznie",
"automaticModeDescription": "Pokaż stronę konserwacyjną tylko wtedy, gdy wszystkie cele zaplecza są wyłączone lub niezdrowe. Twój zasób działa nadal normalnie, o ile przynajmniej jeden cel jest zdrowy.",
"forced": "Wymuszone",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Szacowane zakończenie:",
"createInternalResourceDialogDestinationRequired": "Miejsce docelowe jest wymagane",
"available": "Dostępny",
"disabledResourceDescription": "Kiedy wyłączone, zasób będzie niedostępny dla wszystkich.",
"archived": "Zarchiwizowane",
"noArchivedDevices": "Nie znaleziono zarchiwizowanych urządzeń",
"deviceArchived": "Urządzenie zarchiwizowane",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Czy na pewno chcesz odłączyć tego dostawcę tożsamości od tej organizacji?",
"idpUnassociateDescription": "Wszystkie użytkownicy powiązani z tym dostawcą tożsamości zostaną usunięci z tej organizacji, ale dostawca tożsamości będzie nadal istniał dla innych powiązanych organizacji.",
"idpUnassociateConfirm": "Potwierdź odłączenie dostawcy tożsamości",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Tego nie można cofnąć dla tej organizacji.",
"idpUnassociatedDescription": "Dostawca tożsamości pomyślnie odłączony od tej organizacji",
"idpUnassociateMenu": "Odłącz",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Zasób wyłączony",
"memberPortalShowingResources": "Wyświetlanie zasobów od {start} do {end} z {total}",
"memberPortalPrevious": "Poprzedni",
"memberPortalNext": "Następny"
"memberPortalNext": "Następny",
"httpSettings": "Ustawienia HTTP",
"tcpSettings": "Ustawienia TCP",
"udpSettings": "Ustawienia UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Nawiązywanie bezpiecznego połączenia…",
"sshConnecting": "Łączenie…",
"sshInitializing": "Inicjalizacja…",
"sshSignInTitle": "Zaloguj się do SSH",
"sshSignInDescription": "Wprowadź swoje poświadczenia SSH",
"sshPasswordTab": "Hasło",
"sshPrivateKeyTab": "Klucz prywatny",
"sshPrivateKeyField": "Klucz prywatny",
"sshPrivateKeyDisclaimer": "Twój klucz prywatny nie jest przechowywany ani widoczny dla Pangolin. Alternatywnie, możesz używać certyfikatów krótkoterminowych do bezproblemowego uwierzytelniania za pomocą Twojej istniejącej tożsamości Pangolin.",
"sshLearnMore": "Dowiedz się więcej",
"sshPrivateKeyFile": "Plik klucza prywatnego",
"sshAuthenticate": "Uwierzytelnij",
"sshTerminate": "Zakończ",
"sshPoweredBy": "Obsługiwane przez",
"sshErrorNoTarget": "Nie określono celu",
"sshErrorWebSocket": "Połączenie WebSocket nie powiodło się",
"sshErrorAuthFailed": "Uwierzytelnianie nie powiodło się",
"sshErrorConnectionClosed": "Połączenie zamknięte przed ukończeniem uwierzytelniania",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Visualizar Recursos Privados",
"siteInstallNewt": "Instalar Novo",
"siteInstallNewtDescription": "Novo item em execução no seu sistema",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Configuração do WireGuard",
"WgConfigurationDescription": "Use a seguinte configuração para conectar-se à rede",
"operatingSystem": "Sistema operacional",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Você só será capaz de ver esta vez. Certifique-se de copiá-lo para um lugar seguro.",
"siteInfo": "Informações do Site",
"status": "SItuação",
"shareTitle": "Gerir links partilhados",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Criar links compartilháveis para conceder acesso temporário ou permanente aos recursos do proxy",
"shareSearch": "Pesquisar links de compartilhamento...",
"shareCreate": "Criar Link de Compartilhamento",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Falha ao apagar o link",
"shareErrorDeleteMessage": "Ocorreu um erro ao apagar o link",
"shareDeleted": "Link excluído",
"shareDeletedDescription": "O link foi eliminado",
"shareDelete": "Excluir Link de Compartilhamento",
"shareDeleteConfirm": "Confirmar Exclusão de Link de Compartilhamento",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Tem certeza de que deseja excluir este link de compartilhamento?",
"shareMessageRemove": "Uma vez excluído, o link não funcionará mais e qualquer pessoa que o utilizar perderá o acesso ao recurso.",
"shareTokenDescription": "O token de acesso pode ser passado de duas maneiras: como um parâmetro de consulta ou nos cabeçalhos da solicitação. Estes devem ser passados do cliente em todas as solicitações para acesso autenticado.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Ocorreu um erro ao criar o link de compartilhamento",
"shareCreateDescription": "Qualquer um com este link pode aceder o recurso",
"shareTitleOptional": "Título (opcional)",
"sharePathOptional": "Caminho (opcional)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Expira em",
"neverExpire": "Nunca expirar",
"shareExpireDescription": "Tempo de expiração é quanto tempo o link será utilizável e oferecerá acesso ao recurso. Após este tempo, o link não funcionará mais, e os utilizadores que usaram este link perderão acesso ao recurso.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Por favor, selecione um recurso",
"proxyResourceTitle": "Gerenciar Recursos Públicos",
"proxyResourceDescription": "Criar e gerenciar recursos que são acessíveis publicamente por meio de um navegador da web",
"proxyResourcesBannerTitle": "Acesso Público via Web",
"proxyResourcesBannerDescription": "Os recursos públicos são proxies HTTPS ou TCP/UDP acessíveis a qualquer pessoa na internet por meio de um navegador web. Ao contrário dos recursos privados, eles não requerem software do lado do cliente e podem incluir políticas de acesso conscientes de identidade e contexto.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Gerenciar recursos privados",
"clientResourceDescription": "Criar e gerenciar recursos que só são acessíveis por meio de um cliente conectado",
"privateResourcesBannerTitle": "Acesso Privado com Confiança Zero",
@@ -208,11 +212,36 @@
"resourcesSearch": "Procurar recursos...",
"resourceAdd": "Adicionar Recurso",
"resourceErrorDelte": "Erro ao apagar recurso",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} recurso(s)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "sem recursos",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Pesquisar políticas...",
"resourcePoliciesAdd": "Adicionar Política",
"resourcePoliciesDefaultBadgeText": "Política Padrão",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Siga os passos abaixo para criar uma nova política",
"resourcePolicyName": "Nome da Política",
"resourcePolicyNameDescription": "Dê um nome a esta política para identificá-la em seus recursos",
"resourcePolicyNamePlaceholder": "ex.: Política de Acesso Interno",
"resourcePoliciesSeeAll": "Ver Todas as Políticas",
"resourcePolicyAuthMethodAdd": "Adicionar Método de Autenticação",
"resourcePolicyOtpEmailAdd": "Adicionar emails OTP",
"resourcePolicyRulesAdd": "Adicionar Regras",
"resourcePolicyAuthMethodsDescription": "Permitir acesso aos recursos via métodos de autenticação adicionais",
"resourcePolicyUsersRolesDescription": "Configure quais usuários e funções podem acessar os recursos associados",
"rulesResourcePolicyDescription": "Configure regras para controlar o acesso a recursos associados a esta política",
"authentication": "Autenticação",
"protected": "Protegido",
"notProtected": "Não Protegido",
"resourceMessageRemove": "Uma vez removido, o recurso não estará mais acessível. Todos os alvos associados ao recurso também serão removidos.",
"resourceQuestionRemove": "Você tem certeza que deseja remover o recurso da organização?",
"resourcePolicyMessageRemove": "Uma vez removida, a política de recurso não estará mais acessível. Todos os recursos associados serão desvinculados e deixados sem autenticação.",
"resourcePolicyQuestionRemove": "Tem certeza de que deseja remover a política de recurso da organização?",
"resourceHTTP": "Recurso HTTPS",
"resourceHTTPDescription": "Proxies requests sobre HTTPS usando um nome de domínio totalmente qualificado.",
"resourceRaw": "Recurso TCP/UDP bruto",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy solicita por TCP/UDP bruto usando um número de porta. Requer que sites se conectem a um nó remoto.",
"resourceCreate": "Criar Recurso",
"resourceCreateDescription": "Siga os passos abaixo para criar um novo recurso",
"resourceCreateGeneralDescription": "Configure as configurações gerais do recurso, incluindo o nome e o tipo",
"resourceSeeAll": "Ver todos os recursos",
"resourceInfo": "Informação do recurso",
"resourceCreateGeneral": "Gerais",
"resourceNameDescription": "Este é o nome de exibição para o recurso.",
"siteSelect": "Selecionar site",
"siteSearch": "Procurar no site",
@@ -231,12 +261,15 @@
"noCountryFound": "Nenhum país encontrado.",
"siteSelectionDescription": "Este site fornecerá conectividade ao destino.",
"resourceType": "Tipo de Recurso",
"resourceTypeDescription": "Determine como acessar o recurso",
"resourceTypeDescription": "Isso controla o protocolo do recurso e como ele será renderizado no navegador. Isso não pode ser alterado posteriormente.",
"resourceDomainDescription": "O recurso será servido neste nome de domínio totalmente qualificado.",
"resourceHTTPSSettings": "Configurações de HTTPS",
"resourceHTTPSSettingsDescription": "Configure como o recurso será acessado por HTTPS",
"resourcePortDescription": "A porta externa na instância ou nó Pangolin onde o recurso estará acessível.",
"domainType": "Tipo de domínio",
"subdomain": "Subdomínio",
"baseDomain": "Domínio Base",
"configure": "Configurar",
"subdomnainDescription": "O subdomínio onde o recurso será acessível.",
"resourceRawSettings": "Configurações TCP/UDP",
"resourceRawSettingsDescription": "Configurar como o recurso será acessado sobre TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Aprenda como configurar os recursos TCP/UDP",
"resourceBack": "Voltar aos recursos",
"resourceGoTo": "Ir para o Recurso",
"resourcePolicyDelete": "Excluir Política de Recurso",
"resourcePolicyDeleteConfirm": "Confirmar Exclusão da Política de Recurso",
"resourceDelete": "Excluir Recurso",
"resourceDeleteConfirm": "Confirmar que pretende apagar o recurso",
"labelDelete": "Excluir Etiqueta",
"labelAdd": "Adicionar Etiqueta",
"labelCreateSuccessMessage": "Etiqueta Criada com Sucesso",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etiqueta Modificada com Sucesso",
"labelNameField": "Nome da Etiqueta",
"labelColorField": "Cor da Etiqueta",
"labelPlaceholder": "Ex: homelab",
"labelCreate": "Criar Etiqueta",
"createLabelDialogTitle": "Criar Etiqueta",
"createLabelDialogDescription": "Crie uma nova etiqueta que pode ser anexada a esta organização",
"labelEdit": "Editar Etiqueta",
"editLabelDialogTitle": "Atualizar Etiqueta",
"editLabelDialogDescription": "Edite uma nova etiqueta que pode ser anexada a esta organização",
"labelDeleteConfirm": "Confirmar Exclusão da Etiqueta",
"labelErrorDelete": "Falha ao excluir a etiqueta",
"labelMessageRemove": "Esta ação é permanente. Todos os sites, recursos e clientes etiquetados com esta etiqueta serão desmarcados.",
"labelQuestionRemove": "Tem certeza de que deseja remover a etiqueta da organização?",
"visibility": "Visibilidade",
"enabled": "Ativado",
"disabled": "Desabilitado",
@@ -265,6 +319,8 @@
"rules": "Regras",
"resourceSettingDescription": "Configure as configurações do recurso",
"resourceSetting": "Configurações do {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Configurações de {policyName}",
"alwaysAllow": "Autenticação de bypass",
"alwaysDeny": "Bloquear Acesso",
"passToAuth": "Passar para Autenticação",
@@ -630,7 +686,7 @@
"createdAt": "Criado Em",
"proxyErrorInvalidHeader": "Valor do cabeçalho Host personalizado inválido. Use o formato de nome de domínio ou salve vazio para remover o cabeçalho Host personalizado.",
"proxyErrorTls": "Nome do Servidor TLS inválido. Use o formato de nome de domínio ou salve vazio para remover o Nome do Servidor TLS.",
"proxyEnableSSL": "Habilitar TLS",
"proxyEnableSSL": "Ativar TLS",
"proxyEnableSSLDescription": "Habilitar criptografia SSL/TLS para conexões HTTPS seguras aos alvos.",
"target": "Target",
"configureTarget": "Configurar Alvos",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Regra duplicada",
"rulesErrorDuplicateDescription": "Uma regra com estas configurações já existe",
"rulesErrorInvalidIpAddressRange": "CIDR inválido",
"rulesErrorInvalidIpAddressRangeDescription": "Por favor, insira um valor CIDR válido",
"rulesErrorInvalidUrl": "Caminho URL inválido",
"rulesErrorInvalidUrlDescription": "Por favor, insira um valor de caminho URL válido",
"rulesErrorInvalidIpAddress": "IP inválido",
"rulesErrorInvalidIpAddressDescription": "Por favor, insira um endereço IP válido",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Falha ao atualizar regras",
"rulesErrorUpdateDescription": "Ocorreu um erro ao atualizar regras",
"rulesUpdated": "Ativar Regras",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Insira um endereço no formato CIDR (ex: 103.21.244.0/22)",
"rulesMatchIpAddress": "Insira um endereço IP (ex: 103.21.244.12)",
"rulesMatchUrl": "Insira um caminho URL ou padrão (ex: /api/v1/todos ou /api/v1/*)",
"rulesErrorInvalidPriority": "Prioridade Inválida",
"rulesErrorInvalidPriorityDescription": "Por favor, insira uma prioridade válida",
"rulesErrorDuplicatePriority": "Prioridades Duplicadas",
"rulesErrorDuplicatePriorityDescription": "Por favor, insira prioridades únicas",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Regras atualizadas",
"ruleUpdatedDescription": "Regras atualizadas com sucesso",
"ruleErrorUpdate": "Operação falhou",
"ruleErrorUpdateDescription": "Ocorreu um erro durante a operação de salvamento",
"rulesPriority": "Prioridade",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Ação",
"rulesMatchType": "Tipo de Correspondência",
"value": "Valor",
@@ -744,9 +809,60 @@
"rulesResource": "Configuração de Regras do Recurso",
"rulesResourceDescription": "Configurar regras para controlar o acesso ao recurso",
"ruleSubmit": "Adicionar Regra",
"rulesNoOne": "Sem regras. Adicione uma regra usando o formulário.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "As regras são avaliadas por prioridade em ordem ascendente.",
"rulesSubmit": "Guardar Regras",
"policyErrorCreate": "Erro ao criar política",
"policyErrorCreateDescription": "Ocorreu um erro ao criar a política",
"policyErrorCreateMessageDescription": "Ocorreu um erro inesperado",
"policyErrorUpdate": "Erro ao atualizar política",
"policyErrorUpdateDescription": "Ocorreu um erro ao atualizar a política",
"policyErrorUpdateMessageDescription": "Ocorreu um erro inesperado",
"policyCreatedSuccess": "Política de recurso criada com sucesso",
"policyUpdatedSuccess": "Política de recurso atualizada com sucesso",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Guardar Regras",
"resourceErrorCreate": "Erro ao criar recurso",
"resourceErrorCreateDescription": "Ocorreu um erro ao criar o recurso",
"resourceErrorCreateMessage": "Erro ao criar recurso:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Ocorreu um erro ao atualizar o recurso",
"access": "Acesso",
"accessControl": "Controle de Acesso",
"shareLink": "Link de Compartilhamento {resource}",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Selecionar recurso",
"shareLinks": "Links de Compartilhamento",
"shareLinks": "Shareable Links",
"share": "Links Compartilháveis",
"shareDescription2": "Crie links compartilháveis para recursos. Links fornecem acesso temporário ou ilimitado ao seu recurso. Você pode configurar a duração de expiração do link quando você criar um.",
"shareEasyCreate": "Fácil de criar e compartilhar",
@@ -810,6 +926,17 @@
"pincodeAdd": "Adicionar Código PIN",
"pincodeRemove": "Remover Código PIN",
"resourceAuthMethods": "Métodos de Autenticação",
"resourcePolicyAuthMethodsEmpty": "Nenhum método de autenticação",
"resourcePolicyOtpEmpty": "Sem senha única",
"resourcePolicyReadOnly": "Esta política é apenas leitura",
"resourcePolicyReadOnlyDescription": "Esta política de recurso é compartilhada entre vários recursos, você não pode editá-la nesta página.",
"editSharedPolicy": "Editar Política Compartilhada",
"resourcePolicyTypeSave": "Salvar Tipo de Recurso",
"resourcePolicySelect": "Selecionar política de recurso",
"resourcePolicySelectError": "Selecionar uma política de recurso",
"resourcePolicyNotFound": "Política não encontrada",
"resourcePolicySearch": "Pesquisar políticas",
"resourcePolicyRulesEmpty": "Nenhuma regra de autenticação",
"resourceAuthMethodsDescriptions": "Permitir acesso ao recurso via métodos de autenticação adicionais",
"resourceAuthSettingsSave": "Salvo com sucesso",
"resourceAuthSettingsSaveDescription": "As configurações de autenticação foram salvas",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Definir Código PIN",
"resourcePincodeSetupTitleDescription": "Defina um código PIN para proteger este recurso",
"resourceRoleDescription": "Administradores sempre podem aceder este recurso.",
"resourcePolicySelectTitle": "Política de Acesso ao Recurso",
"resourcePolicySelectDescription": "Selecione o tipo de política de recurso para autenticação",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Política de Recurso Inline",
"resourcePolicyInlineDescription": "Política de Acesso abrange apenas este recurso",
"resourcePolicyShared": "Política de Recurso Compartilhada",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Controlos de Acesso",
"resourceUsersRolesDescription": "Configure quais utilizadores e funções podem visitar este recurso",
"resourceUsersRolesSubmit": "Guardar Controlos de Acesso",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Ocorreu um problema ao ligar a {name}. Por favor, contacte o seu administrador.",
"idpErrorNotFound": "IdP não encontrado",
"inviteInvalid": "Convite Inválido",
"labels": "Etiquetas",
"orgLabelsDescription": "Gerencie etiquetas nesta organização.",
"addLabels": "Adicionar etiquetas",
"siteLabelsTab": "Etiquetas",
"siteLabelsDescription": "Gerencie etiquetas associadas a este site.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Pesquisar etiquetas",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# etiqueta} other {# etiquetas}}",
"labelOverflowCount": "+{count, plural, one {# etiqueta} other {# etiquetas}}",
"accessLabelFilterClear": "Limpar filtros de etiquetas",
"accessFilterClear": "Clear filters",
"selectColor": "Selecionar cor",
"createNewLabel": "Criar nova etiqueta na organização \"{label}\"",
"inviteInvalidDescription": "O link do convite é inválido.",
"inviteErrorWrongUser": "O convite não é para este utilizador",
"inviteErrorUserNotExists": "O utilizador não existe. Por favor, crie uma conta primeiro.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Recursos",
"sidebarProxyResources": "Público",
"sidebarClientResources": "Privado",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Controle de Acesso",
"sidebarLogsAndAnalytics": "Registros e Análises",
"sidebarTeam": "Equipe",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Administrador",
"sidebarInvitations": "Convites",
"sidebarRoles": "Papéis",
"sidebarShareableLinks": "Links",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "Chaves API",
"sidebarProvisioning": "Provisionamento",
"sidebarSettings": "Configurações",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Site {id}",
"standaloneHcFilterResourceIdFallback": "Recurso {id}",
"blueprints": "Diagramas",
"blueprintsDescription": "Aplicar configurações declarativas e ver execuções anteriores",
"blueprintsLog": "Registo dos Blueprint",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Adicionar Diagrama",
"blueprintGoBack": "Ver todos os Diagramas",
"blueprintCreate": "Criar Diagrama",
@@ -1575,7 +1732,17 @@
"contents": "Conteúdo",
"parsedContents": "Conteúdo analisado (Somente Leitura)",
"enableDockerSocket": "Habilitar o Diagrama Docker",
"enableDockerSocketDescription": "Ativar a scraping de rótulo Docker para rótulos de diagramas. Caminho de Socket deve ser fornecido para Newt.",
"enableDockerSocketDescription": "Ative a raspagem de etiquetas do Docker Socket para etiquetas de modelo. O caminho do Socket deve ser fornecido ao conector do site. Leia sobre como isso funciona na <docsLink>documentação</docsLink>.",
"newtAutoUpdate": "Ativar Atualização Automática do Site",
"newtAutoUpdateDescription": "Quando ativado, os conectores de site atualizarão automaticamente para a versão mais recente quando uma nova versão estiver disponível.",
"siteAutoUpdate": "Atualização Automática do Site",
"siteAutoUpdateLabel": "Ativar Atualização Automática",
"siteAutoUpdateDescription": "Controle se o conector deste site baixa automaticamente a versão mais recente.",
"siteAutoUpdateOrgDefault": "Padrão da organização: {state}",
"siteAutoUpdateOverriding": "Substituindo configuração da organização",
"siteAutoUpdateResetToOrg": "Redefinir para Padrão da Organização",
"siteAutoUpdateEnabled": "ativado",
"siteAutoUpdateDisabled": "desabilitado",
"viewDockerContainers": "Ver contêineres Docker",
"containersIn": "Contêineres em {siteName}",
"selectContainerDescription": "Selecione qualquer contêiner para usar como hostname para este alvo. Clique em uma porta para usar uma porta.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Certificado",
"certificateStatusAutoRefreshHint": "Status atualiza automaticamente.",
"loading": "Carregando",
"loadingEllipsis": "Carregando...",
"loadingAnalytics": "Carregando Analytics",
"restart": "Reiniciar",
"domains": "Domínios",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Gerencie sua assinatura para as chaves de licenças auto-hospedadas pagas",
"billingCurrentKeys": "Chaves atuais",
"billingModifyCurrentPlan": "Modificar o Plano Atual",
"billingManageLicenseSubscriptionDescription": "Gerencie sua assinatura de chaves de licença auto-hospedadas pagas e baixe faturas.",
"billingConfirmUpgrade": "Confirmar a atualização",
"billingConfirmDowngrade": "Confirmar downgrade",
"billingConfirmUpgradeDescription": "Você está prestes a atualizar seu plano. Revise os novos limites e preços abaixo.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Desconhecido",
"healthCheck": "Verificação de Saúde",
"configureHealthCheck": "Configurar Verificação de Saúde",
"configureHealthCheckDescription": "Configure a monitorização de saúde para {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Ativar Verificações de Saúde",
"healthCheckDisabledStateDescription": "Quando desativado, o site não realizará verificações de saúde e o estado será considerado desconhecido.",
"enableHealthChecksDescription": "Monitore a saúde deste alvo. Você pode monitorar um ponto de extremidade diferente do alvo, se necessário.",
"healthScheme": "Método",
"healthSelectScheme": "Selecione o Método",
"healthCheckPortInvalid": "A porta do exame de saúde deve estar entre 1 e 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Caminho",
"healthHostname": "IP / Nome do Host",
"healthPort": "Porta",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "O tempo está em segundos",
"requireDeviceApproval": "Exigir aprovação do dispositivo",
"requireDeviceApprovalDescription": "Usuários com esta função precisam de novos dispositivos aprovados por um administrador antes que eles possam se conectar e acessar recursos.",
"sshAccess": "Acesso SSH",
"sshSettings": "Configurações SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Configurações RDP",
"vncSettings": "Configurações VNC",
"sshServer": "Servidor SSH",
"rdpServer": "Servidor RDP",
"vncServer": "Servidor VNC",
"sshServerDescription": "Configure o método de autenticação, localização do daemon e destino do servidor",
"rdpServerDescription": "Configure o destino e a porta do servidor RDP",
"vncServerDescription": "Configure o destino e a porta do servidor VNC",
"sshServerMode": "Modo",
"sshServerModeStandard": "Servidor SSH Padrão",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Roteia comandos pela rede para um servidor SSH como o OpenSSH.",
"sshServerModeNative": "Servidor SSH Nativo",
"sshServerModeNativeDescription": "Executa comandos diretamente no host via Site Connector. Não é necessária configuração de rede.",
"sshAuthenticationMethod": "Método de Autenticação",
"sshAuthMethodManual": "Autenticação Manual",
"sshAuthMethodManualDescription": "Requer credenciais de host existentes. Ignora provisionamento automático.",
"sshAuthMethodAutomated": "Provisionamento Automatizado",
"sshAuthMethodAutomatedDescription": "Cria automaticamente usuários, grupos e permissões sudo no host.",
"sshAuthDaemonLocation": "Localização do Daemon de Autenticação",
"sshDaemonLocationSiteDescription": "Executa locais na máquina que hospeda o conector do site.",
"sshDaemonLocationRemote": "Em Host Remoto",
"sshDaemonLocationRemoteDescription": "Executa em uma máquina de destino separada na mesma rede.",
"sshDaemonDisclaimer": "Certifique-se de que seu host de destino está devidamente configurado para executar o daemon de autenticação antes de concluir esta configuração, ou o provisionamento falhará.",
"sshDaemonPort": "Porta do Daemon",
"sshServerDestination": "Destino do Servidor",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Destino",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Selecionar vários sites permite roteamento resiliente e failover para alta disponibilidade.",
"roleAllowSsh": "Permitir SSH",
"roleAllowSshAllow": "Autorizar",
"roleAllowSshDisallow": "Anular",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Usuário só pode executar os comandos especificados com sudo.",
"sshSudo": "Permitir sudo",
"sshSudoCommands": "Comandos Sudo",
"sshSudoCommandsDescription": "Lista separada por vírgulas de comandos que o usuário pode executar com sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Criar Diretório Inicial",
"sshUnixGroups": "Grupos Unix",
"sshUnixGroupsDescription": "Grupos Unix separados por vírgulas para adicionar o usuário no host alvo.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Tentativas de Repetição",
"expectedResponseCodes": "Códigos de Resposta Esperados",
"expectedResponseCodesDescription": "Código de status HTTP que indica estado saudável. Se deixado em branco, 200-300 é considerado saudável.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Esquema",
"editInternalResourceDialogEnableSsl": "Ativar TLS",
"editInternalResourceDialogEnableSslDescription": "Ativar criptografia SSL/TLS para conexões HTTPS seguras com o destino.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Esquema",
"createInternalResourceDialogScheme": "Esquema",
"createInternalResourceDialogEnableSsl": "Ativar TLS",
@@ -2233,7 +2454,7 @@
"description": "Servidor Pangolin auto-hospedado mais confiável e com baixa manutenção com sinos extras e assobiamentos",
"introTitle": "Pangolin Auto-Hospedado Gerenciado",
"introDescription": "é uma opção de implantação projetada para pessoas que querem simplicidade e confiança adicional, mantendo os seus dados privados e auto-hospedados.",
"introDetail": "Com esta opção, você ainda roda seu próprio nó Pangolin - seus túneis, terminação TLS e tráfego todos permanecem no seu servidor. A diferença é que a gestão e a monitorização são geridos através do nosso painel de nuvem, que desbloqueia vários benefícios:",
"introDetail": "Com esta opção, você ainda roda seu próprio nó Pangolin - seus túneis, terminação TLS e tráfego permanecem no seu servidor. A diferença é que a gestão e a monitorização são feitas através do nosso painel de nuvem, que desbloqueia uma série de benefícios:",
"benefitSimplerOperations": {
"title": "Operações simples",
"description": "Não é necessário executar o seu próprio servidor de e-mail ou configurar um alerta complexo. Você receberá fora de caixa verificações de saúde e alertas de tempo de inatividade."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Inserir confirmação",
"blueprintViewDetails": "Detalhes",
"defaultIdentityProvider": "Provedor de Identidade Padrão",
"defaultIdentityProviderDescription": "Quando um provedor de identidade padrão for selecionado, o usuário será automaticamente redirecionado para o provedor de autenticação.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Configurações de Rede",
"editInternalResourceDialogAccessPolicy": "Política de Acesso",
"editInternalResourceDialogAddRoles": "Adicionar Funções",
@@ -2937,11 +3158,12 @@
"learnMore": "Saiba mais",
"backToHome": "Voltar para a página inicial",
"needToSignInToOrg": "Precisa usar o provedor de identidade da sua organização?",
"maintenanceMode": "Modo de Manutenção",
"maintenanceMode": "Página de Manutenção",
"maintenanceModeDescription": "Exibir uma página de manutenção para os visitantes",
"maintenanceModeType": "Tipo de Modo de Manutenção",
"showMaintenancePage": "Mostrar uma página de manutenção para os visitantes",
"enableMaintenanceMode": "Ativar Modo de Manutenção",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Automático",
"automaticModeDescription": "Exibir página de manutenção apenas quando todos os destinos de back-end estiverem inativos ou não saudáveis. Seu recurso continua funcionando normalmente desde que pelo menos um destino esteja saudável.",
"forced": "Forçado",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Conclusão Estimada:",
"createInternalResourceDialogDestinationRequired": "Destino é obrigatório",
"available": "Disponível",
"disabledResourceDescription": "Quando desativado, o recurso ficará inacessível para todos.",
"archived": "Arquivado",
"noArchivedDevices": "Nenhum dispositivo arquivado encontrado",
"deviceArchived": "Dispositivo arquivado",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Tem certeza de que deseja desassociar este provedor de identidade desta organização?",
"idpUnassociateDescription": "Todos os usuários associados a este provedor de identidade serão removidos desta organização, mas o provedor de identidade continuará a existir para outras organizações associadas.",
"idpUnassociateConfirm": "Confirmar Desassociação do Provedor de Identidade",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Isso não pode ser desfeito para esta organização.",
"idpUnassociatedDescription": "Provedor de identidade desassociado desta organização com sucesso",
"idpUnassociateMenu": "Desassociar",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Recurso Desativado",
"memberPortalShowingResources": "Mostrando {start}-{end} de {total} recursos",
"memberPortalPrevious": "Anterior",
"memberPortalNext": "Próximo"
"memberPortalNext": "Próximo",
"httpSettings": "Configurações HTTP",
"tcpSettings": "Configurações TCP",
"udpSettings": "Configurações UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Estabelecendo uma conexão segura…",
"sshConnecting": "A conectar…",
"sshInitializing": "A iniciar…",
"sshSignInTitle": "Entrar no SSH",
"sshSignInDescription": "Insira suas credenciais SSH",
"sshPasswordTab": "Palavra-passe",
"sshPrivateKeyTab": "Chave Privada",
"sshPrivateKeyField": "Chave Privada",
"sshPrivateKeyDisclaimer": "Sua chave privada não é armazenada ou visível para Pangolin. Alternativamente, você pode usar certificados de curta duração para autenticação perfeita usando sua identidade Pangolin existente.",
"sshLearnMore": "Saiba mais",
"sshPrivateKeyFile": "Arquivo de Chave Privada",
"sshAuthenticate": "Autenticar",
"sshTerminate": "Terminar",
"sshPoweredBy": "Desenvolvido por",
"sshErrorNoTarget": "Nenhum alvo especificado",
"sshErrorWebSocket": "Falha na conexão WebSocket",
"sshErrorAuthFailed": "Falha na autenticação",
"sshErrorConnectionClosed": "Conexão encerrada antes de concluir a autenticação",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Просмотр частных ресурсов",
"siteInstallNewt": "Установить Newt",
"siteInstallNewtDescription": "Запустите Newt в вашей системе",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "Конфигурация WireGuard",
"WgConfigurationDescription": "Используйте следующую конфигурацию для подключения к сети",
"operatingSystem": "Операционная система",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Вы сможете увидеть эти данные только один раз. Обязательно скопируйте их в безопасное место.",
"siteInfo": "Информация о сайте",
"status": "Статус",
"shareTitle": "Управление общими ссылками",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Создавайте общие ссылки, чтобы предоставить временный или постоянный доступ к прокси ресурсам",
"shareSearch": "Поиск общих ссылок...",
"shareCreate": "Создать общую ссылку",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Не удалось удалить ссылку",
"shareErrorDeleteMessage": "Произошла ошибка при удалении ссылки",
"shareDeleted": "Ссылка удалена",
"shareDeletedDescription": "Ссылка была успешно удалена",
"shareDelete": "Удалить общую ссылку",
"shareDeleteConfirm": "Подтвердите удаление общей ссылки",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Вы уверены, что хотите удалить эту общую ссылку?",
"shareMessageRemove": "После удаления ссылка перестанет работать, и все, кто ее использует, потеряют доступ к ресурсу.",
"shareTokenDescription": "Токен доступа может быть передан двумя способами: как параметр запроса или в заголовках запроса. Они должны быть переданы от клиента по каждому запросу для аутентифицированного доступа.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Произошла ошибка при создании общей ссылки",
"shareCreateDescription": "Любой, у кого есть эта ссылка, может получить доступ к ресурсу",
"shareTitleOptional": "Заголовок (необязательно)",
"sharePathOptional": "Путь (необязательно)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Срок действия",
"neverExpire": "Бессрочный доступ",
"shareExpireDescription": "Срок действия - это период, в течение которого ссылка будет работать и предоставлять доступ к ресурсу. После этого времени ссылка перестанет работать, и пользователи, использовавшие эту ссылку, потеряют доступ к ресурсу.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Пожалуйста, выберите ресурс",
"proxyResourceTitle": "Управление публичными ресурсами",
"proxyResourceDescription": "Создание и управление ресурсами, которые доступны через веб-браузер",
"proxyResourcesBannerTitle": "Общедоступный доступ через веб",
"proxyResourcesBannerDescription": "Общедоступные ресурсы - это прокси-по HTTPS или TCP/UDP, доступные любому пользователю в Интернете через веб-браузер. В отличие от частных ресурсов, они не требуют программного обеспечения на стороне клиента и могут включать политики доступа на основе идентификации и контекста.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Управление приватными ресурсами",
"clientResourceDescription": "Создание и управление ресурсами, которые доступны только через подключенный клиент",
"privateResourcesBannerTitle": "Частный доступ с нулевым доверием",
@@ -208,11 +212,36 @@
"resourcesSearch": "Поиск ресурсов...",
"resourceAdd": "Добавить ресурс",
"resourceErrorDelte": "Ошибка при удалении ресурса",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} ресурс(ов)",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "нет ресурсов",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Поиск политик...",
"resourcePoliciesAdd": "Добавить политику",
"resourcePoliciesDefaultBadgeText": "Политика по умолчанию",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Следуйте шагам ниже, чтобы создать новую политику",
"resourcePolicyName": "Имя политики",
"resourcePolicyNameDescription": "Дайте этой политике имя для идентификации ее в ваших ресурсах",
"resourcePolicyNamePlaceholder": "например, Политика внутреннего доступа",
"resourcePoliciesSeeAll": "Просмотреть все политики",
"resourcePolicyAuthMethodAdd": "Добавить метод аутентификации",
"resourcePolicyOtpEmailAdd": "Добавить OTP на email",
"resourcePolicyRulesAdd": "Добавить правила",
"resourcePolicyAuthMethodsDescription": "Разрешить доступ к ресурсам через дополнительные методы аутентификации",
"resourcePolicyUsersRolesDescription": "Настройте, какие пользователи и роли могут посещать связанные ресурсы",
"rulesResourcePolicyDescription": "Настройте правила для управления доступом к ресурсам, связанным с этой политикой",
"authentication": "Аутентификация",
"protected": "Защищён",
"notProtected": "Не защищён",
"resourceMessageRemove": "После удаления ресурс больше не будет доступен. Все целевые узлы, связанные с ресурсом, также будут удалены.",
"resourceQuestionRemove": "Вы уверены, что хотите удалить ресурс из организации?",
"resourcePolicyMessageRemove": "После удаления политика ресурса больше не будет доступна. Все ресурсы, связанные с ресурсом, будут отключены и останутся без аутентификации.",
"resourcePolicyQuestionRemove": "Вы уверены, что хотите удалить политику ресурса из организации?",
"resourceHTTP": "HTTPS-ресурс",
"resourceHTTPDescription": "Проксировать запросы через HTTPS с использованием полного доменного имени.",
"resourceRaw": "Сырой TCP/UDP-ресурс",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Прокси запросы через необработанный TCP/UDP с использованием номера порта. Требуется подключение сайтов к удаленному узлу.",
"resourceCreate": "Создание ресурса",
"resourceCreateDescription": "Следуйте инструкциям ниже для создания нового ресурса",
"resourceCreateGeneralDescription": "Настройте основные параметры ресурса, включая его имя и тип",
"resourceSeeAll": "Посмотреть все ресурсы",
"resourceInfo": "Информация о ресурсе",
"resourceCreateGeneral": "Общие",
"resourceNameDescription": "Отображаемое имя ресурса.",
"siteSelect": "Выберите сайт",
"siteSearch": "Поиск сайта",
@@ -231,12 +261,15 @@
"noCountryFound": "Страна не найдена.",
"siteSelectionDescription": "Этот сайт предоставит подключение к цели.",
"resourceType": "Тип ресурса",
"resourceTypeDescription": "Определить как получить доступ к ресурсу",
"resourceTypeDescription": "Это контролирует протокол ресурса и то, как он будет отображаться в браузере. Это нельзя изменить позже.",
"resourceDomainDescription": "Ресурс будет предоставлен по этому полностью определенному доменному имени.",
"resourceHTTPSSettings": "Настройки HTTPS",
"resourceHTTPSSettingsDescription": "Настройка доступа к ресурсу по HTTPS",
"resourcePortDescription": "Внешний порт на экземпляре или узле Pangolin, где ресурс будет доступен.",
"domainType": "Тип домена",
"subdomain": "Поддомен",
"baseDomain": "Базовый домен",
"configure": "Настроить",
"subdomnainDescription": "Поддомен, в котором ресурс будет доступен.",
"resourceRawSettings": "Настройки TCP/UDP",
"resourceRawSettingsDescription": "Настройка доступа к ресурсу по TCP/UDP",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "Узнайте, как настроить TCP/UDP-ресурсы",
"resourceBack": "Назад к ресурсам",
"resourceGoTo": "Перейти к ресурсу",
"resourcePolicyDelete": "Удалить политику ресурса",
"resourcePolicyDeleteConfirm": "Подтвердите удаление политики ресурса",
"resourceDelete": "Удалить ресурс",
"resourceDeleteConfirm": "Подтвердить удаление",
"labelDelete": "Удалить метку",
"labelAdd": "Добавить метку",
"labelCreateSuccessMessage": "Метка успешно создана",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Метка успешно изменена",
"labelNameField": "Название метки",
"labelColorField": "Цвет метки",
"labelPlaceholder": "Напр.: homelab",
"labelCreate": "Создать метку",
"createLabelDialogTitle": "Создать метку",
"createLabelDialogDescription": "Создайте новую метку, которая может быть прикреплена к этой организации",
"labelEdit": "Редактировать метку",
"editLabelDialogTitle": "Обновить метку",
"editLabelDialogDescription": "Измените новую метку, которую можно прикрепить к этой организации",
"labelDeleteConfirm": "Подтвердите удаление метки",
"labelErrorDelete": "Не удалось удалить метку",
"labelMessageRemove": "Это действие необратимо. Все сайты, ресурсы и клиенты, помеченные этой меткой, будут разметены.",
"labelQuestionRemove": "Вы уверены, что хотите удалить метку из организации?",
"visibility": "Видимость",
"enabled": "Включено",
"disabled": "Отключено",
@@ -265,6 +319,8 @@
"rules": "Правила",
"resourceSettingDescription": "Настройка параметров ресурса",
"resourceSetting": "Настройки {resourceName}",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "Настройки {policyName}",
"alwaysAllow": "Авторизация байпасса",
"alwaysDeny": "Блокировать доступ",
"passToAuth": "Переход к аутентификации",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Дублирующее правило",
"rulesErrorDuplicateDescription": "Правило с такими настройками уже существует",
"rulesErrorInvalidIpAddressRange": "Неверный CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Пожалуйста, введите корректное значение CIDR",
"rulesErrorInvalidUrl": "Неверный URL путь",
"rulesErrorInvalidUrlDescription": "Пожалуйста, введите корректное значение URL пути",
"rulesErrorInvalidIpAddress": "Неверный IP",
"rulesErrorInvalidIpAddressDescription": "Пожалуйста, введите корректный IP адрес",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Не удалось обновить правила",
"rulesErrorUpdateDescription": "Произошла ошибка при обновлении правил",
"rulesUpdated": "Включить правила",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "Введите адрес в формате CIDR (например, 103.21.244.0/22)",
"rulesMatchIpAddress": "Введите IP адрес (например, 103.21.244.12)",
"rulesMatchUrl": "Введите URL путь или шаблон (например, /api/v1/todos или /api/v1/*)",
"rulesErrorInvalidPriority": "Неверный приоритет",
"rulesErrorInvalidPriorityDescription": "Пожалуйста, введите корректный приоритет",
"rulesErrorDuplicatePriority": "Дублирующие приоритеты",
"rulesErrorDuplicatePriorityDescription": "Пожалуйста, введите уникальные приоритеты",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Правила обновлены",
"ruleUpdatedDescription": "Правила успешно обновлены",
"ruleErrorUpdate": "Операция не удалась",
"ruleErrorUpdateDescription": "Произошла ошибка во время операции сохранения",
"rulesPriority": "Приоритет",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Действие",
"rulesMatchType": "Тип совпадения",
"value": "Значение",
@@ -744,9 +809,60 @@
"rulesResource": "Конфигурация правил ресурса",
"rulesResourceDescription": "Настройка правил для контроля доступа к ресурсу",
"ruleSubmit": "Добавить правило",
"rulesNoOne": "Нет правил. Добавьте правило с помощью формы.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Правила оцениваются по приоритету в возрастающем порядке.",
"rulesSubmit": "Сохранить правила",
"policyErrorCreate": "Ошибка создания политики",
"policyErrorCreateDescription": "Произошла ошибка при создании политики",
"policyErrorCreateMessageDescription": "Произошла неожиданная ошибка",
"policyErrorUpdate": "Ошибка обновления политики",
"policyErrorUpdateDescription": "Произошла ошибка при обновлении политики",
"policyErrorUpdateMessageDescription": "Произошла неожиданная ошибка",
"policyCreatedSuccess": "Политика ресурса успешно создана",
"policyUpdatedSuccess": "Политика ресурса успешно обновлена",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Сохранить правила",
"resourceErrorCreate": "Ошибка при создании ресурса",
"resourceErrorCreateDescription": "Произошла ошибка при создании ресурса",
"resourceErrorCreateMessage": "Ошибка создания ресурса:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Произошла ошибка при обновлении ресурса",
"access": "Доступ",
"accessControl": "Контроль доступа",
"shareLink": "Общая ссылка {resource}",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Выберите ресурс",
"shareLinks": "Общие ссылки",
"shareLinks": "Shareable Links",
"share": "Общие ссылки",
"shareDescription2": "Создавайте общие ссылки на ресурсы. Ссылки обеспечивают временный или неограниченный доступ к вашему ресурсу. Вы можете настроить продолжительность действия ссылки при ее создании.",
"shareEasyCreate": "Легко создавать и делиться",
@@ -810,6 +926,17 @@
"pincodeAdd": "Добавить PIN-код",
"pincodeRemove": "Удалить PIN-код",
"resourceAuthMethods": "Методы аутентификации",
"resourcePolicyAuthMethodsEmpty": "Нет метода аутентификации",
"resourcePolicyOtpEmpty": "Нет одноразового пароля",
"resourcePolicyReadOnly": "Эта политика только для чтения",
"resourcePolicyReadOnlyDescription": "Эта политика ресурса разделяется между несколькими ресурсами, вы не можете улучшить ее на этой странице.",
"editSharedPolicy": "Редактировать общую политику",
"resourcePolicyTypeSave": "Сохранить тип ресурса",
"resourcePolicySelect": "Выберите политику ресурса",
"resourcePolicySelectError": "Выберите политику ресурса",
"resourcePolicyNotFound": "Политика не найдена",
"resourcePolicySearch": "Поиск политик",
"resourcePolicyRulesEmpty": "Нет правил аутентификации",
"resourceAuthMethodsDescriptions": "Разрешить доступ к ресурсу через дополнительные методы аутентификации",
"resourceAuthSettingsSave": "Успешно сохранено",
"resourceAuthSettingsSaveDescription": "Настройки аутентификации сохранены",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Установить PIN-код",
"resourcePincodeSetupTitleDescription": "Установите PIN-код для защиты этого ресурса",
"resourceRoleDescription": "Администраторы всегда имеют доступ к этому ресурсу.",
"resourcePolicySelectTitle": "Политика доступа к ресурсам",
"resourcePolicySelectDescription": "Выберите тип политики ресурса для аутентификации",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Политика ресурса на месте",
"resourcePolicyInlineDescription": "Политика доступа ограничена только этим ресурсом",
"resourcePolicyShared": "Общая политика ресурса",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Контроль доступа",
"resourceUsersRolesDescription": "Выберите пользователей и роли с доступом к этому ресурсу",
"resourceUsersRolesSubmit": "Сохранить контроль доступа",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "Возникла проблема при подключении к {name}. Пожалуйста, свяжитесь с вашим администратором.",
"idpErrorNotFound": "IdP не найден",
"inviteInvalid": "Недействительное приглашение",
"labels": "Метки",
"orgLabelsDescription": "Управление метками в этой организации.",
"addLabels": "Добавить метки",
"siteLabelsTab": "Метки",
"siteLabelsDescription": "Управляйте метками, связанными с этим сайтом.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Поиск меток",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# метка} few {# метки} many {# меток} other {# меток}}",
"labelOverflowCount": "+{count, plural, one {# метка} few {# метки} many {# меток} other {# меток}}",
"accessLabelFilterClear": "Очистить фильтры меток",
"accessFilterClear": "Clear filters",
"selectColor": "Выберите цвет",
"createNewLabel": "Создать новую метку организации \"{label}\"",
"inviteInvalidDescription": "Ссылка на приглашение недействительна.",
"inviteErrorWrongUser": "Приглашение не для этого пользователя",
"inviteErrorUserNotExists": "Пользователь не существует. Пожалуйста, сначала создайте учетную запись.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Ресурсы",
"sidebarProxyResources": "Публичный",
"sidebarClientResources": "Приватный",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Контроль доступа",
"sidebarLogsAndAnalytics": "Журналы и аналитика",
"sidebarTeam": "Команда",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Админ",
"sidebarInvitations": "Приглашения",
"sidebarRoles": "Роли",
"sidebarShareableLinks": "Ссылки",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API ключи",
"sidebarProvisioning": "Подготовка",
"sidebarSettings": "Настройки",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Сайт {id}",
"standaloneHcFilterResourceIdFallback": "Ресурс {id}",
"blueprints": "Чертежи",
"blueprintsDescription": "Применить декларирующие конфигурации и просмотреть предыдущие запуски",
"blueprintsLog": "Журнал чертежей",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Добавить чертёж",
"blueprintGoBack": "Посмотреть все чертежи",
"blueprintCreate": "Создать чертёж",
@@ -1575,7 +1732,17 @@
"contents": "Содержание",
"parsedContents": "Переработанное содержимое (только для чтения)",
"enableDockerSocket": "Включить чертёж Docker",
"enableDockerSocketDescription": "Включить scraping ярлыка Docker Socket для ярлыков чертежей. Путь к сокету должен быть предоставлен в Newt.",
"enableDockerSocketDescription": "Включить сбор меток Docker Socket для чертежей. Путь сокета должен быть предоставлен подключателю сайта. Прочтите о том, как это работает, в <docsLink>документации</docsLink>.",
"newtAutoUpdate": "Включить автообновление сайта",
"newtAutoUpdateDescription": "При включении, коннекторы сайта будут автоматически обновляться до последней версии, когда доступен новый выпуск.",
"siteAutoUpdate": "Автообновление сайта",
"siteAutoUpdateLabel": "Включить автообновление",
"siteAutoUpdateDescription": "Контролировать, будет ли коннектор этого сайта автоматически загружать последнюю версию.",
"siteAutoUpdateOrgDefault": "Значение по умолчанию для организации: {state}",
"siteAutoUpdateOverriding": "Переопределение настройки организации",
"siteAutoUpdateResetToOrg": "Сброс до значения по умолчанию для организации",
"siteAutoUpdateEnabled": "включено",
"siteAutoUpdateDisabled": "отключено",
"viewDockerContainers": "Просмотр контейнеров Docker",
"containersIn": "Контейнеры в {siteName}",
"selectContainerDescription": "Выберите любой контейнер для использования в качестве имени хоста для этой цели. Нажмите на порт, чтобы использовать порт.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Сертификат",
"certificateStatusAutoRefreshHint": "Статус обновляется автоматически.",
"loading": "Загрузка",
"loadingEllipsis": "Загрузка...",
"loadingAnalytics": "Загрузка аналитики",
"restart": "Перезагрузка",
"domains": "Домены",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Управление подпиской на платные лицензионные ключи собственного хостинга",
"billingCurrentKeys": "Текущие ключи",
"billingModifyCurrentPlan": "Изменить текущий план",
"billingManageLicenseSubscriptionDescription": "Управление вашей подпиской на платные ключи лицензии для самостоятельной установки и загрузка счетов.",
"billingConfirmUpgrade": "Подтвердить обновление",
"billingConfirmDowngrade": "Подтверждение понижения",
"billingConfirmUpgradeDescription": "Вы собираетесь обновить тарифный план. Проверьте новые лимиты и цены ниже.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Неизвестно",
"healthCheck": "Проверка здоровья",
"configureHealthCheck": "Настроить проверку здоровья",
"configureHealthCheckDescription": "Настройте мониторинг состояния для {target}",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Включить проверки здоровья",
"healthCheckDisabledStateDescription": "Когда отключен, сайт не будет выполнять проверки состояния и состояние будет считаться неизвестным.",
"enableHealthChecksDescription": "Мониторинг здоровья этой цели. При необходимости можно контролировать другую конечную точку.",
"healthScheme": "Метод",
"healthSelectScheme": "Выберите метод",
"healthCheckPortInvalid": "Порт проверки здоровья должен быть от 1 до 65535",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Путь",
"healthHostname": "IP / хост",
"healthPort": "Порт",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Время указано в секундах",
"requireDeviceApproval": "Требовать подтверждения устройства",
"requireDeviceApprovalDescription": "Пользователям с этой ролью нужны новые устройства, одобренные администратором, прежде чем они смогут подключаться и получать доступ к ресурсам.",
"sshAccess": "SSH доступ",
"sshSettings": "Настройки SSH",
"sshAccess": "SSH Access",
"rdpSettings": "Настройки RDP",
"vncSettings": "Настройки VNC",
"sshServer": "SSH сервер",
"rdpServer": "RDP сервер",
"vncServer": "VNC сервер",
"sshServerDescription": "Настройка метода аутентификации, местоположения демона и пункта назначения сервера",
"rdpServerDescription": "Настройте пункт назначения и порт RDP-сервера",
"vncServerDescription": "Настройте пункт назначения и порт VNC-сервера",
"sshServerMode": "Режим",
"sshServerModeStandard": "Стандартный SSH-сервер",
"sshServerModePangolin": "SSH Pangolin",
"sshServerModeStandardDescription": "Маршрутизация команд по сети к SSH-серверу, такому как OpenSSH.",
"sshServerModeNative": "Родной SSH-сервер",
"sshServerModeNativeDescription": "Выполняет команды напрямую на хосте через сайт-коннектор. Настройка сети не требуется.",
"sshAuthenticationMethod": "Метод аутентификации",
"sshAuthMethodManual": "Ручная аутентификация",
"sshAuthMethodManualDescription": "Требуется наличие существующих учетных данных хоста. Обходит автоматическое предоставление.",
"sshAuthMethodAutomated": "Автоматизированное предоставление",
"sshAuthMethodAutomatedDescription": "Автоматически создает пользователей, группы и разрешения sudo на хосте.",
"sshAuthDaemonLocation": "Местоположение демона аутентификации",
"sshDaemonLocationSiteDescription": "Выполняется локально на машине, размещающей сайт-коннектор.",
"sshDaemonLocationRemote": "На удаленном хосте",
"sshDaemonLocationRemoteDescription": "Выполняется на отдельной целевой машине в той же сети.",
"sshDaemonDisclaimer": "Убедитесь, что целевой хост правильно настроен для запуска демона аутентификации перед завершением этой настройки, иначе предоставление не удастся.",
"sshDaemonPort": "Порт демона",
"sshServerDestination": "Пункт назначения сервера",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Пункт назначения",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Выбор нескольких сайтов включает в себя устойчивую маршрутизацию и автоматический отказ для обеспечения высокой доступности.",
"roleAllowSsh": "Разрешить SSH",
"roleAllowSshAllow": "Разрешить",
"roleAllowSshDisallow": "Запретить",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Пользователь может запускать только указанные команды с помощью sudo.",
"sshSudo": "Разрешить sudo",
"sshSudoCommands": "Sudo Команды",
"sshSudoCommandsDescription": "Список команд, разделенных запятыми, которые пользователю разрешено запускать с помощью sudo.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Создать домашний каталог",
"sshUnixGroups": "Unix группы",
"sshUnixGroupsDescription": "Группы Unix через запятую, чтобы добавить пользователя на целевой хост.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Количество попыток повторного запроса",
"expectedResponseCodes": "Ожидаемые коды ответов",
"expectedResponseCodesDescription": "HTTP-код состояния, указывающий на здоровое состояние. Если оставить пустым, 200-300 считается здоровым.",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "СИДР",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Схема",
"editInternalResourceDialogEnableSsl": "Включить TLS",
"editInternalResourceDialogEnableSslDescription": "Включите шифрование SSL/TLS для защищенных HTTPS соединений с конечной точкой.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "СИДР",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Схема",
"createInternalResourceDialogScheme": "Схема",
"createInternalResourceDialogEnableSsl": "Включить TLS",
@@ -2233,7 +2454,7 @@
"description": "Более надежный и низко обслуживаемый сервер Pangolin с дополнительными колокольнями и свистками",
"introTitle": "Управляемый Само-Хост Панголина",
"introDescription": "- это вариант развертывания, предназначенный для людей, которые хотят простоты и надёжности, сохраняя при этом свои данные конфиденциальными и самостоятельными.",
"introDetail": "С помощью этой опции вы по-прежнему используете узел Pangolin - туннели, TLS, и весь остающийся на вашем сервере. Разница заключается в том, что управление и мониторинг осуществляются через нашу панель инструментов из облака, которая открывает ряд преимуществ:",
"introDetail": "С помощью этой опции вы по-прежнему используете узел Pangolin - ваши туннели, завершение TLS и трафик остаются на вашем сервере. Разница заключается в том, что управление и мониторинг осуществляются через наш облачный интерфейс, что открывает ряд преимуществ:",
"benefitSimplerOperations": {
"title": "Более простые операции",
"description": "Не нужно запускать свой собственный почтовый сервер или настроить комплексное оповещение. Вы будете получать проверки состояния здоровья и оповещения о неисправностях из коробки."
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Введите подтверждение",
"blueprintViewDetails": "Подробности",
"defaultIdentityProvider": "Поставщик удостоверений по умолчанию",
"defaultIdentityProviderDescription": "Когда выбран поставщик идентификации по умолчанию, пользователь будет автоматически перенаправлен на провайдер для аутентификации.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Настройки сети",
"editInternalResourceDialogAccessPolicy": "Политика доступа",
"editInternalResourceDialogAddRoles": "Добавить роли",
@@ -2937,11 +3158,12 @@
"learnMore": "Узнать больше",
"backToHome": "Вернуться домой",
"needToSignInToOrg": "Нужно использовать провайдера идентификаций вашей организации?",
"maintenanceMode": "Режим обслуживания",
"maintenanceMode": "Страница обслуживания",
"maintenanceModeDescription": "Показать страницу обслуживания посетителям",
"maintenanceModeType": "Тип режима обслуживания",
"showMaintenancePage": "Показать страницу обслуживания посетителям",
"enableMaintenanceMode": "Включить режим обслуживания",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Автоматический",
"automaticModeDescription": "Показывать страницу обслуживания только когда все цели бэкэнда недоступны или неисправны. Ваш ресурс продолжит работать нормально, пока хотя бы одна цель здорова.",
"forced": "Принудительно",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Предполагаемое завершение:",
"createInternalResourceDialogDestinationRequired": "Укажите адрес назначения. Это может быть имя хоста или IP-адрес.",
"available": "Доступно",
"disabledResourceDescription": "Когда отключено, ресурс будет недоступен для всех.",
"archived": "Архивировано",
"noArchivedDevices": "Архивные устройства не найдены",
"deviceArchived": "Устройство архивировано",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Вы уверены, что хотите рассоединить этого поставщика удостоверений с этой организацией?",
"idpUnassociateDescription": "Все пользователи, связанные с этим поставщиком удостоверений, будут удалены из этой организации, но поставщик удостоверений будет продолжать существовать для других связанных организаций.",
"idpUnassociateConfirm": "Подтвердите рассоединение поставщика удостоверений",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Это не может быть отменено для этой организации.",
"idpUnassociatedDescription": "Поставщик удостоверений успешно рассоединен с этой организацией",
"idpUnassociateMenu": "Рассоединить",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Ресурс отключён",
"memberPortalShowingResources": "Показаны {start}-{end} из {total} ресурсов",
"memberPortalPrevious": "Предыдущий",
"memberPortalNext": "Следующий"
"memberPortalNext": "Следующий",
"httpSettings": "Настройки HTTP",
"tcpSettings": "Настройки TCP",
"udpSettings": "Настройки UDP",
"sshTitle": "SSH",
"sshConnectingDescription": "Установление защищенного соединения…",
"sshConnecting": "Подключение…",
"sshInitializing": "Инициализация…",
"sshSignInTitle": "Вход в SSH",
"sshSignInDescription": "Введите свои учетные данные SSH",
"sshPasswordTab": "Пароль",
"sshPrivateKeyTab": "Закрытый ключ",
"sshPrivateKeyField": "Закрытый ключ",
"sshPrivateKeyDisclaimer": "Ваш закрытый ключ не хранится и не виден для Pangolin. Вместо этого вы можете использовать краткосрочные сертификаты для бесшовной аутентификации с использованием вашей текущей идентификации Pangolin.",
"sshLearnMore": "Узнать больше",
"sshPrivateKeyFile": "Файл закрытого ключа",
"sshAuthenticate": "Аутентификация",
"sshTerminate": "Завершить",
"sshPoweredBy": "Разработано",
"sshErrorNoTarget": "Цель не указана",
"sshErrorWebSocket": "Подключение WebSocket не удалось",
"sshErrorAuthFailed": "Ошибка аутентификации",
"sshErrorConnectionClosed": "Подключение закрыто до завершения аутентификации",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "Özel Kaynakları Görüntüle",
"siteInstallNewt": "Newt Yükle",
"siteInstallNewtDescription": "Newt'i sisteminizde çalıştırma",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard Yapılandırması",
"WgConfigurationDescription": "Ağınıza bağlanmak için aşağıdaki yapılandırmayı kullanın",
"operatingSystem": "İşletim Sistemi",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "Yalnızca bir kez görebileceksiniz. Güvenli bir yere kopyaladığınızdan emin olun.",
"siteInfo": "Site Bilgilendirmesi",
"status": "Durum",
"shareTitle": "Paylaşım Bağlantılarını Yönet",
"shareTitle": "Manage Shareable Links",
"shareDescription": "Kaynaklarınıza geçici veya kalıcı erişim sağlamak için paylaşılabilir bağlantılar oluşturun",
"shareSearch": "Paylaşım bağlantılarını ara...",
"shareCreate": "Paylaşım Bağlantısı Oluştur",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "Bağlantı silinirken hata oluştu",
"shareErrorDeleteMessage": "Bağlantı silinirken bir hata oluştu",
"shareDeleted": "Bağlantı silindi",
"shareDeletedDescription": "Bağlantı silindi",
"shareDelete": "Paylaşım Bağlantısını Sil",
"shareDeleteConfirm": "Paylaşım Bağlantısının Silinmesini Onayla",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "Bu paylaşım bağlantısını silmek istediğinizden emin misiniz?",
"shareMessageRemove": "Silindikten sonra, bağlantı artık çalışmayacak ve kullanan herkes kaynağa erişimini kaybedecek.",
"shareTokenDescription": "Erişim jetonunuz iki şekilde iletilebilir: sorgu parametresi olarak veya istek başlıklarında. Kimlik doğrulanmış erişim için her istekten müşteri tarafından iletilmelidir.",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "Paylaşım bağlantısı oluşturulurken bir hata oluştu",
"shareCreateDescription": "Bu bağlantıya sahip olan herkes kaynağa erişebilir",
"shareTitleOptional": "Başlık (isteğe bağlı)",
"sharePathOptional": "Yol (isteğe bağlı)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "Süresi Dolacak",
"neverExpire": "Hiçbir Zaman Sona Ermez",
"shareExpireDescription": "Son kullanma süresi, bağlantının kullanılabilir ve kaynağa erişim sağlayacak süresidir. Bu süreden sonra bağlantı çalışmayı durduracak ve bu bağlantıyı kullanan kullanıcılar kaynağa erişimini kaybedecektir.",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "Lütfen bir kaynak seçin",
"proxyResourceTitle": "Herkese Açık Kaynakları Yönet",
"proxyResourceDescription": "Bir web tarayıcısı aracılığıyla kamuya açık kaynaklar oluşturun ve yönetin",
"proxyResourcesBannerTitle": "Web Tabanlı Genel Erişim",
"proxyResourcesBannerDescription": "Genel kaynaklar, web tarayıcısı aracılığıyla herkesin internette erişebileceği HTTPS veya TCP/UDP proxy'leridir. Özel kaynakların aksine, istemci tarafı yazılıma ihtiyaç duymazlar ve kimlik ve bağlam farkındalığı erişim politikalarını içerebilirler.",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "Özel Kaynakları Yönet",
"clientResourceDescription": "Sadece bağlı bir istemci aracılığıyla erişilebilen kaynakları oluşturun ve yönetin",
"privateResourcesBannerTitle": "Sıfır Güven Özel Erişim",
@@ -208,11 +212,36 @@
"resourcesSearch": "Kaynakları ara...",
"resourceAdd": "Kaynak Ekle",
"resourceErrorDelte": "Kaynak silinirken hata",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} kaynak",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "hiçbir kaynak",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "Politikaları ara...",
"resourcePoliciesAdd": "Politika Ekle",
"resourcePoliciesDefaultBadgeText": "Varsayılan politika",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "Yeni bir politika oluşturmak için aşağıdaki adımları izleyin",
"resourcePolicyName": "Politika Adı",
"resourcePolicyNameDescription": "Bu politikaya kaynaklarınız arasında kolayca tanımlayabilmek için bir ad verin",
"resourcePolicyNamePlaceholder": "örneğin: İç Erişim Politikası",
"resourcePoliciesSeeAll": "Tüm Politikaları Gör",
"resourcePolicyAuthMethodAdd": "Kimlik Doğrulama Yöntemi Ekle",
"resourcePolicyOtpEmailAdd": "OTP e-postaları ekle",
"resourcePolicyRulesAdd": "Kurallar Ekle",
"resourcePolicyAuthMethodsDescription": "Ek kimlik doğrulama yöntemleri aracılığıyla kaynaklara erişime izin verin",
"resourcePolicyUsersRolesDescription": "Hangi kullanıcılar ve rollerin ilgili kaynakları ziyaret edebileceğini yapılandırın",
"rulesResourcePolicyDescription": "Bu politikayla ilişkilendirilmiş erişim kaynaklarını kontrol etmek için kuralları yapılandırın",
"authentication": "Kimlik Doğrulama",
"protected": "Korunan",
"notProtected": "Korunmayan",
"resourceMessageRemove": "Kaldırıldıktan sonra kaynak artık erişilebilir olmayacaktır. Kaynakla ilişkili tüm hedefler de kaldırılacaktır.",
"resourceQuestionRemove": "Kaynağı organizasyondan kaldırmak istediğinizden emin misiniz?",
"resourcePolicyMessageRemove": "Kaldırıldıktan sonra kaynak politikası artık erişilebilir olmayacak. Kaynakla ilişkili tüm öğeler bağlantıları koparılacak ve kimlik doğrulaması olmadan bırakılacaktır.",
"resourcePolicyQuestionRemove": "Kaynak politikasını organizasyondan kaldırmak istediğinizden emin misiniz?",
"resourceHTTP": "HTTPS Kaynağı",
"resourceHTTPDescription": "Tam nitelikli bir etki alanı adı kullanarak HTTPS üzerinden proxy isteklerini yönlendirin.",
"resourceRaw": "Ham TCP/UDP Kaynağı",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "Proxy isteklerini bir port numarası kullanarak ham TCP/UDP üzerinden yapın. Sitelerin uzak bir düğüme bağlanması gereklidir.",
"resourceCreate": "Kaynak Oluştur",
"resourceCreateDescription": "Yeni bir kaynak oluşturmak için aşağıdaki adımları izleyin",
"resourceCreateGeneralDescription": "Adı ve türü dahil temel kaynak ayarlarını yapılandırın",
"resourceSeeAll": "Tüm Kaynakları Gör",
"resourceInfo": "Kaynak Bilgilendirmesi",
"resourceCreateGeneral": "Genel",
"resourceNameDescription": "Bu, kaynak için görünen addır.",
"siteSelect": "Site seç",
"siteSearch": "Site ara",
@@ -231,12 +261,15 @@
"noCountryFound": "Ülke bulunamadı.",
"siteSelectionDescription": "Bu site hedefe bağlantı sağlayacaktır.",
"resourceType": "Kaynak Türü",
"resourceTypeDescription": "Kaynağınıza nasıl erişmek istediğinizi belirleyin",
"resourceTypeDescription": "Bu, kaynak protokolünü ve tarayıcıda nasıl görüntüleneceğini kontrol eder. Bu daha sonra değiştirilemez.",
"resourceDomainDescription": "Kaynak bu tam etki alanı adıyla sunulacak.",
"resourceHTTPSSettings": "HTTPS Ayarları",
"resourceHTTPSSettingsDescription": "Kaynağınıza HTTPS üzerinden erişimin nasıl sağlanacağını yapılandırın",
"resourcePortDescription": "Kaynağa erişilebilecek Pangolin örneği veya düğüm üzerindeki harici bağlantı noktası.",
"domainType": "Alan Türü",
"subdomain": "Alt Alan Adı",
"baseDomain": "Temel Alan Adı",
"configure": "Yapılandır",
"subdomnainDescription": "Kaynağınızın erişilebileceği alt alan adı.",
"resourceRawSettings": "TCP/UDP Ayarları",
"resourceRawSettingsDescription": "Kaynaklara TCP/UDP üzerinden nasıl erişileceğini yapılandırın",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "TCP/UDP kaynaklarını nasıl yapılandıracağınızı öğrenin",
"resourceBack": "Kaynaklara Geri Dön",
"resourceGoTo": "Kaynağa Git",
"resourcePolicyDelete": "Kaynak Politikasını Sil",
"resourcePolicyDeleteConfirm": "Kaynak Politikasının Silinmesini Onayla",
"resourceDelete": "Kaynağı Sil",
"resourceDeleteConfirm": "Kaynak Silmeyi Onayla",
"labelDelete": "Etiketi Sil",
"labelAdd": "Etiket Ekle",
"labelCreateSuccessMessage": "Etiket Başarıyla Oluşturuldu",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "Etiket Başarıyla Değiştirildi",
"labelNameField": "Etiket Adı",
"labelColorField": "Etiket Rengi",
"labelPlaceholder": "Örn: homelab",
"labelCreate": "Etiket Oluştur",
"createLabelDialogTitle": "Etiket Oluştur",
"createLabelDialogDescription": "Bu kuruluşa eklenebilecek yeni bir etiket oluşturun",
"labelEdit": "Etiketi Düzenle",
"editLabelDialogTitle": "Etiketi Güncelle",
"editLabelDialogDescription": "Bu kuruluşa eklenebilecek yeni bir etiketi düzenleyin",
"labelDeleteConfirm": "Etiketi Silmeyi Onayla",
"labelErrorDelete": "Etiket silinirken hata oluştu",
"labelMessageRemove": "Bu işlem kalıcıdır. Bu etiket ile etiketlenmiş tüm siteler, kaynaklar ve kullanıcılar etiketsiz kalacaktır.",
"labelQuestionRemove": "Etiketi organizasyondan kaldırmak istediğinizden emin misiniz?",
"visibility": "Görünürlük",
"enabled": "Etkin",
"disabled": "Devre Dışı",
@@ -265,6 +319,8 @@
"rules": "Kurallar",
"resourceSettingDescription": "Kaynağınızdaki ayarları yapılandırın",
"resourceSetting": "{resourceName} Ayarları",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} Ayarları",
"alwaysAllow": "Kimlik Doğrulamayı Atla",
"alwaysDeny": "Erişimi Engelle",
"passToAuth": "Kimlik Doğrulamasına Geç",
@@ -630,7 +686,7 @@
"createdAt": "Oluşturulma Tarihi",
"proxyErrorInvalidHeader": "Geçersiz özel Ana Bilgisayar Başlığı değeri. Alan adı formatını kullanın veya özel Ana Bilgisayar Başlığını ayarlamak için boş bırakın.",
"proxyErrorTls": "Geçersiz TLS Sunucu Adı. Alan adı formatını kullanın veya TLS Sunucu Adını kaldırmak için boş bırakılsın.",
"proxyEnableSSL": "TLS Etkinleştir",
"proxyEnableSSL": "TLS'yi Etkinleştir",
"proxyEnableSSLDescription": "Hedeflere güvenli HTTPS bağlantıları için SSL/TLS şifrelemesini etkinleştirin.",
"target": "Hedef",
"configureTarget": "Hedefleri Yapılandır",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "Yinelenen kural",
"rulesErrorDuplicateDescription": "Bu ayarlara sahip bir kural zaten mevcut",
"rulesErrorInvalidIpAddressRange": "Geçersiz CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "Lütfen geçerli bir CIDR değeri girin",
"rulesErrorInvalidUrl": "Geçersiz URL yolu",
"rulesErrorInvalidUrlDescription": "Lütfen geçerli bir URL yolu değeri girin",
"rulesErrorInvalidIpAddress": "Geçersiz IP",
"rulesErrorInvalidIpAddressDescription": "Lütfen geçerli bir IP adresi girin",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "Kurallar güncellenemedi",
"rulesErrorUpdateDescription": "Kurallar güncellenirken bir hata oluştu",
"rulesUpdated": "Kuralları Etkinleştir",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "CIDR formatında bir adres girin (örneğin, 103.21.244.0/22)",
"rulesMatchIpAddress": "Bir IP adresi girin (örneğin, 103.21.244.12)",
"rulesMatchUrl": "Bir URL yolu veya deseni girin (örneğin, /api/v1/todos veya /api/v1/*)",
"rulesErrorInvalidPriority": "Geçersiz Öncelik",
"rulesErrorInvalidPriorityDescription": "Lütfen geçerli bir öncelik girin",
"rulesErrorDuplicatePriority": "Yinelenen Öncelikler",
"rulesErrorDuplicatePriorityDescription": "Lütfen benzersiz öncelikler girin",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "Kurallar güncellendi",
"ruleUpdatedDescription": "Kurallar başarıyla güncellendi",
"ruleErrorUpdate": "Operasyon başarısız oldu",
"ruleErrorUpdateDescription": "Kaydetme operasyonu sırasında bir hata oluştu",
"rulesPriority": "Öncelik",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "Aksiyon",
"rulesMatchType": "Eşleşme Türü",
"value": "Değer",
@@ -744,9 +809,60 @@
"rulesResource": "Kaynak Kuralları Yapılandırması",
"rulesResourceDescription": "Kaynağa erişimi kontrol etmek için kuralları yapılandırın",
"ruleSubmit": "Kural Ekle",
"rulesNoOne": "Kural yok. Formu kullanarak bir kural ekleyin.",
"rulesNoOne": "No rules yet.",
"rulesOrder": "Kurallar, artan öncelik sırasına göre değerlendirilir.",
"rulesSubmit": "Kuralları Kaydet",
"policyErrorCreate": "Politika oluşturulurken hata oluştu",
"policyErrorCreateDescription": "Politikayı oluştururken bir hata oluştu",
"policyErrorCreateMessageDescription": "Beklenmeyen bir hata oluştu",
"policyErrorUpdate": "Politika güncellenirken hata oluştu",
"policyErrorUpdateDescription": "Policayı güncellerken bir hata oluştu",
"policyErrorUpdateMessageDescription": "Beklenmeyen bir hata oluştu",
"policyCreatedSuccess": "Kaynak politikası başarıyla oluşturuldu",
"policyUpdatedSuccess": "Kaynak politikası başarıyla güncellendi",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "Kuralları Kaydet",
"resourceErrorCreate": "Kaynak oluşturma hatası",
"resourceErrorCreateDescription": "Kaynak oluşturulurken bir hata oluştu",
"resourceErrorCreateMessage": "Kaynak oluşturma hatası:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "Kaynak güncellenirken bir hata oluştu",
"access": "Erişim",
"accessControl": "Erişim Kontrolü",
"shareLink": "{resource} Paylaşım Bağlantısı",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "Kaynak seçin",
"shareLinks": "Paylaşım Bağlantıları",
"shareLinks": "Shareable Links",
"share": "Paylaşılabilir Bağlantılar",
"shareDescription2": "Kaynaklarınıza geçici veya sınırsız erişim sağlamak için paylaşılabilir bağlantılar oluşturun. Bağlantı oluştururken sona erme süresini yapılandırabilirsiniz.",
"shareEasyCreate": "Kolayca oluştur ve paylaş",
@@ -810,6 +926,17 @@
"pincodeAdd": "PIN Kodu Ekle",
"pincodeRemove": "PIN Kodu Kaldır",
"resourceAuthMethods": "Kimlik Doğrulama Yöntemleri",
"resourcePolicyAuthMethodsEmpty": "Kimlik doğrulama yöntemi yok",
"resourcePolicyOtpEmpty": "Tek seferlik parola yok",
"resourcePolicyReadOnly": "Bu politika yalnızca okumalıdır",
"resourcePolicyReadOnlyDescription": "Bu kaynak politikası birden fazla kaynakla paylaşılmaktadır, bu sayfada düzenleyemezsiniz.",
"editSharedPolicy": "Paylaşılan Politikayı Düzenle",
"resourcePolicyTypeSave": "Kaynak türünü kaydet",
"resourcePolicySelect": "Kaynak politikasını seçin",
"resourcePolicySelectError": "Bir kaynak politikası seçin",
"resourcePolicyNotFound": "Politika bulunamadı",
"resourcePolicySearch": "Politikaları ara",
"resourcePolicyRulesEmpty": "Kimlik doğrulama kuralı yok",
"resourceAuthMethodsDescriptions": "Ek kimlik doğrulama yöntemleriyle kaynağa erişime izin verin",
"resourceAuthSettingsSave": "Başarıyla kaydedildi",
"resourceAuthSettingsSaveDescription": "Kimlik doğrulama ayarları kaydedildi",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "Pincode Ayarla",
"resourcePincodeSetupTitleDescription": "Bu kaynağı korumak için bir pincode ayarlayın",
"resourceRoleDescription": "Yöneticiler her zaman bu kaynağa erişebilir.",
"resourcePolicySelectTitle": "Kaynak Erişim Politikası",
"resourcePolicySelectDescription": "Kimlik doğrulama için kaynak politika türünü seçin",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "Satır İçi Kaynak Politikası",
"resourcePolicyInlineDescription": "Erişim Politikası sadece bu kaynağa yönelik",
"resourcePolicyShared": "Paylaşılan Kaynak Politikası",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "Erişim Kontrolleri",
"resourceUsersRolesDescription": "Bu kaynağı kimlerin ziyaret edebileceği kullanıcıları ve rolleri yapılandırın",
"resourceUsersRolesSubmit": "Erişim Kontrollerini Kaydet",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "{name} ile bağlantı kurarken bir sorun meydana geldi. Lütfen yöneticiye danışın.",
"idpErrorNotFound": "IdP bulunamadı",
"inviteInvalid": "Geçersiz Davet",
"labels": "Etiketler",
"orgLabelsDescription": "Bu organizasyondaki etiketleri yönetin.",
"addLabels": "Etiketler ekle",
"siteLabelsTab": "Etiketler",
"siteLabelsDescription": "Bu siteyle ilişkili etiketleri yönetin.",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "Etiket ara",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, one {# etiket} other {# etiketler}}",
"labelOverflowCount": "+{count, plural, one {# etiket} other {# etiketler}}",
"accessLabelFilterClear": "Etiket filtrelerini temizle",
"accessFilterClear": "Clear filters",
"selectColor": "Renk seç",
"createNewLabel": "Yeni kuruluş etiketi \"{label}\" oluştur",
"inviteInvalidDescription": "Davet bağlantısı geçersiz.",
"inviteErrorWrongUser": "Davet bu kullanıcı için değil",
"inviteErrorUserNotExists": "Kullanıcı mevcut değil. Lütfen önce bir hesap oluşturun.",
@@ -1374,6 +1528,8 @@
"sidebarResources": "Kaynaklar",
"sidebarProxyResources": "Herkese Açık",
"sidebarClientResources": "Özel",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "Erişim Kontrolü",
"sidebarLogsAndAnalytics": "Kayıtlar & Analitik",
"sidebarTeam": "Ekip",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "Yönetici",
"sidebarInvitations": "Davetiye",
"sidebarRoles": "Roller",
"sidebarShareableLinks": "Bağlantılar",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API Anahtarları",
"sidebarProvisioning": "Tedarik",
"sidebarSettings": "Ayarlar",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "Site {id}",
"standaloneHcFilterResourceIdFallback": "Kaynak {id}",
"blueprints": "Planlar",
"blueprintsDescription": "Deklaratif yapılandırmaları uygulayın ve önceki çalışmaları görüntüleyin",
"blueprintsLog": "Şablonlar Günlüğü",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "Plan Ekle",
"blueprintGoBack": "Tüm Planları Gör",
"blueprintCreate": "Plan Oluştur",
@@ -1575,7 +1732,17 @@
"contents": "İçerik",
"parsedContents": "Verilerin Ayrıştırılmış İçeriği (Salt Okunur)",
"enableDockerSocket": "Docker Soketini Etkinleştir",
"enableDockerSocketDescription": "Plan etiketleri için Docker Socket etiket toplamasını etkinleştirin. Newt'e soket yolu sağlanmalıdır.",
"enableDockerSocketDescription": "Plan etiketleri için Docker Socket etiket toplamasını etkinleştirin. Site bağlantısına soket yolu sağlanmalıdır. Bunun nasıl çalıştığını <docsLink>belgelemede</docsLink> okuyun.",
"newtAutoUpdate": "Site Otomatik-Güncellemesini Etkinleştir",
"newtAutoUpdateDescription": "Etkinleştirildiğinde, site bağdaştırıcıları yeni sürüm mevcut olduğunda otomatik olarak en son sürüme güncellenecek.",
"siteAutoUpdate": "Site Otomatik-Güncellemesi",
"siteAutoUpdateLabel": "Otomatik Güncellemeyi Etkinleştir",
"siteAutoUpdateDescription": "Bu sitenin bağdaştırıcısının en son sürümü otomatik olarak indirip indirmeyeceğini kontrol edin.",
"siteAutoUpdateOrgDefault": "Kuruluş varsayılanı: {state}",
"siteAutoUpdateOverriding": "Kuruluş ayarını geçersiz kılıyor",
"siteAutoUpdateResetToOrg": "Kuruluş Varsayılanına Sıfırla",
"siteAutoUpdateEnabled": "etkin",
"siteAutoUpdateDisabled": "devre dışı",
"viewDockerContainers": "Docker Konteynerlerini Görüntüle",
"containersIn": "{siteName} içindeki konteynerler",
"selectContainerDescription": "Bu hedef için bir ana bilgisayar adı olarak kullanmak üzere herhangi bir konteyner seçin. Bir bağlantı noktası kullanmak için bir bağlantı noktasına tıklayın.",
@@ -1620,6 +1787,7 @@
"certificateStatus": "Sertifika",
"certificateStatusAutoRefreshHint": "Durum otomatik olarak yenilenir.",
"loading": "Yükleniyor",
"loadingEllipsis": "Yükleniyor...",
"loadingAnalytics": "Analiz Yükleniyor",
"restart": "Yeniden Başlat",
"domains": "Alan Adları",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "Kendi barındırdığınız ücretli lisans anahtarları için aboneliğinizi yönetin",
"billingCurrentKeys": "Mevcut Anahtarlar",
"billingModifyCurrentPlan": "Mevcut Planı Düzenle",
"billingManageLicenseSubscriptionDescription": "Ücretli kendi barındırdığı lisans anahtarları için aboneliğinizi yönetin ve faturaları indirin.",
"billingConfirmUpgrade": "Yükseltmeyi Onayla",
"billingConfirmDowngrade": "Düşürmeyi Onayla",
"billingConfirmUpgradeDescription": "Planınızı yükseltmek üzeresiniz. Yeni limitleri ve fiyatları aşağıda inceleyin.",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "Bilinmiyor",
"healthCheck": "Sağlık Kontrolü",
"configureHealthCheck": "Sağlık Kontrolünü Yapılandır",
"configureHealthCheckDescription": "{hedef} için sağlık izleme kurun",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "Sağlık Kontrollerini Etkinleştir",
"healthCheckDisabledStateDescription": "Devre dışı bırakıldığında, site sağlık kontrolleri yapmaz ve durum bilinmeyen olarak kabul edilecektir.",
"enableHealthChecksDescription": "Bu hedefin sağlığını izleyin. Gerekirse hedef dışındaki bir son noktayı izleyebilirsiniz.",
"healthScheme": "Yöntem",
"healthSelectScheme": "Yöntem Seç",
"healthCheckPortInvalid": "Sağlık Kontrolü portu 1 ile 65535 arasında olmalıdır",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "Yol",
"healthHostname": "IP / Hostname",
"healthPort": "Bağlantı Noktası",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "Zaman saniye cinsindendir",
"requireDeviceApproval": "Cihaz Onaylarını Gerektir",
"requireDeviceApprovalDescription": "Bu role sahip kullanıcıların yeni cihazlarının bağlanabilmesi ve kaynaklara erişebilmesi için bir yönetici tarafından onaylanması gerekiyor.",
"sshAccess": "SSH Erişimi",
"sshSettings": "SSH Ayarları",
"sshAccess": "SSH Access",
"rdpSettings": "RDP Ayarları",
"vncSettings": "VNC Ayarları",
"sshServer": "SSH Sunucusu",
"rdpServer": "RDP Sunucusu",
"vncServer": "VNC Sunucusu",
"sshServerDescription": "Kimlik doğrulama yöntemi, daemon konumu ve sunucu hedefini ayarlayın",
"rdpServerDescription": "RDP sunucusunun hedefini ve bağlantı noktasını yapılandırın",
"vncServerDescription": "VNC sunucusunun hedefini ve bağlantı noktasını yapılandırın",
"sshServerMode": "Mod",
"sshServerModeStandard": "Standart SSH Sunucusu",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "Ağ üzerinden OpenSSH gibi bir SSH sunucusuna komutlar gönderir.",
"sshServerModeNative": "Yerel SSH Sunucusu",
"sshServerModeNativeDescription": "Site Bağlayıcısı üzerinden doğrudan ana bilgisayarda komutları çalıştırır. Ağ yapılandırması gerekmez.",
"sshAuthenticationMethod": "Kimlik Doğrulama Yöntemi",
"sshAuthMethodManual": "Manuel Kimlik Doğrulama",
"sshAuthMethodManualDescription": "Mevcut ana bilgisayar kimlik bilgileri gerektiriyor. Otomatik sağlama işlemini atlar.",
"sshAuthMethodAutomated": "Otomatik Sağlama",
"sshAuthMethodAutomatedDescription": "Ana bilgisayarda otomatik olarak kullanıcılar, gruplar ve sudo izinleri oluşturur.",
"sshAuthDaemonLocation": "Kimlik Doğrulama Daemon Konumu",
"sshDaemonLocationSiteDescription": "Site bağdaştırıcısını misafir eden makinada yerel olarak çalıştırır.",
"sshDaemonLocationRemote": "Uzak Ana Bilgisayarda",
"sshDaemonLocationRemoteDescription": "Aynı ağda ayrı bir hedef makinede çalıştırır.",
"sshDaemonDisclaimer": "Bu kurulumu tamamlamadan önce hedef ana bilgisayarınızın kimlik doğrulama daemonunu çalıştıracak şekilde düzgün yapılandırıldığından emin olun, aksi takdirde sağlama başarısız olur.",
"sshDaemonPort": "Daemon Bağlantı Noktası",
"sshServerDestination": "Sunucu Hedefi",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "Hedef",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "Birden fazla site seçmek, yüksek erişilebilirlik için dayanıklı yönlendirme ve failover sağlar.",
"roleAllowSsh": "SSH'a İzin Ver",
"roleAllowSshAllow": "İzin Ver",
"roleAllowSshDisallow": "İzin Verme",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "Kullanıcı sadece belirtilen komutları sudo ile çalıştırabilir.",
"sshSudo": "Sudo'ya izin ver",
"sshSudoCommands": "Sudo Komutları",
"sshSudoCommandsDescription": "Kullanıcının sudo ile çalıştırmasına izin verilen komutların virgülle ayrılmış listesi.",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "Ev Dizini Oluştur",
"sshUnixGroups": "Unix Grupları",
"sshUnixGroupsDescription": "Hedef konakta kullanıcıya eklenecek Unix gruplarının virgülle ayrılmış listesi.",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "Tekrar Deneme Girişimleri",
"expectedResponseCodes": "Beklenen Yanıt Kodları",
"expectedResponseCodesDescription": "Sağlıklı durumu gösteren HTTP durum kodu. Boş bırakılırsa, 200-300 arası sağlıklı kabul edilir.",
@@ -2049,8 +2268,9 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "Şema",
"editInternalResourceDialogEnableSsl": "TLS Etkinleştir",
"editInternalResourceDialogEnableSsl": "TLS'yi Etkinleştir",
"editInternalResourceDialogEnableSslDescription": "Hedefe güvenli HTTPS bağlantıları için SSL/TLS şifrelemeyi etkinleştirin.",
"editInternalResourceDialogDestination": "Hedef",
"editInternalResourceDialogDestinationHostDescription": "Site ağındaki kaynağın IP adresi veya ana bilgisayar adı.",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "Şema",
"createInternalResourceDialogScheme": "Şema",
"createInternalResourceDialogEnableSsl": "TLS'yi Etkinleştir",
@@ -2901,7 +3122,7 @@
"enterConfirmation": "Onayı girin",
"blueprintViewDetails": "Detaylar",
"defaultIdentityProvider": "Varsayılan Kimlik Sağlayıcı",
"defaultIdentityProviderDescription": "Varsayılan bir kimlik sağlayıcı seçildiğinde, kullanıcı kimlik doğrulaması için otomatik olarak sağlayıcıya yönlendirilecektir.",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "Ağ Ayarları",
"editInternalResourceDialogAccessPolicy": "Erişim Politikası",
"editInternalResourceDialogAddRoles": "Roller Ekle",
@@ -2937,11 +3158,12 @@
"learnMore": "Daha fazla bilgi",
"backToHome": "Ana sayfaya geri dön",
"needToSignInToOrg": "Kuruluşunuzun kimlik sağlayıcısını kullanmanız mı gerekiyor?",
"maintenanceMode": "Bakım Modu",
"maintenanceMode": "Bakım Sayfası",
"maintenanceModeDescription": "Ziyaretçilere bir bakım sayfası gösterin",
"maintenanceModeType": "Bakım Modu Türü",
"showMaintenancePage": "Ziyaretçilere bir bakım sayfası gösterin",
"enableMaintenanceMode": "Bakım Modunu Etkinleştir",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "Otomatik",
"automaticModeDescription": "Tüm arka uç hedefleri kapalı veya sağlıksız olduğunda yalnızca bakım sayfasını gösterin. Sağlıklı en az bir hedef olduğu sürece kaynağınız normal şekilde çalışmaya devam eder.",
"forced": "Zorunlu",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "Tahmini Tamamlama:",
"createInternalResourceDialogDestinationRequired": "Hedef gereklidir",
"available": "Mevcut",
"disabledResourceDescription": "Devre dışı bırakıldığında, kaynağa herkes erişemez.",
"archived": "Arşivlenmiş",
"noArchivedDevices": "Arşivlenmiş cihaz bulunamadı",
"deviceArchived": "Cihaz arşivlendi",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "Bu kimlik sağlayıcının bu kuruluştan ilişiğini kesmek istediğinizden emin misiniz?",
"idpUnassociateDescription": "Bu kimlik sağlayıcı ile ilişkilendirilen tüm kullanıcılar bu kuruluştan kaldırılacaktır, ancak kimlik sağlayıcı diğer ilişkilendirilen kuruluşlar için var olmaya devam edecektir.",
"idpUnassociateConfirm": "Kimlik Sağlayıcının İlişkisinin Kesilmesini Onayla",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "Bu işlem bu kuruluş için geri alınamaz.",
"idpUnassociatedDescription": "Kimlik sağlayıcı bu kuruluştan başarıyla ayrıldı",
"idpUnassociateMenu": "İlişkiyi Kes",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "Kaynak Devre Dışı",
"memberPortalShowingResources": "{total} kaynaktan {start}-{end} gösteriliyor",
"memberPortalPrevious": "Önceki",
"memberPortalNext": "Sonraki"
"memberPortalNext": "Sonraki",
"httpSettings": "HTTP Ayarları",
"tcpSettings": "TCP Ayarları",
"udpSettings": "UDP Ayarları",
"sshTitle": "SSH",
"sshConnectingDescription": "Güvenli bir bağlantı kuruluyor…",
"sshConnecting": "Bağlanılıyor…",
"sshInitializing": "Başlatılıyor…",
"sshSignInTitle": "SSH'a Giriş Yap",
"sshSignInDescription": "SSH kimlik bilgilerinizi girin",
"sshPasswordTab": "Şifre",
"sshPrivateKeyTab": "Özel Anahtar",
"sshPrivateKeyField": "Özel Anahtar",
"sshPrivateKeyDisclaimer": "Özel anahtarınız Pangolin'de saklanmaz veya görünmez. Alternatif olarak, mevcut Pangolin kimliğinizle sorunsuz kimlik doğrulama için kısa ömürlü sertifikalar kullanabilirsiniz.",
"sshLearnMore": "Daha fazla bilgi",
"sshPrivateKeyFile": "Özel Anahtar Dosyası",
"sshAuthenticate": "Kimlik Doğrulama",
"sshTerminate": "Sonlandır",
"sshPoweredBy": "Tarafından sağlanmaktadır",
"sshErrorNoTarget": "Belirtilen hedef yok",
"sshErrorWebSocket": "WebSocket bağlantısı başarısız oldu",
"sshErrorAuthFailed": "Kimlik doğrulama başarısız",
"sshErrorConnectionClosed": "Kimlik doğrulama tamamlanmadan bağlantı kapandı",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -101,6 +101,8 @@
"sitesTableViewPrivateResources": "查看私有资源",
"siteInstallNewt": "安装 Newt",
"siteInstallNewtDescription": "在您的系统中运行 Newt",
"siteInstallKubernetesDocsDescription": "For more and up to date Kubernetes installation information, see <docsLink>docs.pangolin.net/manage/sites/install-kubernetes</docsLink>.",
"siteInstallAdvantechDocsDescription": "For Advantech modem installation instructions, see <docsLink>docs.pangolin.net/manage/sites/install-advantech</docsLink>.",
"WgConfiguration": "WireGuard 配置",
"WgConfigurationDescription": "使用以下配置连接到网络",
"operatingSystem": "操作系统",
@@ -148,16 +150,16 @@
"siteCredentialsSaveDescription": "您只能看到一次。请确保将其复制并保存到一个安全的地方。",
"siteInfo": "站点信息",
"status": "状态",
"shareTitle": "管理共享链接",
"shareTitle": "Manage Shareable Links",
"shareDescription": "创建可共享的链接,允许临时或永久访问代理资源",
"shareSearch": "搜索共享链接...",
"shareCreate": "创建共享链接",
"shareSearch": "Search shareable links...",
"shareCreate": "Create Shareable Link",
"shareErrorDelete": "删除链接失败",
"shareErrorDeleteMessage": "删除链接时出错",
"shareDeleted": "链接已删除",
"shareDeletedDescription": "链接已删除",
"shareDelete": "删除共享链接",
"shareDeleteConfirm": "确认删除共享链接",
"shareDelete": "Delete Shareable Link",
"shareDeleteConfirm": "Confirm Delete Shareable Link",
"shareQuestionRemove": "您确定要删除这个共享链接吗?",
"shareMessageRemove": "删除后,该链接将不再可用,使用它的任何人将失去对资源的访问权限。",
"shareTokenDescription": "访问令牌可以通过两种方式传递:作为查询参数或请求标题。 每次验证访问请求都必须从客户端传递。",
@@ -176,6 +178,8 @@
"shareErrorCreateDescription": "创建共享链接时出错",
"shareCreateDescription": "任何具有此链接的人都可以访问资源",
"shareTitleOptional": "标题 (可选)",
"sharePathOptional": "路径(可选)",
"sharePathDescription": "The link will redirect users to this path after authentication.",
"expireIn": "过期时间",
"neverExpire": "永不过期",
"shareExpireDescription": "过期时间是链接可以使用并提供对资源的访问时间。 此时间后,链接将不再工作,使用此链接的用户将失去对资源的访问。",
@@ -199,8 +203,8 @@
"shareErrorSelectResource": "请选择一个资源",
"proxyResourceTitle": "管理公共资源",
"proxyResourceDescription": "创建和管理可通过 Web 浏览器公开访问的资源",
"proxyResourcesBannerTitle": "基于Web的公共访问",
"proxyResourcesBannerDescription": "公共资源是可以通过网络浏览器在互联网上任何人访问的HTTPS或TCP/UDP代理。与私人资源不同它们不需要客户端软件并且可以包含身份和上下文感知访问策略。",
"publicResourcesBannerTitle": "Web-based Public Access",
"publicResourcesBannerDescription": "Public resources are HTTPS proxies accessible to anyone on the internet through a web browser. Unlike private resources, they do not require client-side software and can include identity and context-aware access policies.",
"clientResourceTitle": "管理私有资源",
"clientResourceDescription": "创建和管理只能通过连接客户端访问的资源",
"privateResourcesBannerTitle": "零信任的私人访问",
@@ -208,11 +212,36 @@
"resourcesSearch": "搜索资源...",
"resourceAdd": "添加资源",
"resourceErrorDelte": "删除资源时出错",
"resourcePoliciesBannerTitle": "Re-use Authentication and Access Rules",
"resourcePoliciesBannerDescription": "Shared resource policies let you define authentication methods and access rules once, then attach them to multiple public resources. When you update a policy, every linked resource inherits the change automatically.",
"resourcePoliciesTitle": "Manage Public Resource Policies",
"resourcePoliciesAttachedResourcesColumnTitle": "Resources",
"resourcePoliciesAttachedResources": "{count} 个资源",
"resourcePoliciesAttachedResourcesCount": "{count, plural, one {# resource} other {# resources}}",
"resourcePoliciesAttachedResourcesEmpty": "没有资源",
"resourcePoliciesDescription": "Create and manage authentication policies to control access to your public resources",
"resourcePoliciesSearch": "搜索策略……",
"resourcePoliciesAdd": "添加策略",
"resourcePoliciesDefaultBadgeText": "默认策略",
"resourcePoliciesCreate": "Create Public Resource Policy",
"resourcePoliciesCreateDescription": "按照以下步骤创建新策略",
"resourcePolicyName": "策略名称",
"resourcePolicyNameDescription": "给此策略命名,以便在您的资源中识别它",
"resourcePolicyNamePlaceholder": "例如:内部访问策略",
"resourcePoliciesSeeAll": "查看所有策略",
"resourcePolicyAuthMethodAdd": "添加身份验证方法",
"resourcePolicyOtpEmailAdd": "添加 OTP 电子邮件",
"resourcePolicyRulesAdd": "添加规则",
"resourcePolicyAuthMethodsDescription": "通过额外的认证方法允许访问资源",
"resourcePolicyUsersRolesDescription": "配置哪些用户和角色可以访问关联的资源",
"rulesResourcePolicyDescription": "配置规则以控制与此策略关联的访问资源",
"authentication": "认证",
"protected": "受到保护",
"notProtected": "未受到保护",
"resourceMessageRemove": "一旦删除,资源将不再可访问。与该资源相关的所有目标也将被删除。",
"resourceQuestionRemove": "您确定要从组织中删除资源吗?",
"resourcePolicyMessageRemove": "一旦删除,资源策略将不再可访问。所有与资源关联的资源将取消关联,并且没有身份验证。",
"resourcePolicyQuestionRemove": "您确定要从组织中删除资源策略吗?",
"resourceHTTP": "HTTPS 资源",
"resourceHTTPDescription": "通过使用完全限定的域名的HTTPS代理请求。",
"resourceRaw": "TCP/UDP 资源",
@@ -220,8 +249,9 @@
"resourceRawDescriptionCloud": "正在使用端口号使用 TCP/UDP 代理请求。需要站点连接到远程节点。",
"resourceCreate": "创建资源",
"resourceCreateDescription": "按照下面的步骤创建新资源",
"resourceCreateGeneralDescription": "配置基本资源设置,包括名称和类型",
"resourceSeeAll": "查看所有资源",
"resourceInfo": "资源信息",
"resourceCreateGeneral": "概览",
"resourceNameDescription": "这是资源的显示名称。",
"siteSelect": "选择站点",
"siteSearch": "搜索站点",
@@ -231,12 +261,15 @@
"noCountryFound": "找不到国家。",
"siteSelectionDescription": "此站点将为目标提供连接。",
"resourceType": "资源类型",
"resourceTypeDescription": "确定如何访问资源",
"resourceTypeDescription": "这会控制资源协议及其在浏览器中的渲染方式。之后不能更改。",
"resourceDomainDescription": "资源将在此完全限定的域名上提供。",
"resourceHTTPSSettings": "HTTPS 设置",
"resourceHTTPSSettingsDescription": "配置如何通过 HTTPS 访问资源",
"resourcePortDescription": "在 Pangolin 实例或节点上资源可访问的外部端口。",
"domainType": "域类型",
"subdomain": "子域名",
"baseDomain": "根域名",
"configure": "配置",
"subdomnainDescription": "可访问资源的子域。",
"resourceRawSettings": "TCP/UDP 设置",
"resourceRawSettingsDescription": "配置如何通过 TCP/UDP 访问资源",
@@ -253,8 +286,29 @@
"resourceLearnRaw": "学习如何配置 TCP/UDP 资源",
"resourceBack": "返回资源",
"resourceGoTo": "转到资源",
"resourcePolicyDelete": "删除资源策略",
"resourcePolicyDeleteConfirm": "确认删除资源策略",
"resourceDelete": "删除资源",
"resourceDeleteConfirm": "确认删除资源",
"labelDelete": "删除标签",
"labelAdd": "添加标签",
"labelCreateSuccessMessage": "标签创建成功",
"labelDuplicateError": "Duplicate Label",
"labelDuplicateErrorDescription": "A label with this name already exists.",
"labelEditSuccessMessage": "标签修改成功",
"labelNameField": "标签名称",
"labelColorField": "标签颜色",
"labelPlaceholder": "例homelab",
"labelCreate": "创建标签",
"createLabelDialogTitle": "创建标签",
"createLabelDialogDescription": "创建一个可以附加到此组织的新标签",
"labelEdit": "编辑标签",
"editLabelDialogTitle": "更新标签",
"editLabelDialogDescription": "编辑一个可以附加到此组织的标签",
"labelDeleteConfirm": "确认删除标签",
"labelErrorDelete": "删除标签失败",
"labelMessageRemove": "此操作是永久性的。所有用此标签标记的网站、资源和客户端将取消标记。",
"labelQuestionRemove": "您确定要将标签从组织中移除吗?",
"visibility": "可见性",
"enabled": "已启用",
"disabled": "已禁用",
@@ -265,6 +319,8 @@
"rules": "规则",
"resourceSettingDescription": "配置资源上的设置",
"resourceSetting": "{resourceName} 设置",
"resourcePolicySettingDescription": "Configure the settings on this public resource policy",
"resourcePolicySetting": "{policyName} 设置",
"alwaysAllow": "旁路认证",
"alwaysDeny": "屏蔽访问",
"passToAuth": "传递至认证",
@@ -705,11 +761,11 @@
"rulesErrorDuplicate": "复制规则",
"rulesErrorDuplicateDescription": "带有这些设置的规则已存在",
"rulesErrorInvalidIpAddressRange": "无效的 CIDR",
"rulesErrorInvalidIpAddressRangeDescription": "请输入一个有效的 CIDR 值",
"rulesErrorInvalidUrl": "无效的 URL 路径",
"rulesErrorInvalidUrlDescription": "请输入一个有效的 URL 路径值",
"rulesErrorInvalidIpAddress": "无效的 IP",
"rulesErrorInvalidIpAddressDescription": "请输入一个有效的IP地址",
"rulesErrorInvalidIpAddressRangeDescription": "Enter a valid CIDR range (e.g., 10.0.0.0/8).",
"rulesErrorInvalidUrl": "Invalid path",
"rulesErrorInvalidUrlDescription": "Enter a valid URL path or pattern (e.g., /api/*).",
"rulesErrorInvalidIpAddress": "Invalid IP address",
"rulesErrorInvalidIpAddressDescription": "Enter a valid IPv4 or IPv6 address.",
"rulesErrorUpdate": "更新规则失败",
"rulesErrorUpdateDescription": "更新规则时出错",
"rulesUpdated": "启用规则",
@@ -717,15 +773,24 @@
"rulesMatchIpAddressRangeDescription": "以 CIDR 格式输入地址(如103.21.244.0/22)",
"rulesMatchIpAddress": "输入IP地址(例如103.21.244.12)",
"rulesMatchUrl": "输入一个 URL 路径或模式(例如/api/v1/todos 或 /api/v1/*)",
"rulesErrorInvalidPriority": "无效的优先级",
"rulesErrorInvalidPriorityDescription": "请输入一个有效的优先级",
"rulesErrorDuplicatePriority": "重复的优先级",
"rulesErrorDuplicatePriorityDescription": "请输入唯一的优先级",
"rulesErrorInvalidPriority": "Invalid priority",
"rulesErrorInvalidPriorityDescription": "Enter a whole number of 1 or higher.",
"rulesErrorDuplicatePriority": "Duplicate priorities",
"rulesErrorDuplicatePriorityDescription": "Each rule must have a unique priority number.",
"rulesErrorValidation": "Invalid rules",
"rulesErrorValidationRuleDescription": "Rule {ruleNumber}: {message}",
"rulesErrorInvalidMatchTypeDescription": "Select a valid match type (path, IP, CIDR, country, region, or ASN).",
"rulesErrorValueRequired": "Enter a value for this rule.",
"rulesErrorInvalidCountry": "Invalid country",
"rulesErrorInvalidCountryDescription": "Select a valid country.",
"rulesErrorInvalidAsn": "Invalid ASN",
"rulesErrorInvalidAsnDescription": "Enter a valid ASN (e.g., AS15169).",
"ruleUpdated": "规则已更新",
"ruleUpdatedDescription": "规则更新成功",
"ruleErrorUpdate": "操作失败",
"ruleErrorUpdateDescription": "保存过程中发生错误",
"rulesPriority": "优先权",
"rulesReorderDragHandle": "Drag to reorder rule priority",
"rulesAction": "行为",
"rulesMatchType": "匹配类型",
"value": "值",
@@ -744,9 +809,60 @@
"rulesResource": "资源规则配置",
"rulesResourceDescription": "配置规则来控制对资源的访问",
"ruleSubmit": "添加规则",
"rulesNoOne": "没有规则。使用表单添加规则。",
"rulesNoOne": "No rules yet.",
"rulesOrder": "规则按优先顺序评定。",
"rulesSubmit": "保存规则",
"policyErrorCreate": "创建策略时出错",
"policyErrorCreateDescription": "创建策略时发生错误",
"policyErrorCreateMessageDescription": "发生意外错误",
"policyErrorUpdate": "更新策略时出错",
"policyErrorUpdateDescription": "更新策略时发生错误",
"policyErrorUpdateMessageDescription": "发生意外错误",
"policyCreatedSuccess": "资源策略创建成功",
"policyUpdatedSuccess": "资源策略更新成功",
"authMethodsSave": "Save Settings",
"policyAuthStackTitle": "Authentication",
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
"policyAuthOrLogicTitle": "Multiple authentication methods active",
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
"policyAuthMethodActive": "Active",
"policyAuthMethodOff": "Off",
"policyAuthSsoTitle": "Platform SSO",
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
"policyAuthSsoDefaultIdp": "Default provider",
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
"policyAuthOtherMethodsTitle": "Other Methods",
"policyAuthOtherMethodsDescription": "Optional methods visitors can use instead of or alongside platform SSO",
"policyAuthPasscodeTitle": "Passcode",
"policyAuthPasscodeDescription": "Require a shared alphanumeric passcode to access the resource",
"policyAuthPasscodeSummary": "Passcode set",
"policyAuthPincodeTitle": "PIN Code",
"policyAuthPincodeDescription": "A short numeric code required to access the resource",
"policyAuthPincodeSummary": "6-digit PIN set",
"policyAuthEmailTitle": "Email Whitelist",
"policyAuthEmailDescription": "Allow listed email addresses with one-time passwords",
"policyAuthEmailSummary": "{count} addresses allowed",
"policyAuthEmailOtpCallout": "Enabling email whitelist sends a one-time password to the visitor's email on login.",
"policyAuthHeaderAuthTitle": "Basic Header Auth",
"policyAuthHeaderAuthDescription": "Validate a custom HTTP header name and value on each request",
"policyAuthHeaderAuthSummary": "Header configured",
"policyAuthHeaderName": "Header name",
"policyAuthHeaderValue": "Expected value",
"policyAuthSetPasscode": "Set Passcode",
"policyAuthSetPincode": "Set PIN Code",
"policyAuthSetEmailWhitelist": "Set Email Whitelist",
"policyAuthSetHeaderAuth": "Set Basic Header Auth",
"policyAccessRulesTitle": "Access Rules",
"policyAccessRulesEnableDescription": "When enabled, rules are evaluated in descending order until one evaluates as true.",
"policyAccessRulesFirstMatch": "Rules are evaluated top to bottom. The first matching rule decides the outcome.",
"policyAccessRulesHowItWorks": "Rules match requests by path, IP address, location, or other criteria. Each rule applies an action: bypass authentication, block access, or pass to authentication. If no rule matches, traffic continues to authentication.",
"policyAccessRulesFallthroughOff": "When rules are disabled, all traffic passes through to authentication.",
"policyAccessRulesFallthroughOn": "When no rule matches, traffic passes through to authentication.",
"rulesPlaceholderCidr": "10.0.0.0/8",
"rulesPlaceholderPath": "/admin/*",
"rulesPlaceholderGeo": "RU, KP",
"rulesSave": "保存规则",
"resourceErrorCreate": "创建资源时出错",
"resourceErrorCreateDescription": "创建资源时出错",
"resourceErrorCreateMessage": "创建资源时发生错误:",
@@ -766,9 +882,9 @@
"resourcesErrorUpdateDescription": "更新资源时出错",
"access": "访问权限",
"accessControl": "访问控制",
"shareLink": "{resource} 的分享链接",
"shareLink": "{resource} Shareable Link",
"resourceSelect": "选择资源",
"shareLinks": "分享链接",
"shareLinks": "Shareable Links",
"share": "分享链接",
"shareDescription2": "创建资源的可共享链接。链接提供了对您资源的临时或无限制访问。 当您创建链接时,您可以配置链接的到期时间。",
"shareEasyCreate": "轻松创建和分享",
@@ -810,6 +926,17 @@
"pincodeAdd": "添加 PIN 码",
"pincodeRemove": "移除 PIN 码",
"resourceAuthMethods": "身份验证方法",
"resourcePolicyAuthMethodsEmpty": "无身份验证方法",
"resourcePolicyOtpEmpty": "没有一次性密码",
"resourcePolicyReadOnly": "此策略是只读的",
"resourcePolicyReadOnlyDescription": "此资源策略跨多个资源共享,您无法在此页面上编辑。",
"editSharedPolicy": "编辑共享策略",
"resourcePolicyTypeSave": "保存资源类型",
"resourcePolicySelect": "选择资源策略",
"resourcePolicySelectError": "选择资源策略",
"resourcePolicyNotFound": "找不到策略",
"resourcePolicySearch": "搜索策略",
"resourcePolicyRulesEmpty": "无身份验证规则",
"resourceAuthMethodsDescriptions": "允许通过额外的认证方法访问资源",
"resourceAuthSettingsSave": "保存成功",
"resourceAuthSettingsSaveDescription": "已保存身份验证设置",
@@ -845,6 +972,18 @@
"resourcePincodeSetupTitle": "设置 PIN 码",
"resourcePincodeSetupTitleDescription": "设置 PIN 码来保护此资源",
"resourceRoleDescription": "管理员总是可以访问此资源。",
"resourcePolicySelectTitle": "资源访问策略",
"resourcePolicySelectDescription": "选择用于认证的资源策略类型",
"resourcePolicyTypeLabel": "Policy type",
"resourcePolicyLabel": "Resource policy",
"resourcePolicyInline": "内联资源策略",
"resourcePolicyInlineDescription": "仅限于此资源的访问策略",
"resourcePolicyShared": "共享资源策略",
"resourcePolicySharedDescription": "This resource uses a shared policy.",
"sharedPolicy": "Shared Policy",
"sharedPolicyNoneDescription": "This resource has its own policy.",
"resourceSharedPolicyAuthenticationNotice": "This resource is using a shared policy. Some authentication settings can be edited on this resource. To change the underlying policy, you must edit to <policyLink>{policyName}</policyLink>.",
"resourceSharedPolicyRulesNotice": "This resource is using a shared policy. Some access rules can be edited on this resource. To change the underlying policy, you must edit <policyLink>{policyName}</policyLink>.",
"resourceUsersRoles": "访问控制",
"resourceUsersRolesDescription": "配置用户和角色可以访问此资源",
"resourceUsersRolesSubmit": "保存访问控制",
@@ -1140,6 +1279,21 @@
"idpErrorConnectingTo": "无法连接到 {name},请联系管理员协助处理。",
"idpErrorNotFound": "找不到 IdP",
"inviteInvalid": "无效邀请",
"labels": "标签",
"orgLabelsDescription": "管理此组织的标签。",
"addLabels": "添加标签",
"siteLabelsTab": "标签",
"siteLabelsDescription": "管理与此网站相关的标签。",
"labelsNotFound": "No labels found.",
"labelsEmptyCreateHint": "Start typing above to create a label.",
"labelSearch": "搜索标签",
"labelSearchOrCreate": "Search or create a label",
"accessLabelFilterCount": "{count, plural, other {# 标签}}",
"labelOverflowCount": "+{count, plural, other {# 标签}}",
"accessLabelFilterClear": "清除标签过滤器",
"accessFilterClear": "Clear filters",
"selectColor": "选择颜色",
"createNewLabel": "创建新的组织标签 \"{label}\"",
"inviteInvalidDescription": "邀请链接无效。",
"inviteErrorWrongUser": "邀请不是该用户的",
"inviteErrorUserNotExists": "用户不存在。请先创建帐户。",
@@ -1374,6 +1528,8 @@
"sidebarResources": "资源",
"sidebarProxyResources": "公开的",
"sidebarClientResources": "非公开的",
"sidebarPolicies": "Shared Policies",
"sidebarResourcePolicies": "Public Resources",
"sidebarAccessControl": "访问控制",
"sidebarLogsAndAnalytics": "日志与分析",
"sidebarTeam": "团队",
@@ -1381,7 +1537,7 @@
"sidebarAdmin": "管理员",
"sidebarInvitations": "邀请",
"sidebarRoles": "角色",
"sidebarShareableLinks": "链接",
"sidebarShareableLinks": "Shareable Links",
"sidebarApiKeys": "API密钥",
"sidebarProvisioning": "置备中",
"sidebarSettings": "设置",
@@ -1557,7 +1713,8 @@
"standaloneHcFilterSiteIdFallback": "站点 {id}",
"standaloneHcFilterResourceIdFallback": "资源 {id}",
"blueprints": "蓝图",
"blueprintsDescription": "应用声明配置并查看先前运行的",
"blueprintsLog": "蓝图日志",
"blueprintsDescription": "View past blueprint applications and their results or apply a new blueprint",
"blueprintAdd": "添加蓝图",
"blueprintGoBack": "查看所有蓝图",
"blueprintCreate": "创建蓝图",
@@ -1575,7 +1732,17 @@
"contents": "目录",
"parsedContents": "解析内容 (只读)",
"enableDockerSocket": "启用 Docker 蓝图",
"enableDockerSocketDescription": "启用 Docker Socket 标签擦除蓝图标签。套接字路径必须提供给新的。",
"enableDockerSocketDescription": "启用用于蓝图标签的 Docker 套接字标签擦除。必须为站点连接器提供套接字路径。阅读<docsLink>文档</docsLink>以了解相关工作原理。",
"newtAutoUpdate": "启用站点自动更新",
"newtAutoUpdateDescription": "启用时,站点连接器将在有新版本发布时自动更新到最新版本。",
"siteAutoUpdate": "站点自动更新",
"siteAutoUpdateLabel": "启用自动更新",
"siteAutoUpdateDescription": "控制此站点连接器是否自动下载最新版本。",
"siteAutoUpdateOrgDefault": "组织默认设置:{state}",
"siteAutoUpdateOverriding": "覆盖组织设置",
"siteAutoUpdateResetToOrg": "重置为组织默认设置",
"siteAutoUpdateEnabled": "已启用",
"siteAutoUpdateDisabled": "已禁用",
"viewDockerContainers": "查看停靠容器",
"containersIn": "{siteName} 中的容器",
"selectContainerDescription": "选择任何容器作为目标的主机名。点击端口使用端口。",
@@ -1620,6 +1787,7 @@
"certificateStatus": "证书",
"certificateStatusAutoRefreshHint": "状态自动刷新。",
"loading": "加载中",
"loadingEllipsis": "加载中……",
"loadingAnalytics": "加载分析",
"restart": "重启",
"domains": "域",
@@ -1846,6 +2014,7 @@
"billingManageLicenseSubscription": "管理您对付费的自托管许可证密钥的订阅",
"billingCurrentKeys": "当前密钥",
"billingModifyCurrentPlan": "修改当前计划",
"billingManageLicenseSubscriptionDescription": "管理付费的自托管许可证密钥订阅并下载发票。",
"billingConfirmUpgrade": "确认升级",
"billingConfirmDowngrade": "确认降级",
"billingConfirmUpgradeDescription": "您即将升级您的计划。请检查下面的新限额和定价。",
@@ -1925,13 +2094,13 @@
"healthCheckUnknown": "未知",
"healthCheck": "健康检查",
"configureHealthCheck": "配置健康检查",
"configureHealthCheckDescription": "为 {target} 设置健康监控",
"configureHealthCheckDescription": "Set up monitoring for your resource to ensure it is always available",
"enableHealthChecks": "启用健康检查",
"healthCheckDisabledStateDescription": "禁用后,站点不会进行健康检查,状态将被视为未知。",
"enableHealthChecksDescription": "监视此目标的健康状况。如果需要,您可以监视一个不同的终点。",
"healthScheme": "方法",
"healthSelectScheme": "选择方法",
"healthCheckPortInvalid": "健康检查端口必须介于 1 到 65535 之间",
"healthCheckPortInvalid": "Port must be between 1 and 65535",
"healthCheckPath": "路径",
"healthHostname": "IP / 主机",
"healthPort": "端口",
@@ -1943,7 +2112,42 @@
"timeIsInSeconds": "时间以秒为单位",
"requireDeviceApproval": "需要设备批准",
"requireDeviceApprovalDescription": "具有此角色的用户需要管理员批准的新设备才能连接和访问资源。",
"sshAccess": "SSH 访问",
"sshSettings": "SSH 设置",
"sshAccess": "SSH Access",
"rdpSettings": "RDP 设置",
"vncSettings": "VNC 设置",
"sshServer": "SSH 服务器",
"rdpServer": "RDP 服务器",
"vncServer": "VNC 服务器",
"sshServerDescription": "设置身份验证方法、守护程序位置和服务器目标",
"rdpServerDescription": "配置 RDP 服务器的目标和端口",
"vncServerDescription": "配置 VNC 服务器的目标和端口",
"sshServerMode": "模式",
"sshServerModeStandard": "标准 SSH 服务器",
"sshServerModePangolin": "Pangolin SSH",
"sshServerModeStandardDescription": "将命令通过网络路由到 SSH 服务器,例如 OpenSSH。",
"sshServerModeNative": "本地 SSH 服务器",
"sshServerModeNativeDescription": "通过站点连接器直接在主机上执行命令。无需网络配置。",
"sshAuthenticationMethod": "身份验证方法",
"sshAuthMethodManual": "手动身份验证",
"sshAuthMethodManualDescription": "需要现有的主机凭据。绕过自动配置。",
"sshAuthMethodAutomated": "自动配置",
"sshAuthMethodAutomatedDescription": "在主机上自动创建用户、组和sudo权限。",
"sshAuthDaemonLocation": "认证守护程序位置",
"sshDaemonLocationSiteDescription": "在托管站点连接器的机器上本地执行。",
"sshDaemonLocationRemote": "在远程主机上",
"sshDaemonLocationRemoteDescription": "在同一网络的独立目标机器上执行。",
"sshDaemonDisclaimer": "在完成本设置之前,请确保您的目标主机已经正确配置以运行身份验证守护程序,否则配置将失败。",
"sshDaemonPort": "守护程序端口",
"sshServerDestination": "服务器目标",
"sshServerDestinationDescription": "Configure the destination of the SSH server",
"destination": "目标",
"destinationRequired": "Destination is required.",
"domainRequired": "Domain is required.",
"proxyPortRequired": "Port is required.",
"invalidPathConfiguration": "Invalid path configuration.",
"invalidRewritePathConfiguration": "Invalid rewrite path configuration.",
"bgTargetMultiSiteDisclaimer": "选择多个站点可实现高可用性的弹性路由和故障转移。",
"roleAllowSsh": "允许 SSH",
"roleAllowSshAllow": "允许",
"roleAllowSshDisallow": "不允许",
@@ -1957,10 +2161,25 @@
"sshSudoModeCommandsDescription": "用户只能用 sudo 运行指定的命令。",
"sshSudo": "允许Sudo",
"sshSudoCommands": "Sudo 命令",
"sshSudoCommandsDescription": "逗号分隔的用户允许使用 sudo 运行的命令列表。",
"sshSudoCommandsDescription": "List of commands the user is allowed to run with sudo, separated by commas, spaces, or new lines. Absolute paths must be used.",
"sshCreateHomeDir": "创建主目录",
"sshUnixGroups": "Unix 组",
"sshUnixGroupsDescription": "用逗号分隔了Unix组将用户添加到目标主机上。",
"sshUnixGroupsDescription": "Unix groups to add the user to on the target host, separated by commas, spaces, or new lines.",
"roleTextFieldPlaceholder": "Enter values, or drop a .txt or .csv file",
"roleTextImportTitle": "Import from File",
"roleTextImportDescription": "Importing {fileName} into {fieldLabel}.",
"roleTextImportSkipHeader": "Skip First Row (Header)",
"roleTextImportOverride": "Replace Existing",
"roleTextImportAppend": "Append to Existing",
"roleTextImportMode": "Import Mode",
"roleTextImportPreview": "Preview",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportTotalCount": "{existing} existing + {imported} imported = {total} total",
"roleTextImportConfirm": "Import",
"roleTextImportInvalidFile": "Unsupported file type",
"roleTextImportInvalidFileDescription": "Only .txt and .csv files are supported.",
"roleTextImportEmpty": "No items found in file",
"roleTextImportEmptyDescription": "The file does not contain any importable items.",
"retryAttempts": "重试次数",
"expectedResponseCodes": "期望响应代码",
"expectedResponseCodesDescription": "HTTP 状态码表示健康状态。如留空200-300 被视为健康。",
@@ -2049,6 +2268,7 @@
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeSsh": "SSH",
"editInternalResourceDialogScheme": "方案",
"editInternalResourceDialogEnableSsl": "启用 TLS",
"editInternalResourceDialogEnableSslDescription": "为目标的安全 HTTPS 连接启用 SSL/TLS 加密。",
@@ -2098,6 +2318,7 @@
"createInternalResourceDialogModeCidr": "CIDR",
"createInternalResourceDialogModeHttp": "HTTP",
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"scheme": "方案",
"createInternalResourceDialogScheme": "方案",
"createInternalResourceDialogEnableSsl": "启用 TLS",
@@ -2233,7 +2454,7 @@
"description": "更可靠和低维护自我托管的 Pangolin 服务器,带有额外的铃声和告密器",
"introTitle": "托管自托管的潘戈林公司",
"introDescription": "这是一种部署选择,为那些希望简洁和额外可靠的人设计,同时仍然保持他们的数据的私密性和自我托管性。",
"introDetail": "通过此选项,您仍然运行您自己的 Pangolin 节点 - - 您的隧道、TLS 终止,并且流量在您的服务器上保持所有状态。 不同之处在于,管理和监测是通过我们的云层仪表板进行的,该仪表板开启了一些好处:",
"introDetail": "通过此选项,您仍然运行您自己的 Pangolin 节点 - 您的隧道、TLS 终止,并且流量在您的服务器上保持所有状态。不同之处在于,管理和监测是通过我们的云层仪表板进行的,该仪表板开启了一些好处:",
"benefitSimplerOperations": {
"title": "简单的操作",
"description": "无需运行您自己的邮件服务器或设置复杂的警报。您将从方框中获得健康检查和下限提醒。"
@@ -2901,7 +3122,7 @@
"enterConfirmation": "输入确认",
"blueprintViewDetails": "详细信息",
"defaultIdentityProvider": "默认身份提供商",
"defaultIdentityProviderDescription": "当选择默认身份提供商时,用户将自动重定向到提供商进行身份验证。",
"defaultIdentityProviderDescription": "The user will be automatically redirected to this identity provider for authentication.",
"editInternalResourceDialogNetworkSettings": "网络设置",
"editInternalResourceDialogAccessPolicy": "访问策略",
"editInternalResourceDialogAddRoles": "添加角色",
@@ -2937,11 +3158,12 @@
"learnMore": "了解更多",
"backToHome": "返回首页",
"needToSignInToOrg": "需要使用您组织的身份提供商吗?",
"maintenanceMode": "维护模式",
"maintenanceMode": "维护页面",
"maintenanceModeDescription": "向访客显示维护页面",
"maintenanceModeType": "维护模式类型",
"showMaintenancePage": "只在所有后端目标都故障或不健康时显示维护页面。只要至少一个目标健康,您的资源将正常工作。",
"enableMaintenanceMode": "启用维护模式",
"enableMaintenanceModeDescription": "When enabled, visitors will see a maintenance page instead of your resource.",
"automatic": "自动",
"automaticModeDescription": "如果所有后端目标都故障或不健康,则仅显示维护页面。只要至少一个目标健康,您的资源将正常工作。",
"forced": "强制",
@@ -2967,6 +3189,7 @@
"maintenanceScreenEstimatedCompletion": "预计完成时间:",
"createInternalResourceDialogDestinationRequired": "需要目标地址",
"available": "可用",
"disabledResourceDescription": "禁用后,所有人都不可访问此资源。",
"archived": "已存档",
"noArchivedDevices": "未找到存档设备",
"deviceArchived": "设备已存档",
@@ -3212,6 +3435,8 @@
"idpUnassociateQuestion": "您确定要将此身份提供者从此组织中取消关联吗?",
"idpUnassociateDescription": "与此身份提供者关联的所有用户将从该组织中移除,但身份提供者仍会继续存在于关联的其他组织中。",
"idpUnassociateConfirm": "确认取消关联身份提供者",
"idpConfirmDeleteAndRemoveMeFromOrg": "DELETE AND REMOVE ME FROM ORG",
"idpUnassociateAndRemoveMeFromOrg": "UNASSOCIATE AND REMOVE ME FROM ORG",
"idpUnassociateWarning": "此操作无法对该组织撤销。",
"idpUnassociatedDescription": "身份提供者已成功从该组织中取消关联",
"idpUnassociateMenu": "取消关联",
@@ -3296,5 +3521,67 @@
"memberPortalResourceDisabled": "资源已禁用",
"memberPortalShowingResources": "显示 {start}-{end} 共 {total} 个资源",
"memberPortalPrevious": "上一页",
"memberPortalNext": "下一页"
"memberPortalNext": "下一页",
"httpSettings": "HTTP 设置",
"tcpSettings": "TCP 设置",
"udpSettings": "UDP 设置",
"sshTitle": "SSH",
"sshConnectingDescription": "正在建立安全连接…",
"sshConnecting": "正在连接…",
"sshInitializing": "初始化中…",
"sshSignInTitle": "登录 SSH",
"sshSignInDescription": "输入您的 SSH 凭据",
"sshPasswordTab": "密码",
"sshPrivateKeyTab": "私钥",
"sshPrivateKeyField": "私钥",
"sshPrivateKeyDisclaimer": "您的私钥不会被 Pangolin 存储或显示。或者,您可以使用短期证书,使用您现有的 Pangolin 身份无缝认证。",
"sshLearnMore": "了解更多",
"sshPrivateKeyFile": "私钥文件",
"sshAuthenticate": "验证",
"sshTerminate": "终止",
"sshPoweredBy": "支持者",
"sshErrorNoTarget": "未指定目标",
"sshErrorWebSocket": "WebSocket 连接失败",
"sshErrorAuthFailed": "身份验证失败",
"sshErrorConnectionClosed": "认证完成前连接已关闭",
"sitePangolinSshDescription": "Allow SSH access to resources on this site. This can be changed later.",
"browserGatewayNoResourceForDomain": "No resource found for this domain",
"browserGatewayNoTarget": "No target",
"browserGatewayConnect": "Connect",
"browserGatewayCtrlAltDel": "Ctrl+Alt+Del",
"sshErrorSignKeyFailed": "Failed to sign SSH key for PAM push authentication. Did you sign in as a user?",
"sshTerminalError": "Error: {error}",
"sshConnectionClosedCode": "Connection closed (code {code})",
"sshPrivateKeyPlaceholder": "-----BEGIN OPENSSH PRIVATE KEY-----",
"sshPrivateKeyRequired": "Private key is required",
"vncTitle": "VNC",
"vncSignInDescription": "Enter your VNC password to connect",
"vncPasswordOptional": "Password (optional)",
"vncNoResourceTarget": "No resource target is available",
"vncFailedToLoadNovnc": "Failed to load noVNC",
"vncAuthFailedStatus": "Status {status}",
"vncPasteClipboard": "Paste clipboard",
"rdpTitle": "RDP",
"rdpSignInTitle": "Sign in to Remote Desktop",
"rdpSignInDescription": "Enter Windows credentials to connect",
"rdpLoadingModule": "Loading module...",
"rdpFailedToLoadModule": "Failed to load RDP module",
"rdpNotReady": "Not ready",
"rdpModuleInitializing": "RDP module is still initializing",
"rdpDownloadingFiles": "Downloading {count} file(s) from remote…",
"rdpDownloadFailed": "Download failed: {fileName}",
"rdpUploaded": "Uploaded: {fileName}",
"rdpNoConnectionTarget": "No connection target available",
"rdpConnectionFailed": "Connection failed",
"rdpFit": "Fit",
"rdpFull": "Full",
"rdpReal": "Real",
"rdpMeta": "Meta",
"rdpUploadFiles": "Upload files",
"rdpFilesReadyToPaste": "Files ready to paste",
"rdpFilesReadyToPasteDescription": "{count} file(s) copied to remote clipboard — press Ctrl+V on the remote desktop to paste.",
"rdpUploadFailed": "Upload failed",
"rdpUnicodeKeyboardMode": "Unicode keyboard mode",
"sessionToolbarShow": "Show toolbar",
"sessionToolbarHide": "Hide toolbar"
}

View File

@@ -1,12 +1,42 @@
import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
import fs from "fs";
import path from "path";
const withNextIntl = createNextIntlPlugin();
// read allowedDevOrigins.json if it exists
let allowedDevOrigins: string[] = [];
const allowedDevOriginsPath = path.join(
process.cwd(),
"allowedDevOrigins.json"
);
if (fs.existsSync(allowedDevOriginsPath)) {
try {
const data = fs.readFileSync(allowedDevOriginsPath, "utf-8");
allowedDevOrigins = JSON.parse(data);
} catch {}
}
const nextConfig: NextConfig = {
reactStrictMode: false,
reactCompiler: true,
output: "standalone"
transpilePackages: ["@novnc/novnc"],
output: "standalone",
allowedDevOrigins,
async redirects() {
return [
{
source: "/:orgId/settings/resources/proxy/:path*",
destination: "/:orgId/settings/resources/public/:path*",
permanent: true
},
{
source: "/:orgId/settings/resources/client/:path*",
destination: "/:orgId/settings/resources/private/:path*",
permanent: true
}
];
}
};
export default withNextIntl(nextConfig);

1374
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -33,12 +33,14 @@
},
"dependencies": {
"@asteasolutions/zod-to-openapi": "8.5.0",
"@aws-sdk/client-s3": "3.1047.0",
"@faker-js/faker": "10.4.0",
"@devolutions/iron-remote-desktop": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-0.0.0.tgz",
"@devolutions/iron-remote-desktop-rdp": "https://static.pangolin.net/packages/devolutions-iron-remote-desktop-rdp-0.0.0.tgz",
"@aws-sdk/client-s3": "3.1056.0",
"@headlessui/react": "2.2.10",
"@hookform/resolvers": "5.2.2",
"@hookform/resolvers": "5.4.0",
"@monaco-editor/react": "4.7.0",
"@node-rs/argon2": "2.0.2",
"@novnc/novnc": "^1.7.0",
"@oslojs/crypto": "1.0.1",
"@oslojs/encoding": "1.1.0",
"@radix-ui/react-avatar": "1.1.11",
@@ -64,10 +66,13 @@
"@react-email/render": "2.0.8",
"@react-email/tailwind": "2.0.7",
"@simplewebauthn/browser": "13.3.0",
"@simplewebauthn/server": "13.3.0",
"@simplewebauthn/server": "13.3.1",
"@tailwindcss/forms": "0.5.11",
"@tanstack/react-query": "5.100.10",
"@tanstack/react-query": "5.100.14",
"@tanstack/react-table": "8.21.3",
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"arctic": "3.7.0",
"axios": "1.16.1",
"better-sqlite3": "11.9.1",
@@ -83,38 +88,37 @@
"express": "5.2.1",
"express-rate-limit": "8.5.2",
"glob": "13.0.6",
"helmet": "8.1.0",
"helmet": "8.2.0",
"http-errors": "2.0.1",
"input-otp": "1.4.2",
"ioredis": "5.10.1",
"ioredis": "5.11.0",
"jmespath": "0.16.0",
"js-yaml": "4.1.1",
"jsonwebtoken": "9.0.3",
"lucide-react": "0.577.0",
"lucide-react": "1.17.0",
"maxmind": "5.0.6",
"moment": "2.30.1",
"next": "16.2.6",
"next-intl": "4.12.0",
"next-intl": "4.13.0",
"next-themes": "0.4.6",
"nextjs-toploader": "3.9.17",
"node-cache": "5.1.2",
"nodemailer": "8.0.7",
"nodemailer": "8.0.9",
"oslo": "1.2.1",
"pg": "8.20.0",
"posthog-node": "5.34.1",
"pg": "8.21.0",
"posthog-node": "5.35.6",
"qrcode.react": "4.2.0",
"react": "19.2.6",
"react-day-picker": "9.14.0",
"react-dom": "19.2.6",
"react-easy-sort": "1.8.0",
"react-hook-form": "7.75.0",
"react-hook-form": "7.76.1",
"react-icons": "5.6.0",
"recharts": "3.8.1",
"reodotdev": "1.1.0",
"resend": "6.12.3",
"semver": "7.8.0",
"semver": "7.8.1",
"sshpk": "1.18.0",
"stripe": "20.4.1",
"stripe": "22.2.0",
"swagger-ui-express": "5.0.1",
"tailwind-merge": "3.6.0",
"topojson-client": "3.1.0",
@@ -125,18 +129,18 @@
"visionscarto-world-atlas": "1.0.0",
"winston": "3.19.0",
"winston-daily-rotate-file": "5.0.0",
"ws": "8.20.1",
"ws": "8.21.0",
"yaml": "2.9.0",
"yargs": "18.0.0",
"zod": "4.4.3",
"zod-validation-error": "5.0.0"
},
"devDependencies": {
"@dotenvx/dotenvx": "1.66.0",
"@dotenvx/dotenvx": "1.69.1",
"@esbuild-plugins/tsconfig-paths": "0.1.2",
"@react-email/ui": "^6.1.4",
"@react-email/ui": "^6.5.0",
"@tailwindcss/postcss": "4.3.0",
"@tanstack/react-query-devtools": "5.100.10",
"@tanstack/react-query-devtools": "5.100.14",
"@types/better-sqlite3": "7.6.13",
"@types/cookie-parser": "1.4.10",
"@types/cors": "2.8.19",
@@ -147,11 +151,11 @@
"@types/jmespath": "0.15.2",
"@types/js-yaml": "4.0.9",
"@types/jsonwebtoken": "9.0.10",
"@types/node": "25.8.0",
"@types/node": "25.9.1",
"@types/nodemailer": "8.0.0",
"@types/nprogress": "0.2.3",
"@types/pg": "8.20.0",
"@types/react": "19.2.14",
"@types/react": "19.2.15",
"@types/react-dom": "19.2.3",
"@types/semver": "7.7.1",
"@types/sshpk": "1.17.4",
@@ -163,20 +167,20 @@
"drizzle-kit": "0.31.10",
"esbuild": "0.28.0",
"esbuild-node-externals": "1.22.0",
"eslint": "10.3.0",
"eslint": "10.4.0",
"eslint-config-next": "16.2.6",
"postcss": "8.5.14",
"postcss": "8.5.15",
"prettier": "3.8.3",
"react-email": "6.1.4",
"react-email": "6.5.0",
"tailwindcss": "4.3.0",
"tsc-alias": "1.8.17",
"tsx": "4.22.0",
"tsx": "4.22.3",
"typescript": "6.0.3",
"typescript-eslint": "8.59.3"
"typescript-eslint": "8.60.0"
},
"overrides": {
"esbuild": "0.28.0",
"dompurify": "3.4.0",
"postcss": "8.5.14"
"postcss": "8.5.15"
}
}

View File

@@ -5,6 +5,7 @@ import { and, eq, inArray } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { getUserOrgRoleIds } from "@server/lib/userOrgRoles";
import logger from "@server/logger";
export enum ActionsEnum {
createOrgUser = "createOrgUser",
@@ -158,7 +159,26 @@ export enum ActionsEnum {
createHealthCheck = "createHealthCheck",
updateHealthCheck = "updateHealthCheck",
deleteHealthCheck = "deleteHealthCheck",
listHealthChecks = "listHealthChecks"
listHealthChecks = "listHealthChecks",
createBrowserGatewayTarget = "createBrowserGatewayTarget",
updateBrowserGatewayTarget = "updateBrowserGatewayTarget",
deleteBrowserGatewayTarget = "deleteBrowserGatewayTarget",
getBrowserGatewayTarget = "getBrowserGatewayTarget",
listBrowserGatewayTargets = "listBrowserGatewayTargets",
listResourcePolicies = "listResourcePolicies",
getResourcePolicy = "getResourcePolicy",
createResourcePolicy = "createResourcePolicy",
updateResourcePolicy = "updateResourcePolicy",
deleteResourcePolicy = "deleteResourcePolicy",
listResourcePolicyRoles = "listResourcePolicyRoles",
setResourcePolicyRoles = "setResourcePolicyRoles",
listResourcePolicyUsers = "listResourcePolicyUsers",
setResourcePolicyUsers = "setResourcePolicyUsers",
setResourcePolicyPassword = "setResourcePolicyPassword",
setResourcePolicyPincode = "setResourcePolicyPincode",
setResourcePolicyHeaderAuth = "setResourcePolicyHeaderAuth",
setResourcePolicyWhitelist = "setResourcePolicyWhitelist",
setResourcePolicyRules = "setResourcePolicyRules"
}
export async function checkUserActionPermission(
@@ -191,6 +211,23 @@ export async function checkUserActionPermission(
}
}
// If no direct permission, check role-based permission (any of user's roles)
const roleActionPermission = await db
.select()
.from(roleActions)
.where(
and(
eq(roleActions.actionId, actionId),
inArray(roleActions.roleId, userOrgRoleIds),
eq(roleActions.orgId, req.userOrgId!)
)
)
.limit(1);
if (roleActionPermission.length > 0) {
return true;
}
// Check if the user has direct permission for the action in the current org
const userActionPermission = await db
.select()
@@ -208,20 +245,7 @@ export async function checkUserActionPermission(
return true;
}
// If no direct permission, check role-based permission (any of user's roles)
const roleActionPermission = await db
.select()
.from(roleActions)
.where(
and(
eq(roleActions.actionId, actionId),
inArray(roleActions.roleId, userOrgRoleIds),
eq(roleActions.orgId, req.userOrgId!)
)
)
.limit(1);
return roleActionPermission.length > 0;
return false;
} catch (error) {
console.error("Error checking user action permission:", error);
throw createHttpError(

View File

@@ -19,6 +19,9 @@ export async function createResourceSession(opts: {
userSessionId?: string | null;
whitelistId?: number | null;
accessTokenId?: string | null;
policyPasswordId?: number | null;
policyPincodeId?: number | null;
policyWhitelistId?: number | null;
doNotExtend?: boolean;
expiresAt?: number | null;
sessionLength?: number | null;
@@ -28,7 +31,10 @@ export async function createResourceSession(opts: {
!opts.pincodeId &&
!opts.whitelistId &&
!opts.accessTokenId &&
!opts.userSessionId
!opts.userSessionId &&
!opts.policyPasswordId &&
!opts.policyPincodeId &&
!opts.policyWhitelistId
) {
throw new Error("Auth method must be provided");
}
@@ -49,6 +55,9 @@ export async function createResourceSession(opts: {
whitelistId: opts.whitelistId || null,
doNotExtend: opts.doNotExtend || false,
accessTokenId: opts.accessTokenId || null,
policyPasswordId: opts.policyPasswordId || null,
policyPincodeId: opts.policyPincodeId || null,
policyWhitelistId: opts.policyWhitelistId || null,
isRequestToken: opts.isRequestToken || false,
userSessionId: opts.userSessionId || null,
issuedAt: new Date().getTime()

View File

@@ -1,6 +1,12 @@
import { join } from "path";
import { readFileSync } from "fs";
import { clients, db, resources, siteResources } from "@server/db";
import {
clients,
db,
resourcePolicies,
resources,
siteResources
} from "@server/db";
import { randomInt } from "crypto";
import { exitNodes, sites } from "@server/db";
import { eq, and } from "drizzle-orm";
@@ -107,6 +113,35 @@ export async function getUniqueResourceName(orgId: string): Promise<string> {
}
}
export async function getUniqueResourcePolicyName(
orgId: string
): Promise<string> {
let loops = 0;
while (true) {
if (loops > 100) {
throw new Error("Could not generate a unique name");
}
const name = generateName();
const policyCount = await db
.select({
niceId: resourcePolicies.niceId,
orgId: resourcePolicies.orgId
})
.from(resourcePolicies)
.where(
and(
eq(resourcePolicies.niceId, name),
eq(resourcePolicies.orgId, orgId)
)
);
if (policyCount.length === 0) {
return name;
}
loops++;
}
}
export async function getUniqueSiteResourceName(
orgId: string
): Promise<string> {

View File

@@ -4,3 +4,4 @@ export * from "./safeRead";
export * from "./schema/schema";
export * from "./schema/privateSchema";
export * from "./migrate";
export { alias } from "drizzle-orm/pg-core";

View File

@@ -580,6 +580,24 @@ export const trialNotifications = pgTable("trialNotifications", {
sentAt: bigint("sentAt", { mode: "number" }).notNull()
});
export const browserGatewayTarget = pgTable("browserGatewayTarget", {
browserGatewayTargetId: serial("browserGatewayTargetId").primaryKey(),
resourceId: integer("resourceId")
.references(() => resources.resourceId, {
onDelete: "cascade"
})
.notNull(),
siteId: integer("siteId")
.references(() => sites.siteId, {
onDelete: "cascade"
})
.notNull(),
authToken: varchar("authToken").notNull(),
type: varchar("type").notNull(), // "ssh", "rdp", "vnc"
destination: varchar("destination").notNull(),
destinationPort: integer("destinationPort").notNull()
});
export type Approval = InferSelectModel<typeof approvals>;
export type Limit = InferSelectModel<typeof limits>;
export type Account = InferSelectModel<typeof account>;
@@ -627,3 +645,6 @@ export type AlertEmailRecipients = InferSelectModel<
>;
export type AlertWebhookActions = InferSelectModel<typeof alertWebhookActions>;
export type TrialNotification = InferSelectModel<typeof trialNotifications>;
export type BrowserGatewayTarget = InferSelectModel<
typeof browserGatewayTarget
>;

View File

@@ -65,7 +65,12 @@ export const orgs = pgTable("orgs", {
sshCaPrivateKey: text("sshCaPrivateKey"), // Encrypted SSH CA private key (PEM format)
sshCaPublicKey: text("sshCaPublicKey"), // SSH CA public key (OpenSSH format)
isBillingOrg: boolean("isBillingOrg"),
billingOrgId: varchar("billingOrgId")
billingOrgId: varchar("billingOrgId"),
settingsEnableGlobalNewtAutoUpdate: boolean(
"settingsEnableGlobalNewtAutoUpdate"
)
.notNull()
.default(false)
});
export const orgDomains = pgTable("orgDomains", {
@@ -103,6 +108,10 @@ export const sites = pgTable("sites", {
lastHolePunch: bigint("lastHolePunch", { mode: "number" }),
listenPort: integer("listenPort"),
dockerSocketEnabled: boolean("dockerSocketEnabled").notNull().default(true),
autoUpdateEnabled: boolean("autoUpdateEnabled").notNull().default(false),
autoUpdateOverrideOrg: boolean("autoUpdateOverrideOrg")
.notNull()
.default(false),
status: varchar("status")
.$type<"pending" | "approved">()
.default("approved")
@@ -110,6 +119,16 @@ export const sites = pgTable("sites", {
export const resources = pgTable("resources", {
resourceId: serial("resourceId").primaryKey(),
resourcePolicyId: integer("resourcePolicyId").references(
() => resourcePolicies.resourcePolicyId,
{ onDelete: "set null" }
),
defaultResourcePolicyId: integer("defaultResourcePolicyId").references(
() => resourcePolicies.resourcePolicyId,
{
onDelete: "restrict"
}
),
resourceGuid: varchar("resourceGuid", { length: 36 })
.unique()
.notNull()
@@ -129,8 +148,6 @@ export const resources = pgTable("resources", {
ssl: boolean("ssl").notNull().default(false),
blockAccess: boolean("blockAccess").notNull().default(false),
sso: boolean("sso").notNull().default(true),
http: boolean("http").notNull().default(true),
protocol: varchar("protocol").notNull(),
proxyPort: integer("proxyPort"),
emailWhitelistEnabled: boolean("emailWhitelistEnabled")
.notNull()
@@ -147,7 +164,6 @@ export const resources = pgTable("resources", {
headers: text("headers"), // comma-separated list of headers to add to the request
proxyProtocol: boolean("proxyProtocol").notNull().default(false),
proxyProtocolVersion: integer("proxyProtocolVersion").default(1),
maintenanceModeEnabled: boolean("maintenanceModeEnabled")
.notNull()
.default(false),
@@ -159,7 +175,15 @@ export const resources = pgTable("resources", {
maintenanceEstimatedTime: text("maintenanceEstimatedTime"),
postAuthPath: text("postAuthPath"),
health: varchar("health").default("unknown"), // "healthy", "unhealthy", "unknown"
wildcard: boolean("wildcard").notNull().default(false)
wildcard: boolean("wildcard").notNull().default(false),
mode: text("mode").default("http").notNull(), // rdp, ssh, http, vnc
pamMode: varchar("pamMode", { length: 32 })
.$type<"passthrough" | "push">()
.default("passthrough"),
authDaemonMode: varchar("authDaemonMode", { length: 32 })
.$type<"site" | "remote" | "native">()
.default("site"),
authDaemonPort: integer("authDaemonPort").default(22123)
});
export const labels = pgTable("labels", {
@@ -339,11 +363,11 @@ export const siteResources = pgTable("siteResources", {
niceId: varchar("niceId").notNull(),
name: varchar("name").notNull(),
ssl: boolean("ssl").notNull().default(false),
mode: varchar("mode").$type<"host" | "cidr" | "http">().notNull(), // "host" | "cidr" | "http"
mode: varchar("mode").$type<"host" | "cidr" | "http" | "ssh">().notNull(), // "host" | "cidr" | "http"
scheme: varchar("scheme").$type<"http" | "https">(), // only for when we are doing https or http mode
proxyPort: integer("proxyPort"), // only for port mode
destinationPort: integer("destinationPort"), // only for port mode
destination: varchar("destination").notNull(), // ip, cidr, hostname; validate against the mode
destination: varchar("destination"), // ip, cidr, hostname; validate against the mode
enabled: boolean("enabled").notNull().default(true),
alias: varchar("alias"),
aliasAddress: varchar("aliasAddress"),
@@ -351,8 +375,11 @@ export const siteResources = pgTable("siteResources", {
udpPortRangeString: varchar("udpPortRangeString").notNull().default("*"),
disableIcmp: boolean("disableIcmp").notNull().default(false),
authDaemonPort: integer("authDaemonPort").default(22123),
pamMode: varchar("pamMode", { length: 32 })
.$type<"passthrough" | "push">()
.default("passthrough"),
authDaemonMode: varchar("authDaemonMode", { length: 32 })
.$type<"site" | "remote">()
.$type<"site" | "remote" | "native">()
.default("site"),
domainId: varchar("domainId").references(() => domains.domainId, {
onDelete: "set null"
@@ -606,6 +633,38 @@ export const userResources = pgTable("userResources", {
.references(() => resources.resourceId, { onDelete: "cascade" })
});
export const rolePolicies = pgTable("rolePolicies", {
roleId: integer("roleId")
.notNull()
.references(() => roles.roleId, { onDelete: "cascade" }),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const userPolicies = pgTable("userPolicies", {
userId: varchar("userId")
.notNull()
.references(() => users.userId, { onDelete: "cascade" }),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyWhiteList = pgTable("resourcePolicyWhitelist", {
whitelistId: serial("id").primaryKey(),
email: varchar("email").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const userInvites = pgTable("userInvites", {
inviteId: varchar("inviteId").primaryKey(),
orgId: varchar("orgId")
@@ -671,6 +730,40 @@ export const resourceHeaderAuthExtendedCompatibility = pgTable(
}
);
export const resourcePolicyPincode = pgTable("resourcePolicyPincode", {
pincodeId: serial("pincodeId").primaryKey(),
pincodeHash: varchar("pincodeHash").notNull(),
digitLength: integer("digitLength").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyPassword = pgTable("resourcePolicyPassword", {
passwordId: serial("passwordId").primaryKey(),
passwordHash: varchar("passwordHash").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyHeaderAuth = pgTable("resourcePolicyHeaderAuth", {
headerAuthId: serial("headerAuthId").primaryKey(),
headerAuthHash: varchar("headerAuthHash").notNull(),
extendedCompatibility: boolean("extendedCompatibility")
.notNull()
.default(true),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourceAccessToken = pgTable("resourceAccessToken", {
accessTokenId: varchar("accessTokenId").primaryKey(),
orgId: varchar("orgId")
@@ -679,6 +772,7 @@ export const resourceAccessToken = pgTable("resourceAccessToken", {
resourceId: integer("resourceId")
.notNull()
.references(() => resources.resourceId, { onDelete: "cascade" }),
path: varchar("path"),
tokenHash: varchar("tokenHash").notNull(),
sessionLength: bigint("sessionLength", { mode: "number" }).notNull(),
expiresAt: bigint("expiresAt", { mode: "number" }),
@@ -726,6 +820,24 @@ export const resourceSessions = pgTable("resourceSessions", {
onDelete: "cascade"
}
),
policyPasswordId: integer("policyPasswordId").references(
() => resourcePolicyPassword.passwordId,
{
onDelete: "cascade"
}
),
policyPincodeId: integer("policyPincodeId").references(
() => resourcePolicyPincode.pincodeId,
{
onDelete: "cascade"
}
),
policyWhitelistId: integer("policyWhitelistId").references(
() => resourcePolicyWhiteList.whitelistId,
{
onDelete: "cascade"
}
),
issuedAt: bigint("issuedAt", { mode: "number" })
});
@@ -764,6 +876,43 @@ export const resourceRules = pgTable("resourceRules", {
value: varchar("value").notNull()
});
export const resourcePolicyRules = pgTable("resourcePolicyRules", {
ruleId: serial("ruleId").primaryKey(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
}),
enabled: boolean("enabled").notNull().default(true),
priority: integer("priority").notNull(),
action: varchar("action").$type<"ACCEPT" | "DROP" | "PASS">().notNull(),
match: varchar("match").$type<"CIDR" | "PATH" | "IP">().notNull(),
value: varchar("value").notNull()
});
export const resourcePolicies = pgTable("resourcePolicies", {
resourcePolicyId: serial("resourcePolicyId").primaryKey(),
sso: boolean("sso").notNull().default(true),
applyRules: boolean("applyRules").notNull().default(false),
scope: varchar("scope")
.$type<"global" | "resource">()
.notNull()
.default("global"),
emailWhitelistEnabled: boolean("emailWhitelistEnabled")
.notNull()
.default(false),
idpId: integer("idpId").references(() => idp.idpId, {
onDelete: "set null"
}),
niceId: text("niceId").notNull(),
name: varchar("name").notNull(),
orgId: varchar("orgId")
.references(() => orgs.orgId, {
onDelete: "cascade"
})
.notNull()
});
export const supporterKey = pgTable("supporterKey", {
keyId: serial("keyId").primaryKey(),
key: varchar("key").notNull(),
@@ -1243,6 +1392,16 @@ export type ResourceHeaderAuthExtendedCompatibility = InferSelectModel<
export type ResourceOtp = InferSelectModel<typeof resourceOtp>;
export type ResourceAccessToken = InferSelectModel<typeof resourceAccessToken>;
export type ResourceWhitelist = InferSelectModel<typeof resourceWhitelist>;
export type ResourcePolicyPincode = InferSelectModel<
typeof resourcePolicyPincode
>;
export type ResourcePolicyPassword = InferSelectModel<
typeof resourcePolicyPassword
>;
export type ResourcePolicyHeaderAuth = InferSelectModel<
typeof resourcePolicyHeaderAuth
>;
export type VersionMigration = InferSelectModel<typeof versionMigrations>;
export type ResourceRule = InferSelectModel<typeof resourceRules>;
export type Domain = InferSelectModel<typeof domains>;
@@ -1276,3 +1435,6 @@ export type RoundTripMessageTracker = InferSelectModel<
export type Network = InferSelectModel<typeof networks>;
export type StatusHistory = InferSelectModel<typeof statusHistory>;
export type Label = InferSelectModel<typeof labels>;
export type ResourcePolicy = InferSelectModel<typeof resourcePolicies>;
export type RolePolicy = InferSelectModel<typeof rolePolicies>;
export type UserPolicy = InferSelectModel<typeof userPolicies>;

View File

@@ -17,22 +17,37 @@ import {
resourceHeaderAuth,
ResourceHeaderAuth,
resourceRules,
resourcePolicyRules,
resources,
roleResources,
rolePolicies,
sessions,
userResources,
userPolicies,
users,
ResourceHeaderAuthExtendedCompatibility,
resourceHeaderAuthExtendedCompatibility
resourceHeaderAuthExtendedCompatibility,
resourcePolicies,
resourcePolicyPincode,
ResourcePolicyPincode,
resourcePolicyPassword,
ResourcePolicyPassword,
resourcePolicyHeaderAuth,
ResourcePolicyHeaderAuth
} from "@server/db";
import { and, eq, inArray, or, sql } from "drizzle-orm";
import { alias } from "@server/db";
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
import logger from "@server/logger";
export type ResourceWithAuth = {
resource: Resource | null;
pincode: ResourcePincode | null;
password: ResourcePassword | null;
headerAuth: ResourceHeaderAuth | null;
pincode: ResourcePincode | ResourcePolicyPincode | null;
password: ResourcePassword | ResourcePolicyPassword | null;
headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean;
sso: boolean;
emailWhitelistEnabled: boolean;
org: Org;
};
@@ -57,6 +72,33 @@ export async function getResourceByDomain(
wildcardCandidates.push(`*.${parts.slice(i).join(".")}`);
}
const sharedPolicy = alias(resourcePolicies, "sharedPolicy");
const defaultPolicy = alias(resourcePolicies, "defaultPolicy");
const sharedPolicyPincode = alias(
resourcePolicyPincode,
"sharedPolicyPincode"
);
const defaultPolicyPincode = alias(
resourcePolicyPincode,
"defaultPolicyPincode"
);
const sharedPolicyPassword = alias(
resourcePolicyPassword,
"sharedPolicyPassword"
);
const defaultPolicyPassword = alias(
resourcePolicyPassword,
"defaultPolicyPassword"
);
const sharedPolicyHeaderAuth = alias(
resourcePolicyHeaderAuth,
"sharedPolicyHeaderAuth"
);
const defaultPolicyHeaderAuth = alias(
resourcePolicyHeaderAuth,
"defaultPolicyHeaderAuth"
);
const potentialResults = await db
.select()
.from(resources)
@@ -79,6 +121,59 @@ export async function getResourceByDomain(
resources.resourceId
)
)
.leftJoin(
sharedPolicy,
eq(sharedPolicy.resourcePolicyId, resources.resourcePolicyId)
)
.leftJoin(
sharedPolicyPincode,
eq(
sharedPolicyPincode.resourcePolicyId,
sharedPolicy.resourcePolicyId
)
)
.leftJoin(
sharedPolicyPassword,
eq(
sharedPolicyPassword.resourcePolicyId,
sharedPolicy.resourcePolicyId
)
)
.leftJoin(
sharedPolicyHeaderAuth,
eq(
sharedPolicyHeaderAuth.resourcePolicyId,
sharedPolicy.resourcePolicyId
)
)
.leftJoin(
defaultPolicy,
eq(
defaultPolicy.resourcePolicyId,
resources.defaultResourcePolicyId
)
)
.leftJoin(
defaultPolicyPincode,
eq(
defaultPolicyPincode.resourcePolicyId,
defaultPolicy.resourcePolicyId
)
)
.leftJoin(
defaultPolicyPassword,
eq(
defaultPolicyPassword.resourcePolicyId,
defaultPolicy.resourcePolicyId
)
)
.leftJoin(
defaultPolicyHeaderAuth,
eq(
defaultPolicyHeaderAuth.resourcePolicyId,
defaultPolicy.resourcePolicyId
)
)
.innerJoin(orgs, eq(orgs.orgId, resources.orgId))
.where(
or(
@@ -108,13 +203,51 @@ export async function getResourceByDomain(
return null;
}
// If a shared (custom) policy is assigned to the resource, use ONLY
// its values — do not fall back to the default policy. The default
// policy is only consulted when no shared policy is assigned at all.
const hasSharedPolicy = result.sharedPolicy !== null;
const effectivePolicyPincode = hasSharedPolicy
? result.sharedPolicyPincode
: (result.defaultPolicyPincode ?? null);
const effectivePolicyPassword = hasSharedPolicy
? result.sharedPolicyPassword
: (result.defaultPolicyPassword ?? null);
const effectivePolicyHeaderAuth = hasSharedPolicy
? result.sharedPolicyHeaderAuth
: (result.defaultPolicyHeaderAuth ?? null);
const selectedPolicy = hasSharedPolicy
? result.sharedPolicy
: result.defaultPolicy;
const effectiveApplyRules =
selectedPolicy?.applyRules ?? result.resources.applyRules;
const effectiveSSO = selectedPolicy?.sso ?? result.resources.sso;
const effectiveEmailWhitelistEnabled =
selectedPolicy?.emailWhitelistEnabled ??
result.resources.emailWhitelistEnabled;
return {
resource: result.resources,
pincode: result.resourcePincode,
password: result.resourcePassword,
headerAuth: result.resourceHeaderAuth,
headerAuthExtendedCompatibility:
result.resourceHeaderAuthExtendedCompatibility,
resource: {
...result.resources,
applyRules: effectiveApplyRules,
sso: effectiveSSO,
emailWhitelistEnabled: effectiveEmailWhitelistEnabled
}, // doing this for backward compatability so the remote nodes get the value as part of the resource struct
pincode: effectivePolicyPincode ?? result.resourcePincode,
password: effectivePolicyPassword ?? result.resourcePassword,
headerAuth: effectivePolicyHeaderAuth ?? result.resourceHeaderAuth,
headerAuthExtendedCompatibility: effectivePolicyHeaderAuth
? ({
headerAuthExtendedCompatibilityId: 0,
resourceId: result.resources.resourceId,
extendedCompatibilityIsActivated:
effectivePolicyHeaderAuth.extendedCompatibility
} as ResourceHeaderAuthExtendedCompatibility)
: result.resourceHeaderAuthExtendedCompatibility,
applyRules: effectiveApplyRules,
sso: effectiveSSO,
emailWhitelistEnabled: effectiveEmailWhitelistEnabled,
org: result.orgs
};
}
@@ -154,58 +287,165 @@ export async function getRoleName(roleId: number): Promise<string | null> {
}
/**
* Check if role has access to resource
* Check if role has access to resource (direct or via resource policy)
*/
export async function getRoleResourceAccess(
resourceId: number,
roleIds: number[]
) {
const roleResourceAccess = await db
.select()
.from(roleResources)
.where(
and(
eq(roleResources.resourceId, resourceId),
inArray(roleResources.roleId, roleIds)
const [direct, viaPolicies] = await Promise.all([
db
.select()
.from(roleResources)
.where(
and(
eq(roleResources.resourceId, resourceId),
inArray(roleResources.roleId, roleIds)
)
),
db
.select({
roleId: rolePolicies.roleId,
resourcePolicyId: rolePolicies.resourcePolicyId
})
.from(rolePolicies)
.innerJoin(
resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq(
resources.resourcePolicyId,
rolePolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
rolePolicies.resourcePolicyId
)
)
)
)
);
.where(
and(
eq(resources.resourceId, resourceId),
inArray(rolePolicies.roleId, roleIds)
)
)
]);
return roleResourceAccess.length > 0 ? roleResourceAccess : null;
const combined = [...direct, ...viaPolicies];
return combined.length > 0 ? combined : null;
}
/**
* Check if user has direct access to resource
* Check if user has access to resource (direct or via resource policy)
*/
export async function getUserResourceAccess(
userId: string,
resourceId: number
) {
const userResourceAccess = await db
.select()
.from(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resourceId)
const [direct, viaPolicies] = await Promise.all([
db
.select()
.from(userResources)
.where(
and(
eq(userResources.userId, userId),
eq(userResources.resourceId, resourceId)
)
)
)
.limit(1);
.limit(1),
db
.select({
userId: userPolicies.userId,
resourcePolicyId: userPolicies.resourcePolicyId
})
.from(userPolicies)
.innerJoin(
resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq(
resources.resourcePolicyId,
userPolicies.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
userPolicies.resourcePolicyId
)
)
)
)
.where(
and(
eq(resources.resourceId, resourceId),
eq(userPolicies.userId, userId)
)
)
.limit(1)
]);
return userResourceAccess.length > 0 ? userResourceAccess[0] : null;
return direct[0] ?? viaPolicies[0] ?? null;
}
/**
* Get resource rules for a given resource
* Get resource rules for a given resource (direct and via resource policy)
*/
export async function getResourceRules(
resourceId: number
): Promise<ResourceRule[]> {
const rules = await db
.select()
.from(resourceRules)
.where(eq(resourceRules.resourceId, resourceId));
const [directRules, policyRules] = await Promise.all([
db
.select()
.from(resourceRules)
.where(eq(resourceRules.resourceId, resourceId)),
db
.select({
ruleId: resourcePolicyRules.ruleId,
resourceId: sql<number>`${resourceId}`,
enabled: resourcePolicyRules.enabled,
priority: resourcePolicyRules.priority,
action: resourcePolicyRules.action,
match: resourcePolicyRules.match,
value: resourcePolicyRules.value
})
.from(resourcePolicyRules)
.innerJoin(
resources,
// Shared policy wins; only use default policy when no shared
// policy is assigned to the resource.
or(
eq(
resources.resourcePolicyId,
resourcePolicyRules.resourcePolicyId
),
and(
isNull(resources.resourcePolicyId),
eq(
resources.defaultResourcePolicyId,
resourcePolicyRules.resourcePolicyId
)
)
)
)
.where(eq(resources.resourceId, resourceId))
]);
return rules;
const maxDirectPriority = directRules.reduce(
(max, r) => Math.max(max, r.priority),
0
);
const offsetPolicyRules = policyRules.map((r) => ({
...r,
priority: maxDirectPriority + r.priority
}));
return [...directRules, ...offsetPolicyRules] as ResourceRule[];
}
/**

View File

@@ -4,3 +4,4 @@ export * from "./safeRead";
export * from "./schema/schema";
export * from "./schema/privateSchema";
export * from "./migrate";
export { alias } from "drizzle-orm/sqlite-core";

View File

@@ -588,6 +588,26 @@ export const trialNotifications = sqliteTable("trialNotifications", {
sentAt: integer("sentAt").notNull()
});
export const browserGatewayTarget = sqliteTable("browserGatewayTarget", {
browserGatewayTargetId: integer("browserGatewayTargetId").primaryKey({
autoIncrement: true
}),
resourceId: integer("resourceId")
.references(() => resources.resourceId, {
onDelete: "cascade"
})
.notNull(),
siteId: integer("siteId")
.references(() => sites.siteId, {
onDelete: "cascade"
})
.notNull(),
authToken: text("authToken").notNull(),
type: text("type").notNull(), // "ssh", "rdp", "vnc"
destination: text("destination").notNull(),
destinationPort: integer("destinationPort").notNull()
});
export type Approval = InferSelectModel<typeof approvals>;
export type Limit = InferSelectModel<typeof limits>;
export type Account = InferSelectModel<typeof account>;
@@ -627,3 +647,6 @@ export type AlertEmailAction = InferSelectModel<typeof alertEmailActions>;
export type AlertEmailRecipient = InferSelectModel<typeof alertEmailRecipients>;
export type AlertWebhookAction = InferSelectModel<typeof alertWebhookActions>;
export type TrialNotification = InferSelectModel<typeof trialNotifications>;
export type BrowserGatewayTarget = InferSelectModel<
typeof browserGatewayTarget
>;

View File

@@ -62,7 +62,13 @@ export const orgs = sqliteTable("orgs", {
sshCaPrivateKey: text("sshCaPrivateKey"), // Encrypted SSH CA private key (PEM format)
sshCaPublicKey: text("sshCaPublicKey"), // SSH CA public key (OpenSSH format)
isBillingOrg: integer("isBillingOrg", { mode: "boolean" }),
billingOrgId: text("billingOrgId")
billingOrgId: text("billingOrgId"),
settingsEnableGlobalNewtAutoUpdate: integer(
"settingsEnableGlobalNewtAutoUpdate",
{ mode: "boolean" }
)
.notNull()
.default(false)
});
export const userDomains = sqliteTable("userDomains", {
@@ -116,11 +122,29 @@ export const sites = sqliteTable("sites", {
dockerSocketEnabled: integer("dockerSocketEnabled", { mode: "boolean" })
.notNull()
.default(true),
autoUpdateEnabled: integer("autoUpdateEnabled", { mode: "boolean" })
.notNull()
.default(false),
autoUpdateOverrideOrg: integer("autoUpdateOverrideOrg", {
mode: "boolean"
})
.notNull()
.default(false),
status: text("status").$type<"pending" | "approved">().default("approved")
});
export const resources = sqliteTable("resources", {
resourceId: integer("resourceId").primaryKey({ autoIncrement: true }),
resourcePolicyId: integer("resourcePolicyId").references(
() => resourcePolicies.resourcePolicyId,
{ onDelete: "set null" }
),
defaultResourcePolicyId: integer("defaultResourcePolicyId").references(
() => resourcePolicies.resourcePolicyId,
{
onDelete: "restrict"
}
),
resourceGuid: text("resourceGuid", { length: 36 })
.unique()
.notNull()
@@ -142,8 +166,6 @@ export const resources = sqliteTable("resources", {
.notNull()
.default(false),
sso: integer("sso", { mode: "boolean" }).notNull().default(true),
http: integer("http", { mode: "boolean" }).notNull().default(true),
protocol: text("protocol").notNull(),
proxyPort: integer("proxyPort"),
emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" })
.notNull()
@@ -166,7 +188,6 @@ export const resources = sqliteTable("resources", {
.notNull()
.default(false),
proxyProtocolVersion: integer("proxyProtocolVersion").default(1),
maintenanceModeEnabled: integer("maintenanceModeEnabled", {
mode: "boolean"
})
@@ -180,7 +201,15 @@ export const resources = sqliteTable("resources", {
maintenanceEstimatedTime: text("maintenanceEstimatedTime"),
postAuthPath: text("postAuthPath"),
health: text("health").default("unknown"), // "healthy", "unhealthy", "unknown"
wildcard: integer("wildcard", { mode: "boolean" }).notNull().default(false)
wildcard: integer("wildcard", { mode: "boolean" }).notNull().default(false),
mode: text("mode").default("http").notNull(), // rdp, ssh, http, vnc
pamMode: text("pamMode")
.$type<"passthrough" | "push">()
.default("passthrough"),
authDaemonMode: text("authDaemonMode")
.$type<"site" | "remote" | "native">()
.default("site"),
authDaemonPort: integer("authDaemonPort").default(22123)
});
export const labels = sqliteTable("labels", {
@@ -372,11 +401,11 @@ export const siteResources = sqliteTable("siteResources", {
niceId: text("niceId").notNull(),
name: text("name").notNull(),
ssl: integer("ssl", { mode: "boolean" }).notNull().default(false),
mode: text("mode").$type<"host" | "cidr" | "http">().notNull(), // "host" | "cidr" | "http"
mode: text("mode").$type<"host" | "cidr" | "http" | "ssh">().notNull(), // "host" | "cidr" | "http"
scheme: text("scheme").$type<"http" | "https">(), // only for when we are doing https or http mode
proxyPort: integer("proxyPort"), // only for port mode
destinationPort: integer("destinationPort"), // only for port mode
destination: text("destination").notNull(), // ip, cidr, hostname
destination: text("destination"), // ip, cidr, hostname
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
alias: text("alias"),
aliasAddress: text("aliasAddress"),
@@ -386,8 +415,11 @@ export const siteResources = sqliteTable("siteResources", {
.notNull()
.default(false),
authDaemonPort: integer("authDaemonPort").default(22123),
pamMode: text("pamMode")
.$type<"passthrough" | "push">()
.default("passthrough"),
authDaemonMode: text("authDaemonMode")
.$type<"site" | "remote">()
.$type<"site" | "remote" | "native">()
.default("site"),
domainId: text("domainId").references(() => domains.domainId, {
onDelete: "set null"
@@ -1000,6 +1032,47 @@ export const resourceHeaderAuth = sqliteTable("resourceHeaderAuth", {
headerAuthHash: text("headerAuthHash").notNull()
});
export const resourcePolicyPincode = sqliteTable("resourcePolicyPincode", {
pincodeId: integer("pincodeId").primaryKey({ autoIncrement: true }),
pincodeHash: text("pincodeHash").notNull(),
digitLength: integer("digitLength").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyPassword = sqliteTable("resourcePolicyPassword", {
passwordId: integer("passwordId").primaryKey({ autoIncrement: true }),
passwordHash: text("passwordHash").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyHeaderAuth = sqliteTable(
"resourcePolicyHeaderAuth",
{
headerAuthId: integer("headerAuthId").primaryKey({
autoIncrement: true
}),
headerAuthHash: text("headerAuthHash").notNull(),
extendedCompatibility: integer("extendedCompatibility", {
mode: "boolean"
})
.notNull()
.default(true),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
}
);
export const resourceHeaderAuthExtendedCompatibility = sqliteTable(
"resourceHeaderAuthExtendedCompatibility",
{
@@ -1028,6 +1101,7 @@ export const resourceAccessToken = sqliteTable("resourceAccessToken", {
resourceId: integer("resourceId")
.notNull()
.references(() => resources.resourceId, { onDelete: "cascade" }),
path: text("path"),
tokenHash: text("tokenHash").notNull(),
sessionLength: integer("sessionLength").notNull(),
expiresAt: integer("expiresAt"),
@@ -1074,6 +1148,24 @@ export const resourceSessions = sqliteTable("resourceSessions", {
onDelete: "cascade"
}
),
policyPasswordId: integer("policyPasswordId").references(
() => resourcePolicyPassword.passwordId,
{
onDelete: "cascade"
}
),
policyPincodeId: integer("policyPincodeId").references(
() => resourcePolicyPincode.pincodeId,
{
onDelete: "cascade"
}
),
policyWhitelistId: integer("policyWhitelistId").references(
() => resourcePolicyWhiteList.whitelistId,
{
onDelete: "cascade"
}
),
issuedAt: integer("issuedAt")
});
@@ -1114,6 +1206,77 @@ export const resourceRules = sqliteTable("resourceRules", {
value: text("value").notNull()
});
export const rolePolicies = sqliteTable("rolePolicies", {
roleId: integer("roleId")
.notNull()
.references(() => roles.roleId, { onDelete: "cascade" }),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const userPolicies = sqliteTable("userPolicies", {
userId: text("userId")
.notNull()
.references(() => users.userId, { onDelete: "cascade" }),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyWhiteList = sqliteTable("resourcePolicyWhitelist", {
whitelistId: integer("id").primaryKey({ autoIncrement: true }),
email: text("email").notNull(),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
})
});
export const resourcePolicyRules = sqliteTable("resourcePolicyRules", {
ruleId: integer("ruleId").primaryKey({ autoIncrement: true }),
resourcePolicyId: integer("resourcePolicyId")
.notNull()
.references(() => resourcePolicies.resourcePolicyId, {
onDelete: "cascade"
}),
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
priority: integer("priority").notNull(),
action: text("action").$type<"ACCEPT" | "DROP" | "PASS">().notNull(),
match: text("match").$type<"CIDR" | "PATH" | "IP">().notNull(),
value: text("value").notNull()
});
export const resourcePolicies = sqliteTable("resourcePolicies", {
resourcePolicyId: integer("resourcePolicyId").primaryKey(),
sso: integer("sso", { mode: "boolean" }).notNull().default(true),
applyRules: integer("applyRules", { mode: "boolean" })
.notNull()
.default(false),
scope: text("scope")
.$type<"global" | "resource">()
.notNull()
.default("global"),
emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" })
.notNull()
.default(false),
niceId: text("niceId").notNull(),
idpId: integer("idpId").references(() => idp.idpId, {
onDelete: "set null"
}),
name: text("name").notNull(),
orgId: text("orgId")
.references(() => orgs.orgId, {
onDelete: "cascade"
})
.notNull()
});
export const supporterKey = sqliteTable("supporterKey", {
keyId: integer("keyId").primaryKey({ autoIncrement: true }),
key: text("key").notNull(),
@@ -1381,3 +1544,15 @@ export type RoundTripMessageTracker = InferSelectModel<
>;
export type StatusHistory = InferSelectModel<typeof statusHistory>;
export type Label = InferSelectModel<typeof labels>;
export type ResourcePolicy = InferSelectModel<typeof resourcePolicies>;
export type ResourcePolicyPincode = InferSelectModel<
typeof resourcePolicyPincode
>;
export type ResourcePolicyPassword = InferSelectModel<
typeof resourcePolicyPassword
>;
export type ResourcePolicyHeaderAuth = InferSelectModel<
typeof resourcePolicyHeaderAuth
>;
export type RolePolicy = InferSelectModel<typeof rolePolicies>;
export type UserPolicy = InferSelectModel<typeof userPolicies>;

View File

@@ -152,11 +152,17 @@ function getOpenApiDocumentation() {
if (!hasExistingResponses) {
def.route.responses = {
"*": {
description: "",
"200": {
description: "Successful response",
content: {
"application/json": {
schema: z.object({})
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}

View File

@@ -221,10 +221,18 @@ async function handleResource(
)
.where(eq(targets.resourceId, resource.resourceId));
const monitoredTargets = otherTargets.filter(
(t) => t.hcHealth !== "unknown"
);
let health = "healthy";
const allUnknown = otherTargets.every((t) => t.hcHealth === "unknown");
const allHealthy = otherTargets.every((t) => t.hcHealth === "healthy");
const allUnhealthy = otherTargets.every((t) => t.hcHealth === "unhealthy");
const allUnknown = monitoredTargets.length === 0;
const allHealthy = monitoredTargets.every(
(t) => t.hcHealth === "healthy"
);
const allUnhealthy = monitoredTargets.every(
(t) => t.hcHealth === "unhealthy"
);
if (allUnknown) {
logger.debug(

View File

@@ -16,16 +16,18 @@ export enum TierFeature {
SessionDurationPolicies = "sessionDurationPolicies", // handle downgrade by setting to default duration
PasswordExpirationPolicies = "passwordExpirationPolicies", // handle downgrade by setting to default duration
AutoProvisioning = "autoProvisioning", // handle downgrade by disabling auto provisioning
SshPam = "sshPam",
FullRbac = "fullRbac",
SiteProvisioningKeys = "siteProvisioningKeys", // handle downgrade by revoking keys if needed
SIEM = "siem", // handle downgrade by disabling SIEM integrations
HTTPPrivateResources = "httpPrivateResources", // handle downgrade by disabling HTTP private resources
DomainNamespaces = "domainNamespaces", // handle downgrade by removing custom domain namespaces
StandaloneHealthChecks = "standaloneHealthChecks",
AlertingRules = "alertingRules",
WildcardSubdomain = "wildcardSubdomain",
Labels = "labels"
Labels = "labels",
NewtAutoUpdate = "newtAutoUpdate",
ResourcePolicies = "resourcePolicies",
AdvancedPublicResources = "advancedPublicResources",
AdvancedPrivateResources = "advancedPrivateResources"
}
export const tierMatrix: Record<TierFeature, Tier[]> = {
@@ -60,13 +62,25 @@ export const tierMatrix: Record<TierFeature, Tier[]> = {
"enterprise"
],
[TierFeature.AutoProvisioning]: ["tier1", "tier3", "enterprise"],
[TierFeature.SshPam]: ["tier1", "tier3", "enterprise"],
[TierFeature.FullRbac]: ["tier1", "tier2", "tier3", "enterprise"],
[TierFeature.SiteProvisioningKeys]: ["tier3", "enterprise"],
[TierFeature.SIEM]: ["enterprise"],
[TierFeature.HTTPPrivateResources]: ["tier3", "enterprise"],
[TierFeature.DomainNamespaces]: ["tier1", "tier2", "tier3", "enterprise"],
[TierFeature.StandaloneHealthChecks]: ["tier3", "enterprise"],
[TierFeature.AlertingRules]: ["tier3", "enterprise"],
[TierFeature.WildcardSubdomain]: ["tier1", "tier2", "tier3", "enterprise"]
[TierFeature.WildcardSubdomain]: ["tier1", "tier2", "tier3", "enterprise"],
[TierFeature.NewtAutoUpdate]: ["tier1", "tier2", "tier3", "enterprise"],
[TierFeature.ResourcePolicies]: ["tier3", "enterprise"],
[TierFeature.AdvancedPublicResources]: [
"tier1",
"tier2",
"tier3",
"enterprise"
],
[TierFeature.AdvancedPrivateResources]: [
"tier1",
"tier2",
"tier3",
"enterprise"
]
};

View File

@@ -16,14 +16,13 @@ import logger from "@server/logger";
import { sites } from "@server/db";
import { eq, and, isNotNull } from "drizzle-orm";
import { addTargets as addProxyTargets } from "@server/routers/newt/targets";
import { addTargets as addClientTargets } from "@server/routers/client/targets";
import {
ClientResourcesResults,
updateClientResources
} from "./clientResources";
import { BlueprintSource } from "@server/routers/blueprints/types";
import { stringify as stringifyYaml } from "yaml";
import { faker } from "@faker-js/faker";
import { generateName } from "@server/db/names";
import { handleMessagingForUpdatedSiteResource } from "@server/routers/siteResource";
import { rebuildClientAssociationsFromSiteResource } from "../rebuildClientAssociations";
@@ -106,7 +105,7 @@ export async function applyBlueprint({
site.newt.newtId,
[target],
matchingHealthcheck ? [matchingHealthcheck] : [],
result.proxyResource.protocol,
result.proxyResource.mode === "udp" ? "udp" : "tcp",
site.newt.version
);
}
@@ -291,9 +290,7 @@ export async function applyBlueprint({
.insert(blueprints)
.values({
orgId,
name:
name ??
`${faker.word.adjective()}-${faker.word.adjective()}-${faker.word.noun()}`,
name: name ?? generateName(),
contents: stringifyYaml(configData),
createdAt: Math.floor(Date.now() / 1000),
succeeded: blueprintSucceeded,

View File

@@ -1,10 +1,56 @@
import { sendToClient } from "#dynamic/routers/ws";
import { processContainerLabels } from "./parseDockerContainers";
import { applyBlueprint } from "./applyBlueprint";
import { PrivateResourceSchema, PublicResourceSchema } from "./types";
import { db, sites } from "@server/db";
import { eq } from "drizzle-orm";
import logger from "@server/logger";
type BlueprintResult = ReturnType<typeof processContainerLabels>;
function filterInvalidResources(blueprint: BlueprintResult): {
skippedCount: number;
skippedKeys: string[];
} {
const skippedKeys: string[] = [];
for (const section of ["proxy-resources", "public-resources"] as const) {
const resources = blueprint[section];
for (const [key, value] of Object.entries(resources)) {
const result = PublicResourceSchema.safeParse(value);
if (!result.success) {
const errors = result.error.issues
.map((i) => `${i.path.join(".")}: ${i.message}`)
.join("; ");
logger.warn(
`Skipping invalid Docker ${section} "${key}": ${errors}`
);
delete resources[key];
skippedKeys.push(`${section}.${key}`);
}
}
}
for (const section of ["client-resources", "private-resources"] as const) {
const resources = blueprint[section];
for (const [key, value] of Object.entries(resources)) {
const result = PrivateResourceSchema.safeParse(value);
if (!result.success) {
const errors = result.error.issues
.map((i) => `${i.path.join(".")}: ${i.message}`)
.join("; ");
logger.warn(
`Skipping invalid Docker ${section} "${key}": ${errors}`
);
delete resources[key];
skippedKeys.push(`${section}.${key}`);
}
}
}
return { skippedCount: skippedKeys.length, skippedKeys };
}
export async function applyNewtDockerBlueprint(
siteId: number,
newtId: string,
@@ -21,17 +67,24 @@ export async function applyNewtDockerBlueprint(
return;
}
// logger.debug(`Applying Docker blueprint to site: ${siteId}`);
// logger.debug(`Containers: ${JSON.stringify(containers, null, 2)}`);
let skippedCount = 0;
let skippedKeys: string[] = [];
try {
const blueprint = processContainerLabels(containers);
logger.debug(`Received Docker blueprint: ${JSON.stringify(blueprint)}`);
logger.debug(
`Received Docker blueprint with ${Object.keys(blueprint["proxy-resources"]).length} proxy, ${Object.keys(blueprint["client-resources"]).length} client resource(s)`
);
// make sure this is not an empty object
if (isEmptyObject(blueprint)) {
return;
const filterResult = filterInvalidResources(blueprint);
skippedCount = filterResult.skippedCount;
skippedKeys = filterResult.skippedKeys;
if (skippedCount > 0) {
logger.warn(
`Filtered ${skippedCount} invalid resource(s) from Docker blueprint: ${skippedKeys.join(", ")}`
);
}
if (
@@ -40,6 +93,15 @@ export async function applyNewtDockerBlueprint(
isEmptyObject(blueprint["public-resources"]) &&
isEmptyObject(blueprint["private-resources"])
) {
if (skippedCount > 0) {
await sendToClient(newtId, {
type: "newt/blueprint/results",
data: {
success: false,
message: `All resources were invalid and skipped: ${skippedKeys.join(", ")}`
}
});
}
return;
}
@@ -66,7 +128,10 @@ export async function applyNewtDockerBlueprint(
type: "newt/blueprint/results",
data: {
success: true,
message: "Config updated successfully"
message:
skippedCount > 0
? `Config updated successfully. Skipped ${skippedCount} invalid resource(s): ${skippedKeys.join(", ")}`
: "Config updated successfully"
}
});
}

View File

@@ -3,6 +3,7 @@ import {
clientSiteResources,
domains,
orgDomains,
roleActions,
roles,
roleSiteResources,
Site,
@@ -19,6 +20,7 @@ import { sites } from "@server/db";
import { eq, and, ne, inArray, or, isNotNull } from "drizzle-orm";
import { Config } from "./types";
import logger from "@server/logger";
import { defaultRoleAllowedActions } from "@server/routers/role/createRole";
import { getNextAvailableAliasAddress } from "../ip";
import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
@@ -225,7 +227,11 @@ export async function updateClientResources(
: resourceData["udp-ports"],
fullDomain: resourceData["full-domain"] || null,
subdomain: domainInfo ? domainInfo.subdomain : null,
domainId: domainInfo ? domainInfo.domainId : null
domainId: domainInfo ? domainInfo.domainId : null,
pamMode: resourceData["auth-daemon"]?.pam || "passthrough",
authDaemonMode:
resourceData["auth-daemon"]?.mode || "native",
authDaemonPort: resourceData["auth-daemon"]?.port || 22123
})
.where(
eq(
@@ -332,8 +338,7 @@ export async function updateClientResources(
}
if (resourceData.roles.length > 0) {
// Re-add specified roles but we need to get the roleIds from the role name in the array
const rolesToUpdate = await trx
const existingRoles = await trx
.select()
.from(roles)
.where(
@@ -343,7 +348,28 @@ export async function updateClientResources(
)
);
const roleIds = rolesToUpdate.map((role) => role.roleId);
const foundNames = new Set(existingRoles.map((r) => r.name));
const missingNames = resourceData.roles.filter(
(n) => !foundNames.has(n)
);
for (const name of missingNames) {
const [created] = await trx
.insert(roles)
.values({ name, orgId })
.returning();
await trx.insert(roleActions).values(
defaultRoleAllowedActions.map((action) => ({
roleId: created.roleId,
actionId: action,
orgId
}))
);
existingRoles.push(created);
logger.info(`Auto-created role "${name}" in org ${orgId} from blueprint`);
}
const roleIds = existingRoles.map((role) => role.roleId);
await trx
.insert(roleSiteResources)
@@ -360,8 +386,14 @@ export async function updateClientResources(
});
} else {
let aliasAddress: string | null = null;
let releaseAliasLock: (() => Promise<void>) | null = null;
if (resourceData.mode === "host" || resourceData.mode === "http") {
aliasAddress = await getNextAvailableAliasAddress(orgId, trx);
const { value, release } = await getNextAvailableAliasAddress(
orgId,
trx
);
aliasAddress = value;
releaseAliasLock = release;
}
let domainInfo:
@@ -415,10 +447,16 @@ export async function updateClientResources(
: resourceData["udp-ports"],
fullDomain: resourceData["full-domain"] || null,
subdomain: domainInfo ? domainInfo.subdomain : null,
domainId: domainInfo ? domainInfo.domainId : null
domainId: domainInfo ? domainInfo.domainId : null,
pamMode: resourceData["auth-daemon"]?.pam || "passthrough",
authDaemonMode:
resourceData["auth-daemon"]?.mode || "native",
authDaemonPort: resourceData["auth-daemon"]?.port || 22123
})
.returning();
await releaseAliasLock?.();
const siteResourceId = newResource.siteResourceId;
for (const site of allSites) {
@@ -444,8 +482,7 @@ export async function updateClientResources(
});
if (resourceData.roles.length > 0) {
// get roleIds from role names
const rolesToUpdate = await trx
const existingRoles = await trx
.select()
.from(roles)
.where(
@@ -455,7 +492,28 @@ export async function updateClientResources(
)
);
const roleIds = rolesToUpdate.map((role) => role.roleId);
const foundNames = new Set(existingRoles.map((r) => r.name));
const missingNames = resourceData.roles.filter(
(n) => !foundNames.has(n)
);
for (const name of missingNames) {
const [created] = await trx
.insert(roles)
.values({ name, orgId })
.returning();
await trx.insert(roleActions).values(
defaultRoleAllowedActions.map((action) => ({
roleId: created.roleId,
actionId: action,
orgId
}))
);
existingRoles.push(created);
logger.info(`Auto-created role "${name}" in org ${orgId} from blueprint`);
}
const roleIds = existingRoles.map((role) => role.roleId);
await trx
.insert(roleSiteResources)

File diff suppressed because it is too large Load Diff

View File

@@ -82,7 +82,7 @@ export const RuleSchema = z
.object({
action: z.enum(["allow", "deny", "pass"]),
match: z.enum(["cidr", "path", "ip", "country", "asn", "region"]),
value: z.string(),
value: z.coerce.string(),
priority: z.int().optional()
})
.refine(
@@ -161,11 +161,34 @@ export const HeaderSchema = z.object({
value: z.string().min(1)
});
export const AuthDaemonSchema = z
.object({
pam: z.enum(["passthrough", "push"]).optional().default("passthrough"),
mode: z.enum(["site", "remote", "native"]).optional().default("site"),
port: z.int().min(1).max(65535).optional()
})
.refine(
(data) => {
if (data.mode === "remote") {
return data.port !== undefined;
}
return true;
},
{
path: ["port"],
message: "port is required when auth-daemon mode is 'remote'"
}
);
// Schema for individual resource
export const ResourceSchema = z
export const PublicResourceSchema = z
.object({
name: z.string().optional(),
protocol: z.enum(["http", "tcp", "udp"]).optional(),
protocol: z
.enum(["http", "tcp", "udp", "ssh", "rdp", "vnc"])
.optional(), // this was the old one and is now DEPRECATED in favor of the mode
mode: z.enum(["http", "tcp", "udp", "ssh", "rdp", "vnc"]).optional(),
policy: z.string().optional(),
ssl: z.boolean().optional(),
scheme: z.enum(["http", "https"]).optional(),
"full-domain": z.string().optional(),
@@ -177,7 +200,10 @@ export const ResourceSchema = z
"tls-server-name": z.string().optional(),
headers: z.array(HeaderSchema).optional(),
rules: z.array(RuleSchema).optional(),
maintenance: MaintenanceSchema.optional()
maintenance: MaintenanceSchema.optional(),
"auth-daemon": AuthDaemonSchema.optional(),
"proxy-protocol": z.boolean().optional(),
"proxy-protocol-version": z.int().min(1).optional()
})
.refine(
(resource) => {
@@ -185,9 +211,10 @@ export const ResourceSchema = z
return true;
}
// Otherwise, require name and protocol for full resource definition
// Otherwise, require name and protocol/mode for full resource definition
return (
resource.name !== undefined && resource.protocol !== undefined
resource.name !== undefined &&
(resource.mode !== undefined || resource.protocol !== undefined)
);
},
{
@@ -201,8 +228,8 @@ export const ResourceSchema = z
return true;
}
// If protocol is http, all targets must have method field
if (resource.protocol === "http") {
// If protocol/mode is http, all targets must have method field
if ((resource.mode ?? resource.protocol) === "http") {
return resource.targets.every(
(target) => target == null || target.method !== undefined
);
@@ -220,8 +247,9 @@ export const ResourceSchema = z
return true;
}
// If protocol is tcp or udp, no target should have method field
if (resource.protocol === "tcp" || resource.protocol === "udp") {
// If protocol/mode is tcp or udp, no target should have method field
const effectiveProtocol1 = resource.mode ?? resource.protocol;
if (effectiveProtocol1 === "tcp" || effectiveProtocol1 === "udp") {
return resource.targets.every(
(target) => target == null || target.method === undefined
);
@@ -239,8 +267,8 @@ export const ResourceSchema = z
return true;
}
// If protocol is http, it must have a full-domain
if (resource.protocol === "http") {
// If protocol/mode is http, it must have a full-domain
if ((resource.mode ?? resource.protocol) === "http") {
return (
resource["full-domain"] !== undefined &&
resource["full-domain"].length > 0
@@ -259,8 +287,9 @@ export const ResourceSchema = z
return true;
}
// If protocol is tcp or udp, it must have both proxy-port
if (resource.protocol === "tcp" || resource.protocol === "udp") {
// If protocol/mode is tcp or udp, it must have both proxy-port
const effectiveProtocol2 = resource.mode ?? resource.protocol;
if (effectiveProtocol2 === "tcp" || effectiveProtocol2 === "udp") {
return resource["proxy-port"] !== undefined;
}
return true;
@@ -277,8 +306,9 @@ export const ResourceSchema = z
return true;
}
// If protocol is tcp or udp, it must not have auth
if (resource.protocol === "tcp" || resource.protocol === "udp") {
// If protocol/mode is tcp or udp, it must not have auth
const effectiveProtocol3 = resource.mode ?? resource.protocol;
if (effectiveProtocol3 === "tcp" || effectiveProtocol3 === "udp") {
return resource.auth === undefined;
}
return true;
@@ -340,7 +370,8 @@ export const ResourceSchema = z
if (parts.includes("*", 1)) return false; // no further wildcards
if (parts.length < 3) return false; // need at least *.label.tld
const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$|^[a-zA-Z0-9]$/;
const labelRegex =
/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$|^[a-zA-Z0-9]$/;
return parts.slice(1).every((label) => labelRegex.test(label));
},
{
@@ -348,22 +379,46 @@ export const ResourceSchema = z
message:
'Wildcard full-domain must have "*" as the leftmost label only, followed by at least two valid hostname labels (e.g. "*.example.com" or "*.level1.example.com"). Patterns like "*example.com" or "level2.*.example.com" are not supported.'
}
);
)
.refine(
(resource) => {
const effectiveMode = resource.mode ?? resource.protocol;
if (effectiveMode !== "tcp") {
return (
resource["proxy-protocol"] === undefined &&
resource["proxy-protocol-version"] === undefined
);
}
return true;
},
{
path: ["proxy-protocol"],
message:
"'proxy-protocol' and 'proxy-protocol-version' can only be set when mode is 'tcp'"
}
)
.transform((resource) => {
// Normalize: prefer mode, fall back to protocol for backwards compatibility
if (resource.mode === undefined && resource.protocol !== undefined) {
resource.mode = resource.protocol;
}
return resource;
});
export function isTargetsOnlyResource(resource: any): boolean {
return Object.keys(resource).length === 1 && resource.targets;
}
export const ClientResourceSchema = z
export const PrivateResourceSchema = z
.object({
name: z.string().min(1).max(255),
mode: z.enum(["host", "cidr", "http"]),
mode: z.enum(["host", "cidr", "http", "ssh"]),
site: z.string().optional(), // DEPRECATED IN FAVOR OF sites
sites: z.array(z.string()).optional().default([]),
// protocol: z.enum(["tcp", "udp"]).optional(),
// proxyPort: z.int().positive().optional(),
"destination-port": z.int().positive().optional(),
destination: z.string().min(1),
destination: z.string().min(1).optional(),
// enabled: z.boolean().default(true),
"tcp-ports": portRangeStringSchema.optional().default("*"),
"udp-ports": portRangeStringSchema.optional().default("*"),
@@ -386,11 +441,31 @@ export const ClientResourceSchema = z
error: "Admin role cannot be included in roles"
}),
users: z.array(z.string()).optional().default([]),
machines: z.array(z.string()).optional().default([])
machines: z.array(z.string()).optional().default([]),
"auth-daemon": AuthDaemonSchema.optional()
})
.refine(
(data) => {
// destination is optional only for ssh+native; required for everything else
const isNativeSSH =
data.mode === "ssh" &&
(data["auth-daemon"] === undefined ||
data["auth-daemon"].mode === "native");
if (!isNativeSSH && !data.destination) {
return false;
}
return true;
},
{
path: ["destination"],
message:
"destination is required unless mode is 'ssh' with auth-daemon mode 'native'"
}
)
.refine(
(data) => {
if (data.mode === "host") {
if (!data.destination) return true; // caught by the destination-required refine
// Check if it's a valid IP address using zod (v4 or v6)
const isValidIP = z
.union([z.ipv4(), z.ipv6()])
@@ -418,6 +493,7 @@ export const ClientResourceSchema = z
.refine(
(data) => {
if (data.mode === "cidr") {
if (!data.destination) return true; // caught by the destination-required refine
// Check if it's a valid CIDR (v4 or v6)
const isValidCIDR = z
.union([z.cidrv4(), z.cidrv6()])
@@ -435,19 +511,19 @@ export const ClientResourceSchema = z
export const ConfigSchema = z
.object({
"proxy-resources": z
.record(z.string(), ResourceSchema)
.record(z.string(), PublicResourceSchema)
.optional()
.prefault({}),
"public-resources": z
.record(z.string(), ResourceSchema)
.record(z.string(), PublicResourceSchema)
.optional()
.prefault({}),
"client-resources": z
.record(z.string(), ClientResourceSchema)
.record(z.string(), PrivateResourceSchema)
.optional()
.prefault({}),
"private-resources": z
.record(z.string(), ClientResourceSchema)
.record(z.string(), PrivateResourceSchema)
.optional()
.prefault({}),
sites: z.record(z.string(), SiteSchema).optional().prefault({})
@@ -472,10 +548,13 @@ export const ConfigSchema = z
}
return data as {
"proxy-resources": Record<string, z.infer<typeof ResourceSchema>>;
"proxy-resources": Record<
string,
z.infer<typeof PublicResourceSchema>
>;
"client-resources": Record<
string,
z.infer<typeof ClientResourceSchema>
z.infer<typeof PrivateResourceSchema>
>;
sites: Record<string, z.infer<typeof SiteSchema>>;
};
@@ -614,5 +693,5 @@ export const ConfigSchema = z
// Type inference from the schema
export type Site = z.infer<typeof SiteSchema>;
export type Target = z.infer<typeof TargetSchema>;
export type Resource = z.infer<typeof ResourceSchema>;
export type Resource = z.infer<typeof PublicResourceSchema>;
export type Config = z.infer<typeof ConfigSchema>;

View File

@@ -331,16 +331,8 @@ export async function calculateUserClientsForOrgs(
];
// Get next available subnet
const newSubnet = await getNextAvailableClientSubnet(
orgId,
transaction
);
if (!newSubnet) {
logger.warn(
`Skipping org ${orgId} for OLM ${olm.olmId} (user ${userId}): no available subnet found`
);
continue;
}
const { value: newSubnet, release: releaseSubnetLock } =
await getNextAvailableClientSubnet(orgId, transaction);
const subnet = newSubnet.split("/")[0];
const updatedSubnet = `${subnet}/${org.subnet.split("/")[1]}`;
@@ -370,6 +362,7 @@ export async function calculateUserClientsForOrgs(
.insert(clients)
.values(newClientData)
.returning();
await releaseSubnetLock();
existingClientCache.set(
getOrgOlmKey(orgId, olm.olmId),
newClient

View File

@@ -2,7 +2,7 @@ import path from "path";
import { fileURLToPath } from "url";
// This is a placeholder value replaced by the build process
export const APP_VERSION = "1.18.4";
export const APP_VERSION = "1.19.0";
export const __FILENAME = fileURLToPath(import.meta.url);
export const __DIRNAME = path.dirname(__FILENAME);

View File

@@ -327,127 +327,145 @@ export function doCidrsOverlap(cidr1: string, cidr2: string): boolean {
export async function getNextAvailableClientSubnet(
orgId: string,
transaction: Transaction | typeof db = db
): Promise<string> {
return await lockManager.withLock(
`client-subnet-allocation:${orgId}`,
async () => {
const [org] = await transaction
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
): Promise<{ value: string; release: () => Promise<void> }> {
const lockKey = `client-subnet-allocation:${orgId}`;
const acquired = await lockManager.acquireLockWithRetry(lockKey, 6000);
if (!acquired) {
throw new Error(`Failed to acquire lock: ${lockKey}`);
}
const release = () => lockManager.releaseLock(lockKey);
if (!org) {
throw new Error(`Organization with ID ${orgId} not found`);
}
try {
const [org] = await transaction
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
if (!org.subnet) {
throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
}
const existingAddressesSites = await transaction
.select({
address: sites.address
})
.from(sites)
.where(and(isNotNull(sites.address), eq(sites.orgId, orgId)));
const existingAddressesClients = await transaction
.select({
address: clients.subnet
})
.from(clients)
.where(
and(isNotNull(clients.subnet), eq(clients.orgId, orgId))
);
const addresses = [
...existingAddressesSites.map(
(site) => `${site.address?.split("/")[0]}/32`
), // we are overriding the 32 so that we pick individual addresses in the subnet of the org for the site and the client even though they are stored with the /block_size of the org
...existingAddressesClients.map(
(client) => `${client.address.split("/")}/32`
)
].filter((address) => address !== null) as string[];
const subnet = findNextAvailableCidr(addresses, 32, org.subnet); // pick the sites address in the org
if (!subnet) {
throw new Error("No available subnets remaining in space");
}
return subnet;
if (!org) {
throw new Error(`Organization with ID ${orgId} not found`);
}
);
if (!org.subnet) {
throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
}
const existingAddressesSites = await transaction
.select({
address: sites.address
})
.from(sites)
.where(and(isNotNull(sites.address), eq(sites.orgId, orgId)));
const existingAddressesClients = await transaction
.select({
address: clients.subnet
})
.from(clients)
.where(and(isNotNull(clients.subnet), eq(clients.orgId, orgId)));
const addresses = [
...existingAddressesSites.map(
(site) => `${site.address?.split("/")[0]}/32`
), // we are overriding the 32 so that we pick individual addresses in the subnet of the org for the site and the client even though they are stored with the /block_size of the org
...existingAddressesClients.map(
(client) => `${client.address.split("/")[0]}/32`
)
].filter((address) => address !== null) as string[];
const subnet = findNextAvailableCidr(addresses, 32, org.subnet); // pick the sites address in the org
if (!subnet) {
throw new Error("No available subnets remaining in space");
}
return { value: subnet, release };
} catch (e) {
await release();
throw e;
}
}
export async function getNextAvailableAliasAddress(
orgId: string,
trx: Transaction | typeof db = db
): Promise<string> {
return await lockManager.withLock(
`alias-address-allocation:${orgId}`,
async () => {
const [org] = await trx
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
): Promise<{ value: string; release: () => Promise<void> }> {
const lockKey = `alias-address-allocation:${orgId}`;
const acquired = await lockManager.acquireLockWithRetry(lockKey, 6000);
if (!acquired) {
throw new Error(`Failed to acquire lock: ${lockKey}`);
}
const release = () => lockManager.releaseLock(lockKey);
if (!org) {
throw new Error(`Organization with ID ${orgId} not found`);
}
try {
const [org] = await trx
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId));
if (!org.subnet) {
throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
}
if (!org.utilitySubnet) {
throw new Error(
`Organization with ID ${orgId} has no utility subnet defined`
);
}
const existingAddresses = await trx
.select({
aliasAddress: siteResources.aliasAddress
})
.from(siteResources)
.where(
and(
isNotNull(siteResources.aliasAddress),
eq(siteResources.orgId, orgId)
)
);
const addresses = [
...existingAddresses.map(
(site) => `${site.aliasAddress?.split("/")[0]}/32`
),
// reserve a /29 for the dns server and other stuff
`${org.utilitySubnet.split("/")[0]}/29`
].filter((address) => address !== null) as string[];
let subnet = findNextAvailableCidr(
addresses,
32,
org.utilitySubnet
);
if (!subnet) {
throw new Error("No available subnets remaining in space");
}
// remove the cidr
subnet = subnet.split("/")[0];
return subnet;
if (!org) {
throw new Error(`Organization with ID ${orgId} not found`);
}
);
if (!org.subnet) {
throw new Error(
`Organization with ID ${orgId} has no subnet defined`
);
}
if (!org.utilitySubnet) {
throw new Error(
`Organization with ID ${orgId} has no utility subnet defined`
);
}
const existingAddresses = await trx
.select({
aliasAddress: siteResources.aliasAddress
})
.from(siteResources)
.where(
and(
isNotNull(siteResources.aliasAddress),
eq(siteResources.orgId, orgId)
)
);
const addresses = [
...existingAddresses.map(
(site) => `${site.aliasAddress?.split("/")[0]}/32`
),
// reserve a /29 for the dns server and other stuff
`${org.utilitySubnet.split("/")[0]}/29`
].filter((address) => address !== null) as string[];
let subnet = findNextAvailableCidr(addresses, 32, org.utilitySubnet);
if (!subnet) {
throw new Error("No available subnets remaining in space");
}
// remove the cidr
subnet = subnet.split("/")[0];
return { value: subnet, release };
} catch (e) {
await release();
throw e;
}
}
export async function getNextAvailableOrgSubnet(): Promise<string> {
return await lockManager.withLock("org-subnet-allocation", async () => {
export async function getNextAvailableOrgSubnet(): Promise<{
value: string;
release: () => Promise<void>;
}> {
const lockKey = "org-subnet-allocation";
const acquired = await lockManager.acquireLockWithRetry(lockKey, 6000);
if (!acquired) {
throw new Error(`Failed to acquire lock: ${lockKey}`);
}
const release = () => lockManager.releaseLock(lockKey);
try {
const existingAddresses = await db
.select({
subnet: orgs.subnet
@@ -466,8 +484,11 @@ export async function getNextAvailableOrgSubnet(): Promise<string> {
throw new Error("No available subnets remaining in space");
}
return subnet;
});
return { value: subnet, release };
} catch (e) {
await release();
throw e;
}
}
export function generateRemoteSubnets(
@@ -475,6 +496,8 @@ export function generateRemoteSubnets(
): string[] {
const remoteSubnets = allSiteResources
.filter((sr) => {
if (!sr.destination) return false;
if (sr.mode === "cidr") {
// check if its a valid CIDR using zod
const cidrSchema = z.union([z.cidrv4(), z.cidrv6()]);
@@ -496,7 +519,7 @@ export function generateRemoteSubnets(
}
return ""; // This should never be reached due to filtering, but satisfies TypeScript
})
.filter((subnet) => subnet !== ""); // Remove empty strings just to be safe
.filter((subnet): subnet is string => subnet !== "" && subnet !== null); // Remove invalid values just to be safe
// remove duplicates
return Array.from(new Set(remoteSubnets));
}
@@ -581,7 +604,7 @@ export function generateSubnetProxyTargets(
targets.push({
sourcePrefix: clientPrefix,
destPrefix: `${siteResource.aliasAddress}/32`,
rewriteTo: destination,
rewriteTo: destination!,
portRange,
disableIcmp
});
@@ -589,7 +612,7 @@ export function generateSubnetProxyTargets(
} else if (siteResource.mode == "cidr") {
targets.push({
sourcePrefix: clientPrefix,
destPrefix: siteResource.destination,
destPrefix: siteResource.destination!,
portRange,
disableIcmp
});
@@ -671,7 +694,7 @@ export async function generateSubnetProxyTargetV2(
targets.push({
sourcePrefixes: [],
destPrefix: `${siteResource.aliasAddress}/32`,
rewriteTo: destination,
rewriteTo: destination!,
portRange,
disableIcmp,
resourceId: siteResource.siteResourceId
@@ -680,7 +703,7 @@ export async function generateSubnetProxyTargetV2(
} else if (siteResource.mode == "cidr") {
targets.push({
sourcePrefixes: [],
destPrefix: siteResource.destination,
destPrefix: siteResource.destination!,
portRange,
disableIcmp,
resourceId: siteResource.siteResourceId
@@ -738,7 +761,7 @@ export async function generateSubnetProxyTargetV2(
protocol: siteResource.ssl ? "https" : "http",
httpTargets: [
{
destAddr: siteResource.destination,
destAddr: siteResource.destination!,
destPort: siteResource.destinationPort,
scheme: siteResource.scheme
}
@@ -873,7 +896,13 @@ export const portRangeStringSchema = z
message:
'Port range must be "*" for all ports, or a comma-separated list of ports and ranges (e.g., "80,443,8000-9000"). Ports must be between 1 and 65535, and ranges must have start <= end.'
}
);
)
.openapi({
type: "string",
description:
'Port range string. Use "*" for all ports, a comma-separated list of ports, or ranges (e.g., "80,443,8000-9000"). Ports must be between 1 and 65535.',
example: "80,443,8000-9000"
});
/**
* Parses a port range string into an array of port range objects

View File

@@ -0,0 +1,11 @@
import { z } from "zod";
export function createApiResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {
return z.object({
data: dataSchema.nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
});
}

View File

@@ -890,6 +890,9 @@ async function handleSubnetProxyTargetUpdates(
}
for (const client of removedClients) {
if (!siteResource.destination) {
continue;
}
// Check if this client still has access to another resource
// on this specific site with the same destination. We scope
// by siteId (via siteNetworks) rather than networkId because
@@ -1563,6 +1566,9 @@ async function handleMessagesForClientResources(
}
try {
if (!resource.destination) {
continue;
}
// Check if this client still has access to another resource
// on this specific site with the same destination. We scope
// by siteId (via siteNetworks) rather than networkId because
@@ -1826,3 +1832,77 @@ export async function verifyClientAssociationsCache(
extraSiteIds: extraSiteIds.sort((a, b) => a - b)
};
}
// cleanupSiteAssociations efficiently removes all client associations for a
// site that is being deleted. Instead of calling
// rebuildClientAssociationsFromSiteResource once per site resource (which is
// O(resources) in DB round-trips and message fan-out), this function performs
// a single bulk lookup of affected clients and site resources, deletes all
// cache rows at once, and fires all peer/proxy removal messages in parallel.
//
// The caller is responsible for deleting the site row itself (and for sending
// the newt/wg/terminate signal to the newt process).
export async function cleanupSiteAssociations(
site: Site,
trx: Transaction | typeof db = db
): Promise<void> {
const siteId = site.siteId;
logger.debug(`cleanupSiteAssociations: START siteId=${siteId}`);
// 1. Find every client currently cached against this site.
const cachedSiteClientRows = await trx
.select({ clientId: clientSitesAssociationsCache.clientId })
.from(clientSitesAssociationsCache)
.where(eq(clientSitesAssociationsCache.siteId, siteId));
const cachedClientIds = cachedSiteClientRows.map((r) => r.clientId);
// 2. Load full client details (needed for WireGuard public-key references).
const allClients =
cachedClientIds.length > 0
? await trx
.select({
clientId: clients.clientId,
pubKey: clients.pubKey,
subnet: clients.subnet
})
.from(clients)
.where(inArray(clients.clientId, cachedClientIds))
: [];
// 6. Bulk-delete all cache entries for this site. Do this before sending
// destination-update messages so updateClientSiteDestinations computes
// the correct (post-deletion) set of destinations.
await trx
.delete(clientSitesAssociationsCache)
.where(eq(clientSitesAssociationsCache.siteId, siteId));
logger.debug(
`cleanupSiteAssociations: siteId=${siteId} cache cleared. clients=${allClients.length}`
);
// 7. Fire all removal messages in parallel.
const jobs: Promise<any>[] = [];
for (const client of allClients) {
// Tell each olm to drop the site's WireGuard peer.
if (site.publicKey) {
jobs.push(olmDeletePeer(client.clientId, siteId, site.publicKey));
}
// Recompute and push updated relay destinations (now excluding this site).
if (client.pubKey && client.subnet) {
jobs.push(updateClientSiteDestinations(client, trx));
}
}
await Promise.all(jobs).catch((error) => {
logger.error(
`cleanupSiteAssociations: error sending cleanup messages for siteId=${siteId}:`,
error
);
});
logger.debug(`cleanupSiteAssociations: DONE siteId=${siteId}`);
}

View File

@@ -2,7 +2,14 @@ import { PostHog } from "posthog-node";
import config from "./config";
import { getHostMeta } from "./hostMeta";
import logger from "@server/logger";
import { alertRules, apiKeys, blueprints, db, roles, siteResources } from "@server/db";
import {
alertRules,
apiKeys,
blueprints,
db,
roles,
siteResources
} from "@server/db";
import { sites, users, orgs, resources, clients, idp } from "@server/db";
import { eq, count, notInArray, and, isNotNull, isNull } from "drizzle-orm";
import { APP_VERSION } from "./consts";
@@ -143,8 +150,7 @@ class TelemetryClient {
.select({
name: resources.name,
sso: resources.sso,
protocol: resources.protocol,
http: resources.http
mode: resources.mode
})
.from(resources);
@@ -311,7 +317,7 @@ class TelemetryClient {
(r) => r.sso
).length,
num_resources_non_http: stats.resources.filter(
(r) => !r.http
(r) => r.mode !== "http"
).length,
num_newt_sites: stats.sites.filter((s) => s.type === "newt")
.length,

View File

@@ -520,7 +520,8 @@ export class TraefikConfigManager {
build != "oss", // generate the login pages on the cloud and hybrid,
build == "saas"
? false
: config.getRawConfig().traefik.allow_raw_resources // dont allow raw resources on saas otherwise use config
: config.getRawConfig().traefik.allow_raw_resources, // dont allow raw resources on saas otherwise use config
build != "oss" // generate browser gateway targets on cloud and enterprise
);
const domains = new Set<string>();

View File

@@ -55,9 +55,7 @@ export async function getTraefikConfig(
resourceName: resources.name,
fullDomain: resources.fullDomain,
ssl: resources.ssl,
http: resources.http,
proxyPort: resources.proxyPort,
protocol: resources.protocol,
subdomain: resources.subdomain,
domainId: resources.domainId,
enabled: resources.enabled,
@@ -68,6 +66,7 @@ export async function getTraefikConfig(
headers: resources.headers,
proxyProtocol: resources.proxyProtocol,
proxyProtocolVersion: resources.proxyProtocolVersion,
mode: resources.mode,
// Target fields
targetId: targets.targetId,
@@ -115,8 +114,8 @@ export async function getTraefikConfig(
),
inArray(sites.type, siteTypes),
allowRawResources
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
: eq(resources.http, true)
? inArray(resources.mode, ["http", "udp", "tcp"]) // allow all three
: eq(resources.mode, "http")
)
)
.orderBy(desc(targets.priority), targets.targetId); // stable ordering
@@ -166,9 +165,8 @@ export async function getTraefikConfig(
key: key,
fullDomain: row.fullDomain,
ssl: row.ssl,
http: row.http,
mode: row.mode,
proxyPort: row.proxyPort,
protocol: row.protocol,
subdomain: row.subdomain,
domainId: row.domainId,
enabled: row.enabled,
@@ -580,7 +578,7 @@ export async function getTraefikConfig(
continue;
}
const protocol = resource.protocol.toLowerCase();
const protocol = resource.mode === "udp" ? "udp" : "tcp"; // all of the other ones are tcp
const port = resource.proxyPort;
if (!port) {

View File

@@ -244,4 +244,5 @@ try {
runTests();
} catch (error) {
console.error("Test failed:", error);
process.exit(1);
}

View File

@@ -28,7 +28,9 @@ export * from "./verifyApiKeyAccess";
export * from "./verifySiteProvisioningKeyAccess";
export * from "./verifyDomainAccess";
export * from "./verifyUserIsOrgOwner";
export * from "./verifyUserFromResourceSession";
export * from "./verifySiteResourceAccess";
export * from "./logActionAudit";
export * from "./verifyOlmAccess";
export * from "./verifyLimits";
export * from "./verifyResourcePolicyAccess";

View File

@@ -16,3 +16,4 @@ export * from "./verifyApiKeyClientAccess";
export * from "./verifyApiKeySiteResourceAccess";
export * from "./verifyApiKeyIdpAccess";
export * from "./verifyApiKeyDomainAccess";
export * from "./verifyApiKeyResourcePolicyAccess";

View File

@@ -0,0 +1,92 @@
import { Request, Response, NextFunction } from "express";
import { db } from "@server/db";
import { resourcePolicies, apiKeyOrg } from "@server/db";
import { eq, and } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
export async function verifyApiKeyResourcePolicyAccess(
req: Request,
res: Response,
next: NextFunction
) {
const apiKey = req.apiKey;
const resourcePolicyId =
req.params.resourcePolicyId ||
req.body.resourcePolicyId ||
req.query.resourcePolicyId;
if (!apiKey) {
return next(
createHttpError(HttpCode.UNAUTHORIZED, "Key not authenticated")
);
}
try {
// Retrieve the resource policy
const [policy] = await db
.select()
.from(resourcePolicies)
.where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId))
.limit(1);
if (!policy) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource policy with ID ${resourcePolicyId} not found`
)
);
}
if (apiKey.isRoot) {
// Root keys can access any resource policy in any org
return next();
}
if (!policy.orgId) {
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
`Resource policy with ID ${resourcePolicyId} does not have an organization ID`
)
);
}
// Verify that the API key is linked to the resource policy's organization
if (!req.apiKeyOrg) {
const apiKeyOrgResult = await db
.select()
.from(apiKeyOrg)
.where(
and(
eq(apiKeyOrg.apiKeyId, apiKey.apiKeyId),
eq(apiKeyOrg.orgId, policy.orgId)
)
)
.limit(1);
if (apiKeyOrgResult.length > 0) {
req.apiKeyOrg = apiKeyOrgResult[0];
}
}
if (!req.apiKeyOrg) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"Key does not have access to this organization"
)
);
}
return next();
} catch (error) {
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Error verifying resource policy access"
)
);
}
}

View File

@@ -0,0 +1,127 @@
import { Request, Response, NextFunction } from "express";
import { db } from "@server/db";
import { resourcePolicies, userOrgs } from "@server/db";
import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { checkOrgAccessPolicy } from "#dynamic/lib/checkOrgAccessPolicy";
import { getUserOrgRoleIds } from "@server/lib/userOrgRoles";
export async function verifyResourcePolicyAccess(
req: Request,
res: Response,
next: NextFunction
) {
const userId = req.user!.userId;
const resourcePolicyIdStr =
req.params?.resourcePolicyId ||
req.body?.resourcePolicyId ||
req.query?.resourcePolicyId;
const niceId = req.params?.niceId || req.body?.niceId || req.query?.niceId;
const orgId = req.params?.orgId || req.body?.orgId || req.query?.orgId;
try {
if (!userId) {
return next(
createHttpError(HttpCode.UNAUTHORIZED, "User not authenticated")
);
}
let policy: typeof resourcePolicies.$inferSelect | null = null;
if (orgId && niceId) {
const [policyRes] = await db
.select()
.from(resourcePolicies)
.where(
and(
eq(resourcePolicies.niceId, niceId),
eq(resourcePolicies.orgId, orgId)
)
)
.limit(1);
policy = policyRes ?? null;
} else {
const resourcePolicyId = parseInt(resourcePolicyIdStr);
if (isNaN(resourcePolicyId)) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
"Invalid resource policy ID"
)
);
}
const [policyRes] = await db
.select()
.from(resourcePolicies)
.where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId))
.limit(1);
policy = policyRes ?? null;
}
if (!policy) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource policy with ID ${resourcePolicyIdStr ?? niceId} not found`
)
);
}
if (!req.userOrg) {
const userOrgRes = await db
.select()
.from(userOrgs)
.where(
and(
eq(userOrgs.userId, userId),
eq(userOrgs.orgId, policy.orgId)
)
)
.limit(1);
req.userOrg = userOrgRes[0];
}
if (!req.userOrg || req.userOrg.orgId !== policy.orgId) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have access to this organization"
)
);
}
if (req.orgPolicyAllowed === undefined && req.userOrg.orgId) {
const policyCheck = await checkOrgAccessPolicy({
orgId: req.userOrg.orgId,
userId,
session: req.session
});
req.orgPolicyAllowed = policyCheck.allowed;
if (!policyCheck.allowed || policyCheck.error) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"Failed organization access policy check: " +
(policyCheck.error || "Unknown error")
)
);
}
}
req.userOrgRoleIds = await getUserOrgRoleIds(
req.userOrg.userId,
policy.orgId
);
req.userOrgId = policy.orgId;
return next();
} catch (error) {
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Error verifying resource policy access"
)
);
}
}

View File

@@ -38,7 +38,7 @@ export function verifyUserCanSetUserOrgRoles() {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"User does not have permission perform this action"
"User does not have permission to set user organization roles"
)
);
} catch (error) {

View File

@@ -0,0 +1,102 @@
import { Response, NextFunction } from "express";
import { db } from "@server/db";
import { resourceSessions, users } from "@server/db";
import { eq } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { getUserOrgRoleIds } from "@server/lib/userOrgRoles";
import { getUserSessionWithUser } from "@server/db/queries/verifySessionQueries";
import { encodeHexLowerCase } from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2";
import config from "@server/lib/config";
import logger from "@server/logger";
export const verifyUserFromResourceSessionMiddleware = async (
req: any,
res: Response,
next: NextFunction
) => {
if (!req.user) {
const sessionCookieName =
config.getRawConfig().server.session_cookie_name;
// Collect all resource session cookies (format: {name}[_s].{timestamp}=token)
const cookieHeader: string | undefined = req.headers.cookie;
const candidates: { timestamp: number; token: string }[] = [];
if (cookieHeader) {
for (const part of cookieHeader.split(";")) {
const trimmed = part.trim();
const eqIdx = trimmed.indexOf("=");
if (eqIdx === -1) continue;
const cookieName = trimmed.slice(0, eqIdx).trim();
const cookieValue = trimmed.slice(eqIdx + 1).trim();
// Match both secure (_s.timestamp) and non-secure (.timestamp) variants
const securePrefix = `${sessionCookieName}_s.`;
const httpPrefix = `${sessionCookieName}.`;
let timestampStr: string | null = null;
if (cookieName.startsWith(securePrefix)) {
timestampStr = cookieName.slice(securePrefix.length);
} else if (cookieName.startsWith(httpPrefix)) {
timestampStr = cookieName.slice(httpPrefix.length);
}
if (timestampStr !== null && /^\d+$/.test(timestampStr)) {
candidates.push({
timestamp: parseInt(timestampStr, 10),
token: cookieValue
});
}
}
}
// Pick the most recently issued session (highest timestamp)
candidates.sort((a, b) => b.timestamp - a.timestamp);
const best = candidates[0];
if (best) {
try {
const sessionId = encodeHexLowerCase(
sha256(new TextEncoder().encode(best.token))
);
const [resourceSession] = await db
.select()
.from(resourceSessions)
.where(eq(resourceSessions.sessionId, sessionId))
.limit(1);
if (resourceSession && Date.now() < resourceSession.expiresAt) {
if (resourceSession.userSessionId) {
const result = await getUserSessionWithUser(
resourceSession.userSessionId
);
if (result?.user && result?.session) {
req.user = result.user;
req.session = result.session;
}
}
}
} catch (e) {
logger.error(
"verifyUserFromResourceSessionMiddleware: failed to validate resource session",
e
);
}
}
}
// Populate userOrgRoleIds if an orgId is available in route params
if (req.user && req.params?.orgId && !req.userOrgRoleIds) {
req.userOrgRoleIds = await getUserOrgRoleIds(
req.user.userId,
req.params.orgId
);
}
next();
};

View File

@@ -7,6 +7,7 @@ export enum OpenAPITags {
Org = "Organization",
PublicResource = "Public Resource",
PrivateResource = "Private Resource",
Policy = "Policy",
Role = "Role",
User = "User",
Invitation = "User Invitation",

View File

@@ -780,9 +780,9 @@ async function syncAcmeCerts(acmeJsonPath: string): Promise<void> {
}
}
logger.debug(
`acmeCertSync: cert for ${mainDomain} covers ${allDomains.size} domain(s): ${[...allDomains].join(", ")}`
);
// logger.debug(
// `acmeCertSync: cert for ${mainDomain} covers ${allDomains.size} domain(s): ${[...allDomains].join(", ")}`
// );
for (const domain of allDomains) {
try {
@@ -863,9 +863,9 @@ export function initAcmeCertSync(): void {
);
return;
}
logger.debug(
`acmeCertSync: found ${files.length} acme.json file(s) in directory "${acmeJsonPath}"`
);
// logger.debug(
// `acmeCertSync: found ${files.length} acme.json file(s) in directory "${acmeJsonPath}"`
// );
for (const file of files) {
syncAcmeCerts(file).catch((err) => {
logger.error(

View File

@@ -36,8 +36,6 @@ export async function getValidCertificatesForDomains(
domains: Set<string>,
useCache: boolean = true
): Promise<Array<CertificateResult>> {
const finalResults: CertificateResult[] = [];
const domainsToQuery = new Set<string>();
@@ -49,7 +47,26 @@ export async function getValidCertificatesForDomains(
if (cachedCert) {
finalResults.push(cachedCert); // Valid cache hit
} else {
domainsToQuery.add(domain); // Cache miss or expired
// Also check for a wildcard cache entry covering this domain's parent
const parts = domain.split(".");
let wildcardHit = false;
if (parts.length > 1) {
const parentDomain = parts.slice(1).join(".");
const wildcardCacheKey = `cert:*.${parentDomain}`;
const cachedWildcard =
await cache.get<CertificateResult>(wildcardCacheKey);
if (cachedWildcard) {
// Re-stamp queriedDomain so callers see the originally requested domain
finalResults.push({
...cachedWildcard,
queriedDomain: domain
});
wildcardHit = true;
}
}
if (!wildcardHit) {
domainsToQuery.add(domain); // Cache miss or expired
}
}
}
} else {
@@ -59,7 +76,10 @@ export async function getValidCertificatesForDomains(
// 2. If all domains were resolved from the cache, return early
if (domainsToQuery.size === 0) {
const decryptedResults = decryptFinalResults(finalResults, config.getRawConfig().server.secret!);
const decryptedResults = decryptFinalResults(
finalResults,
config.getRawConfig().server.secret!
);
return decryptedResults;
}
@@ -78,7 +98,8 @@ export async function getValidCertificatesForDomains(
const parentDomainsArray = Array.from(parentDomainsToQuery);
// Build wildcard variants: for each parent domain "example.com", also query "*.example.com"
const wildcardPrefixedArray = build != "saas" ? parentDomainsArray.map((d) => `*.${d}`) : [];
const wildcardPrefixedArray =
build != "saas" ? parentDomainsArray.map((d) => `*.${d}`) : [];
// 4. Build and execute a single, efficient Drizzle query
// This query fetches all potential exact and wildcard matches in one database round-trip.
@@ -172,11 +193,24 @@ export async function getValidCertificatesForDomains(
if (useCache) {
const cacheKey = `cert:${domain}`;
await cache.set(cacheKey, resultCert, 180);
// Also cache wildcard certs under a pattern key so other subdomains
// can find them without a DB round-trip
if (resultCert.wildcard) {
const normalizedCertDomain = normalizeWildcardDomain(
resultCert.domain
);
const wildcardCacheKey = `cert:*.${normalizedCertDomain}`;
await cache.set(wildcardCacheKey, resultCert, 180);
}
}
}
}
const decryptedResults = decryptFinalResults(finalResults, config.getRawConfig().server.secret!);
const decryptedResults = decryptFinalResults(
finalResults,
config.getRawConfig().server.secret!
);
return decryptedResults;
}

View File

@@ -12,6 +12,7 @@
*/
import {
browserGatewayTarget,
certificates,
db,
domainNamespaces,
@@ -84,7 +85,8 @@ export async function getTraefikConfig(
filterOutNamespaceDomains = false,
generateLoginPageRouters = false,
allowRawResources = true,
allowMaintenancePage = true
allowMaintenancePage = true,
allowBrowserGatewayResources = true
): Promise<any> {
// Get resources with their targets and sites in a single optimized query
// Start from sites on this exit node, then join to targets and resources
@@ -95,9 +97,7 @@ export async function getTraefikConfig(
resourceName: resources.name,
fullDomain: resources.fullDomain,
ssl: resources.ssl,
http: resources.http,
proxyPort: resources.proxyPort,
protocol: resources.protocol,
subdomain: resources.subdomain,
domainId: resources.domainId,
enabled: resources.enabled,
@@ -109,6 +109,7 @@ export async function getTraefikConfig(
proxyProtocol: resources.proxyProtocol,
proxyProtocolVersion: resources.proxyProtocolVersion,
wildcard: resources.wildcard,
mode: resources.mode,
maintenanceModeEnabled: resources.maintenanceModeEnabled,
maintenanceModeType: resources.maintenanceModeType,
@@ -171,8 +172,8 @@ export async function getTraefikConfig(
),
inArray(sites.type, siteTypes),
allowRawResources
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
: eq(resources.http, true)
? inArray(resources.mode, ["http", "udp", "tcp"]) // allow all three
: eq(resources.mode, "http")
)
)
.orderBy(desc(targets.priority), targets.targetId); // stable ordering
@@ -226,9 +227,8 @@ export async function getTraefikConfig(
key: key,
fullDomain: row.fullDomain,
ssl: row.ssl,
http: row.http,
proxyPort: row.proxyPort,
protocol: row.protocol,
mode: row.mode,
subdomain: row.subdomain,
domainId: row.domainId,
enabled: row.enabled,
@@ -277,10 +277,138 @@ export async function getTraefikConfig(
});
});
// Group browser gateway targets by resource
type BrowserGatewayResourceEntry = {
resourceId: number;
name: string;
fullDomain: string | null;
ssl: boolean | null;
subdomain: string | null;
domainId: string | null;
enabled: boolean | null;
wildcard: boolean | null;
domainCertResolver: string | null;
preferWildcardCert: boolean | null;
maintenanceModeEnabled: boolean | null;
maintenanceModeType: string | null;
maintenanceTitle: string | null;
maintenanceMessage: string | null;
maintenanceEstimatedTime: string | null;
targets: {
browserGatewayTargetId: number;
bgType: string;
siteId: number;
siteType: string;
siteOnline: boolean | null;
subnet: string | null;
siteExitNodeId: number | null;
}[];
};
const browserGatewayResourcesMap = new Map<
number,
BrowserGatewayResourceEntry
>();
if (allowBrowserGatewayResources) {
// Query browser gateway targets for this exit node
const browserGatewayRows = await db
.select({
// Resource fields
resourceId: resources.resourceId,
resourceName: resources.name,
fullDomain: resources.fullDomain,
ssl: resources.ssl,
subdomain: resources.subdomain,
domainId: resources.domainId,
enabled: resources.enabled,
wildcard: resources.wildcard,
domainCertResolver: domains.certResolver,
preferWildcardCert: domains.preferWildcardCert,
domainNamespaceId: domainNamespaces.domainNamespaceId,
// Maintenance fields
maintenanceModeEnabled: resources.maintenanceModeEnabled,
maintenanceModeType: resources.maintenanceModeType,
maintenanceTitle: resources.maintenanceTitle,
maintenanceMessage: resources.maintenanceMessage,
maintenanceEstimatedTime: resources.maintenanceEstimatedTime,
// Browser gateway target fields
browserGatewayTargetId:
browserGatewayTarget.browserGatewayTargetId,
bgType: browserGatewayTarget.type,
// Site fields
siteId: sites.siteId,
siteType: sites.type,
siteOnline: sites.online,
subnet: sites.subnet,
siteExitNodeId: sites.exitNodeId
})
.from(browserGatewayTarget)
.innerJoin(sites, eq(sites.siteId, browserGatewayTarget.siteId))
.innerJoin(
resources,
eq(resources.resourceId, browserGatewayTarget.resourceId)
)
.leftJoin(domains, eq(domains.domainId, resources.domainId))
.leftJoin(
domainNamespaces,
eq(domainNamespaces.domainId, resources.domainId)
)
.where(
and(
eq(resources.enabled, true),
or(
eq(sites.exitNodeId, exitNodeId),
and(
isNull(sites.exitNodeId),
sql`(${siteTypes.includes("local") ? 1 : 0} = 1)`,
eq(sites.type, "local"),
sql`(${build != "saas" ? 1 : 0} = 1)`
)
),
inArray(sites.type, siteTypes)
)
);
for (const row of browserGatewayRows) {
if (filterOutNamespaceDomains && row.domainNamespaceId) {
continue;
}
if (!browserGatewayResourcesMap.has(row.resourceId)) {
browserGatewayResourcesMap.set(row.resourceId, {
resourceId: row.resourceId,
name: sanitize(row.resourceName) || "",
fullDomain: row.fullDomain,
ssl: row.ssl,
subdomain: row.subdomain,
domainId: row.domainId,
enabled: row.enabled,
wildcard: row.wildcard,
domainCertResolver: row.domainCertResolver,
preferWildcardCert: row.preferWildcardCert,
maintenanceModeEnabled: row.maintenanceModeEnabled,
maintenanceModeType: row.maintenanceModeType,
maintenanceTitle: row.maintenanceTitle,
maintenanceMessage: row.maintenanceMessage,
maintenanceEstimatedTime: row.maintenanceEstimatedTime,
targets: []
});
}
browserGatewayResourcesMap.get(row.resourceId)!.targets.push({
browserGatewayTargetId: row.browserGatewayTargetId,
bgType: row.bgType,
siteId: row.siteId,
siteType: row.siteType,
siteOnline: row.siteOnline,
subnet: row.subnet,
siteExitNodeId: row.siteExitNodeId
});
}
}
let siteResourcesWithFullDomain: {
siteResourceId: number;
fullDomain: string | null;
mode: "http" | "host" | "cidr";
mode: "http" | "host" | "cidr" | "ssh";
}[] = [];
if (build == "enterprise") {
// we dont want to do this on the cloud
@@ -324,6 +452,12 @@ export async function getTraefikConfig(
domains.add(sr.fullDomain);
}
}
// Include browser gateway resource domains
for (const bgResource of browserGatewayResourcesMap.values()) {
if (bgResource.enabled && bgResource.ssl && bgResource.fullDomain) {
domains.add(bgResource.fullDomain);
}
}
// get the valid certs for these domains
validCerts = await getValidCertificatesForDomains(domains, true); // we are caching here because this is called often
// logger.debug(`Valid certs for domains: ${JSON.stringify(validCerts)}`);
@@ -589,7 +723,7 @@ export async function getTraefikConfig(
resource.ssl ? entrypointHttps : entrypointHttp
],
service: maintenanceServiceName,
rule: `${rule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`))`,
rule: `${rule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`)) `,
priority: 2001,
...(resource.ssl ? { tls } : {})
};
@@ -830,7 +964,7 @@ export async function getTraefikConfig(
continue;
}
const protocol = resource.protocol.toLowerCase();
const protocol = resource.mode == "udp" ? "udp" : "tcp";
const port = resource.proxyPort;
if (!port) {
@@ -925,6 +1059,267 @@ export async function getTraefikConfig(
}
}
if (allowBrowserGatewayResources) {
// Generate Traefik config for browser gateway resources
const browserGatewayPort = 39999;
for (const [, bgResource] of browserGatewayResourcesMap.entries()) {
if (!bgResource.enabled) continue;
if (!bgResource.domainId) continue;
if (!bgResource.fullDomain) continue;
if (!config_output.http.routers) config_output.http.routers = {};
if (!config_output.http.services) config_output.http.services = {};
const fullDomain = bgResource.fullDomain;
const additionalMiddlewares =
config.getRawConfig().traefik.additional_middlewares || [];
const routerMiddlewares = [
badgerMiddlewareName,
...additionalMiddlewares
];
const hostRule = `Host(\`${fullDomain}\`)`;
// Build TLS config
let tls = {};
if (!privateConfig.getRawPrivateConfig().flags.use_pangolin_dns) {
const domainParts = fullDomain.split(".");
let wildCard: string;
if (domainParts.length <= 2) {
wildCard = `*.${domainParts.join(".")}`;
} else {
wildCard = `*.${domainParts.slice(1).join(".")}`;
}
if (!bgResource.subdomain) {
wildCard = fullDomain;
}
const globalDefaultResolver =
config.getRawConfig().traefik.cert_resolver;
const globalDefaultPreferWildcard =
config.getRawConfig().traefik.prefer_wildcard_cert;
const resolverName = bgResource.domainCertResolver
? bgResource.domainCertResolver.trim()
: globalDefaultResolver;
const preferWildcard =
bgResource.preferWildcardCert !== undefined &&
bgResource.preferWildcardCert !== null
? bgResource.preferWildcardCert
: globalDefaultPreferWildcard;
tls = {
certResolver: resolverName,
...(preferWildcard ? { domains: [{ main: wildCard }] } : {})
};
} else {
const matchingCert = validCerts.find(
(cert) => cert.queriedDomain === fullDomain
);
if (!matchingCert) {
logger.debug(
`No matching certificate found for browser gateway domain: ${fullDomain}`
);
continue;
}
}
const bgUiServiceName = `bg-r${bgResource.resourceId}-ui-service`;
if (bgResource.ssl) {
const redirectRouterName = `bg-r${bgResource.resourceId}-redirect`;
config_output.http.routers![redirectRouterName] = {
entryPoints: [
config.getRawConfig().traefik.http_entrypoint
],
middlewares: [redirectHttpsMiddlewareName],
service: bgUiServiceName,
rule: hostRule,
priority: 100
};
}
// Collect online sites for this resource (for any type)
const anySiteOnline = bgResource.targets.some((t) => t.siteOnline);
// Maintenance page logic for browser gateway resources
let showBgMaintenancePage = false;
if (bgResource.maintenanceModeEnabled) {
if (bgResource.maintenanceModeType === "forced") {
showBgMaintenancePage = true;
} else if (bgResource.maintenanceModeType === "automatic") {
showBgMaintenancePage = !anySiteOnline;
}
}
if (showBgMaintenancePage && allowMaintenancePage) {
const bgMaintenanceServiceName = `bg-r${bgResource.resourceId}-maintenance-service`;
const bgMaintenanceRouterName = `bg-r${bgResource.resourceId}-maintenance-router`;
const bgRewriteMiddlewareName = `bg-r${bgResource.resourceId}-maintenance-rewrite`;
const entrypointHttp =
config.getRawConfig().traefik.http_entrypoint;
const entrypointHttps =
config.getRawConfig().traefik.https_entrypoint;
const maintenancePort = config.getRawConfig().server.next_port;
const maintenanceHost =
config.getRawConfig().server.internal_hostname;
if (!config_output.http.services)
config_output.http.services = {};
if (!config_output.http.middlewares)
config_output.http.middlewares = {};
if (!config_output.http.routers)
config_output.http.routers = {};
config_output.http.services![bgMaintenanceServiceName] = {
loadBalancer: {
servers: [
{
url: `http://${maintenanceHost}:${maintenancePort}`
}
],
passHostHeader: true
}
};
config_output.http.middlewares![bgRewriteMiddlewareName] = {
replacePathRegex: {
regex: "^/(.*)",
replacement: "/maintenance-screen"
}
};
config_output.http.routers![bgMaintenanceRouterName] = {
entryPoints: [
bgResource.ssl ? entrypointHttps : entrypointHttp
],
service: bgMaintenanceServiceName,
middlewares: [bgRewriteMiddlewareName],
rule: hostRule,
priority: 2000,
...(bgResource.ssl ? { tls } : {})
};
config_output.http.routers![
`${bgMaintenanceRouterName}-assets`
] = {
entryPoints: [
bgResource.ssl ? entrypointHttps : entrypointHttp
],
service: bgMaintenanceServiceName,
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
priority: 2001,
...(bgResource.ssl ? { tls } : {})
};
continue;
}
// Group targets by type and generate per-type websocket routers and services
const typeMap = new Map<string, typeof bgResource.targets>();
for (const t of bgResource.targets) {
if (!typeMap.has(t.bgType)) typeMap.set(t.bgType, []);
typeMap.get(t.bgType)!.push(t);
}
for (const [bgType, typedTargets] of typeMap.entries()) {
const bgKey = `bg-r${bgResource.resourceId}-${bgType}`;
const bgRouterName = `${bgKey}-router`;
const bgServiceName = `${bgKey}-service`;
const bgRule = `${hostRule} && PathPrefix(\`/gateway/${bgType}\`)`;
const servers = typedTargets
.filter((t) => {
if (!t.siteOnline && anySiteOnline) return false;
if (t.siteType === "newt") return !!t.subnet;
return false; // browser gateway only supported on newt sites
})
.map((t) => ({
url: `http://${t.subnet!.split("/")[0]}:${browserGatewayPort}`
}))
.filter(
(v, i, a) => a.findIndex((u) => u.url === v.url) === i
);
config_output.http.routers![bgRouterName] = {
entryPoints: [
bgResource.ssl
? config.getRawConfig().traefik.https_entrypoint
: config.getRawConfig().traefik.http_entrypoint
],
middlewares: routerMiddlewares,
service: bgServiceName,
rule: bgRule,
priority: 110, // highest - websocket path takes precedence
...(bgResource.ssl ? { tls } : {})
};
config_output.http.services![bgServiceName] = {
loadBalancer: {
servers
}
};
}
// UI: serve the browser gateway page from the internal pangolin instance.
// The primary type is used for the path rewrite (e.g. /rdp), mirroring
// how the maintenance page rewrites everything to /maintenance-screen.
const primaryType = typeMap.keys().next().value as string;
const internalHost = config.getRawConfig().server.internal_hostname;
const internalPort = config.getRawConfig().server.next_port;
const uiRewriteMiddlewareName = `bg-r${bgResource.resourceId}-ui-rewrite`;
const entrypoint = bgResource.ssl
? config.getRawConfig().traefik.https_entrypoint
: config.getRawConfig().traefik.http_entrypoint;
if (!config_output.http.middlewares) {
config_output.http.middlewares = {};
}
config_output.http.middlewares![uiRewriteMiddlewareName] = {
replacePathRegex: {
regex: "^/(.*)",
replacement: `/${primaryType}`
}
};
config_output.http.services![bgUiServiceName] = {
loadBalancer: {
servers: [
{
url: `http://${internalHost}:${internalPort}`
}
]
}
};
// Assets router at higher priority so /_next files load without rewrite
config_output.http.routers![
`bg-r${bgResource.resourceId}-assets-router`
] = {
entryPoints: [entrypoint],
middlewares: routerMiddlewares,
service: bgUiServiceName,
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
priority: 101,
...(bgResource.ssl ? { tls } : {})
};
// Catch-all router rewrites everything on the domain to /{primaryType}
config_output.http.routers![
`bg-r${bgResource.resourceId}-ui-router`
] = {
entryPoints: [entrypoint],
middlewares: [...routerMiddlewares, uiRewriteMiddlewareName],
service: bgUiServiceName,
rule: hostRule,
priority: 100,
...(bgResource.ssl ? { tls } : {})
};
}
}
// Add Traefik routes for siteResource aliases (HTTP mode + SSL) so that
// Traefik generates TLS certificates for those domains even when no
// matching resource exists yet.
@@ -1040,7 +1435,7 @@ export async function getTraefikConfig(
config_output.http.routers[`${siteResourceRouterName}-assets`] = {
entryPoints: [config.getRawConfig().traefik.https_entrypoint],
service: siteResourceServiceName,
rule: `Host(\`${fullDomain}\`) && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`))`,
rule: `Host(\`${fullDomain}\`) && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
priority: 101,
tls
};
@@ -1143,7 +1538,7 @@ export async function getTraefikConfig(
config.getRawConfig().traefik.https_entrypoint
],
service: "landing-service",
rule: `Host(\`${fullDomain}\`) && (PathRegexp(\`^/auth/resource/[^/]+$\`) || PathRegexp(\`^/auth/idp/[0-9]+/oidc/callback\`) || PathPrefix(\`/_next\`) || Path(\`/auth/org\`) || PathRegexp(\`^/__nextjs*\`))`,
rule: `Host(\`${fullDomain}\`) && (PathRegexp(\`^/auth/resource/[^/]+$\`) || PathRegexp(\`^/auth/idp/[0-9]+/oidc/callback\`) || PathPrefix(\`/_next\`) || Path(\`/auth/org\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
priority: 203,
tls: tls
};

View File

@@ -202,7 +202,22 @@ registry.registerPath({
}
}
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function createAlertRule(

View File

@@ -38,7 +38,22 @@ registry.registerPath({
request: {
params: paramsSchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function deleteAlertRule(

View File

@@ -49,7 +49,22 @@ registry.registerPath({
request: {
params: paramsSchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function getAlertRule(

View File

@@ -95,7 +95,22 @@ registry.registerPath({
query: querySchema,
params: paramsSchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function listAlertRules(

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db";
import {
alertRules,
@@ -148,6 +149,10 @@ const bodySchema = z
export type UpdateAlertRuleResponse = {
alertRuleId: number;
};
const UpdateAlertRuleResponseDataSchema = z.object({
alertRuleId: z.number()
});
registry.registerPath({
method: "post",
@@ -164,7 +169,16 @@ registry.registerPath({
}
}
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(UpdateAlertRuleResponseDataSchema)
}
}
}
}
});
export async function updateAlertRule(

View File

@@ -24,7 +24,7 @@ import type { NextFunction, Request, Response } from "express";
const paramsSchema = z.strictObject({
orgId: z.string(),
approvalId: z.string().transform(Number).pipe(z.int().positive())
approvalId: z.coerce.number().int().positive()
});
const bodySchema = z.strictObject({

View File

@@ -18,6 +18,7 @@ import { OpenAPITags } from "@server/openApi";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error";
import { z } from "zod";
import logger from "@server/logger";
import {
queryAccessAuditLogsParams,
@@ -37,7 +38,22 @@ registry.registerPath({
query: queryAccessAuditLogsQuery,
params: queryAccessAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function exportAccessAuditLogs(

View File

@@ -18,6 +18,7 @@ import { OpenAPITags } from "@server/openApi";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error";
import { z } from "zod";
import logger from "@server/logger";
import {
queryActionAuditLogsParams,
@@ -37,7 +38,22 @@ registry.registerPath({
query: queryActionAuditLogsQuery,
params: queryActionAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function exportActionAuditLogs(

View File

@@ -18,6 +18,7 @@ import { OpenAPITags } from "@server/openApi";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error";
import { z } from "zod";
import logger from "@server/logger";
import {
queryConnectionAuditLogsParams,
@@ -37,7 +38,22 @@ registry.registerPath({
query: queryConnectionAuditLogsQuery,
params: queryConnectionAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function exportConnectionAuditLogs(

View File

@@ -93,6 +93,20 @@ export const queryAccessAuditLogsCombined = queryAccessAuditLogsQuery.merge(
);
type Q = z.infer<typeof queryAccessAuditLogsCombined>;
function sortNamedFilterOptions<T extends { id: number; name: string | null }>(
items: T[]
): T[] {
return [...items].sort((a, b) => {
const nameA = a.name ?? "";
const nameB = b.name ?? "";
if (nameA < nameB) return -1;
if (nameA > nameB) return 1;
return a.id - b.id;
});
}
function getWhere(data: Q) {
return and(
gt(accessAuditLog.timestamp, data.timeStart),
@@ -308,7 +322,7 @@ async function queryUniqueFilterAttributes(
actors: uniqueActors
.map((row) => row.actor)
.filter((actor): actor is string => actor !== null),
resources: resourcesWithNames,
resources: sortNamedFilterOptions(resourcesWithNames),
locations: uniqueLocations
.map((row) => row.locations)
.filter((location): location is string => location !== null)
@@ -324,7 +338,22 @@ registry.registerPath({
query: queryAccessAuditLogsQuery,
params: queryAccessAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function queryAccessAuditLogs(

View File

@@ -165,7 +165,22 @@ registry.registerPath({
query: queryActionAuditLogsQuery,
params: queryActionAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function queryActionAuditLogs(

View File

@@ -107,6 +107,20 @@ export const queryConnectionAuditLogsCombined =
queryConnectionAuditLogsQuery.merge(queryConnectionAuditLogsParams);
type Q = z.infer<typeof queryConnectionAuditLogsCombined>;
function sortNamedFilterOptions<T extends { id: number; name: string | null }>(
items: T[]
): T[] {
return [...items].sort((a, b) => {
const nameA = a.name ?? "";
const nameB = b.name ?? "";
if (nameA < nameB) return -1;
if (nameA > nameB) return 1;
return a.id - b.id;
});
}
function getWhere(data: Q) {
return and(
gt(connectionAuditLog.startedAt, data.timeStart),
@@ -425,7 +439,7 @@ async function queryUniqueFilterAttributes(
.map((row) => row.destAddr)
.filter((addr): addr is string => addr !== null),
clients: clientsWithNames,
resources: resourcesWithNames,
resources: sortNamedFilterOptions(resourcesWithNames),
users: usersWithEmails
};
}
@@ -439,7 +453,22 @@ registry.registerPath({
query: queryConnectionAuditLogsQuery,
params: queryConnectionAuditLogsParams
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function queryConnectionAuditLogs(

View File

@@ -308,8 +308,8 @@ async function disableFeature(
await disableAutoProvisioning(orgId);
break;
case TierFeature.SshPam:
await disableSshPam(orgId);
case TierFeature.AdvancedPrivateResources:
await disableAdvancedPrivateResources(orgId);
break;
case TierFeature.FullRbac:
@@ -357,10 +357,11 @@ async function disableDeviceApprovals(orgId: string): Promise<void> {
logger.info(`Disabled device approvals on all roles for org ${orgId}`);
}
async function disableSshPam(orgId: string): Promise<void> {
logger.info(
`Disabled SSH PAM options on all roles and site resources for org ${orgId}`
);
async function disableAdvancedPrivateResources(orgId: string): Promise<void> {
// TODO: implement logic to disable advanced private resourcs like ssh and ssh pam
// logger.info(
// `Disabled advanced private resources on all roles and site resources for org ${orgId}`
// );
}
async function disableFullRbac(orgId: string): Promise<void> {

View File

@@ -39,7 +39,22 @@ const getOrgSchema = z.strictObject({
// request: {
// params: getOrgSchema
// },
// responses: {}
// responses: {
// 200: {
// description: "Successful response",
// content: {
// "application/json": {
// schema: z.object({
// data: z.unknown().nullable(),
// success: z.boolean(),
// error: z.boolean(),
// message: z.string(),
// status: z.number()
// })
// }
// }
// }
// }
// });
export async function getOrgUsage(

View File

@@ -0,0 +1,187 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import {
browserGatewayTarget,
BrowserGatewayTarget,
db,
newts,
resources,
sites
} from "@server/db";
import { eq, and } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
import { encrypt } from "@server/lib/crypto";
import config from "@server/lib/config";
import { sendBrowserGatewayTargets } from "@server/routers/newt/targets";
import { generateId } from "@server/auth/sessions/app";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const bodySchema = z.strictObject({
siteId: z.number().int().positive(),
type: z.enum(["ssh", "rdp", "vnc"]),
destination: z.string().nonempty(),
destinationPort: z.number().int().min(1).max(65535)
});
export type CreateBrowserGatewayTargetResponse = BrowserGatewayTarget;
registry.registerPath({
method: "put",
path: "/org/{orgId}/resource/{resourceId}/browser-gateway-target",
description: "Create a browser gateway target for a resource.",
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: bodySchema
}
}
}
},
responses: {}
});
export async function createBrowserGatewayTarget(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = paramsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { orgId, resourceId } = parsedParams.data;
const parsedBody = bodySchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedBody.error).toString()
)
);
}
const { siteId, type, destination, destinationPort } = parsedBody.data;
const [resource] = await db
.select()
.from(resources)
.where(
and(
eq(resources.resourceId, resourceId),
eq(resources.orgId, orgId)
)
)
.limit(1);
if (!resource) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource with ID ${resourceId} not found in organization ${orgId}`
)
);
}
const [site] = await db
.select()
.from(sites)
.where(and(eq(sites.siteId, siteId), eq(sites.orgId, orgId)))
.limit(1);
if (!site) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Site with ID ${siteId} not found in organization ${orgId}`
)
);
}
const plainToken = generateId(48);
const encryptedToken = encrypt(
plainToken,
config.getRawConfig().server.secret!
);
const [record] = await db
.insert(browserGatewayTarget)
.values({
resourceId,
siteId,
type,
destination,
destinationPort,
authToken: encryptedToken
})
.returning();
if (site.type === "newt") {
const [newt] = await db
.select()
.from(newts)
.where(eq(newts.siteId, siteId))
.limit(1);
if (newt) {
await sendBrowserGatewayTargets(
newt.newtId,
[record],
newt.version
);
}
}
logger.info(
`Created browser gateway target ${record.browserGatewayTargetId} for resource ${resourceId}`
);
return response<CreateBrowserGatewayTargetResponse>(res, {
data: record,
success: true,
error: false,
message: "Browser gateway target created successfully",
status: HttpCode.CREATED
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to create browser gateway target"
)
);
}
}

View File

@@ -0,0 +1,130 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { browserGatewayTarget, db, newts, sites } from "@server/db";
import { eq, and } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
import { removeBrowserGatewayTarget } from "@server/routers/newt/targets";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
browserGatewayTargetId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
});
registry.registerPath({
method: "delete",
path: "/org/{orgId}/browser-gateway-target/{browserGatewayTargetId}",
description: "Delete a browser gateway target.",
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
responses: {}
});
export async function deleteBrowserGatewayTarget(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = paramsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { orgId, browserGatewayTargetId } = parsedParams.data;
const [existing] = await db
.select({ bgt: browserGatewayTarget, site: sites })
.from(browserGatewayTarget)
.innerJoin(sites, eq(sites.siteId, browserGatewayTarget.siteId))
.where(
and(
eq(
browserGatewayTarget.browserGatewayTargetId,
browserGatewayTargetId
),
eq(sites.orgId, orgId)
)
)
.limit(1);
if (!existing) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Browser gateway target with ID ${browserGatewayTargetId} not found`
)
);
}
await db
.delete(browserGatewayTarget)
.where(
eq(
browserGatewayTarget.browserGatewayTargetId,
browserGatewayTargetId
)
);
if (existing.site.type === "newt") {
const [newt] = await db
.select()
.from(newts)
.where(eq(newts.siteId, existing.bgt.siteId))
.limit(1);
if (newt) {
await removeBrowserGatewayTarget(
newt.newtId,
browserGatewayTargetId,
newt.version
);
}
}
logger.info(`Deleted browser gateway target ${browserGatewayTargetId}`);
return response(res, {
data: null,
success: true,
error: false,
message: "Browser gateway target deleted successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to delete browser gateway target"
)
);
}
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import {
browserGatewayTarget,
BrowserGatewayTarget,
db,
sites
} from "@server/db";
import { eq, and } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
browserGatewayTargetId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
});
export type GetBrowserGatewayTargetResponse = BrowserGatewayTarget;
registry.registerPath({
method: "get",
path: "/org/{orgId}/browser-gateway-target/{browserGatewayTargetId}",
description: "Get a browser gateway target.",
tags: [OpenAPITags.Org],
request: {
params: paramsSchema
},
responses: {}
});
export async function getBrowserGatewayTarget(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = paramsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { orgId, browserGatewayTargetId } = parsedParams.data;
const [result] = await db
.select({ bgt: browserGatewayTarget })
.from(browserGatewayTarget)
.innerJoin(sites, eq(sites.siteId, browserGatewayTarget.siteId))
.where(
and(
eq(
browserGatewayTarget.browserGatewayTargetId,
browserGatewayTargetId
),
eq(sites.orgId, orgId)
)
)
.limit(1);
if (!result) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Browser gateway target with ID ${browserGatewayTargetId} not found`
)
);
}
return response<GetBrowserGatewayTargetResponse>(res, {
data: result.bgt,
success: true,
error: false,
message: "Browser gateway target retrieved successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to retrieve browser gateway target"
)
);
}
}

View File

@@ -0,0 +1,112 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { browserGatewayTarget, db } from "@server/db";
import { resources, targets } from "@server/db";
import { eq } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { decrypt } from "@server/lib/crypto";
import config from "@server/lib/config";
import { GetBrowserTargetResponse } from "@server/routers/browserGatewayTarget";
const getBrowserTargetSchema = z
.object({
fullDomain: z.string().min(1, "fullDomain is required")
})
.strict();
export async function getBrowserTarget(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsed = getBrowserTargetSchema.safeParse(req.query);
if (!parsed.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsed.error).toString()
)
);
}
const { fullDomain } = parsed.data;
logger.info(`Retrieving browser target for domain: ${fullDomain}`);
const [browserTarget] = await db
.select({
destination: browserGatewayTarget.destination,
destinationPort: browserGatewayTarget.destinationPort,
authToken: browserGatewayTarget.authToken,
resourceId: resources.resourceId,
niceId: resources.niceId,
orgId: resources.orgId,
pamMode: resources.pamMode,
authDaemonMode: resources.authDaemonMode
})
.from(browserGatewayTarget)
.innerJoin(
resources,
eq(browserGatewayTarget.resourceId, resources.resourceId)
)
.where(eq(resources.fullDomain, fullDomain))
.limit(1);
const decryptedAuthToken = decrypt(
browserTarget.authToken,
config.getRawConfig().server.secret!
);
if (!browserTarget) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
"No resource found for this domain"
)
);
}
return response<GetBrowserTargetResponse>(res, {
data: {
ip: browserTarget.destination,
port: browserTarget.destinationPort,
authToken: decryptedAuthToken,
pamMode: browserTarget.pamMode,
authDaemonMode: browserTarget.authDaemonMode,
orgId: browserTarget.orgId,
resourceId: browserTarget.resourceId,
niceId: browserTarget.niceId
},
success: true,
error: false,
message: "Browser target retrieved successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"An error occurred while retrieving the browser target"
)
);
}
}

View File

@@ -0,0 +1,19 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
export * from "./createBrowserGatewayTarget";
export * from "./updateBrowserGatewayTarget";
export * from "./deleteBrowserGatewayTarget";
export * from "./getBrowserGatewayTarget";
export * from "./listBrowserGatewayTargets";
export * from "./getBrowserTarget";

View File

@@ -0,0 +1,159 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import {
browserGatewayTarget,
BrowserGatewayTarget,
db,
resources,
sites
} from "@server/db";
import { eq, and } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
resourceId: z.string().transform(Number).pipe(z.number().int().positive())
});
const querySchema = z.object({
limit: z
.string()
.optional()
.default("1000")
.transform(Number)
.pipe(z.number().int().positive()),
offset: z
.string()
.optional()
.default("0")
.transform(Number)
.pipe(z.number().int().nonnegative())
});
export type ListBrowserGatewayTargetsResponse = {
targets: BrowserGatewayTarget[];
total: number;
limit: number;
offset: number;
};
registry.registerPath({
method: "get",
path: "/org/{orgId}/resource/{resourceId}/browser-gateway-targets",
description: "List browser gateway targets for a resource.",
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
query: querySchema
},
responses: {}
});
export async function listBrowserGatewayTargets(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = paramsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { orgId, resourceId } = parsedParams.data;
const parsedQuery = querySchema.safeParse(req.query);
if (!parsedQuery.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedQuery.error).toString()
)
);
}
const { limit, offset } = parsedQuery.data;
const [resource] = await db
.select()
.from(resources)
.where(
and(
eq(resources.resourceId, resourceId),
eq(resources.orgId, orgId)
)
)
.limit(1);
if (!resource) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Resource with ID ${resourceId} not found in organization ${orgId}`
)
);
}
const rows = await db
.select({
browserGatewayTargetId:
browserGatewayTarget.browserGatewayTargetId,
resourceId: browserGatewayTarget.resourceId,
siteId: browserGatewayTarget.siteId,
authToken: browserGatewayTarget.authToken,
type: browserGatewayTarget.type,
destination: browserGatewayTarget.destination,
destinationPort: browserGatewayTarget.destinationPort,
siteName: sites.name
})
.from(browserGatewayTarget)
.leftJoin(sites, eq(sites.siteId, browserGatewayTarget.siteId))
.where(eq(browserGatewayTarget.resourceId, resourceId))
.limit(limit)
.offset(offset);
return response<ListBrowserGatewayTargetsResponse>(res, {
data: {
targets: rows as any,
total: rows.length,
limit,
offset
},
success: true,
error: false,
message: "Browser gateway targets retrieved successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to list browser gateway targets"
)
);
}
}

View File

@@ -0,0 +1,180 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025-2026 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import {
browserGatewayTarget,
BrowserGatewayTarget,
db,
newts,
sites
} from "@server/db";
import { eq, and } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
import logger from "@server/logger";
import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
import { sendBrowserGatewayTargets } from "@server/routers/newt/targets";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty(),
browserGatewayTargetId: z
.string()
.transform(Number)
.pipe(z.number().int().positive())
});
const bodySchema = z.strictObject({
siteId: z.number().int().positive().optional(),
type: z.enum(["ssh", "rdp", "vnc"]).optional(),
destination: z.string().nonempty().optional(),
destinationPort: z.number().int().min(1).max(65535).optional()
});
export type UpdateBrowserGatewayTargetResponse = BrowserGatewayTarget;
registry.registerPath({
method: "post",
path: "/org/{orgId}/browser-gateway-target/{browserGatewayTargetId}",
description: "Update a browser gateway target.",
tags: [OpenAPITags.Org],
request: {
params: paramsSchema,
body: {
content: {
"application/json": {
schema: bodySchema
}
}
}
},
responses: {}
});
export async function updateBrowserGatewayTarget(
req: Request,
res: Response,
next: NextFunction
): Promise<any> {
try {
const parsedParams = paramsSchema.safeParse(req.params);
if (!parsedParams.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedParams.error).toString()
)
);
}
const { orgId, browserGatewayTargetId } = parsedParams.data;
const parsedBody = bodySchema.safeParse(req.body);
if (!parsedBody.success) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
fromError(parsedBody.error).toString()
)
);
}
const { siteId, type, destination, destinationPort } = parsedBody.data;
const [existing] = await db
.select({ bgt: browserGatewayTarget, site: sites })
.from(browserGatewayTarget)
.innerJoin(sites, eq(sites.siteId, browserGatewayTarget.siteId))
.where(
and(
eq(
browserGatewayTarget.browserGatewayTargetId,
browserGatewayTargetId
),
eq(sites.orgId, orgId)
)
)
.limit(1);
if (!existing) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Browser gateway target with ID ${browserGatewayTargetId} not found`
)
);
}
const updateValues: Partial<BrowserGatewayTarget> = {};
if (siteId !== undefined) updateValues.siteId = siteId;
if (type !== undefined) updateValues.type = type;
if (destination !== undefined) updateValues.destination = destination;
if (destinationPort !== undefined)
updateValues.destinationPort = destinationPort;
const [updated] = await db
.update(browserGatewayTarget)
.set(updateValues)
.where(
eq(
browserGatewayTarget.browserGatewayTargetId,
browserGatewayTargetId
)
)
.returning();
const targetSiteId = siteId ?? existing.bgt.siteId;
const [site] = await db
.select()
.from(sites)
.where(eq(sites.siteId, targetSiteId))
.limit(1);
if (site && site.type === "newt") {
const [newt] = await db
.select()
.from(newts)
.where(eq(newts.siteId, targetSiteId))
.limit(1);
if (newt) {
await sendBrowserGatewayTargets(
newt.newtId,
[updated],
newt.version
);
}
}
logger.info(`Updated browser gateway target ${browserGatewayTargetId}`);
return response<UpdateBrowserGatewayTargetResponse>(res, {
data: updated,
success: true,
error: false,
message: "Browser gateway target updated successfully",
status: HttpCode.OK
});
} catch (error) {
logger.error(error);
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to update browser gateway target"
)
);
}
}

View File

@@ -115,7 +115,22 @@ registry.registerPath({
orgId: z.string()
})
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function getCertificate(

View File

@@ -25,7 +25,7 @@ import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
const restartCertificateParamsSchema = z.strictObject({
certId: z.string().transform(stoi).pipe(z.int().positive()),
certId: z.coerce.number().int().positive(),
orgId: z.string()
});
@@ -36,11 +36,26 @@ registry.registerPath({
tags: ["Certificate"],
request: {
params: z.object({
certId: z.string().transform(stoi).pipe(z.int().positive()),
certId: z.coerce.number().int().positive(),
orgId: z.string()
})
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function restartCertificate(

View File

@@ -42,7 +42,22 @@ registry.registerPath({
params: paramsSchema,
query: querySchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function checkDomainNamespaceAvailability(

View File

@@ -25,6 +25,7 @@ import { OpenAPITags, registry } from "@server/openApi";
import { isSubscribed } from "#private/lib/isSubscribed";
import { build } from "@server/build";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.strictObject({});
@@ -65,6 +66,20 @@ export type ListDomainNamespacesResponse = {
pagination: { total: number; limit: number; offset: number };
};
const ListDomainNamespacesResponseDataSchema = z.object({
domainNamespaces: z.array(
z.object({
domainNamespaceId: z.string(),
domainId: z.string()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
registry.registerPath({
method: "get",
path: "/domains/namepaces",
@@ -73,7 +88,18 @@ registry.registerPath({
request: {
query: querySchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(
ListDomainNamespacesResponseDataSchema
)
}
}
}
}
});
export async function listDomainNamespaces(

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db";
import { eventStreamingDestinations } from "@server/db";
import { logStreamingManager } from "#private/lib/logStreaming";
@@ -42,6 +43,10 @@ const bodySchema = z.strictObject({
export type CreateEventStreamingDestinationResponse = {
destinationId: number;
};
const CreateEventStreamingDestinationResponseDataSchema = z.object({
destinationId: z.number()
});
registry.registerPath({
method: "put",
@@ -58,7 +63,16 @@ registry.registerPath({
}
}
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(CreateEventStreamingDestinationResponseDataSchema)
}
}
}
}
});
export async function createEventStreamingDestination(

View File

@@ -38,7 +38,22 @@ registry.registerPath({
request: {
params: paramsSchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: z.object({
data: z.unknown().nullable(),
success: z.boolean(),
error: z.boolean(),
message: z.string(),
status: z.number()
})
}
}
}
}
});
export async function deleteEventStreamingDestination(

View File

@@ -24,6 +24,7 @@ import { OpenAPITags, registry } from "@server/openApi";
import { eq, sql } from "drizzle-orm";
import { decrypt } from "@server/lib/crypto";
import config from "@server/lib/config";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty()
@@ -67,6 +68,31 @@ export type ListEventStreamingDestinationsResponse = {
};
};
const ListEventStreamingDestinationsResponseDataSchema = z.object({
destinations: z.array(
z.object({
destinationId: z.number(),
orgId: z.string(),
type: z.string(),
config: z.string(),
enabled: z.boolean(),
lastError: z.string().nullable(),
lastErrorAt: z.number().nullable(),
createdAt: z.number(),
updatedAt: z.number(),
sendConnectionLogs: z.boolean(),
sendRequestLogs: z.boolean(),
sendActionLogs: z.boolean(),
sendAccessLogs: z.boolean()
})
),
pagination: z.object({
total: z.number(),
limit: z.number(),
offset: z.number()
})
});
async function query(orgId: string, limit: number, offset: number) {
const res = await db
.select()
@@ -88,7 +114,18 @@ registry.registerPath({
query: querySchema,
params: paramsSchema
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(
ListEventStreamingDestinationsResponseDataSchema
)
}
}
}
}
});
export async function listEventStreamingDestinations(

View File

@@ -13,6 +13,7 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
import { db } from "@server/db";
import { eventStreamingDestinations } from "@server/db";
import response from "@server/lib/response";
@@ -45,6 +46,10 @@ const bodySchema = z.strictObject({
export type UpdateEventStreamingDestinationResponse = {
destinationId: number;
};
const UpdateEventStreamingDestinationResponseDataSchema = z.object({
destinationId: z.number()
});
registry.registerPath({
method: "post",
@@ -61,7 +66,16 @@ registry.registerPath({
}
}
},
responses: {}
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: createApiResponseSchema(UpdateEventStreamingDestinationResponseDataSchema)
}
}
}
}
});
export async function updateEventStreamingDestination(

View File

@@ -31,8 +31,11 @@ import * as siteProvisioning from "#private/routers/siteProvisioning";
import * as eventStreamingDestination from "#private/routers/eventStreamingDestination";
import * as alertRule from "#private/routers/alertRule";
import * as healthChecks from "#private/routers/healthChecks";
import * as browserGatewayTarget from "#private/routers/browserGatewayTarget";
import * as labels from "#private/routers/labels";
import * as client from "@server/routers/client";
import * as resource from "#private/routers/resource";
import * as policy from "#private/routers/policy";
import {
verifyOrgAccess,
@@ -46,7 +49,8 @@ import {
verifyUserCanSetUserOrgRoles,
verifySiteProvisioningKeyAccess,
verifyIsLoggedInUser,
verifyAdmin
verifyAdmin,
verifyResourcePolicyAccess
} from "@server/middlewares";
import { ActionsEnum } from "@server/auth/actions";
import {
@@ -384,6 +388,39 @@ authenticated.get(
approval.countApprovals
);
authenticated.delete(
"/resource-policy/:resourcePolicyId",
verifyResourcePolicyAccess,
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyLimits,
verifyUserHasAction(ActionsEnum.deleteResourcePolicy),
logActionAudit(ActionsEnum.deleteResourcePolicy),
policy.deleteResourcePolicy
);
authenticated.get(
"/org/:orgId/resource-policies",
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.listResourcePolicies),
logActionAudit(ActionsEnum.listResourcePolicies),
policy.listResourcePolicies
);
authenticated.post(
"/org/:orgId/resource-policy",
verifyValidLicense,
verifyValidSubscription(tierMatrix.resourcePolicies),
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.createResourcePolicy),
logActionAudit(ActionsEnum.createResourcePolicy),
policy.createResourcePolicy
);
authenticated.put(
"/org/:orgId/approvals/:approvalId",
verifyValidLicense,
@@ -573,7 +610,7 @@ authenticated.put(
authenticated.post(
"/org/:orgId/ssh/sign-key",
verifyValidLicense,
verifyValidSubscription(tierMatrix.sshPam),
verifyValidSubscription(tierMatrix.advancedPrivateResources),
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.signSshKey),
@@ -842,3 +879,48 @@ authenticated.post(
verifyClientAccess,
client.rebuildClientAssociationsCacheRoute
);
authenticated.put(
"/org/:orgId/resource/:resourceId/browser-gateway-target",
verifyValidLicense,
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.createBrowserGatewayTarget),
logActionAudit(ActionsEnum.createBrowserGatewayTarget),
browserGatewayTarget.createBrowserGatewayTarget
);
authenticated.get(
"/org/:orgId/resource/:resourceId/browser-gateway-targets",
verifyValidLicense,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.listBrowserGatewayTargets),
browserGatewayTarget.listBrowserGatewayTargets
);
authenticated.get(
"/org/:orgId/browser-gateway-target/:browserGatewayTargetId",
verifyValidLicense,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.getBrowserGatewayTarget),
browserGatewayTarget.getBrowserGatewayTarget
);
authenticated.post(
"/org/:orgId/browser-gateway-target/:browserGatewayTargetId",
verifyValidLicense,
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.updateBrowserGatewayTarget),
logActionAudit(ActionsEnum.updateBrowserGatewayTarget),
browserGatewayTarget.updateBrowserGatewayTarget
);
authenticated.delete(
"/org/:orgId/browser-gateway-target/:browserGatewayTargetId",
verifyValidLicense,
verifyOrgAccess,
verifyUserHasAction(ActionsEnum.deleteBrowserGatewayTarget),
logActionAudit(ActionsEnum.deleteBrowserGatewayTarget),
browserGatewayTarget.deleteBrowserGatewayTarget
);

Some files were not shown because too many files have changed in this diff Show More