mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-29 06:10:47 +00:00
Compare commits
1060 Commits
patch
...
1.12.2-s.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de8262d7b9 | ||
|
|
8ad7bcc0d6 | ||
|
|
e62806d6fb | ||
|
|
aabe39137b | ||
|
|
ca66637270 | ||
|
|
fbce392137 | ||
|
|
d38b321f85 | ||
|
|
b0ff50a76f | ||
|
|
37acdc2796 | ||
|
|
f3d31cb6de | ||
|
|
a336955066 | ||
|
|
a229fc1c61 | ||
|
|
7995fd364e | ||
|
|
5e0d822d45 | ||
|
|
4fddaa8f11 | ||
|
|
4a87cecf89 | ||
|
|
ac5ee5c7ca | ||
|
|
8a8c357563 | ||
|
|
263fd80c18 | ||
|
|
7bdf05bdf5 | ||
|
|
d00f12967d | ||
|
|
d9991a18e2 | ||
|
|
a51c21cdd2 | ||
|
|
265cab5b64 | ||
|
|
da15e5e77b | ||
|
|
a717ca2675 | ||
|
|
564b290244 | ||
|
|
84d78df67e | ||
|
|
107053a98f | ||
|
|
6422a78e6f | ||
|
|
5f11630e27 | ||
|
|
a776b2ea94 | ||
|
|
b83ec1b503 | ||
|
|
83bd5957cd | ||
|
|
66c14c2d09 | ||
|
|
51db267a4a | ||
|
|
669817818a | ||
|
|
b84453bfbe | ||
|
|
15d561f59f | ||
|
|
749cea5a4d | ||
|
|
2a7529c39e | ||
|
|
fce887436d | ||
|
|
3489107a49 | ||
|
|
296b220bf3 | ||
|
|
0a9f37c44d | ||
|
|
ef5d72663f | ||
|
|
6ddfc9b8fe | ||
|
|
301654b63e | ||
|
|
3b12a77cf0 | ||
|
|
7cd31313d8 | ||
|
|
9822deb4bf | ||
|
|
8942cb7aa7 | ||
|
|
f0f219f293 | ||
|
|
6174599754 | ||
|
|
8ba04aeb74 | ||
|
|
43590896e9 | ||
|
|
3547c4832b | ||
|
|
1cd098252e | ||
|
|
4adbc31dae | ||
|
|
99031feb35 | ||
|
|
d363b06d0e | ||
|
|
2af100cc86 | ||
|
|
3e90211108 | ||
|
|
6dd161fe17 | ||
|
|
558bd040c6 | ||
|
|
f2c48975f6 | ||
|
|
fc43a56bb3 | ||
|
|
ca7f557a3c | ||
|
|
7477713eef | ||
|
|
c16e762fa4 | ||
|
|
41592133a6 | ||
|
|
54f7525f1b | ||
|
|
ad6bb3da9f | ||
|
|
49bc2dc5da | ||
|
|
cdf77087cd | ||
|
|
8e5dde887c | ||
|
|
f21188000e | ||
|
|
1b3eb32bf4 | ||
|
|
eec3f183e6 | ||
|
|
31b66cd911 | ||
|
|
ad425e8d9e | ||
|
|
da0196a308 | ||
|
|
e585972b7b | ||
|
|
cc62cd4add | ||
|
|
25225a452c | ||
|
|
678644c7fb | ||
|
|
32f20ed984 | ||
|
|
4eb5bf08d5 | ||
|
|
35c93f38e0 | ||
|
|
f60c2f4fb9 | ||
|
|
b2cf152b9e | ||
|
|
444928dffd | ||
|
|
4d7e2d5840 | ||
|
|
318046ce1d | ||
|
|
808ad1e272 | ||
|
|
05a1195661 | ||
|
|
c46322c6a6 | ||
|
|
80d5efc41f | ||
|
|
0409ab7dc1 | ||
|
|
63f079ec76 | ||
|
|
5988f1e8da | ||
|
|
ed0c0edeba | ||
|
|
34b4841f4d | ||
|
|
ff47c5a8ad | ||
|
|
9430a53c0c | ||
|
|
03334e3f0f | ||
|
|
6f2ecf9d0d | ||
|
|
6f803c3b4b | ||
|
|
15d400c842 | ||
|
|
3ddf150661 | ||
|
|
5b519afee4 | ||
|
|
15ea9f3dcc | ||
|
|
d5e2536f8d | ||
|
|
d7e9083e06 | ||
|
|
e0cc338c3a | ||
|
|
624c5741e2 | ||
|
|
558507dd71 | ||
|
|
565340bd53 | ||
|
|
756745487a | ||
|
|
d2ece4d370 | ||
|
|
d5f5d1da1e | ||
|
|
dfaf1a72cc | ||
|
|
ff8e5b871c | ||
|
|
927dda4e53 | ||
|
|
0e51bac307 | ||
|
|
7a50af14f3 | ||
|
|
396477c2e2 | ||
|
|
8765874d9a | ||
|
|
49dffe086d | ||
|
|
77ddadcded | ||
|
|
05b297ddec | ||
|
|
feb0de9a08 | ||
|
|
f4f2361d22 | ||
|
|
cae6a9f51c | ||
|
|
2872f5c018 | ||
|
|
0512c21ad7 | ||
|
|
922a69feed | ||
|
|
24192c79d4 | ||
|
|
17c22a635f | ||
|
|
bcbcf417b5 | ||
|
|
acf7596368 | ||
|
|
34c7d925ca | ||
|
|
c10730ebb9 | ||
|
|
e50743b922 | ||
|
|
75b0745e42 | ||
|
|
ebd99f95a3 | ||
|
|
0e649883cb | ||
|
|
3d376c8d14 | ||
|
|
adedb0e391 | ||
|
|
521935786c | ||
|
|
885b9d186b | ||
|
|
356f023539 | ||
|
|
de8d3f45da | ||
|
|
72c9956190 | ||
|
|
6dc4cbe448 | ||
|
|
77364488c2 | ||
|
|
5a61040027 | ||
|
|
c6f7be40df | ||
|
|
c36fb63f8c | ||
|
|
48aebea6cf | ||
|
|
55082d2ef8 | ||
|
|
cc03b97234 | ||
|
|
5542873368 | ||
|
|
1db5d76ef1 | ||
|
|
ca6c45087b | ||
|
|
3333eb95f9 | ||
|
|
d681725fc3 | ||
|
|
f5eadc9e1e | ||
|
|
219e213c1e | ||
|
|
af654e663b | ||
|
|
39b3b4ef9d | ||
|
|
6c62a0900f | ||
|
|
ddd772eb43 | ||
|
|
69458ab649 | ||
|
|
c7df70143e | ||
|
|
a81ea7cc8f | ||
|
|
02330a0756 | ||
|
|
db49b599b5 | ||
|
|
bb0bfd440a | ||
|
|
10ce732b8d | ||
|
|
4c567cf2d7 | ||
|
|
2783d2989d | ||
|
|
c3d6510231 | ||
|
|
3bb948991f | ||
|
|
4b9ce22f06 | ||
|
|
772bda69f9 | ||
|
|
8b4722b1c9 | ||
|
|
9e5c9d9c34 | ||
|
|
ee533df38f | ||
|
|
52dc8e011c | ||
|
|
bd5cc790d6 | ||
|
|
7d6d5a7787 | ||
|
|
ba6e7dd06a | ||
|
|
6270fb3237 | ||
|
|
16ec50a6ee | ||
|
|
3d2021c8a1 | ||
|
|
15d63ddffa | ||
|
|
7ce6fadb3d | ||
|
|
6b18a24f9b | ||
|
|
a38cb961c7 | ||
|
|
3c5fe21078 | ||
|
|
b44305694f | ||
|
|
be217e2b6f | ||
|
|
6ce04c2aa1 | ||
|
|
85e4b649db | ||
|
|
73a3335148 | ||
|
|
32845c5a3d | ||
|
|
05a878ac34 | ||
|
|
847d015243 | ||
|
|
51cde2681c | ||
|
|
9c0606942c | ||
|
|
646d476bdb | ||
|
|
31261681a0 | ||
|
|
f6fae820c4 | ||
|
|
b3cbf925aa | ||
|
|
aa1ae3ee42 | ||
|
|
80f6c8b74e | ||
|
|
79d8e8d59d | ||
|
|
9193375586 | ||
|
|
240bcb8759 | ||
|
|
a5dcafb84c | ||
|
|
192207a857 | ||
|
|
d18fafb0ef | ||
|
|
380c86898c | ||
|
|
b59a6b82ef | ||
|
|
77ba568c36 | ||
|
|
a0f05cc77b | ||
|
|
80f43a9774 | ||
|
|
c04d9eda6b | ||
|
|
cabf3e9695 | ||
|
|
ff7b4386d6 | ||
|
|
4dbbe159ee | ||
|
|
eeab92719a | ||
|
|
43e6b7de07 | ||
|
|
4cfd1b1ff5 | ||
|
|
09ba018493 | ||
|
|
7acf7dd0eb | ||
|
|
592d085de6 | ||
|
|
2cf2c64651 | ||
|
|
560974f7d2 | ||
|
|
85270f497a | ||
|
|
9fbea4a380 | ||
|
|
cbf9c5361e | ||
|
|
44316731c0 | ||
|
|
60513af8ed | ||
|
|
24cfe02979 | ||
|
|
8f3324560a | ||
|
|
2041edcf30 | ||
|
|
1227b3c11a | ||
|
|
8973726f63 | ||
|
|
5559fef1bc | ||
|
|
9cb3c3821a | ||
|
|
c85e367ded | ||
|
|
5e20487216 | ||
|
|
bc6b9eb905 | ||
|
|
5940bbd498 | ||
|
|
f4a0f6a2e6 | ||
|
|
0df7d45678 | ||
|
|
a05ee2483b | ||
|
|
f5dbc18c05 | ||
|
|
dd052fa1af | ||
|
|
2cc4ad9c30 | ||
|
|
4dd741cc3f | ||
|
|
9ce81b34c9 | ||
|
|
460df46abc | ||
|
|
1e70e4289b | ||
|
|
5fa0ac5927 | ||
|
|
4b40e7b8d6 | ||
|
|
29cd035a05 | ||
|
|
39d6b93d42 | ||
|
|
629f17294a | ||
|
|
10a5af67aa | ||
|
|
b542d82553 | ||
|
|
2a644c3f88 | ||
|
|
f6de61968d | ||
|
|
68f0c4df3a | ||
|
|
0743daf56a | ||
|
|
58b6ab2601 | ||
|
|
038f8829c2 | ||
|
|
ddcf77a62d | ||
|
|
adefbdbeb3 | ||
|
|
921285e5b1 | ||
|
|
264bf46798 | ||
|
|
5a7b5d65a4 | ||
|
|
23b13f0a0e | ||
|
|
90ddffce0e | ||
|
|
e30fde5237 | ||
|
|
ac683c3ff7 | ||
|
|
b5a931c96e | ||
|
|
5b61742075 | ||
|
|
4e4a38f7e9 | ||
|
|
c1bb029a1c | ||
|
|
eae2c37388 | ||
|
|
7193fea068 | ||
|
|
9b85deebf8 | ||
|
|
0211f75cb6 | ||
|
|
fa6b7ca3ed | ||
|
|
007d03e7f6 | ||
|
|
a534301eb7 | ||
|
|
1baa987016 | ||
|
|
a5b48ab392 | ||
|
|
7f981f05fb | ||
|
|
259cea1c42 | ||
|
|
9024b2a974 | ||
|
|
f2c31d3ca6 | ||
|
|
6f8b5dd909 | ||
|
|
6521b66b7c | ||
|
|
202d2075a6 | ||
|
|
e575fae73b | ||
|
|
d84ee3d03d | ||
|
|
ba745588e9 | ||
|
|
84731bdc19 | ||
|
|
f748c5dbe4 | ||
|
|
fdd4d5244f | ||
|
|
9301477262 | ||
|
|
9a787e6ef8 | ||
|
|
5b8cdf7884 | ||
|
|
5fd104bb30 | ||
|
|
9ba42a8fa3 | ||
|
|
fe8fd2e3a8 | ||
|
|
9ebce35d2b | ||
|
|
654145be84 | ||
|
|
3662d42374 | ||
|
|
d392fb371e | ||
|
|
1142d6ac48 | ||
|
|
bdc3b2425b | ||
|
|
9a64f45815 | ||
|
|
3633e02ff7 | ||
|
|
2c502ec764 | ||
|
|
b17d7f0e27 | ||
|
|
65364d6b0f | ||
|
|
6fd6c77ce6 | ||
|
|
e447549de1 | ||
|
|
6b0dd00aa5 | ||
|
|
461866836e | ||
|
|
3ae42f054f | ||
|
|
5a571f19e1 | ||
|
|
70aeaf7b5d | ||
|
|
7a6838f5a5 | ||
|
|
07f5e8f215 | ||
|
|
2b05bc1f5f | ||
|
|
edf64ae7b5 | ||
|
|
7370448be9 | ||
|
|
51af293d66 | ||
|
|
d37e28215e | ||
|
|
2c01849f2e | ||
|
|
c29ba9bb5f | ||
|
|
8fdf120ec2 | ||
|
|
a9b9161c40 | ||
|
|
43f907ebec | ||
|
|
ae670e1eb5 | ||
|
|
f102718901 | ||
|
|
9d452efc7d | ||
|
|
156fe529b5 | ||
|
|
df24525105 | ||
|
|
d938345deb | ||
|
|
d6681733dd | ||
|
|
2f1aec02f0 | ||
|
|
d30e0a3c51 | ||
|
|
3f3e9cf1bb | ||
|
|
e77909d498 | ||
|
|
d10830f892 | ||
|
|
18d8f72da2 | ||
|
|
4a59823e58 | ||
|
|
f3149e46cd | ||
|
|
60379a7b4e | ||
|
|
605b3cccee | ||
|
|
843799f4f6 | ||
|
|
a69cda5c13 | ||
|
|
dbaa3dbd52 | ||
|
|
58197c6fb2 | ||
|
|
7813093452 | ||
|
|
3f2c3dc987 | ||
|
|
08ddba25d0 | ||
|
|
d47fa7e64f | ||
|
|
c87aa2e537 | ||
|
|
bc430546bc | ||
|
|
9428e065eb | ||
|
|
10408c5717 | ||
|
|
ae902da913 | ||
|
|
0be5a91eff | ||
|
|
7dcf46ce98 | ||
|
|
33e6e4b411 | ||
|
|
bab6e4eb0d | ||
|
|
6a7c7521d8 | ||
|
|
d070244ea7 | ||
|
|
9219bb7d6e | ||
|
|
54e83f35e5 | ||
|
|
eb138d6526 | ||
|
|
edd0c3099b | ||
|
|
04455d40cf | ||
|
|
221af94d15 | ||
|
|
48ac3bb7af | ||
|
|
07273b8b7f | ||
|
|
bfb5b2864d | ||
|
|
07330e84fb | ||
|
|
0e39704b3a | ||
|
|
f25e794e7c | ||
|
|
df46ce8bdc | ||
|
|
4d83f537dc | ||
|
|
58443ef53f | ||
|
|
1ee52ad86b | ||
|
|
bc941239ec | ||
|
|
9a52d5387d | ||
|
|
1f50bc3752 | ||
|
|
0819df0910 | ||
|
|
663787c15b | ||
|
|
2c39d07261 | ||
|
|
dce84b9b09 | ||
|
|
a5bab6bb80 | ||
|
|
7536c03f63 | ||
|
|
ada5d2ef0e | ||
|
|
b8bead0590 | ||
|
|
68f852d6d1 | ||
|
|
d9fe5a8819 | ||
|
|
346183a23f | ||
|
|
dcfd7f5443 | ||
|
|
e59cd6672b | ||
|
|
7c8c440f67 | ||
|
|
f258c41f15 | ||
|
|
ae4a24f4aa | ||
|
|
476cdcfe86 | ||
|
|
f869df2f65 | ||
|
|
03cfabacd9 | ||
|
|
47ac5875f3 | ||
|
|
f67327358e | ||
|
|
4901823f15 | ||
|
|
5407e3c821 | ||
|
|
1d5cdad8b7 | ||
|
|
cd2424cb77 | ||
|
|
c17efde6bf | ||
|
|
40cd8cdec7 | ||
|
|
6768672a44 | ||
|
|
240c5b005b | ||
|
|
8dde170a35 | ||
|
|
c07abf8ff9 | ||
|
|
e5a436593f | ||
|
|
bb6e093ac6 | ||
|
|
59a334ce24 | ||
|
|
d241dcfb27 | ||
|
|
af263e7913 | ||
|
|
6610e7d405 | ||
|
|
c476e65cf2 | ||
|
|
b69b2eeeb3 | ||
|
|
89dab0917b | ||
|
|
73efdb95ae | ||
|
|
1bcca88614 | ||
|
|
3af1e0ef56 | ||
|
|
8387571c1d | ||
|
|
1d017f60b4 | ||
|
|
81effda9e8 | ||
|
|
9343906ab1 | ||
|
|
08b7d6735c | ||
|
|
a91ebd1e91 | ||
|
|
312e03b4eb | ||
|
|
e8a57e432c | ||
|
|
bca2eef2e8 | ||
|
|
ec7211a15d | ||
|
|
46807c6477 | ||
|
|
b578786e62 | ||
|
|
2e0ad8d262 | ||
|
|
003f0cfa6d | ||
|
|
ee3df081ef | ||
|
|
08eeb12519 | ||
|
|
e66c6b2505 | ||
|
|
d2a880d9c8 | ||
|
|
edc0b86470 | ||
|
|
aebe6b80b7 | ||
|
|
4d87333b43 | ||
|
|
ef32f3ed5a | ||
|
|
216ded3034 | ||
|
|
cb59fe2cee | ||
|
|
7776f6d09c | ||
|
|
c50392c947 | ||
|
|
ceee978fcd | ||
|
|
c5a73dc87e | ||
|
|
7198ef2774 | ||
|
|
7e9a066797 | ||
|
|
ba96332313 | ||
|
|
e2d0338b0b | ||
|
|
59ecab5738 | ||
|
|
721bf3403d | ||
|
|
3b8ba47377 | ||
|
|
e752929f69 | ||
|
|
e41c3e6f54 | ||
|
|
9dedd1a8de | ||
|
|
c4a5fae28f | ||
|
|
5f95a3233f | ||
|
|
d3174d0196 | ||
|
|
3710d71974 | ||
|
|
f62e88eb67 | ||
|
|
904b302fb6 | ||
|
|
5fc096f2d5 | ||
|
|
87668c492f | ||
|
|
6d7a8b97ad | ||
|
|
282d444933 | ||
|
|
f3d7d97fb9 | ||
|
|
de857a7c4e | ||
|
|
20a0ebfc9d | ||
|
|
ba8166bdeb | ||
|
|
2b634fc6c5 | ||
|
|
5429bc03ab | ||
|
|
a558b34608 | ||
|
|
1850d56977 | ||
|
|
61b4c62824 | ||
|
|
10e5ccfe86 | ||
|
|
9f5d475e80 | ||
|
|
9bb9a3acbe | ||
|
|
0923b7e3c5 | ||
|
|
ccd81f6fe2 | ||
|
|
0f74107e86 | ||
|
|
8377434c08 | ||
|
|
1fbf2bfb8d | ||
|
|
42facf8e12 | ||
|
|
4bb3d85c25 | ||
|
|
c0039190bd | ||
|
|
a8d00a47cd | ||
|
|
57bcbf6c48 | ||
|
|
c57db1479e | ||
|
|
cd8062ada3 | ||
|
|
244d05adb1 | ||
|
|
812bd64325 | ||
|
|
276d1361ac | ||
|
|
881eac4722 | ||
|
|
2a2a550a6a | ||
|
|
e75001080a | ||
|
|
6fbba38a76 | ||
|
|
902b413881 | ||
|
|
8b2f8ad3ef | ||
|
|
377cb77307 | ||
|
|
733bf0b169 | ||
|
|
8faff3e075 | ||
|
|
48af91c976 | ||
|
|
6664efaa13 | ||
|
|
e5ee96cf52 | ||
|
|
38faf1f905 | ||
|
|
2cff142266 | ||
|
|
2c99cfacc0 | ||
|
|
0c63ea1f50 | ||
|
|
f50df66e3a | ||
|
|
4b93491160 | ||
|
|
19210cbf7d | ||
|
|
9af206b69a | ||
|
|
b6b9c71c5e | ||
|
|
c000c4502f | ||
|
|
b6c1d9a592 | ||
|
|
7a75fe0cad | ||
|
|
a83e660902 | ||
|
|
65eb3e4b95 | ||
|
|
093fb419f3 | ||
|
|
026e56aead | ||
|
|
fa9bc59f62 | ||
|
|
06ec80db42 | ||
|
|
24d564b79b | ||
|
|
2f5e6248cd | ||
|
|
c0cc81ed96 | ||
|
|
b33a54a449 | ||
|
|
94137e587c | ||
|
|
a6086d3724 | ||
|
|
0a377150e3 | ||
|
|
d20e0a228a | ||
|
|
ca146a1b57 | ||
|
|
c7c3e3ee73 | ||
|
|
cd27f6459c | ||
|
|
b1e212721e | ||
|
|
ccd2773331 | ||
|
|
cfa82b51fb | ||
|
|
9c91a8db46 | ||
|
|
b160eee8d2 | ||
|
|
37ceabdf5d | ||
|
|
e7828a43fa | ||
|
|
ccb1f04ad8 | ||
|
|
4c14ccbb63 | ||
|
|
25c24ca9cf | ||
|
|
787869fe21 | ||
|
|
b51c27a823 | ||
|
|
5917881b47 | ||
|
|
c7a40d59b7 | ||
|
|
a50c0d84e9 | ||
|
|
f17a957058 | ||
|
|
2c63851130 | ||
|
|
6b125bba7c | ||
|
|
d92b87b7c8 | ||
|
|
f64a477c3d | ||
|
|
b6f8ed1e4a | ||
|
|
bad88e4741 | ||
|
|
01db519691 | ||
|
|
e601038c0f | ||
|
|
e0996a17ef | ||
|
|
526307e192 | ||
|
|
1b01c4f053 | ||
|
|
a184e23f16 | ||
|
|
06156e0ca6 | ||
|
|
02b1de3266 | ||
|
|
c5b3d92466 | ||
|
|
186a78b064 | ||
|
|
9a808dc139 | ||
|
|
977404b8c3 | ||
|
|
b00143ce9b | ||
|
|
4435d9a248 | ||
|
|
7d0303e2be | ||
|
|
a0da9c1129 | ||
|
|
5e73690570 | ||
|
|
b0409b7d52 | ||
|
|
fe474b3989 | ||
|
|
5154d5d3ee | ||
|
|
62df92f63a | ||
|
|
e2534af40e | ||
|
|
b627e391ac | ||
|
|
40a3eac704 | ||
|
|
2ee3f10e02 | ||
|
|
5a3bf2f758 | ||
|
|
e121dd0d1d | ||
|
|
2c46a37a53 | ||
|
|
23f05d7f4e | ||
|
|
6105eea7a9 | ||
|
|
850e9a734a | ||
|
|
2d30b155f2 | ||
|
|
1333e21553 | ||
|
|
4c412528f5 | ||
|
|
a8fce47ba0 | ||
|
|
cb7c57fd03 | ||
|
|
494d0f7c14 | ||
|
|
a4e480e02b | ||
|
|
cd285cc019 | ||
|
|
9e8e00d4bb | ||
|
|
389834f735 | ||
|
|
b14ddc07fb | ||
|
|
4447fb8202 | ||
|
|
1c9c4b1802 | ||
|
|
19e15f4ef5 | ||
|
|
c2c29e2cd2 | ||
|
|
7b33dc591d | ||
|
|
a95f2e76f4 | ||
|
|
979860a951 | ||
|
|
9e9a81d9e8 | ||
|
|
8f09561114 | ||
|
|
b167d94ead | ||
|
|
e4c0a157e3 | ||
|
|
956869ab58 | ||
|
|
e5f4da9a99 | ||
|
|
9649d9a46b | ||
|
|
22477b7e81 | ||
|
|
b6c76a2164 | ||
|
|
043834274d | ||
|
|
1e4ca69c89 | ||
|
|
ff2bcfb0e7 | ||
|
|
b47fc9f901 | ||
|
|
165f4023d0 | ||
|
|
d51053ce86 | ||
|
|
229872589c | ||
|
|
e4c47c46a6 | ||
|
|
84fe2fb92e | ||
|
|
076912c648 | ||
|
|
033653e234 | ||
|
|
0624087373 | ||
|
|
346d886f8a | ||
|
|
67ac01b31a | ||
|
|
87f1cf6730 | ||
|
|
0f46651500 | ||
|
|
65bf055e0f | ||
|
|
4c995f786b | ||
|
|
4853c8c872 | ||
|
|
170da08001 | ||
|
|
a39a133ee5 | ||
|
|
1251b1e870 | ||
|
|
418120196f | ||
|
|
759661420e | ||
|
|
bb28f856da | ||
|
|
f90e6bef9e | ||
|
|
cabaa2e6d6 | ||
|
|
c8bddd4289 | ||
|
|
71ba980757 | ||
|
|
38c3c49778 | ||
|
|
ab7ac9cb60 | ||
|
|
e4787924e7 | ||
|
|
3385a92b0f | ||
|
|
e73e6956a5 | ||
|
|
024eb2b157 | ||
|
|
ccff0592ca | ||
|
|
942f7c2bc9 | ||
|
|
b3a6cd0660 | ||
|
|
c5569fccf1 | ||
|
|
cc7c443145 | ||
|
|
8d7e5baf9d | ||
|
|
ed64d4b5ae | ||
|
|
8fe42bc6aa | ||
|
|
a67aa3852d | ||
|
|
c2c907852d | ||
|
|
3123f858bb | ||
|
|
6a18369891 | ||
|
|
0f4ef40600 | ||
|
|
42a7fb949a | ||
|
|
bbfa6e9c82 | ||
|
|
0d8ae0d615 | ||
|
|
7bbbc88c34 | ||
|
|
e2ad197d7e | ||
|
|
ca8f52d304 | ||
|
|
7395a64b26 | ||
|
|
4dd672a590 | ||
|
|
cff3f739db | ||
|
|
7fb35cfebb | ||
|
|
ddfda31924 | ||
|
|
353e085b0e | ||
|
|
989b548ef9 | ||
|
|
8f60e7e200 | ||
|
|
ec74525fde | ||
|
|
a317c50737 | ||
|
|
c62b46268a | ||
|
|
42ef075d4f | ||
|
|
f52605289b | ||
|
|
68e0911866 | ||
|
|
756fcbb590 | ||
|
|
a49d900951 | ||
|
|
38f212d632 | ||
|
|
204fdfd233 | ||
|
|
b5e04e8111 | ||
|
|
21fc829766 | ||
|
|
39851c3412 | ||
|
|
21811465b6 | ||
|
|
7574726815 | ||
|
|
236e0f9ab6 | ||
|
|
8e95f0b73f | ||
|
|
bed45a5fbd | ||
|
|
c50c2e2b01 | ||
|
|
adf982fcd6 | ||
|
|
9b4103be75 | ||
|
|
672eec0c33 | ||
|
|
0d8c06595e | ||
|
|
a5a7ca5fcc | ||
|
|
8767d20c47 | ||
|
|
4cbf3fffb1 | ||
|
|
51fad19d0d | ||
|
|
664aa6ed2a | ||
|
|
574cd2a754 | ||
|
|
1b34ee7369 | ||
|
|
7b2f1dd4c6 | ||
|
|
a97b6efe9c | ||
|
|
3722b67724 | ||
|
|
218a5ec9e4 | ||
|
|
90d3ac07a9 | ||
|
|
149a4b916b | ||
|
|
70914e836f | ||
|
|
a2dae8aa13 | ||
|
|
b6ea0808e4 | ||
|
|
089e43e1ce | ||
|
|
42936ab8dc | ||
|
|
411fa9345f | ||
|
|
336e118096 | ||
|
|
d1707801bf | ||
|
|
71bcf25718 | ||
|
|
288da0ef05 | ||
|
|
fec29eb349 | ||
|
|
032d48e394 | ||
|
|
a433d97573 | ||
|
|
6bd571f1b3 | ||
|
|
1dd89601ad | ||
|
|
a7cf359672 | ||
|
|
baa98952fa | ||
|
|
55afbf4db5 | ||
|
|
dca0fb327b | ||
|
|
e34a31941d | ||
|
|
dbba5002d9 | ||
|
|
4dd9e34a11 | ||
|
|
a30222a13e | ||
|
|
5797144083 | ||
|
|
db513b43e7 | ||
|
|
d387fa3bfb | ||
|
|
1bff9f550e | ||
|
|
0167b30bf1 | ||
|
|
bf993d04f1 | ||
|
|
be2b2c6c77 | ||
|
|
8851156f23 | ||
|
|
1a13694843 | ||
|
|
3872831bd7 | ||
|
|
ef4ce115ff | ||
|
|
516b300731 | ||
|
|
88d97dd49b | ||
|
|
be9494dd54 | ||
|
|
e43fc59634 | ||
|
|
4523a8df0f | ||
|
|
2c8082451f | ||
|
|
7ab498702c | ||
|
|
a06e8c8f83 | ||
|
|
1a01e8d53a | ||
|
|
5ce60cf1cd | ||
|
|
de1a6025d0 | ||
|
|
ca6ae53fe6 | ||
|
|
4eff52ab62 | ||
|
|
e5c5780547 | ||
|
|
f348c9daa7 | ||
|
|
e1dd29dd0b | ||
|
|
558f302342 | ||
|
|
5fee1c3ebd | ||
|
|
248debb7c4 | ||
|
|
8504fd8d9d | ||
|
|
e360a5323d | ||
|
|
1ad5eb010a | ||
|
|
ca7f1e5db8 | ||
|
|
2981e35c75 | ||
|
|
f3e8677ae4 | ||
|
|
d209c8af9d | ||
|
|
26b2233168 | ||
|
|
b2669aaa34 | ||
|
|
1438eef62b | ||
|
|
a92f7dbb7c | ||
|
|
4710bab697 | ||
|
|
52aa27025d | ||
|
|
8e544c056f | ||
|
|
3c2a8b9031 | ||
|
|
fff4883bca | ||
|
|
dc234beab1 | ||
|
|
66d310fcca | ||
|
|
702b5eb3dd | ||
|
|
06477b6e7f | ||
|
|
fc76899384 | ||
|
|
97102b9be9 | ||
|
|
1c0dfa830e | ||
|
|
53bfaac0c0 | ||
|
|
30790fdcb6 | ||
|
|
b8b256da2e | ||
|
|
0472dc1b25 | ||
|
|
1ec3e53e11 | ||
|
|
9f66e09e44 | ||
|
|
a71b0a8924 | ||
|
|
e555d3c496 | ||
|
|
df92e41384 | ||
|
|
d10fdac670 | ||
|
|
b63bffa524 | ||
|
|
957cfdd5d7 | ||
|
|
1352316492 | ||
|
|
73cd82081a | ||
|
|
812820472f | ||
|
|
21f0cd6e3f | ||
|
|
b2ee8ef7de | ||
|
|
1e066cbabd | ||
|
|
4cc38d44e0 | ||
|
|
dcf7393259 | ||
|
|
bab070b09c | ||
|
|
2bd4ad5770 | ||
|
|
61ecebf911 | ||
|
|
33c8663a5b | ||
|
|
76da2ee324 | ||
|
|
31896c9be9 | ||
|
|
f61d722aee | ||
|
|
1f9f3fdede | ||
|
|
a778109214 | ||
|
|
cb7fa9375b | ||
|
|
515ecb09e7 | ||
|
|
a12a620697 | ||
|
|
0c3b2bc2f5 | ||
|
|
78ba27dc63 | ||
|
|
dc20b863ed | ||
|
|
c9a211d5cf | ||
|
|
95f94cffd2 | ||
|
|
0da95cbdb8 | ||
|
|
dadd1e3101 | ||
|
|
d523ae3ffa | ||
|
|
9a41cac6e1 | ||
|
|
5d3c5ab7cc | ||
|
|
08c930e6cf | ||
|
|
e94ded920b | ||
|
|
c882fbd59a | ||
|
|
46b50a042e | ||
|
|
fda9e95786 | ||
|
|
ea1ad23bff | ||
|
|
7ffc5e0212 | ||
|
|
acba9444f4 | ||
|
|
f7e3671801 | ||
|
|
a1b2e36a5d | ||
|
|
44e96942b3 | ||
|
|
f2efa760ff | ||
|
|
256df9042b | ||
|
|
6d7091fb5c | ||
|
|
0d1f88a368 | ||
|
|
2ae601717d | ||
|
|
c7c8b463b4 | ||
|
|
282f839211 | ||
|
|
b2eb846b69 | ||
|
|
62cf925dcf | ||
|
|
e699f84c4d | ||
|
|
c1189dadc5 | ||
|
|
76bc080a6d | ||
|
|
7f989f77ac | ||
|
|
b916f768fe | ||
|
|
e4509c5714 | ||
|
|
ddb6893a64 | ||
|
|
248751ba1d | ||
|
|
b4b74ed53a | ||
|
|
76903cd67f | ||
|
|
e4f2eac703 | ||
|
|
3aa45007a7 | ||
|
|
f452892c88 | ||
|
|
a0fece8a0e | ||
|
|
e3d493209b | ||
|
|
2e8b63553d | ||
|
|
fb8f4b95b7 | ||
|
|
83e107c713 | ||
|
|
e97642a790 | ||
|
|
426d8684bf | ||
|
|
5e7409a4f0 | ||
|
|
c225a4cd48 | ||
|
|
24df9e1ce6 | ||
|
|
eab1fd3722 | ||
|
|
93bd041693 | ||
|
|
665ebe993c | ||
|
|
4086130371 | ||
|
|
29aacf5238 | ||
|
|
497e6a8422 | ||
|
|
af8572add9 | ||
|
|
d6aea96400 | ||
|
|
17e26ff1a6 | ||
|
|
f5f223348d | ||
|
|
e4f90fd7ea | ||
|
|
96dff20760 | ||
|
|
d639f7f6de | ||
|
|
5b35ec2ea2 | ||
|
|
bc78b95265 | ||
|
|
97f22eccbb | ||
|
|
a4fe86e38a | ||
|
|
4bc1e10ecb | ||
|
|
5b840d73bb | ||
|
|
afa9acfb1e | ||
|
|
7b7f65da39 | ||
|
|
806da59f47 | ||
|
|
9a009a4ea3 | ||
|
|
083d890053 | ||
|
|
e693a8aeb8 | ||
|
|
831b46d7b5 | ||
|
|
8dd3022b94 | ||
|
|
b278eb7110 | ||
|
|
7a66163216 | ||
|
|
dda2043401 | ||
|
|
08d6183c9b | ||
|
|
eea0b86d6d | ||
|
|
58c04fd196 | ||
|
|
09de6f6b5f | ||
|
|
d0bbd2b539 | ||
|
|
ee8952de10 | ||
|
|
134595a6b7 | ||
|
|
4ff46f1650 | ||
|
|
4779201d4c | ||
|
|
3a8643d83c | ||
|
|
806a49b822 | ||
|
|
95d74825ee | ||
|
|
e4960909ed | ||
|
|
6cb36aaf13 | ||
|
|
cb06e93650 | ||
|
|
e3a2f7a514 | ||
|
|
01b1e817d8 | ||
|
|
c3a5195575 | ||
|
|
99765c7bd5 | ||
|
|
8929f389f4 | ||
|
|
4141d91f1b | ||
|
|
90272c84d2 | ||
|
|
3006a8e58c | ||
|
|
52a9dbd45d | ||
|
|
b2fb55d2c1 | ||
|
|
a1c16d22d8 | ||
|
|
0e9504ee4d | ||
|
|
e8cad6fc20 | ||
|
|
bc261f7739 | ||
|
|
0b8983a86b | ||
|
|
5a61da3c53 | ||
|
|
800fe6244c | ||
|
|
9e1fec812c | ||
|
|
61632f9c97 | ||
|
|
f5e44129d8 | ||
|
|
3eaca924da | ||
|
|
da1c706334 | ||
|
|
3b726dfb1e | ||
|
|
d51e7f7e40 | ||
|
|
2551e0c291 | ||
|
|
2efd5c31ab | ||
|
|
1eacb8ff36 | ||
|
|
612446c3c9 | ||
|
|
e121e16ad9 | ||
|
|
23616b41be | ||
|
|
1778ba49b2 | ||
|
|
b6f2bd4703 | ||
|
|
5fd67224f6 | ||
|
|
c9d21dde0c | ||
|
|
de2c5aa068 | ||
|
|
ad01cecae6 | ||
|
|
75ef14c75b | ||
|
|
03a5a0eddb | ||
|
|
66befd35eb | ||
|
|
3cbad16c30 | ||
|
|
3bba7c5956 | ||
|
|
0daa84c583 | ||
|
|
92358a52c0 | ||
|
|
faf17e9e86 | ||
|
|
ef6efe94b4 | ||
|
|
819d7ea23e | ||
|
|
61ff192cfd | ||
|
|
ceb1b07ce2 | ||
|
|
90188d4358 | ||
|
|
35aa0ab4e7 | ||
|
|
14dd76db8b | ||
|
|
fb26dfad65 | ||
|
|
bedc5adb75 | ||
|
|
800b1f1520 | ||
|
|
a4571a80ae | ||
|
|
db94728a5b | ||
|
|
04352a670a | ||
|
|
fe6e3b013e | ||
|
|
a947a74194 | ||
|
|
06055ff62b | ||
|
|
45cb1562e5 | ||
|
|
2f89a16852 | ||
|
|
86956b8cac | ||
|
|
84fb3add33 | ||
|
|
122902968f | ||
|
|
b55c30065f | ||
|
|
9e2a58dd46 | ||
|
|
64722617c1 | ||
|
|
5845ddbdda | ||
|
|
bf9ce0df9b | ||
|
|
8aee2ec3a1 | ||
|
|
9ad31b2c81 | ||
|
|
374ed79a18 | ||
|
|
3d5f73e344 | ||
|
|
6761428a96 | ||
|
|
0a9b463eaa | ||
|
|
c219256fff | ||
|
|
7e48803dc5 | ||
|
|
d496b8a414 | ||
|
|
4825129560 | ||
|
|
adc54b2582 | ||
|
|
863567c9b6 | ||
|
|
102555023b | ||
|
|
f1a9eef531 | ||
|
|
5f007a5b0f | ||
|
|
9455141262 | ||
|
|
37e1379c88 | ||
|
|
55d597e519 | ||
|
|
da5ee5c951 | ||
|
|
b0bd9279fc | ||
|
|
90456339ca | ||
|
|
a653c8bad7 | ||
|
|
c4fa6cf458 | ||
|
|
268fc7b923 | ||
|
|
02604f5290 | ||
|
|
1dad7e86a0 | ||
|
|
838e3efbca | ||
|
|
3e353717f5 | ||
|
|
0a4b74b91a | ||
|
|
e69fbf3ccf | ||
|
|
0b2349d6bf | ||
|
|
3a8f04cf14 | ||
|
|
e941cf956f | ||
|
|
29f7bcf6f5 | ||
|
|
1cf1e0dc57 | ||
|
|
175283805e | ||
|
|
063c0405e8 | ||
|
|
947cb77753 | ||
|
|
28b3b305ea | ||
|
|
df85f13aea | ||
|
|
4292d3262e | ||
|
|
35d070ad29 |
@@ -28,4 +28,7 @@ LICENSE
|
||||
CONTRIBUTING.md
|
||||
dist
|
||||
.git
|
||||
config/
|
||||
migrations/
|
||||
config/
|
||||
build.ts
|
||||
tsconfig.json
|
||||
47
.github/DISCUSSION_TEMPLATE/feature-requests.yml
vendored
Normal file
47
.github/DISCUSSION_TEMPLATE/feature-requests.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Summary
|
||||
description: A clear and concise summary of the requested feature.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: |
|
||||
Why is this feature important?
|
||||
Explain the problem this feature would solve or what use case it would enable.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: |
|
||||
How would you like to see this feature implemented?
|
||||
Provide as much detail as possible about the desired behavior, configuration, or changes.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Describe any alternative solutions or workarounds you've thought about.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context, mockups, or screenshots about the feature request here.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before submitting, please:
|
||||
- Check if there is an existing issue for this feature.
|
||||
- Clearly explain the benefit and use case.
|
||||
- Be as specific as possible to help contributors evaluate and implement.
|
||||
51
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
Normal file
51
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Bug Report
|
||||
description: Create a bug report
|
||||
labels: []
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please fill out the relevant details below for your environment.
|
||||
value: |
|
||||
- OS Type & Version: (e.g., Ubuntu 22.04)
|
||||
- Pangolin Version:
|
||||
- Gerbil Version:
|
||||
- Traefik Version:
|
||||
- Newt Version:
|
||||
- Olm Version: (if applicable)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: |
|
||||
Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below.
|
||||
|
||||
If using code blocks, make sure syntax highlighting is correct and double-check that the rendered preview is not broken.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before posting the issue go through the steps you've written down to make sure the steps provided are detailed and clear.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Contributors should be able to follow the steps provided in order to reproduce the bug.
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Need help or have questions?
|
||||
url: https://github.com/orgs/fosrl/discussions
|
||||
about: Ask questions, get help, and discuss with other community members
|
||||
- name: Request a Feature
|
||||
url: https://github.com/orgs/fosrl/discussions/new?category=feature-requests
|
||||
about: Feature requests should be opened as discussions so others can upvote and comment
|
||||
120
.github/workflows/cicd.yml
vendored
120
.github/workflows/cicd.yml
vendored
@@ -1,34 +1,62 @@
|
||||
name: CI/CD Pipeline
|
||||
|
||||
# CI/CD workflow for building, publishing, mirroring, signing container images and building release binaries.
|
||||
# Actions are pinned to specific SHAs to reduce supply-chain risk. This workflow triggers on tag push events.
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # for GHCR push
|
||||
id-token: write # for Cosign Keyless (OIDC) Signing
|
||||
|
||||
# Required secrets:
|
||||
# - DOCKER_HUB_USERNAME / DOCKER_HUB_ACCESS_TOKEN: push to Docker Hub
|
||||
# - GITHUB_TOKEN: used for GHCR login and OIDC keyless signing
|
||||
# - COSIGN_PRIVATE_KEY / COSIGN_PASSWORD / COSIGN_PUBLIC_KEY: for key-based signing
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
- "[0-9]+.[0-9]+.[0-9]+.rc.[0-9]+"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build and Release
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: [self-hosted, linux, x64]
|
||||
# Job-level timeout to avoid runaway or stuck runs
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
# Target images
|
||||
DOCKERHUB_IMAGE: docker.io/fosrl/${{ github.event.repository.name }}
|
||||
GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: docker.io
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
- name: Extract tag name
|
||||
id: get-tag
|
||||
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
go-version: 1.24
|
||||
|
||||
@@ -37,18 +65,21 @@ jobs:
|
||||
TAG=${{ env.TAG }}
|
||||
sed -i "s/export const APP_VERSION = \".*\";/export const APP_VERSION = \"$TAG\";/" server/lib/consts.ts
|
||||
cat server/lib/consts.ts
|
||||
shell: bash
|
||||
|
||||
- name: Pull latest Gerbil version
|
||||
id: get-gerbil-tag
|
||||
run: |
|
||||
LATEST_TAG=$(curl -s https://api.github.com/repos/fosrl/gerbil/tags | jq -r '.[0].name')
|
||||
echo "LATEST_GERBIL_TAG=$LATEST_TAG" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Pull latest Badger version
|
||||
id: get-badger-tag
|
||||
run: |
|
||||
LATEST_TAG=$(curl -s https://api.github.com/repos/fosrl/badger/tags | jq -r '.[0].name')
|
||||
echo "LATEST_BADGER_TAG=$LATEST_TAG" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
|
||||
- name: Update install/main.go
|
||||
run: |
|
||||
@@ -60,6 +91,7 @@ jobs:
|
||||
sed -i "s/config.BadgerVersion = \".*\"/config.BadgerVersion = \"$BADGER_VERSION\"/" install/main.go
|
||||
echo "Updated install/main.go with Pangolin version $PANGOLIN_VERSION, Gerbil version $GERBIL_VERSION, and Badger version $BADGER_VERSION"
|
||||
cat install/main.go
|
||||
shell: bash
|
||||
|
||||
- name: Build installer
|
||||
working-directory: install
|
||||
@@ -67,12 +99,82 @@ jobs:
|
||||
make go-build-release
|
||||
|
||||
- name: Upload artifacts from /install/bin
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: install-bin
|
||||
path: install/bin/
|
||||
|
||||
- name: Build and push Docker images
|
||||
- name: Build and push Docker images (Docker Hub)
|
||||
run: |
|
||||
TAG=${{ env.TAG }}
|
||||
make build-release tag=$TAG
|
||||
echo "Built & pushed to: ${{ env.DOCKERHUB_IMAGE }}:${TAG}"
|
||||
shell: bash
|
||||
|
||||
- name: Install skopeo + jq
|
||||
# skopeo: copy/inspect images between registries
|
||||
# jq: JSON parsing tool used to extract digest values
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y skopeo jq
|
||||
skopeo --version
|
||||
shell: bash
|
||||
|
||||
- name: Login to GHCR
|
||||
run: |
|
||||
skopeo login ghcr.io -u "${{ github.actor }}" -p "${{ secrets.GITHUB_TOKEN }}"
|
||||
shell: bash
|
||||
|
||||
- name: Copy tag from Docker Hub to GHCR
|
||||
# Mirror the already-built image (all architectures) to GHCR so we can sign it
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG=${{ env.TAG }}
|
||||
echo "Copying ${{ env.DOCKERHUB_IMAGE }}:${TAG} -> ${{ env.GHCR_IMAGE }}:${TAG}"
|
||||
skopeo copy --all --retry-times 3 \
|
||||
docker://$DOCKERHUB_IMAGE:$TAG \
|
||||
docker://$GHCR_IMAGE:$TAG
|
||||
shell: bash
|
||||
|
||||
- name: Install cosign
|
||||
# cosign is used to sign and verify container images (key and keyless)
|
||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||
|
||||
- name: Dual-sign and verify (GHCR & Docker Hub)
|
||||
# Sign each image by digest using keyless (OIDC) and key-based signing,
|
||||
# then verify both the public key signature and the keyless OIDC signature.
|
||||
env:
|
||||
TAG: ${{ env.TAG }}
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
COSIGN_YES: "true"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
issuer="https://token.actions.githubusercontent.com"
|
||||
id_regex="^https://github.com/${{ github.repository }}/.+" # accept this repo (all workflows/refs)
|
||||
|
||||
for IMAGE in "${GHCR_IMAGE}" "${DOCKERHUB_IMAGE}"; do
|
||||
echo "Processing ${IMAGE}:${TAG}"
|
||||
|
||||
DIGEST="$(skopeo inspect --retry-times 3 docker://${IMAGE}:${TAG} | jq -r '.Digest')"
|
||||
REF="${IMAGE}@${DIGEST}"
|
||||
echo "Resolved digest: ${REF}"
|
||||
|
||||
echo "==> cosign sign (keyless) --recursive ${REF}"
|
||||
cosign sign --recursive "${REF}"
|
||||
|
||||
echo "==> cosign sign (key) --recursive ${REF}"
|
||||
cosign sign --key env://COSIGN_PRIVATE_KEY --recursive "${REF}"
|
||||
|
||||
echo "==> cosign verify (public key) ${REF}"
|
||||
cosign verify --key env://COSIGN_PUBLIC_KEY "${REF}" -o text
|
||||
|
||||
echo "==> cosign verify (keyless policy) ${REF}"
|
||||
cosign verify \
|
||||
--certificate-oidc-issuer "${issuer}" \
|
||||
--certificate-identity-regexp "${id_regex}" \
|
||||
"${REF}" -o text
|
||||
done
|
||||
shell: bash
|
||||
|
||||
16
.github/workflows/linting.yml
vendored
16
.github/workflows/linting.yml
vendored
@@ -1,5 +1,8 @@
|
||||
name: ESLint
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -18,17 +21,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm ci
|
||||
run: npm ci
|
||||
|
||||
- name: Create build file
|
||||
run: npm run set:oss
|
||||
|
||||
- name: Run ESLint
|
||||
run: |
|
||||
npx eslint . --ext .js,.jsx,.ts,.tsx
|
||||
run: npx eslint . --ext .js,.jsx,.ts,.tsx
|
||||
|
||||
132
.github/workflows/mirror.yaml
vendored
Normal file
132
.github/workflows/mirror.yaml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
name: Mirror & Sign (Docker Hub to GHCR)
|
||||
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write # for keyless OIDC
|
||||
|
||||
env:
|
||||
SOURCE_IMAGE: docker.io/fosrl/pangolin
|
||||
DEST_IMAGE: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}
|
||||
|
||||
jobs:
|
||||
mirror-and-dual-sign:
|
||||
runs-on: amd64-runner
|
||||
steps:
|
||||
- name: Install skopeo + jq
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y skopeo jq
|
||||
skopeo --version
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||
|
||||
- name: Input check
|
||||
run: |
|
||||
test -n "${SOURCE_IMAGE}" || (echo "SOURCE_IMAGE is empty" && exit 1)
|
||||
echo "Source : ${SOURCE_IMAGE}"
|
||||
echo "Target : ${DEST_IMAGE}"
|
||||
|
||||
# Auth for skopeo (containers-auth)
|
||||
- name: Skopeo login to GHCR
|
||||
run: |
|
||||
skopeo login ghcr.io -u "${{ github.actor }}" -p "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
# Auth for cosign (docker-config)
|
||||
- name: Docker login to GHCR (for cosign)
|
||||
run: |
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
|
||||
- name: List source tags
|
||||
run: |
|
||||
set -euo pipefail
|
||||
skopeo list-tags --retry-times 3 docker://"${SOURCE_IMAGE}" \
|
||||
| jq -r '.Tags[]' | sort -u > src-tags.txt
|
||||
echo "Found source tags: $(wc -l < src-tags.txt)"
|
||||
head -n 20 src-tags.txt || true
|
||||
|
||||
- name: List destination tags (skip existing)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if skopeo list-tags --retry-times 3 docker://"${DEST_IMAGE}" >/tmp/dst.json 2>/dev/null; then
|
||||
jq -r '.Tags[]' /tmp/dst.json | sort -u > dst-tags.txt
|
||||
else
|
||||
: > dst-tags.txt
|
||||
fi
|
||||
echo "Existing destination tags: $(wc -l < dst-tags.txt)"
|
||||
|
||||
- name: Mirror, dual-sign, and verify
|
||||
env:
|
||||
# keyless
|
||||
COSIGN_YES: "true"
|
||||
# key-based
|
||||
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
# verify
|
||||
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
copied=0; skipped=0; v_ok=0; errs=0
|
||||
|
||||
issuer="https://token.actions.githubusercontent.com"
|
||||
id_regex="^https://github.com/${{ github.repository }}/.+"
|
||||
|
||||
while read -r tag; do
|
||||
[ -z "$tag" ] && continue
|
||||
|
||||
if grep -Fxq "$tag" dst-tags.txt; then
|
||||
echo "::notice ::Skip (exists) ${DEST_IMAGE}:${tag}"
|
||||
skipped=$((skipped+1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "==> Copy ${SOURCE_IMAGE}:${tag} → ${DEST_IMAGE}:${tag}"
|
||||
if ! skopeo copy --all --retry-times 3 \
|
||||
docker://"${SOURCE_IMAGE}:${tag}" docker://"${DEST_IMAGE}:${tag}"; then
|
||||
echo "::warning title=Copy failed::${SOURCE_IMAGE}:${tag}"
|
||||
errs=$((errs+1)); continue
|
||||
fi
|
||||
copied=$((copied+1))
|
||||
|
||||
digest="$(skopeo inspect --retry-times 3 docker://"${DEST_IMAGE}:${tag}" | jq -r '.Digest')"
|
||||
ref="${DEST_IMAGE}@${digest}"
|
||||
|
||||
echo "==> cosign sign (keyless) --recursive ${ref}"
|
||||
if ! cosign sign --recursive "${ref}"; then
|
||||
echo "::warning title=Keyless sign failed::${ref}"
|
||||
errs=$((errs+1))
|
||||
fi
|
||||
|
||||
echo "==> cosign sign (key) --recursive ${ref}"
|
||||
if ! cosign sign --key env://COSIGN_PRIVATE_KEY --recursive "${ref}"; then
|
||||
echo "::warning title=Key sign failed::${ref}"
|
||||
errs=$((errs+1))
|
||||
fi
|
||||
|
||||
echo "==> cosign verify (public key) ${ref}"
|
||||
if ! cosign verify --key env://COSIGN_PUBLIC_KEY "${ref}" -o text; then
|
||||
echo "::warning title=Verify(pubkey) failed::${ref}"
|
||||
errs=$((errs+1))
|
||||
fi
|
||||
|
||||
echo "==> cosign verify (keyless policy) ${ref}"
|
||||
if ! cosign verify \
|
||||
--certificate-oidc-issuer "${issuer}" \
|
||||
--certificate-identity-regexp "${id_regex}" \
|
||||
"${ref}" -o text; then
|
||||
echo "::warning title=Verify(keyless) failed::${ref}"
|
||||
errs=$((errs+1))
|
||||
else
|
||||
v_ok=$((v_ok+1))
|
||||
fi
|
||||
done < src-tags.txt
|
||||
|
||||
echo "---- Summary ----"
|
||||
echo "Copied : $copied"
|
||||
echo "Skipped : $skipped"
|
||||
echo "Verified OK : $v_ok"
|
||||
echo "Errors : $errs"
|
||||
4
.github/workflows/stale-bot.yml
vendored
4
.github/workflows/stale-bot.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
- uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
|
||||
with:
|
||||
days-before-stale: 14
|
||||
days-before-close: 14
|
||||
@@ -34,4 +34,4 @@ jobs:
|
||||
operations-per-run: 100
|
||||
remove-stale-when-updated: true
|
||||
delete-branch: false
|
||||
enable-statistics: true
|
||||
enable-statistics: true
|
||||
|
||||
15
.github/workflows/test.yml
vendored
15
.github/workflows/test.yml
vendored
@@ -1,5 +1,8 @@
|
||||
name: Run Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
@@ -11,9 +14,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
@@ -24,7 +27,10 @@ jobs:
|
||||
run: npm ci
|
||||
|
||||
- name: Create database index.ts
|
||||
run: echo 'export * from "./sqlite";' > server/db/index.ts
|
||||
run: npm run set:sqlite
|
||||
|
||||
- name: Create build file
|
||||
run: npm run set:oss
|
||||
|
||||
- name: Generate database migrations
|
||||
run: npm run db:sqlite:generate
|
||||
@@ -32,6 +38,9 @@ jobs:
|
||||
- name: Apply database migrations
|
||||
run: npm run db:sqlite:push
|
||||
|
||||
- name: Test with tsc
|
||||
run: npx tsc --noEmit
|
||||
|
||||
- name: Start app in background
|
||||
run: nohup npm run dev &
|
||||
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -26,6 +26,10 @@ next-env.d.ts
|
||||
migrations
|
||||
tsconfig.tsbuildinfo
|
||||
config/config.yml
|
||||
config/config.saas.yml
|
||||
config/config.oss.yml
|
||||
config/config.enterprise.yml
|
||||
config/privateConfig.yml
|
||||
config/postgres
|
||||
config/postgres*
|
||||
config/openapi.yaml
|
||||
@@ -43,4 +47,6 @@ server/db/index.ts
|
||||
server/build.ts
|
||||
postgres/
|
||||
dynamic/
|
||||
certificates/
|
||||
*.mmdb
|
||||
scratch/
|
||||
tsconfig.json
|
||||
@@ -4,7 +4,7 @@ Contributions are welcome!
|
||||
|
||||
Please see the contribution and local development guide on the docs page before getting started:
|
||||
|
||||
https://docs.digpangolin.com/development/contributing
|
||||
https://docs.pangolin.net/development/contributing
|
||||
|
||||
### Licensing Considerations
|
||||
|
||||
|
||||
28
Dockerfile
28
Dockerfile
@@ -15,9 +15,29 @@ RUN echo "export * from \"./$DATABASE\";" > server/db/index.ts
|
||||
|
||||
RUN echo "export const build = \"$BUILD\" as any;" > server/build.ts
|
||||
|
||||
RUN if [ "$DATABASE" = "pg" ]; then npx drizzle-kit generate --dialect postgresql --schema ./server/db/pg/schema.ts --out init; else npx drizzle-kit generate --dialect $DATABASE --schema ./server/db/$DATABASE/schema.ts --out init; fi
|
||||
# Copy the appropriate TypeScript configuration based on build type
|
||||
RUN if [ "$BUILD" = "oss" ]; then cp tsconfig.oss.json tsconfig.json; \
|
||||
elif [ "$BUILD" = "saas" ]; then cp tsconfig.saas.json tsconfig.json; \
|
||||
elif [ "$BUILD" = "enterprise" ]; then cp tsconfig.enterprise.json tsconfig.json; \
|
||||
fi
|
||||
|
||||
# if the build is oss then remove the server/private directory
|
||||
RUN if [ "$BUILD" = "oss" ]; then rm -rf server/private; fi
|
||||
|
||||
RUN if [ "$DATABASE" = "pg" ]; then npx drizzle-kit generate --dialect postgresql --schema ./server/db/pg/schema --out init; else npx drizzle-kit generate --dialect $DATABASE --schema ./server/db/$DATABASE/schema --out init; fi
|
||||
|
||||
RUN mkdir -p dist
|
||||
RUN npm run next:build
|
||||
RUN node esbuild.mjs -e server/index.ts -o dist/server.mjs -b $BUILD
|
||||
RUN if [ "$DATABASE" = "pg" ]; then \
|
||||
node esbuild.mjs -e server/setup/migrationsPg.ts -o dist/migrations.mjs; \
|
||||
else \
|
||||
node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs; \
|
||||
fi
|
||||
|
||||
# test to make sure the build output is there and error if not
|
||||
RUN test -f dist/server.mjs
|
||||
|
||||
RUN npm run build:$DATABASE
|
||||
RUN npm run build:cli
|
||||
|
||||
FROM node:22-alpine AS runner
|
||||
@@ -25,10 +45,11 @@ FROM node:22-alpine AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# Curl used for the health checks
|
||||
RUN apk add --no-cache curl
|
||||
RUN apk add --no-cache curl tzdata
|
||||
|
||||
# COPY package.json package-lock.json ./
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm ci --omit=dev && npm cache clean --force
|
||||
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
@@ -40,7 +61,6 @@ COPY ./cli/wrapper.sh /usr/local/bin/pangctl
|
||||
RUN chmod +x /usr/local/bin/pangctl ./dist/cli.mjs
|
||||
|
||||
COPY server/db/names.json ./dist/names.json
|
||||
|
||||
COPY public ./public
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
|
||||
31
LICENSE
31
LICENSE
@@ -1,3 +1,34 @@
|
||||
Copyright (c) 2025 Fossorial, Inc.
|
||||
|
||||
Portions of this software are licensed as follows:
|
||||
|
||||
* All files that include a header specifying they are licensed under the
|
||||
"Fossorial Commercial License" are governed by the Fossorial Commercial
|
||||
License terms. The specific terms applicable to each customer depend on the
|
||||
commercial license tier agreed upon in writing with Fossorial, Inc.
|
||||
Unauthorized use, copying, modification, or distribution is strictly
|
||||
prohibited.
|
||||
|
||||
* All files that include a header specifying they are licensed under the GNU
|
||||
Affero General Public License, Version 3 ("AGPL-3"), are governed by the
|
||||
AGPL-3 terms. A full copy of the AGPL-3 license is provided below. However,
|
||||
these files are also available under the Fossorial Commercial License if a
|
||||
separate commercial license agreement has been executed between the customer
|
||||
and Fossorial, Inc.
|
||||
|
||||
* All files without a license header are, by default, licensed under the GNU
|
||||
Affero General Public License, Version 3 (AGPL-3). These files may also be
|
||||
made available under the Fossorial Commercial License upon agreement with
|
||||
Fossorial, Inc.
|
||||
|
||||
* All third-party components included in this repository are licensed under
|
||||
their respective original licenses, as provided by their authors.
|
||||
|
||||
Please consult the header of each individual file to determine the applicable
|
||||
license. For AGPL-3 licensed files, dual-licensing under the Fossorial
|
||||
Commercial License is available subject to written agreement with Fossorial,
|
||||
Inc.
|
||||
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
|
||||
72
Makefile
72
Makefile
@@ -1,14 +1,78 @@
|
||||
.PHONY: build build-pg build-release build-arm build-x86 test clean
|
||||
|
||||
major_tag := $(shell echo $(tag) | cut -d. -f1)
|
||||
minor_tag := $(shell echo $(tag) | cut -d. -f1,2)
|
||||
build-release:
|
||||
@if [ -z "$(tag)" ]; then \
|
||||
echo "Error: tag is required. Usage: make build-release tag=<tag>"; \
|
||||
exit 1; \
|
||||
fi
|
||||
docker buildx build --build-arg DATABASE=sqlite --platform linux/arm64,linux/amd64 -t fosrl/pangolin:latest --push .
|
||||
docker buildx build --build-arg DATABASE=sqlite --platform linux/arm64,linux/amd64 -t fosrl/pangolin:$(tag) --push .
|
||||
docker buildx build --build-arg DATABASE=pg --platform linux/arm64,linux/amd64 -t fosrl/pangolin:postgresql-latest --push .
|
||||
docker buildx build --build-arg DATABASE=pg --platform linux/arm64,linux/amd64 -t fosrl/pangolin:postgresql-$(tag) --push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=oss \
|
||||
--build-arg DATABASE=sqlite \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:latest \
|
||||
--tag fosrl/pangolin:$(major_tag) \
|
||||
--tag fosrl/pangolin:$(minor_tag) \
|
||||
--tag fosrl/pangolin:$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=oss \
|
||||
--build-arg DATABASE=pg \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:postgresql-latest \
|
||||
--tag fosrl/pangolin:postgresql-$(major_tag) \
|
||||
--tag fosrl/pangolin:postgresql-$(minor_tag) \
|
||||
--tag fosrl/pangolin:postgresql-$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=enterprise \
|
||||
--build-arg DATABASE=sqlite \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:ee-latest \
|
||||
--tag fosrl/pangolin:ee-$(major_tag) \
|
||||
--tag fosrl/pangolin:ee-$(minor_tag) \
|
||||
--tag fosrl/pangolin:ee-$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=enterprise \
|
||||
--build-arg DATABASE=pg \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:ee-postgresql-latest \
|
||||
--tag fosrl/pangolin:ee-postgresql-$(major_tag) \
|
||||
--tag fosrl/pangolin:ee-postgresql-$(minor_tag) \
|
||||
--tag fosrl/pangolin:ee-postgresql-$(tag) \
|
||||
--push .
|
||||
|
||||
build-rc:
|
||||
@if [ -z "$(tag)" ]; then \
|
||||
echo "Error: tag is required. Usage: make build-release tag=<tag>"; \
|
||||
exit 1; \
|
||||
fi
|
||||
docker buildx build \
|
||||
--build-arg BUILD=oss \
|
||||
--build-arg DATABASE=sqlite \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=oss \
|
||||
--build-arg DATABASE=pg \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:postgresql-$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=enterprise \
|
||||
--build-arg DATABASE=sqlite \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:ee-$(tag) \
|
||||
--push .
|
||||
docker buildx build \
|
||||
--build-arg BUILD=enterprise \
|
||||
--build-arg DATABASE=pg \
|
||||
--platform linux/arm64,linux/amd64 \
|
||||
--tag fosrl/pangolin:ee-postgresql-$(tag) \
|
||||
--push .
|
||||
|
||||
build-arm:
|
||||
docker buildx build --platform linux/arm64 -t fosrl/pangolin:latest .
|
||||
|
||||
143
README.md
143
README.md
@@ -1,146 +1,95 @@
|
||||
<div align="center">
|
||||
<h2>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="public/logo/word_mark_white.png">
|
||||
<img alt="Pangolin Logo" src="public/logo/word_mark_black.png" width="250">
|
||||
<a href="https://pangolin.net/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="public/logo/word_mark_white.png">
|
||||
<img alt="Pangolin Logo" src="public/logo/word_mark_black.png" width="350">
|
||||
</picture>
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<h4 align="center">Secure gateway to your private networks</h4>
|
||||
<div align="center">
|
||||
|
||||
_Pangolin tunnels your services to the internet so you can access anything from anywhere._
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<h5>
|
||||
<a href="https://digpangolin.com">
|
||||
<a href="https://pangolin.net/">
|
||||
Website
|
||||
</a>
|
||||
<span> | </span>
|
||||
<a href="https://docs.digpangolin.com/self-host/quick-install-managed">
|
||||
Quick Install Guide
|
||||
<a href="https://docs.pangolin.net/">
|
||||
Documentation
|
||||
</a>
|
||||
<span> | </span>
|
||||
<a href="mailto:contact@fossorial.io">
|
||||
<a href="mailto:contact@pangolin.net">
|
||||
Contact Us
|
||||
</a>
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://discord.gg/HCJR8Xhme4)
|
||||
[](https://pangolin.net/slack)
|
||||
[](https://hub.docker.com/r/fosrl/pangolin)
|
||||

|
||||
[](https://discord.gg/HCJR8Xhme4)
|
||||
[](https://www.youtube.com/@fossorial-app)
|
||||
[](https://www.youtube.com/@fossorial-app)
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<strong>
|
||||
Start testing Pangolin at <a href="https://pangolin.fossorial.io/auth/signup">pangolin.fossorial.io</a>
|
||||
Start testing Pangolin at <a href="https://app.pangolin.net/auth/signup">app.pangolin.net</a>
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
Pangolin is a self-hosted tunneled reverse proxy server with identity and access control, designed to securely expose private resources on distributed networks. Acting as a central hub, it connects isolated networks — even those behind restrictive firewalls — through encrypted tunnels, enabling easy access to remote services without opening ports.
|
||||
Pangolin is a self-hosted tunneled reverse proxy server with identity and context aware access control, designed to easily expose and protect applications running anywhere. Pangolin acts as a central hub and connects isolated networks — even those behind restrictive firewalls — through encrypted tunnels, enabling easy access to remote services without opening ports or requiring a VPN.
|
||||
|
||||
<img src="public/screenshots/hero.png" alt="Preview"/>
|
||||
## Installation
|
||||
|
||||

|
||||
- Check out the [quick install guide](https://docs.pangolin.net/self-host/quick-install) for how to install and set up Pangolin.
|
||||
- Install from the [DigitalOcean marketplace](https://marketplace.digitalocean.com/apps/pangolin-ce-1?refcode=edf0480eeb81) for a one-click pre-configured installer.
|
||||
|
||||
## Key Features
|
||||
|
||||
### Reverse Proxy Through WireGuard Tunnel
|
||||
|
||||
- Expose private resources on your network **without opening ports** (firewall punching).
|
||||
- Secure and easy to configure private connectivity via a custom **user space WireGuard client**, [Newt](https://github.com/fosrl/newt).
|
||||
- Built-in support for any WireGuard client.
|
||||
- Automated **SSL certificates** (https) via [LetsEncrypt](https://letsencrypt.org/).
|
||||
- Support for HTTP/HTTPS and **raw TCP/UDP services**.
|
||||
- Load balancing.
|
||||
- Extend functionality with existing [Traefik](https://github.com/traefik/traefik) plugins, such as [CrowdSec](https://plugins.traefik.io/plugins/6335346ca4caa9ddeffda116/crowdsec-bouncer-traefik-plugin) and [Geoblock](https://github.com/PascalMinder/geoblock).
|
||||
- **Automatically install and configure Crowdsec via Pangolin's installer script.**
|
||||
- Attach as many sites to the central server as you wish.
|
||||
|
||||
### Identity & Access Management
|
||||
|
||||
- Centralized authentication system using platform SSO. **Users will only have to manage one login.**
|
||||
- **Define access control rules for IPs, IP ranges, and URL paths per resource.**
|
||||
- TOTP with backup codes for two-factor authentication.
|
||||
- Create organizations, each with multiple sites, users, and roles.
|
||||
- **Role-based access control** to manage resource access permissions.
|
||||
- Additional authentication options include:
|
||||
- Email whitelisting with **one-time passcodes.**
|
||||
- **Temporary, self-destructing share links.**
|
||||
- Resource specific pin codes.
|
||||
- Resource specific passwords.
|
||||
- Passkeys
|
||||
- External identity provider (IdP) support with OAuth2/OIDC, such as Authentik, Keycloak, Okta, and others.
|
||||
- Auto-provision users and roles from your IdP.
|
||||
|
||||
<img src="public/auth-diagram1.png" alt="Auth and diagram"/>
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Manage Access to Internal Apps
|
||||
|
||||
- Grant users access to your apps from anywhere using just a web browser. No client software required.
|
||||
|
||||
### Developers and DevOps
|
||||
|
||||
- Expose and test internal tools and dashboards like **Grafana**. Bring localhost or private IPs online for easy access.
|
||||
|
||||
### Secure API Gateway
|
||||
|
||||
- One application load balancer across multiple clouds and on-premises.
|
||||
|
||||
### IoT and Edge Devices
|
||||
|
||||
- Easily expose **IoT devices**, **edge servers**, or **Raspberry Pi** to the internet for field equipment monitoring.
|
||||
|
||||
<img src="public/screenshots/sites.png" alt="Sites"/>
|
||||
<img src="public/screenshots/hero.png" />
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Fully Self Hosted
|
||||
| <img width=500 /> | Description |
|
||||
|-----------------|--------------|
|
||||
| **Self-Host: Community Edition** | Free, open source, and licensed under AGPL-3. |
|
||||
| **Self-Host: Enterprise Edition** | Licensed under Fossorial Commercial License. Free for personal and hobbyist use, and for businesses earning under \$100K USD annually. |
|
||||
| **Pangolin Cloud** | Fully managed service with instant setup and pay-as-you-go pricing — no infrastructure required. Or, self-host your own [remote node](https://docs.pangolin.net/manage/remote-node/nodes) and connect to our control plane. |
|
||||
|
||||
Host the full application on your own server or on the cloud with a VPS. Take a look at the [documentation](https://docs.digpangolin.com/self-host/quick-install) to get started.
|
||||
## Key Features
|
||||
|
||||
> Many of our users have had a great experience with [RackNerd](https://my.racknerd.com/aff.php?aff=13788). Depending on promotions, you can get a [**VPS with 1 vCPU, 1GB RAM, and ~20GB SSD for just around $12/year**](https://my.racknerd.com/aff.php?aff=13788&pid=912). That's a great deal!
|
||||
Pangolin packages everything you need for seamless application access and exposure into one cohesive platform.
|
||||
|
||||
### Pangolin Cloud
|
||||
| <img width=500 /> | <img width=500 /> |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
|
||||
| **Manage applications in one place**<br /><br /> Pangolin provides a unified dashboard where you can monitor, configure, and secure all of your services regardless of where they are hosted. | <img src="public/screenshots/hero.png" width=500 /><tr></tr> |
|
||||
| **Reverse proxy across networks anywhere**<br /><br />Route traffic via tunnels to any private network. Pangolin works like a reverse proxy that spans multiple networks and handles routing, load balancing, health checking, and more to the right services on the other end. | <img src="public/screenshots/sites.png" width=500 /><tr></tr> |
|
||||
| **Enforce identity and context aware rules**<br /><br />Protect your applications with identity and context aware rules such as SSO, OIDC, PIN, password, temporary share links, geolocation, IP, and more. | <img src="public/auth-diagram1.png" width=500 /><tr></tr> |
|
||||
| **Quickly connect Pangolin sites**<br /><br />Pangolin's lightweight [Newt](https://github.com/fosrl/newt) client runs in userspace and can run anywhere. Use it as a site connector to route traffic to backends across all of your environments. | <img src="public/clip.gif" width=500 /><tr></tr> |
|
||||
|
||||
Easy to use with simple [pay as you go pricing](https://digpangolin.com/pricing). [Check it out here](https://pangolin.fossorial.io/auth/signup).
|
||||
## Get Started
|
||||
|
||||
- Everything you get with self hosted Pangolin, but fully managed for you.
|
||||
### Check out the docs
|
||||
|
||||
### Managed & High Availability
|
||||
We encourage everyone to read the full documentation first, which is
|
||||
available at [docs.pangolin.net](https://docs.pangolin.net). This README provides only a very brief subset of
|
||||
the docs to illustrate some basic ideas.
|
||||
|
||||
Managed control plane, your infrastructure
|
||||
### Sign up and try now
|
||||
|
||||
- We manage database and control plane.
|
||||
- You self-host lightweight exit-node.
|
||||
- Traffic flows through your infra.
|
||||
- We coordinate failover between your nodes or to Cloud when things go bad.
|
||||
|
||||
Try it out using [Pangolin Cloud](https://pangolin.fossorial.io)
|
||||
|
||||
### Full Enterprise On-Premises
|
||||
|
||||
[Contact us](mailto:numbat@fossorial.io) for a full distributed and enterprise deployments on your infrastructure controlled by your team.
|
||||
|
||||
## Project Development / Roadmap
|
||||
|
||||
We want to hear your feature requests! Add them to the [discussion board](https://github.com/orgs/fosrl/discussions/categories/feature-requests).
|
||||
For Pangolin's managed service, you will first need to create an account at
|
||||
[app.pangolin.net](https://app.pangolin.net). We have a generous free tier to get started.
|
||||
|
||||
## Licensing
|
||||
|
||||
Pangolin is dual licensed under the AGPL-3 and the Fossorial Commercial license. For inquiries about commercial licensing, please contact us at [numbat@fossorial.io](mailto:numbat@fossorial.io).
|
||||
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).
|
||||
|
||||
## Contributions
|
||||
|
||||
Looking for something to contribute? Take a look at issues marked with [help wanted](https://github.com/fosrl/pangolin/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22). Also take a look through the freature requests in Discussions - any are available and some are marked as a good first issue.
|
||||
|
||||
Please see [CONTRIBUTING](./CONTRIBUTING.md) in the repository for guidelines and best practices.
|
||||
|
||||
Please post bug reports and other functional issues in the [Issues](https://github.com/fosrl/pangolin/issues) section of the repository.
|
||||
---
|
||||
|
||||
WireGuard® is a registered trademark of Jason A. Donenfeld.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
If you discover a security vulnerability, please follow the steps below to responsibly disclose it to us:
|
||||
|
||||
1. **Do not create a public GitHub issue or discussion post.** This could put the security of other users at risk.
|
||||
2. Send a detailed report to [security@fossorial.io](mailto:security@fossorial.io) or send a **private** message to a maintainer on [Discord](https://discord.gg/HCJR8Xhme4). Include:
|
||||
2. Send a detailed report to [security@pangolin.net](mailto:security@pangolin.net) or send a **private** message to a maintainer on [Discord](https://discord.gg/HCJR8Xhme4). Include:
|
||||
|
||||
- Description and location of the vulnerability.
|
||||
- Potential impact of the vulnerability.
|
||||
|
||||
72
blueprint.py
Normal file
72
blueprint.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import requests
|
||||
import yaml
|
||||
import json
|
||||
import base64
|
||||
|
||||
# The file path for the YAML file to be read
|
||||
# You can change this to the path of your YAML file
|
||||
YAML_FILE_PATH = 'blueprint.yaml'
|
||||
|
||||
# The API endpoint and headers from the curl request
|
||||
API_URL = 'http://api.pangolin.net/v1/org/test/blueprint'
|
||||
HEADERS = {
|
||||
'accept': '*/*',
|
||||
'Authorization': 'Bearer <your_token_here>',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
def convert_and_send(file_path, url, headers):
|
||||
"""
|
||||
Reads a YAML file, converts its content to a JSON payload,
|
||||
and sends it via a PUT request to a specified URL.
|
||||
"""
|
||||
try:
|
||||
# Read the YAML file content
|
||||
with open(file_path, 'r') as file:
|
||||
yaml_content = file.read()
|
||||
|
||||
# Parse the YAML string to a Python dictionary
|
||||
# This will be used to ensure the YAML is valid before sending
|
||||
parsed_yaml = yaml.safe_load(yaml_content)
|
||||
|
||||
# convert the parsed YAML to a JSON string
|
||||
json_payload = json.dumps(parsed_yaml)
|
||||
print("Converted JSON payload:")
|
||||
print(json_payload)
|
||||
|
||||
# Encode the JSON string to Base64
|
||||
encoded_json = base64.b64encode(json_payload.encode('utf-8')).decode('utf-8')
|
||||
|
||||
# Create the final payload with the base64 encoded data
|
||||
final_payload = {
|
||||
"blueprint": encoded_json
|
||||
}
|
||||
|
||||
print("Sending the following Base64 encoded JSON payload:")
|
||||
print(final_payload)
|
||||
print("-" * 20)
|
||||
|
||||
# Make the PUT request with the base64 encoded payload
|
||||
response = requests.put(url, headers=headers, json=final_payload)
|
||||
|
||||
# Print the API response for debugging
|
||||
print(f"API Response Status Code: {response.status_code}")
|
||||
print("API Response Content:")
|
||||
print(response.text)
|
||||
|
||||
# Raise an exception for bad status codes (4xx or 5xx)
|
||||
response.raise_for_status()
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: The file '{file_path}' was not found.")
|
||||
except yaml.YAMLError as e:
|
||||
print(f"Error parsing YAML file: {e}")
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"An error occurred during the API request: {e}")
|
||||
except Exception as e:
|
||||
print(f"An unexpected error occurred: {e}")
|
||||
|
||||
# Run the function
|
||||
if __name__ == "__main__":
|
||||
convert_and_send(YAML_FILE_PATH, API_URL, HEADERS)
|
||||
|
||||
69
blueprint.yaml
Normal file
69
blueprint.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
client-resources:
|
||||
client-resource-nice-id-uno:
|
||||
name: this is my resource
|
||||
protocol: tcp
|
||||
proxy-port: 3001
|
||||
hostname: localhost
|
||||
internal-port: 3000
|
||||
site: lively-yosemite-toad
|
||||
client-resource-nice-id-duce:
|
||||
name: this is my resource
|
||||
protocol: udp
|
||||
proxy-port: 3000
|
||||
hostname: localhost
|
||||
internal-port: 3000
|
||||
site: lively-yosemite-toad
|
||||
|
||||
proxy-resources:
|
||||
resource-nice-id-uno:
|
||||
name: this is my resource
|
||||
protocol: http
|
||||
full-domain: duce.test.example.com
|
||||
host-header: example.com
|
||||
tls-server-name: example.com
|
||||
# auth:
|
||||
# pincode: 123456
|
||||
# password: sadfasdfadsf
|
||||
# sso-enabled: true
|
||||
# sso-roles:
|
||||
# - Member
|
||||
# sso-users:
|
||||
# - owen@pangolin.net
|
||||
# whitelist-users:
|
||||
# - owen@pangolin.net
|
||||
headers:
|
||||
- name: X-Example-Header
|
||||
value: example-value
|
||||
- name: X-Another-Header
|
||||
value: another-value
|
||||
rules:
|
||||
- action: allow
|
||||
match: ip
|
||||
value: 1.1.1.1
|
||||
- action: deny
|
||||
match: cidr
|
||||
value: 2.2.2.2/32
|
||||
- action: pass
|
||||
match: path
|
||||
value: /admin
|
||||
targets:
|
||||
- site: lively-yosemite-toad
|
||||
path: /path
|
||||
pathMatchType: prefix
|
||||
hostname: localhost
|
||||
method: http
|
||||
port: 8000
|
||||
- site: slim-alpine-chipmunk
|
||||
hostname: localhost
|
||||
path: /yoman
|
||||
pathMatchType: exact
|
||||
method: http
|
||||
port: 8001
|
||||
resource-nice-id-duce:
|
||||
name: this is other resource
|
||||
protocol: tcp
|
||||
proxy-port: 3000
|
||||
targets:
|
||||
- site: lively-yosemite-toad
|
||||
hostname: localhost
|
||||
port: 3000
|
||||
17
bruno/API Keys/Create API Key.bru
Normal file
17
bruno/API Keys/Create API Key.bru
Normal file
@@ -0,0 +1,17 @@
|
||||
meta {
|
||||
name: Create API Key
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
put {
|
||||
url: http://localhost:3000/api/v1/api-key
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"isRoot": true
|
||||
}
|
||||
}
|
||||
11
bruno/API Keys/Delete API Key.bru
Normal file
11
bruno/API Keys/Delete API Key.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: Delete API Key
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
delete {
|
||||
url: http://localhost:3000/api/v1/api-key/dm47aacqxxn3ubj
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
11
bruno/API Keys/List API Key Actions.bru
Normal file
11
bruno/API Keys/List API Key Actions.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: List API Key Actions
|
||||
type: http
|
||||
seq: 6
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3000/api/v1/api-key/ex0izu2c37fjz9x/actions
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
11
bruno/API Keys/List Org API Keys.bru
Normal file
11
bruno/API Keys/List Org API Keys.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: List Org API Keys
|
||||
type: http
|
||||
seq: 4
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3000/api/v1/org/home-lab/api-keys
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
11
bruno/API Keys/List Root API Keys.bru
Normal file
11
bruno/API Keys/List Root API Keys.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: List Root API Keys
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3000/api/v1/root/api-keys
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
17
bruno/API Keys/Set API Key Actions.bru
Normal file
17
bruno/API Keys/Set API Key Actions.bru
Normal file
@@ -0,0 +1,17 @@
|
||||
meta {
|
||||
name: Set API Key Actions
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:3000/api/v1/api-key/ex0izu2c37fjz9x/actions
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"actionIds": ["listSites"]
|
||||
}
|
||||
}
|
||||
17
bruno/API Keys/Set API Key Orgs.bru
Normal file
17
bruno/API Keys/Set API Key Orgs.bru
Normal file
@@ -0,0 +1,17 @@
|
||||
meta {
|
||||
name: Set API Key Orgs
|
||||
type: http
|
||||
seq: 7
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:3000/api/v1/api-key/ex0izu2c37fjz9x/orgs
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"orgIds": ["home-lab"]
|
||||
}
|
||||
}
|
||||
3
bruno/API Keys/folder.bru
Normal file
3
bruno/API Keys/folder.bru
Normal file
@@ -0,0 +1,3 @@
|
||||
meta {
|
||||
name: API Keys
|
||||
}
|
||||
@@ -5,14 +5,14 @@ meta {
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:3000/api/v1/auth/login
|
||||
url: http://localhost:4000/api/v1/auth/login
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"email": "admin@fosrl.io",
|
||||
"email": "owen@pangolin.net",
|
||||
"password": "Password123!"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ meta {
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:3000/api/v1/auth/logout
|
||||
url: http://localhost:4000/api/v1/auth/logout
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ post {
|
||||
|
||||
body:json {
|
||||
{
|
||||
"email": "milo@fossorial.io"
|
||||
"email": "milo@pangolin.net"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ put {
|
||||
|
||||
body:json {
|
||||
{
|
||||
"email": "numbat@fossorial.io",
|
||||
"email": "numbat@pangolin.net",
|
||||
"password": "Password123!"
|
||||
}
|
||||
}
|
||||
|
||||
22
bruno/IDP/Create OIDC Provider.bru
Normal file
22
bruno/IDP/Create OIDC Provider.bru
Normal file
@@ -0,0 +1,22 @@
|
||||
meta {
|
||||
name: Create OIDC Provider
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
put {
|
||||
url: http://localhost:3000/api/v1/org/home-lab/idp/oidc
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"clientId": "JJoSvHCZcxnXT2sn6CObj6a21MuKNRXs3kN5wbys",
|
||||
"clientSecret": "2SlGL2wOGgMEWLI9yUuMAeFxre7qSNJVnXMzyepdNzH1qlxYnC4lKhhQ6a157YQEkYH3vm40KK4RCqbYiF8QIweuPGagPX3oGxEj2exwutoXFfOhtq4hHybQKoFq01Z3",
|
||||
"authUrl": "http://localhost:9000/application/o/authorize/",
|
||||
"tokenUrl": "http://localhost:9000/application/o/token/",
|
||||
"scopes": ["email", "openid", "profile"],
|
||||
"userIdentifier": "email"
|
||||
}
|
||||
}
|
||||
11
bruno/IDP/Generate OIDC URL.bru
Normal file
11
bruno/IDP/Generate OIDC URL.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: Generate OIDC URL
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3000/api/v1
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
3
bruno/IDP/folder.bru
Normal file
3
bruno/IDP/folder.bru
Normal file
@@ -0,0 +1,3 @@
|
||||
meta {
|
||||
name: IDP
|
||||
}
|
||||
11
bruno/Internal/Traefik Config.bru
Normal file
11
bruno/Internal/Traefik Config.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: Traefik Config
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3001/api/v1/traefik-config
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
3
bruno/Internal/folder.bru
Normal file
3
bruno/Internal/folder.bru
Normal file
@@ -0,0 +1,3 @@
|
||||
meta {
|
||||
name: Internal
|
||||
}
|
||||
11
bruno/Remote Exit Node/createRemoteExitNode.bru
Normal file
11
bruno/Remote Exit Node/createRemoteExitNode.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: createRemoteExitNode
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
put {
|
||||
url: http://localhost:4000/api/v1/org/org_i21aifypnlyxur2/remote-exit-node
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
11
bruno/Test.bru
Normal file
11
bruno/Test.bru
Normal file
@@ -0,0 +1,11 @@
|
||||
meta {
|
||||
name: Test
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:3000/api/v1
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "Pangolin",
|
||||
"name": "Pangolin Saas",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
|
||||
@@ -90,7 +90,8 @@ export const setAdminCredentials: CommandModule<{}, SetAdminCredentialsArgs> = {
|
||||
passwordHash,
|
||||
dateCreated: moment().toISOString(),
|
||||
serverAdmin: true,
|
||||
emailVerified: true
|
||||
emailVerified: true,
|
||||
lastPasswordChange: new Date().getTime()
|
||||
});
|
||||
|
||||
console.log("Server admin created");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# To see all available options, please visit the docs:
|
||||
# https://docs.digpangolin.com/self-host/advanced/config-file
|
||||
# https://docs.pangolin.net/self-host/advanced/config-file
|
||||
|
||||
app:
|
||||
dashboard_url: http://localhost:3002
|
||||
|
||||
15
docker-compose.drizzle.yml
Normal file
15
docker-compose.drizzle.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
drizzle-gateway:
|
||||
image: ghcr.io/drizzle-team/gateway:latest
|
||||
ports:
|
||||
- "4984:4983"
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
- STORE_PATH=/app
|
||||
- DATABASE_URL=postgresql://postgres:password@db:5432/postgres
|
||||
volumes:
|
||||
- drizzle-gateway-data:/app
|
||||
|
||||
volumes:
|
||||
drizzle-gateway-data:
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
pangolin:
|
||||
condition: service_healthy
|
||||
command:
|
||||
- --reachableAt=http://gerbil:3003
|
||||
- --reachableAt=http://gerbil:3004
|
||||
- --generateAndSaveKeyTo=/var/config/key
|
||||
- --remoteConfig=http://pangolin:3001/api/v1/
|
||||
volumes:
|
||||
|
||||
@@ -12,3 +12,10 @@ services:
|
||||
ports:
|
||||
- "5432:5432" # Map host port 5432 to container port 5432
|
||||
restart: no
|
||||
|
||||
redis:
|
||||
image: redis:latest # Use the latest Redis image
|
||||
container_name: dev_redis # Name your Redis container
|
||||
ports:
|
||||
- "6379:6379" # Map host port 6379 to container port 6379
|
||||
restart: no
|
||||
@@ -1,32 +0,0 @@
|
||||
name: pangolin
|
||||
services:
|
||||
gerbil:
|
||||
image: gerbil
|
||||
container_name: gerbil
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- --reachableAt=http://localhost:3003
|
||||
- --generateAndSaveKeyTo=/var/config/key
|
||||
- --remoteConfig=http://localhost:3001/api/v1/
|
||||
- --sni-port=443
|
||||
volumes:
|
||||
- ./config/:/var/config
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
|
||||
traefik:
|
||||
image: docker.io/traefik:v3.4.1
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
command:
|
||||
- --configFile=/etc/traefik/traefik_config.yml
|
||||
volumes:
|
||||
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
|
||||
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
|
||||
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
|
||||
- ./certificates:/var/certificates:ro
|
||||
- ./dynamic:/var/dynamic:ro
|
||||
|
||||
@@ -13,7 +13,6 @@ services:
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- ENVIRONMENT=dev
|
||||
- DB_TYPE=pg
|
||||
volumes:
|
||||
# Mount source code for hot reload
|
||||
- ./src:/app/src
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
import path from "path";
|
||||
|
||||
const schema = [
|
||||
path.join("server", "db", "pg", "schema"),
|
||||
];
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "postgresql",
|
||||
schema: [path.join("server", "db", "pg", "schema.ts")],
|
||||
schema: schema,
|
||||
out: path.join("server", "migrations"),
|
||||
verbose: true,
|
||||
dbCredentials: {
|
||||
|
||||
@@ -2,9 +2,13 @@ import { APP_PATH } from "@server/lib/consts";
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
import path from "path";
|
||||
|
||||
const schema = [
|
||||
path.join("server", "db", "sqlite", "schema"),
|
||||
];
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "sqlite",
|
||||
schema: path.join("server", "db", "sqlite", "schema.ts"),
|
||||
schema: schema,
|
||||
out: path.join("server", "migrations"),
|
||||
verbose: true,
|
||||
dbCredentials: {
|
||||
|
||||
214
esbuild.mjs
214
esbuild.mjs
@@ -2,8 +2,9 @@ import esbuild from "esbuild";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { nodeExternalsPlugin } from "esbuild-node-externals";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
// import { glob } from "glob";
|
||||
// import path from "path";
|
||||
|
||||
const banner = `
|
||||
// patch __dirname
|
||||
@@ -18,7 +19,7 @@ const require = topLevelCreateRequire(import.meta.url);
|
||||
`;
|
||||
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.usage("Usage: $0 -entry [string] -out [string]")
|
||||
.usage("Usage: $0 -entry [string] -out [string] -build [string]")
|
||||
.option("entry", {
|
||||
alias: "e",
|
||||
describe: "Entry point file",
|
||||
@@ -31,6 +32,13 @@ const argv = yargs(hideBin(process.argv))
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("build", {
|
||||
alias: "b",
|
||||
describe: "Build type (oss, saas, enterprise)",
|
||||
type: "string",
|
||||
choices: ["oss", "saas", "enterprise"],
|
||||
default: "oss",
|
||||
})
|
||||
.help()
|
||||
.alias("help", "h").argv;
|
||||
|
||||
@@ -46,27 +54,223 @@ function getPackagePaths() {
|
||||
return ["package.json"];
|
||||
}
|
||||
|
||||
// Plugin to guard against bad imports from #private
|
||||
function privateImportGuardPlugin() {
|
||||
return {
|
||||
name: "private-import-guard",
|
||||
setup(build) {
|
||||
const violations = [];
|
||||
|
||||
build.onResolve({ filter: /^#private\// }, (args) => {
|
||||
const importingFile = args.importer;
|
||||
|
||||
// Check if the importing file is NOT in server/private
|
||||
const normalizedImporter = path.normalize(importingFile);
|
||||
const isInServerPrivate = normalizedImporter.includes(path.normalize("server/private"));
|
||||
|
||||
if (!isInServerPrivate) {
|
||||
const violation = {
|
||||
file: importingFile,
|
||||
importPath: args.path,
|
||||
resolveDir: args.resolveDir
|
||||
};
|
||||
violations.push(violation);
|
||||
|
||||
console.log(`PRIVATE IMPORT VIOLATION:`);
|
||||
console.log(` File: ${importingFile}`);
|
||||
console.log(` Import: ${args.path}`);
|
||||
console.log(` Resolve dir: ${args.resolveDir || 'N/A'}`);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Return null to let the default resolver handle it
|
||||
return null;
|
||||
});
|
||||
|
||||
build.onEnd((result) => {
|
||||
if (violations.length > 0) {
|
||||
console.log(`\nSUMMARY: Found ${violations.length} private import violation(s):`);
|
||||
violations.forEach((v, i) => {
|
||||
console.log(` ${i + 1}. ${path.relative(process.cwd(), v.file)} imports ${v.importPath}`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
result.errors.push({
|
||||
text: `Private import violations detected: ${violations.length} violation(s) found`,
|
||||
location: null,
|
||||
notes: violations.map(v => ({
|
||||
text: `${path.relative(process.cwd(), v.file)} imports ${v.importPath}`,
|
||||
location: null
|
||||
}))
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Plugin to guard against bad imports from #private
|
||||
function dynamicImportGuardPlugin() {
|
||||
return {
|
||||
name: "dynamic-import-guard",
|
||||
setup(build) {
|
||||
const violations = [];
|
||||
|
||||
build.onResolve({ filter: /^#dynamic\// }, (args) => {
|
||||
const importingFile = args.importer;
|
||||
|
||||
// Check if the importing file is NOT in server/private
|
||||
const normalizedImporter = path.normalize(importingFile);
|
||||
const isInServerPrivate = normalizedImporter.includes(path.normalize("server/private"));
|
||||
|
||||
if (isInServerPrivate) {
|
||||
const violation = {
|
||||
file: importingFile,
|
||||
importPath: args.path,
|
||||
resolveDir: args.resolveDir
|
||||
};
|
||||
violations.push(violation);
|
||||
|
||||
console.log(`DYNAMIC IMPORT VIOLATION:`);
|
||||
console.log(` File: ${importingFile}`);
|
||||
console.log(` Import: ${args.path}`);
|
||||
console.log(` Resolve dir: ${args.resolveDir || 'N/A'}`);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Return null to let the default resolver handle it
|
||||
return null;
|
||||
});
|
||||
|
||||
build.onEnd((result) => {
|
||||
if (violations.length > 0) {
|
||||
console.log(`\nSUMMARY: Found ${violations.length} dynamic import violation(s):`);
|
||||
violations.forEach((v, i) => {
|
||||
console.log(` ${i + 1}. ${path.relative(process.cwd(), v.file)} imports ${v.importPath}`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
result.errors.push({
|
||||
text: `Dynamic import violations detected: ${violations.length} violation(s) found`,
|
||||
location: null,
|
||||
notes: violations.map(v => ({
|
||||
text: `${path.relative(process.cwd(), v.file)} imports ${v.importPath}`,
|
||||
location: null
|
||||
}))
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Plugin to dynamically switch imports based on build type
|
||||
function dynamicImportSwitcherPlugin(buildValue) {
|
||||
return {
|
||||
name: "dynamic-import-switcher",
|
||||
setup(build) {
|
||||
const switches = [];
|
||||
|
||||
build.onStart(() => {
|
||||
console.log(`Dynamic import switcher using build type: ${buildValue}`);
|
||||
});
|
||||
|
||||
build.onResolve({ filter: /^#dynamic\// }, (args) => {
|
||||
// Extract the path after #dynamic/
|
||||
const dynamicPath = args.path.replace(/^#dynamic\//, '');
|
||||
|
||||
// Determine the replacement based on build type
|
||||
let replacement;
|
||||
if (buildValue === "oss") {
|
||||
replacement = `#open/${dynamicPath}`;
|
||||
} else if (buildValue === "saas" || buildValue === "enterprise") {
|
||||
replacement = `#closed/${dynamicPath}`; // We use #closed here so that the route guards dont complain after its been changed but this is the same as #private
|
||||
} else {
|
||||
console.warn(`Unknown build type '${buildValue}', defaulting to #open/`);
|
||||
replacement = `#open/${dynamicPath}`;
|
||||
}
|
||||
|
||||
const switchInfo = {
|
||||
file: args.importer,
|
||||
originalPath: args.path,
|
||||
replacementPath: replacement,
|
||||
buildType: buildValue
|
||||
};
|
||||
switches.push(switchInfo);
|
||||
|
||||
console.log(`DYNAMIC IMPORT SWITCH:`);
|
||||
console.log(` File: ${args.importer}`);
|
||||
console.log(` Original: ${args.path}`);
|
||||
console.log(` Switched to: ${replacement} (build: ${buildValue})`);
|
||||
console.log('');
|
||||
|
||||
// Rewrite the import path and let the normal resolution continue
|
||||
return build.resolve(replacement, {
|
||||
importer: args.importer,
|
||||
namespace: args.namespace,
|
||||
resolveDir: args.resolveDir,
|
||||
kind: args.kind
|
||||
});
|
||||
});
|
||||
|
||||
build.onEnd((result) => {
|
||||
if (switches.length > 0) {
|
||||
console.log(`\nDYNAMIC IMPORT SUMMARY: Switched ${switches.length} import(s) for build type '${buildValue}':`);
|
||||
switches.forEach((s, i) => {
|
||||
console.log(` ${i + 1}. ${path.relative(process.cwd(), s.file)}`);
|
||||
console.log(` ${s.originalPath} → ${s.replacementPath}`);
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
esbuild
|
||||
.build({
|
||||
entryPoints: [argv.entry],
|
||||
bundle: true,
|
||||
outfile: argv.out,
|
||||
format: "esm",
|
||||
minify: true,
|
||||
minify: false,
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
platform: "node",
|
||||
external: ["body-parser"],
|
||||
plugins: [
|
||||
privateImportGuardPlugin(),
|
||||
dynamicImportGuardPlugin(),
|
||||
dynamicImportSwitcherPlugin(argv.build),
|
||||
nodeExternalsPlugin({
|
||||
packagePath: getPackagePaths(),
|
||||
}),
|
||||
],
|
||||
sourcemap: "external",
|
||||
sourcemap: "inline",
|
||||
target: "node22",
|
||||
})
|
||||
.then(() => {
|
||||
.then((result) => {
|
||||
// Check if there were any errors in the build result
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
console.error(`Build failed with ${result.errors.length} error(s):`);
|
||||
result.errors.forEach((error, i) => {
|
||||
console.error(`${i + 1}. ${error.text}`);
|
||||
if (error.notes) {
|
||||
error.notes.forEach(note => {
|
||||
console.error(` - ${note.text}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// remove the output file if it was created
|
||||
if (fs.existsSync(argv.out)) {
|
||||
fs.unlinkSync(argv.out);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log("Build completed successfully");
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -18,7 +18,11 @@ put-back:
|
||||
mv main.go.bak main.go
|
||||
|
||||
dev-update-versions:
|
||||
PANGOLIN_VERSION=$$(curl -s https://api.github.com/repos/fosrl/pangolin/tags | jq -r '.[0].name') && \
|
||||
if [ -z "$(tag)" ]; then \
|
||||
PANGOLIN_VERSION=$$(curl -s https://api.github.com/repos/fosrl/pangolin/tags | jq -r '.[0].name'); \
|
||||
else \
|
||||
PANGOLIN_VERSION=$(tag); \
|
||||
fi && \
|
||||
GERBIL_VERSION=$$(curl -s https://api.github.com/repos/fosrl/gerbil/tags | jq -r '.[0].name') && \
|
||||
BADGER_VERSION=$$(curl -s https://api.github.com/repos/fosrl/badger/tags | jq -r '.[0].name') && \
|
||||
echo "Latest versions - Pangolin: $$PANGOLIN_VERSION, Gerbil: $$GERBIL_VERSION, Badger: $$BADGER_VERSION" && \
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
# To see all available options, please visit the docs:
|
||||
# https://docs.digpangolin.com/self-host/advanced/config-file
|
||||
# https://docs.pangolin.net/
|
||||
|
||||
gerbil:
|
||||
start_port: 51820
|
||||
base_endpoint: "{{.DashboardDomain}}"
|
||||
{{if .HybridMode}}
|
||||
managed:
|
||||
id: "{{.HybridId}}"
|
||||
secret: "{{.HybridSecret}}"
|
||||
|
||||
{{else}}
|
||||
|
||||
app:
|
||||
dashboard_url: "https://{{.DashboardDomain}}"
|
||||
log_level: "info"
|
||||
@@ -19,7 +14,6 @@ app:
|
||||
domains:
|
||||
domain1:
|
||||
base_domain: "{{.BaseDomain}}"
|
||||
cert_resolver: "letsencrypt"
|
||||
|
||||
server:
|
||||
secret: "{{.Secret}}"
|
||||
@@ -28,6 +22,7 @@ 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 .EnableEmail}}
|
||||
email:
|
||||
smtp_host: "{{.EmailSMTPHost}}"
|
||||
@@ -41,4 +36,3 @@ flags:
|
||||
disable_signup_without_invite: true
|
||||
disable_user_create_org: false
|
||||
allow_raw_resources: true
|
||||
{{end}}
|
||||
@@ -6,8 +6,6 @@ services:
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./config:/app/config
|
||||
- pangolin-data:/var/certificates
|
||||
- pangolin-data:/var/dynamic
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
|
||||
interval: "10s"
|
||||
@@ -22,7 +20,7 @@ services:
|
||||
pangolin:
|
||||
condition: service_healthy
|
||||
command:
|
||||
- --reachableAt=http://gerbil:3003
|
||||
- --reachableAt=http://gerbil:3004
|
||||
- --generateAndSaveKeyTo=/var/config/key
|
||||
- --remoteConfig=http://pangolin:3001/api/v1/
|
||||
volumes:
|
||||
@@ -33,7 +31,7 @@ services:
|
||||
ports:
|
||||
- 51820:51820/udp
|
||||
- 21820:21820/udp
|
||||
- 443:{{if .HybridMode}}8443{{else}}443{{end}}
|
||||
- 443:443
|
||||
- 80:80
|
||||
{{end}}
|
||||
traefik:
|
||||
@@ -56,15 +54,9 @@ services:
|
||||
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
|
||||
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
|
||||
- ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs
|
||||
# Shared volume for certificates and dynamic config in file mode
|
||||
- pangolin-data:/var/certificates:ro
|
||||
- pangolin-data:/var/dynamic:ro
|
||||
|
||||
networks:
|
||||
default:
|
||||
driver: bridge
|
||||
name: pangolin
|
||||
{{if .EnableIPv6}} enable_ipv6: true{{end}}
|
||||
|
||||
volumes:
|
||||
pangolin-data:
|
||||
{{if .EnableIPv6}} enable_ipv6: true{{end}}
|
||||
@@ -51,3 +51,12 @@ http:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://pangolin:3000" # API/WebSocket server
|
||||
|
||||
tcp:
|
||||
serversTransports:
|
||||
pp-transport-v1:
|
||||
proxyProtocol:
|
||||
version: 1
|
||||
pp-transport-v2:
|
||||
proxyProtocol:
|
||||
version: 2
|
||||
@@ -3,17 +3,12 @@ api:
|
||||
dashboard: true
|
||||
|
||||
providers:
|
||||
{{if not .HybridMode}}
|
||||
http:
|
||||
endpoint: "http://pangolin:3001/api/v1/traefik-config"
|
||||
pollInterval: "5s"
|
||||
file:
|
||||
filename: "/etc/traefik/dynamic_config.yml"
|
||||
{{else}}
|
||||
file:
|
||||
directory: "/var/dynamic"
|
||||
watch: true
|
||||
{{end}}
|
||||
|
||||
experimental:
|
||||
plugins:
|
||||
badger:
|
||||
@@ -27,7 +22,7 @@ log:
|
||||
maxBackups: 3
|
||||
maxAge: 3
|
||||
compress: true
|
||||
{{if not .HybridMode}}
|
||||
|
||||
certificatesResolvers:
|
||||
letsencrypt:
|
||||
acme:
|
||||
@@ -36,22 +31,18 @@ certificatesResolvers:
|
||||
email: "{{.LetsEncryptEmail}}"
|
||||
storage: "/letsencrypt/acme.json"
|
||||
caServer: "https://acme-v02.api.letsencrypt.org/directory"
|
||||
{{end}}
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
{{if .HybridMode}} proxyProtocol:
|
||||
trustedIPs:
|
||||
- 0.0.0.0/0
|
||||
- ::1/128{{end}}
|
||||
transport:
|
||||
respondingTimeouts:
|
||||
readTimeout: "30m"
|
||||
{{if not .HybridMode}} http:
|
||||
http:
|
||||
tls:
|
||||
certResolver: "letsencrypt"{{end}}
|
||||
certResolver: "letsencrypt"
|
||||
|
||||
serversTransport:
|
||||
insecureSkipVerify: true
|
||||
|
||||
@@ -73,7 +73,7 @@ func installDocker() error {
|
||||
case strings.Contains(osRelease, "ID=ubuntu"):
|
||||
installCmd = exec.Command("bash", "-c", fmt.Sprintf(`
|
||||
apt-get update &&
|
||||
apt-get install -y apt-transport-https ca-certificates curl software-properties-common &&
|
||||
apt-get install -y apt-transport-https ca-certificates curl &&
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg &&
|
||||
echo "deb [arch=%s signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list &&
|
||||
apt-get update &&
|
||||
@@ -82,7 +82,7 @@ func installDocker() error {
|
||||
case strings.Contains(osRelease, "ID=debian"):
|
||||
installCmd = exec.Command("bash", "-c", fmt.Sprintf(`
|
||||
apt-get update &&
|
||||
apt-get install -y apt-transport-https ca-certificates curl software-properties-common &&
|
||||
apt-get install -y apt-transport-https ca-certificates curl &&
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg &&
|
||||
echo "deb [arch=%s signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list &&
|
||||
apt-get update &&
|
||||
|
||||
180
install/get-installer.sh
Normal file
180
install/get-installer.sh
Normal file
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get installer - Cross-platform installation script
|
||||
# Usage: curl -fsSL https://raw.githubusercontent.com/fosrl/installer/refs/heads/main/get-installer.sh | bash
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# GitHub repository info
|
||||
REPO="fosrl/pangolin"
|
||||
GITHUB_API_URL="https://api.github.com/repos/${REPO}/releases/latest"
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Function to get latest version from GitHub API
|
||||
get_latest_version() {
|
||||
local latest_info
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
latest_info=$(curl -fsSL "$GITHUB_API_URL" 2>/dev/null)
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
latest_info=$(wget -qO- "$GITHUB_API_URL" 2>/dev/null)
|
||||
else
|
||||
print_error "Neither curl nor wget is available. Please install one of them." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$latest_info" ]; then
|
||||
print_error "Failed to fetch latest version information" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract version from JSON response (works without jq)
|
||||
local version=$(echo "$latest_info" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
print_error "Could not parse version from GitHub API response" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove 'v' prefix if present
|
||||
version=$(echo "$version" | sed 's/^v//')
|
||||
|
||||
echo "$version"
|
||||
}
|
||||
|
||||
# Detect OS and architecture
|
||||
detect_platform() {
|
||||
local os arch
|
||||
|
||||
# Detect OS - only support Linux
|
||||
case "$(uname -s)" in
|
||||
Linux*) os="linux" ;;
|
||||
*)
|
||||
print_error "Unsupported operating system: $(uname -s). Only Linux is supported."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Detect architecture - only support amd64 and arm64
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) arch="amd64" ;;
|
||||
arm64|aarch64) arch="arm64" ;;
|
||||
*)
|
||||
print_error "Unsupported architecture: $(uname -m). Only amd64 and arm64 are supported on Linux."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "${os}_${arch}"
|
||||
}
|
||||
|
||||
# Get installation directory
|
||||
get_install_dir() {
|
||||
# Install to the current directory
|
||||
local install_dir="$(pwd)"
|
||||
if [ ! -d "$install_dir" ]; then
|
||||
print_error "Installation directory does not exist: $install_dir"
|
||||
exit 1
|
||||
fi
|
||||
echo "$install_dir"
|
||||
}
|
||||
|
||||
# Download and install installer
|
||||
install_installer() {
|
||||
local platform="$1"
|
||||
local install_dir="$2"
|
||||
local binary_name="installer_${platform}"
|
||||
|
||||
local download_url="${BASE_URL}/${binary_name}"
|
||||
local temp_file="/tmp/installer"
|
||||
local final_path="${install_dir}/installer"
|
||||
|
||||
print_status "Downloading installer from ${download_url}"
|
||||
|
||||
# Download the binary
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL "$download_url" -o "$temp_file"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q "$download_url" -O "$temp_file"
|
||||
else
|
||||
print_error "Neither curl nor wget is available. Please install one of them."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create install directory if it doesn't exist
|
||||
mkdir -p "$install_dir"
|
||||
|
||||
# Move binary to install directory
|
||||
mv "$temp_file" "$final_path"
|
||||
|
||||
# Make executable
|
||||
chmod +x "$final_path"
|
||||
|
||||
print_status "Installer downloaded to ${final_path}"
|
||||
}
|
||||
|
||||
# Verify installation
|
||||
verify_installation() {
|
||||
local install_dir="$1"
|
||||
local installer_path="${install_dir}/installer"
|
||||
|
||||
if [ -f "$installer_path" ] && [ -x "$installer_path" ]; then
|
||||
print_status "Installation successful!"
|
||||
return 0
|
||||
else
|
||||
print_error "Installation failed. Binary not found or not executable."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main installation process
|
||||
main() {
|
||||
print_status "Installing latest version of installer..."
|
||||
|
||||
# Get latest version
|
||||
print_status "Fetching latest version from GitHub..."
|
||||
VERSION=$(get_latest_version)
|
||||
print_status "Latest version: v${VERSION}"
|
||||
|
||||
# Set base URL with the fetched version
|
||||
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
|
||||
|
||||
# Detect platform
|
||||
PLATFORM=$(detect_platform)
|
||||
print_status "Detected platform: ${PLATFORM}"
|
||||
|
||||
# Get install directory
|
||||
INSTALL_DIR=$(get_install_dir)
|
||||
print_status "Install directory: ${INSTALL_DIR}"
|
||||
|
||||
# Install installer
|
||||
install_installer "$PLATFORM" "$INSTALL_DIR"
|
||||
|
||||
# Verify installation
|
||||
if verify_installation "$INSTALL_DIR"; then
|
||||
print_status "Installer is ready to use!"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -1,10 +1,10 @@
|
||||
module installer
|
||||
|
||||
go 1.24
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
golang.org/x/term v0.34.0
|
||||
golang.org/x/term v0.36.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.35.0 // indirect
|
||||
require golang.org/x/sys v0.37.0 // indirect
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
307
install/main.go
307
install/main.go
@@ -2,12 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -15,7 +17,6 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
"net"
|
||||
)
|
||||
|
||||
// DO NOT EDIT THIS FUNCTION; IT MATCHED BY REGEX IN CICD
|
||||
@@ -46,10 +47,8 @@ type Config struct {
|
||||
InstallGerbil bool
|
||||
TraefikBouncerKey string
|
||||
DoCrowdsecInstall bool
|
||||
EnableGeoblocking bool
|
||||
Secret string
|
||||
HybridMode bool
|
||||
HybridId string
|
||||
HybridSecret string
|
||||
}
|
||||
|
||||
type SupportedContainer string
|
||||
@@ -57,6 +56,7 @@ type SupportedContainer string
|
||||
const (
|
||||
Docker SupportedContainer = "docker"
|
||||
Podman SupportedContainer = "podman"
|
||||
Undefined SupportedContainer = "undefined"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -74,7 +74,7 @@ func main() {
|
||||
if err := checkPortsAvailable(p); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
||||
fmt.Printf("Please close any services on ports 80/443 in order to run the installation smoothly")
|
||||
fmt.Printf("Please close any services on ports 80/443 in order to run the installation smoothly. If you already have the Pangolin stack running, shut them down before proceeding.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,7 @@ func main() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
var config Config
|
||||
var alreadyInstalled = false
|
||||
|
||||
// check if there is already a config file
|
||||
if _, err := os.Stat("config/config.yml"); err != nil {
|
||||
@@ -94,24 +95,6 @@ func main() {
|
||||
|
||||
fmt.Println("\n=== Generating Configuration Files ===")
|
||||
|
||||
// If the secret and id are not generated then generate them
|
||||
if config.HybridMode && (config.HybridId == "" || config.HybridSecret == "") {
|
||||
// fmt.Println("Requesting hybrid credentials from cloud...")
|
||||
credentials, err := requestHybridCredentials()
|
||||
if err != nil {
|
||||
fmt.Printf("Error requesting hybrid credentials: %v\n", err)
|
||||
fmt.Println("Please obtain credentials manually from the dashboard and run the installer again.")
|
||||
os.Exit(1)
|
||||
}
|
||||
config.HybridId = credentials.RemoteExitNodeId
|
||||
config.HybridSecret = credentials.Secret
|
||||
fmt.Printf("Your managed credentials have been obtained successfully.\n")
|
||||
fmt.Printf(" ID: %s\n", config.HybridId)
|
||||
fmt.Printf(" Secret: %s\n", config.HybridSecret)
|
||||
fmt.Println("Take these to the Pangolin dashboard https://pangolin.fossorial.io to adopt your node.")
|
||||
readBool(reader, "Have you adopted your node?", true)
|
||||
}
|
||||
|
||||
if err := createConfigFiles(config); err != nil {
|
||||
fmt.Printf("Error creating config files: %v\n", err)
|
||||
os.Exit(1)
|
||||
@@ -121,12 +104,21 @@ func main() {
|
||||
|
||||
fmt.Println("\nConfiguration files created successfully!")
|
||||
|
||||
// Download MaxMind database if requested
|
||||
if config.EnableGeoblocking {
|
||||
fmt.Println("\n=== Downloading MaxMind Database ===")
|
||||
if err := downloadMaxMindDatabase(); err != nil {
|
||||
fmt.Printf("Error downloading MaxMind database: %v\n", err)
|
||||
fmt.Println("You can download it manually later if needed.")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n=== Starting installation ===")
|
||||
|
||||
if readBool(reader, "Would you like to install and start the containers?", true) {
|
||||
|
||||
config.InstallationContainerType = podmanOrDocker(reader)
|
||||
|
||||
|
||||
if !isDockerInstalled() && runtime.GOOS == "linux" && config.InstallationContainerType == Docker {
|
||||
if readBool(reader, "Docker is not installed. Would you like to install it?", true) {
|
||||
installDocker()
|
||||
@@ -166,10 +158,36 @@ func main() {
|
||||
}
|
||||
|
||||
} else {
|
||||
alreadyInstalled = true
|
||||
fmt.Println("Looks like you already installed Pangolin!")
|
||||
|
||||
// Check if MaxMind database exists and offer to update it
|
||||
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(reader, "Would you like to update the MaxMind database 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(reader, "Would you like to download the MaxMind GeoLite2 database for geoblocking 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.")
|
||||
}
|
||||
// Now you need to update your config file accordingly to enable geoblocking
|
||||
fmt.Println("Please remember to update your config/config.yml file to enable geoblocking! \n")
|
||||
// add maxmind_db_path: "./config/GeoLite2-Country.mmdb" under server
|
||||
fmt.Println("Add the following line under the 'server' section:")
|
||||
fmt.Println(" maxmind_db_path: \"./config/GeoLite2-Country.mmdb\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !checkIsCrowdsecInstalledInCompose() && !checkIsPangolinInstalledWithHybrid() {
|
||||
if !checkIsCrowdsecInstalledInCompose() {
|
||||
fmt.Println("\n=== CrowdSec Install ===")
|
||||
// check if crowdsec is installed
|
||||
if readBool(reader, "Would you like to install CrowdSec?", false) {
|
||||
@@ -189,7 +207,13 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
config.DashboardDomain = appConfig.DashboardURL
|
||||
parsedURL, err := url.Parse(appConfig.DashboardURL)
|
||||
if err != nil {
|
||||
fmt.Printf("Error parsing URL: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
config.DashboardDomain = parsedURL.Hostname()
|
||||
config.LetsEncryptEmail = traefikConfig.LetsEncryptEmail
|
||||
config.BadgerVersion = traefikConfig.BadgerVersion
|
||||
|
||||
@@ -204,13 +228,21 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
config.InstallationContainerType = podmanOrDocker(reader)
|
||||
|
||||
config.DoCrowdsecInstall = true
|
||||
installCrowdsec(config)
|
||||
err := installCrowdsec(config)
|
||||
if err != nil {
|
||||
fmt.Printf("Error installing CrowdSec: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("CrowdSec installed successfully!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !config.HybridMode {
|
||||
if !alreadyInstalled {
|
||||
// Setup Token Section
|
||||
fmt.Println("\n=== Setup Token ===")
|
||||
|
||||
@@ -231,9 +263,7 @@ func main() {
|
||||
|
||||
fmt.Println("\nInstallation complete!")
|
||||
|
||||
if !config.HybridMode && !checkIsPangolinInstalledWithHybrid() {
|
||||
fmt.Printf("\nTo complete the initial setup, please visit:\nhttps://%s/auth/initial-setup\n", config.DashboardDomain)
|
||||
}
|
||||
fmt.Printf("\nTo complete the initial setup, please visit:\nhttps://%s/auth/initial-setup\n", config.DashboardDomain)
|
||||
}
|
||||
|
||||
func podmanOrDocker(reader *bufio.Reader) SupportedContainer {
|
||||
@@ -308,61 +338,38 @@ func collectUserInput(reader *bufio.Reader) Config {
|
||||
|
||||
// Basic configuration
|
||||
fmt.Println("\n=== Basic Configuration ===")
|
||||
for {
|
||||
response := readString(reader, "Do you want to install Pangolin as a cloud-managed (beta) node? (yes/no)", "")
|
||||
if strings.EqualFold(response, "yes") || strings.EqualFold(response, "y") {
|
||||
config.HybridMode = true
|
||||
break
|
||||
} else if strings.EqualFold(response, "no") || strings.EqualFold(response, "n") {
|
||||
config.HybridMode = false
|
||||
break
|
||||
}
|
||||
fmt.Println("Please answer 'yes' or 'no'")
|
||||
|
||||
config.BaseDomain = readString(reader, "Enter your base domain (no subdomain e.g. example.com)", "")
|
||||
|
||||
// Set default dashboard domain after base domain is collected
|
||||
defaultDashboardDomain := ""
|
||||
if config.BaseDomain != "" {
|
||||
defaultDashboardDomain = "pangolin." + config.BaseDomain
|
||||
}
|
||||
config.DashboardDomain = readString(reader, "Enter the domain for the Pangolin dashboard", defaultDashboardDomain)
|
||||
config.LetsEncryptEmail = readString(reader, "Enter email for Let's Encrypt certificates", "")
|
||||
config.InstallGerbil = readBool(reader, "Do you want to use Gerbil to allow tunneled connections", true)
|
||||
|
||||
// Email configuration
|
||||
fmt.Println("\n=== Email Configuration ===")
|
||||
config.EnableEmail = readBool(reader, "Enable email functionality (SMTP)", false)
|
||||
|
||||
if config.EnableEmail {
|
||||
config.EmailSMTPHost = readString(reader, "Enter SMTP host", "")
|
||||
config.EmailSMTPPort = readInt(reader, "Enter SMTP port (default 587)", 587)
|
||||
config.EmailSMTPUser = readString(reader, "Enter SMTP username", "")
|
||||
config.EmailSMTPPass = readString(reader, "Enter SMTP password", "") // Should this be readPassword?
|
||||
config.EmailNoReply = readString(reader, "Enter no-reply email address", "")
|
||||
}
|
||||
|
||||
if config.HybridMode {
|
||||
alreadyHaveCreds := readBool(reader, "Do you already have credentials from the dashboard? If not, we will create them later", false)
|
||||
|
||||
if alreadyHaveCreds {
|
||||
config.HybridId = readString(reader, "Enter your ID", "")
|
||||
config.HybridSecret = readString(reader, "Enter your secret", "")
|
||||
}
|
||||
|
||||
config.DashboardDomain = readString(reader, "The public addressable IP address for this node or a domain pointing to it", "")
|
||||
config.InstallGerbil = true
|
||||
} else {
|
||||
config.BaseDomain = readString(reader, "Enter your base domain (no subdomain e.g. example.com)", "")
|
||||
|
||||
// Set default dashboard domain after base domain is collected
|
||||
defaultDashboardDomain := ""
|
||||
if config.BaseDomain != "" {
|
||||
defaultDashboardDomain = "pangolin." + config.BaseDomain
|
||||
}
|
||||
config.DashboardDomain = readString(reader, "Enter the domain for the Pangolin dashboard", defaultDashboardDomain)
|
||||
config.LetsEncryptEmail = readString(reader, "Enter email for Let's Encrypt certificates", "")
|
||||
config.InstallGerbil = readBool(reader, "Do you want to use Gerbil to allow tunneled connections", true)
|
||||
|
||||
// Email configuration
|
||||
fmt.Println("\n=== Email Configuration ===")
|
||||
config.EnableEmail = readBool(reader, "Enable email functionality (SMTP)", false)
|
||||
|
||||
if config.EnableEmail {
|
||||
config.EmailSMTPHost = readString(reader, "Enter SMTP host", "")
|
||||
config.EmailSMTPPort = readInt(reader, "Enter SMTP port (default 587)", 587)
|
||||
config.EmailSMTPUser = readString(reader, "Enter SMTP username", "")
|
||||
config.EmailSMTPPass = readString(reader, "Enter SMTP password", "") // Should this be readPassword?
|
||||
config.EmailNoReply = readString(reader, "Enter no-reply email address", "")
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if config.BaseDomain == "" {
|
||||
fmt.Println("Error: Domain name is required")
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.LetsEncryptEmail == "" {
|
||||
fmt.Println("Error: Let's Encrypt email is required")
|
||||
os.Exit(1)
|
||||
}
|
||||
// Validate required fields
|
||||
if config.BaseDomain == "" {
|
||||
fmt.Println("Error: Domain name is required")
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.LetsEncryptEmail == "" {
|
||||
fmt.Println("Error: Let's Encrypt email is required")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Advanced configuration
|
||||
@@ -370,6 +377,7 @@ func collectUserInput(reader *bufio.Reader) Config {
|
||||
fmt.Println("\n=== Advanced Configuration ===")
|
||||
|
||||
config.EnableIPv6 = readBool(reader, "Is your server IPv6 capable?", true)
|
||||
config.EnableGeoblocking = readBool(reader, "Do you want to download the MaxMind GeoLite2 database for geoblocking functionality?", true)
|
||||
|
||||
if config.DashboardDomain == "" {
|
||||
fmt.Println("Error: Dashboard Domain name is required")
|
||||
@@ -404,11 +412,6 @@ func createConfigFiles(config Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// the hybrid does not need the dynamic config
|
||||
if config.HybridMode && strings.Contains(path, "dynamic_config.yml") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// skip .DS_Store
|
||||
if strings.Contains(path, ".DS_Store") {
|
||||
return nil
|
||||
@@ -522,12 +525,12 @@ func printSetupToken(containerType SupportedContainer, dashboardDomain string) {
|
||||
tokenStart := strings.Index(trimmedLine, "Token:")
|
||||
if tokenStart != -1 {
|
||||
token := strings.TrimSpace(trimmedLine[tokenStart+6:])
|
||||
fmt.Printf("Setup token: %s\n", token)
|
||||
fmt.Println("")
|
||||
fmt.Println("This token is required to register the first admin account in the web UI at:")
|
||||
fmt.Printf("https://%s/auth/initial-setup\n", dashboardDomain)
|
||||
fmt.Println("")
|
||||
fmt.Println("Save this token securely. It will be invalid after the first admin is created.")
|
||||
fmt.Printf("Setup token: %s\n", token)
|
||||
fmt.Println("")
|
||||
fmt.Println("This token is required to register the first admin account in the web UI at:")
|
||||
fmt.Printf("https://%s/auth/initial-setup\n", dashboardDomain)
|
||||
fmt.Println("")
|
||||
fmt.Println("Save this token securely. It will be invalid after the first admin is created.")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -541,28 +544,30 @@ func showSetupTokenInstructions(containerType SupportedContainer, dashboardDomai
|
||||
fmt.Println("\n=== Setup Token Instructions ===")
|
||||
fmt.Println("To get your setup token, you need to:")
|
||||
fmt.Println("")
|
||||
fmt.Println("1. Start the containers:")
|
||||
fmt.Println("1. Start the containers")
|
||||
if containerType == Docker {
|
||||
fmt.Println(" docker-compose up -d")
|
||||
} else {
|
||||
fmt.Println(" docker compose up -d")
|
||||
} else if containerType == Podman {
|
||||
fmt.Println(" podman-compose up -d")
|
||||
} else {
|
||||
}
|
||||
fmt.Println("")
|
||||
fmt.Println("2. Wait for the Pangolin container to start and generate the token")
|
||||
fmt.Println("")
|
||||
fmt.Println("3. Check the container logs for the setup token:")
|
||||
fmt.Println("3. Check the container logs for the setup token")
|
||||
if containerType == Docker {
|
||||
fmt.Println(" docker logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
||||
} else {
|
||||
} else if containerType == Podman {
|
||||
fmt.Println(" podman logs pangolin | grep -A 2 -B 2 'SETUP TOKEN'")
|
||||
} else {
|
||||
}
|
||||
fmt.Println("")
|
||||
fmt.Println("4. Look for output like:")
|
||||
fmt.Println("4. Look for output like")
|
||||
fmt.Println(" === SETUP TOKEN GENERATED ===")
|
||||
fmt.Println(" Token: [your-token-here]")
|
||||
fmt.Println(" Use this token on the initial setup page")
|
||||
fmt.Println("")
|
||||
fmt.Println("5. Use the token to complete initial setup at:")
|
||||
fmt.Println("5. Use the token to complete initial setup at")
|
||||
fmt.Printf(" https://%s/auth/initial-setup\n", dashboardDomain)
|
||||
fmt.Println("")
|
||||
fmt.Println("The setup token is required to register the first admin account.")
|
||||
@@ -584,6 +589,32 @@ func generateRandomSecretKey() string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func getPublicIP() string {
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
resp, err := client.Get("https://ifconfig.io/ip")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
ip := strings.TrimSpace(string(body))
|
||||
|
||||
// Validate that it's a valid IP address
|
||||
if net.ParseIP(ip) != nil {
|
||||
return ip
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Run external commands with stdio/stderr attached.
|
||||
func run(name string, args ...string) error {
|
||||
cmd := exec.Command(name, args...)
|
||||
@@ -593,35 +624,47 @@ func run(name string, args ...string) error {
|
||||
}
|
||||
|
||||
func checkPortsAvailable(port int) error {
|
||||
addr := fmt.Sprintf(":%d", port)
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"ERROR: port %d is occupied or cannot be bound: %w\n\n",
|
||||
port, err,
|
||||
)
|
||||
}
|
||||
if closeErr := ln.Close(); closeErr != nil {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"WARNING: failed to close test listener on port %d: %v\n",
|
||||
port, closeErr,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkIsPangolinInstalledWithHybrid() bool {
|
||||
// Check if config/config.yml exists and contains hybrid section
|
||||
if _, err := os.Stat("config/config.yml"); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Read config file to check for hybrid section
|
||||
content, err := os.ReadFile("config/config.yml")
|
||||
addr := fmt.Sprintf(":%d", port)
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return false
|
||||
return fmt.Errorf(
|
||||
"ERROR: port %d is occupied or cannot be bound: %w\n\n",
|
||||
port, err,
|
||||
)
|
||||
}
|
||||
|
||||
// Check for hybrid section
|
||||
return bytes.Contains(content, []byte("managed:"))
|
||||
if closeErr := ln.Close(); closeErr != nil {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"WARNING: failed to close test listener on port %d: %v\n",
|
||||
port, closeErr,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadMaxMindDatabase() error {
|
||||
fmt.Println("Downloading MaxMind GeoLite2 Country database...")
|
||||
|
||||
// Download the GeoLite2 Country database
|
||||
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)
|
||||
}
|
||||
|
||||
// Extract the database
|
||||
if err := run("tar", "-xzf", "GeoLite2-Country.tar.gz"); err != nil {
|
||||
return fmt.Errorf("failed to extract GeoLite2 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
fmt.Println("MaxMind GeoLite2 Country database downloaded successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
FRONTEND_SECRET_KEY = "af4e4785-7e09-11f0-b93a-74563c4e2a7e"
|
||||
// CLOUD_API_URL = "https://pangolin.fossorial.io/api/v1/remote-exit-node/quick-start"
|
||||
CLOUD_API_URL = "https://pangolin.fossorial.io/api/v1/remote-exit-node/quick-start"
|
||||
)
|
||||
|
||||
// HybridCredentials represents the response from the cloud API
|
||||
type HybridCredentials struct {
|
||||
RemoteExitNodeId string `json:"remoteExitNodeId"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
// APIResponse represents the full response structure from the cloud API
|
||||
type APIResponse struct {
|
||||
Data HybridCredentials `json:"data"`
|
||||
}
|
||||
|
||||
// RequestPayload represents the request body structure
|
||||
type RequestPayload struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func generateValidationToken() string {
|
||||
timestamp := time.Now().UnixMilli()
|
||||
data := fmt.Sprintf("%s|%d", FRONTEND_SECRET_KEY, timestamp)
|
||||
obfuscated := make([]byte, len(data))
|
||||
for i, char := range []byte(data) {
|
||||
obfuscated[i] = char + 5
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(obfuscated)
|
||||
}
|
||||
|
||||
// requestHybridCredentials makes an HTTP POST request to the cloud API
|
||||
// to get hybrid credentials (ID and secret)
|
||||
func requestHybridCredentials() (*HybridCredentials, error) {
|
||||
// Generate validation token
|
||||
token := generateValidationToken()
|
||||
|
||||
// Create request payload
|
||||
payload := RequestPayload{
|
||||
Token: token,
|
||||
}
|
||||
|
||||
// Marshal payload to JSON
|
||||
jsonData, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request payload: %v", err)
|
||||
}
|
||||
|
||||
// Create HTTP request
|
||||
req, err := http.NewRequest("POST", CLOUD_API_URL, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create HTTP request: %v", err)
|
||||
}
|
||||
|
||||
// Set headers
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-CSRF-Token", "x-csrf-protection")
|
||||
|
||||
// Create HTTP client with timeout
|
||||
client := &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
// Make the request
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make HTTP request: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check response status
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("API request failed with status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Read response body for debugging
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %v", err)
|
||||
}
|
||||
|
||||
// Print the raw JSON response for debugging
|
||||
// fmt.Printf("Raw JSON response: %s\n", string(body))
|
||||
|
||||
// Parse response
|
||||
var apiResponse APIResponse
|
||||
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode API response: %v", err)
|
||||
}
|
||||
|
||||
// Validate response data
|
||||
if apiResponse.Data.RemoteExitNodeId == "" || apiResponse.Data.Secret == "" {
|
||||
return nil, fmt.Errorf("invalid response: missing remoteExitNodeId or secret")
|
||||
}
|
||||
|
||||
return &apiResponse.Data, nil
|
||||
}
|
||||
3455
messages/bg-BG.json
3455
messages/bg-BG.json
File diff suppressed because it is too large
Load Diff
3137
messages/cs-CZ.json
3137
messages/cs-CZ.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -47,9 +47,8 @@
|
||||
"edit": "Edit",
|
||||
"siteConfirmDelete": "Confirm Delete Site",
|
||||
"siteDelete": "Delete Site",
|
||||
"siteMessageRemove": "Once removed, the site will no longer be accessible. All resources and targets associated with the site will also be removed.",
|
||||
"siteMessageConfirm": "To confirm, please type the name of the site below.",
|
||||
"siteQuestionRemove": "Are you sure you want to remove the site {selectedSite} from the organization?",
|
||||
"siteMessageRemove": "Once removed the site will no longer be accessible. All targets associated with the site will also be removed.",
|
||||
"siteQuestionRemove": "Are you sure you want to remove the site from the organization?",
|
||||
"siteManageSites": "Manage Sites",
|
||||
"siteDescription": "Allow connectivity to your network through secure tunnels",
|
||||
"siteCreate": "Create Site",
|
||||
@@ -94,9 +93,9 @@
|
||||
"siteNewtTunnelDescription": "Easiest way to create an entrypoint into your network. No extra setup.",
|
||||
"siteWg": "Basic WireGuard",
|
||||
"siteWgDescription": "Use any WireGuard client to establish a tunnel. Manual NAT setup required.",
|
||||
"siteWgDescriptionSaas": "Use any WireGuard client to establish a tunnel. Manual NAT setup required. ONLY WORKS ON SELF HOSTED NODES",
|
||||
"siteWgDescriptionSaas": "Use any WireGuard client to establish a tunnel. Manual NAT setup required.",
|
||||
"siteLocalDescription": "Local resources only. No tunneling.",
|
||||
"siteLocalDescriptionSaas": "Local resources only. No tunneling. ONLY WORKS ON SELF HOSTED NODES",
|
||||
"siteLocalDescriptionSaas": "Local resources only. No tunneling. Only available on remote nodes.",
|
||||
"siteSeeAll": "See All Sites",
|
||||
"siteTunnelDescription": "Determine how you want to connect to your site",
|
||||
"siteNewtCredentials": "Newt Credentials",
|
||||
@@ -132,7 +131,7 @@
|
||||
"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.",
|
||||
"shareSeeOnce": "You will only be able to see this linkonce. Make sure to copy it.",
|
||||
"shareSeeOnce": "You will only be able to see this link once. Make sure to copy it.",
|
||||
"shareAccessHint": "Anyone with this link can access the resource. Share it with care.",
|
||||
"shareTokenUsage": "See Access Token Usage",
|
||||
"createLink": "Create Link",
|
||||
@@ -154,12 +153,11 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "To confirm, please type the name of the resource below.",
|
||||
"resourceQuestionRemove": "Are you sure you want to remove the resource {selectedResource} from the organization?",
|
||||
"resourceQuestionRemove": "Are you sure you want to remove the resource from the organization?",
|
||||
"resourceHTTP": "HTTPS Resource",
|
||||
"resourceHTTPDescription": "Proxy requests to your app over HTTPS using a subdomain or base domain.",
|
||||
"resourceRaw": "Raw TCP/UDP Resource",
|
||||
"resourceRawDescription": "Proxy requests to your app over TCP/UDP using a port number.",
|
||||
"resourceRawDescription": "Proxy requests to your app over TCP/UDP using a port number. This only works when sites are connected to nodes.",
|
||||
"resourceCreate": "Create Resource",
|
||||
"resourceCreateDescription": "Follow the steps below to create a new resource",
|
||||
"resourceSeeAll": "See All Resources",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Select site",
|
||||
"siteSearch": "Search site",
|
||||
"siteNotFound": "No site found.",
|
||||
"selectCountry": "Select country",
|
||||
"searchCountries": "Search countries...",
|
||||
"noCountryFound": "No country found.",
|
||||
"siteSelectionDescription": "This site will provide connectivity to the target.",
|
||||
"resourceType": "Resource Type",
|
||||
"resourceTypeDescription": "Determine how you want to access your resource",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Base Domain",
|
||||
"subdomnainDescription": "The subdomain where your resource will be accessible.",
|
||||
"resourceRawSettings": "TCP/UDP Settings",
|
||||
"resourceRawSettingsDescription": "Configure how your resource will be accessed over TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configure how your resource will be accessed over TCP/UDP. You map the resource to a port on the host Pangolin server, so you can access the resource from server-public-ip:mapped-port.",
|
||||
"protocol": "Protocol",
|
||||
"protocolSelect": "Select a protocol",
|
||||
"resourcePortNumber": "Port Number",
|
||||
@@ -206,7 +207,7 @@
|
||||
"alwaysAllow": "Always Allow",
|
||||
"alwaysDeny": "Always Deny",
|
||||
"passToAuth": "Pass to Auth",
|
||||
"orgSettingsDescription": "Configure your organization's general settings",
|
||||
"orgSettingsDescription": "Configure your organization's settings",
|
||||
"orgGeneralSettings": "Organization Settings",
|
||||
"orgGeneralSettingsDescription": "Manage your organization details and configuration",
|
||||
"saveGeneralSettings": "Save General Settings",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Confirm Delete Organization",
|
||||
"orgMessageRemove": "This action is irreversible and will delete all associated data.",
|
||||
"orgMessageConfirm": "To confirm, please type the name of the organization below.",
|
||||
"orgQuestionRemove": "Are you sure you want to remove the organization {selectedOrg}?",
|
||||
"orgQuestionRemove": "Are you sure you want to remove the organization?",
|
||||
"orgUpdated": "Organization updated",
|
||||
"orgUpdatedDescription": "The organization has been updated.",
|
||||
"orgErrorUpdate": "Failed to update organization",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Generate API Key",
|
||||
"apiKeysErrorDelete": "Error deleting API key",
|
||||
"apiKeysErrorDeleteMessage": "Error deleting API key",
|
||||
"apiKeysQuestionRemove": "Are you sure you want to remove the API key {selectedApiKey} from the organization?",
|
||||
"apiKeysQuestionRemove": "Are you sure you want to remove the API key from the organization?",
|
||||
"apiKeysMessageRemove": "Once removed, the API key will no longer be able to be used.",
|
||||
"apiKeysMessageConfirm": "To confirm, please type the name of the API key below.",
|
||||
"apiKeysDeleteConfirm": "Confirm Delete API Key",
|
||||
"apiKeysDelete": "Delete API Key",
|
||||
"apiKeysManage": "Manage API Keys",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Confirm Delete User",
|
||||
"userDeleteServer": "Delete User from Server",
|
||||
"userMessageRemove": "The user will be removed from all organizations and be completely removed from the server.",
|
||||
"userMessageConfirm": "To confirm, please type the name of the user below.",
|
||||
"userQuestionRemove": "Are you sure you want to permanently delete {selectedUser} from the server?",
|
||||
"userQuestionRemove": "Are you sure you want to permanently delete user from the server?",
|
||||
"licenseKey": "License Key",
|
||||
"valid": "Valid",
|
||||
"numberOfSites": "Number of Sites",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "View Fossorial Commercial License & Subscription Terms",
|
||||
"licenseMessageRemove": "This will remove the license key and all associated permissions granted by it.",
|
||||
"licenseMessageConfirm": "To confirm, please type the license key below.",
|
||||
"licenseQuestionRemove": "Are you sure you want to delete the license key {selectedKey} ?",
|
||||
"licenseQuestionRemove": "Are you sure you want to delete the license key ?",
|
||||
"licenseKeyDelete": "Delete License Key",
|
||||
"licenseKeyDeleteConfirm": "Confirm Delete License Key",
|
||||
"licenseTitle": "Manage License Status",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "An error occurred while removing the invitation.",
|
||||
"inviteRemoved": "Invitation removed",
|
||||
"inviteRemovedDescription": "The invitation for {email} has been removed.",
|
||||
"inviteQuestionRemove": "Are you sure you want to remove the invitation {email}?",
|
||||
"inviteQuestionRemove": "Are you sure you want to remove the invitation?",
|
||||
"inviteMessageRemove": "Once removed, this invitation will no longer be valid. You can always re-invite the user later.",
|
||||
"inviteMessageConfirm": "To confirm, please type the email address of the invitation below.",
|
||||
"inviteQuestionRegenerate": "Are you sure you want to regenerate the invitation for {email}? This will revoke the previous invitation.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "An error occurred while removing the user.",
|
||||
"userOrgRemoved": "User removed",
|
||||
"userOrgRemovedDescription": "The user {email} has been removed from the organization.",
|
||||
"userQuestionOrgRemove": "Are you sure you want to remove {email} from the organization?",
|
||||
"userQuestionOrgRemove": "Are you sure you want to remove this user from the organization?",
|
||||
"userMessageOrgRemove": "Once removed, this user will no longer have access to the organization. You can always re-invite them later, but they will need to accept the invitation again.",
|
||||
"userMessageOrgConfirm": "To confirm, please type the name of the of the user below.",
|
||||
"userRemoveOrgConfirm": "Confirm Remove User",
|
||||
"userRemoveOrg": "Remove User from Organization",
|
||||
"users": "Users",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "An error occurred while adding user to the role.",
|
||||
"userSaved": "User saved",
|
||||
"userSavedDescription": "The user has been updated.",
|
||||
"autoProvisioned": "Auto Provisioned",
|
||||
"autoProvisionedDescription": "Allow this user to be automatically managed by identity provider",
|
||||
"accessControlsDescription": "Manage what this user can access and do in the organization",
|
||||
"accessControlsSubmit": "Save Access Controls",
|
||||
"roles": "Roles",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Created At",
|
||||
"proxyErrorInvalidHeader": "Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header.",
|
||||
"proxyErrorTls": "Invalid TLS Server Name. Use domain name format, or save empty to remove the TLS Server Name.",
|
||||
"proxyEnableSSL": "Enable SSL (https)",
|
||||
"proxyEnableSSL": "Enable SSL",
|
||||
"proxyEnableSSLDescription": "Enable SSL/TLS encryption for secure HTTPS connections to your targets.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Configure Targets",
|
||||
"targetErrorFetch": "Failed to fetch targets",
|
||||
"targetErrorFetchDescription": "An error occurred while fetching targets",
|
||||
"siteErrorFetch": "Failed to fetch resource",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Secure Connection Configuration",
|
||||
"targetTlsSettingsDescription": "Configure SSL/TLS settings for your resource",
|
||||
"targetTlsSettingsAdvanced": "Advanced TLS Settings",
|
||||
"targetTlsSni": "TLS Server Name (SNI)",
|
||||
"targetTlsSni": "TLS Server Name",
|
||||
"targetTlsSniDescription": "The TLS Server Name to use for SNI. Leave empty to use the default.",
|
||||
"targetTlsSubmit": "Save Settings",
|
||||
"targets": "Targets Configuration",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Keep connections on the same backend target for their entire session.",
|
||||
"methodSelect": "Select method",
|
||||
"targetSubmit": "Add Target",
|
||||
"targetNoOne": "No targets. Add a target using the form.",
|
||||
"targetNoOne": "This resource doesn't have any targets. Add a target to configure where to send requests to your backend.",
|
||||
"targetNoOneDescription": "Adding more than one target above will enable load balancing.",
|
||||
"targetsSubmit": "Save Targets",
|
||||
"addTarget": "Add Target",
|
||||
"targetErrorInvalidIp": "Invalid IP address",
|
||||
"targetErrorInvalidIpDescription": "Please enter a valid IP address or hostname",
|
||||
"targetErrorInvalidPort": "Invalid port",
|
||||
"targetErrorInvalidPortDescription": "Please enter a valid port number",
|
||||
"targetErrorNoSite": "No site selected",
|
||||
"targetErrorNoSiteDescription": "Please select a site for the target",
|
||||
"targetCreated": "Target created",
|
||||
"targetCreatedDescription": "Target has been created successfully",
|
||||
"targetErrorCreate": "Failed to create target",
|
||||
"targetErrorCreateDescription": "An error occurred while creating the target",
|
||||
"save": "Save",
|
||||
"proxyAdditional": "Additional Proxy Settings",
|
||||
"proxyAdditionalDescription": "Configure how your resource handles proxy settings",
|
||||
"proxyCustomHeader": "Custom Host Header",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Invalid IP address format",
|
||||
"ipAddressErrorInvalidOctet": "Invalid IP address octet",
|
||||
"path": "Path",
|
||||
"matchPath": "Match Path",
|
||||
"ipAddressRange": "IP Range",
|
||||
"rulesErrorFetch": "Failed to fetch rules",
|
||||
"rulesErrorFetchDescription": "An error occurred while fetching rules",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Server Admin - Pangolin",
|
||||
"licenseTierProfessional": "Professional License",
|
||||
"licenseTierEnterprise": "Enterprise License",
|
||||
"licenseTierCommercial": "Commercial License",
|
||||
"licenseTierPersonal": "Personal License",
|
||||
"licensed": "Licensed",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "View and manage identity providers in the system",
|
||||
"idpDeletedDescription": "Identity provider deleted successfully",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Are you sure you want to permanently delete the identity provider {name}?",
|
||||
"idpQuestionRemove": "Are you sure you want to permanently delete the identity provider?",
|
||||
"idpMessageRemove": "This will remove the identity provider and all associated configurations. Users who authenticate through this provider will no longer be able to log in.",
|
||||
"idpMessageConfirm": "To confirm, please type the name of the identity provider below.",
|
||||
"idpConfirmDelete": "Confirm Delete Identity Provider",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "A display name for this identity provider",
|
||||
"idpAutoProvisionUsers": "Auto Provision Users",
|
||||
"idpAutoProvisionUsersDescription": "When enabled, users will be automatically created in the system upon first login with the ability to map users to roles and organizations.",
|
||||
"licenseBadge": "Professional",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Provider Type",
|
||||
"idpTypeDescription": "Select the type of identity provider you want to configure",
|
||||
"idpOidcConfigure": "OAuth2/OIDC Configuration",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Check your email for the reset code.",
|
||||
"passwordNew": "New Password",
|
||||
"passwordNewConfirm": "Confirm New Password",
|
||||
"changePassword": "Change Password",
|
||||
"changePasswordDescription": "Update your account password",
|
||||
"oldPassword": "Current Password",
|
||||
"newPassword": "New Password",
|
||||
"confirmNewPassword": "Confirm New Password",
|
||||
"changePasswordError": "Failed to change password",
|
||||
"changePasswordErrorDescription": "An error occurred while changing your password",
|
||||
"changePasswordSuccess": "Password Changed Successfully",
|
||||
"changePasswordSuccessDescription": "Your password has been updated successfully",
|
||||
"passwordExpiryRequired": "Password Expiry Required",
|
||||
"passwordExpiryDescription": "This organization requires you to change your password every {maxDays} days.",
|
||||
"changePasswordNow": "Change Password Now",
|
||||
"pincodeAuth": "Authenticator Code",
|
||||
"pincodeSubmit2": "Submit Code",
|
||||
"passwordResetSubmit": "Request Reset",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Professional Edition Required",
|
||||
"licenseTierProfessionalRequiredDescription": "This feature is only available in the Professional Edition.",
|
||||
"actionGetOrg": "Get Organization",
|
||||
"updateOrgUser": "Update Org User",
|
||||
"createOrgUser": "Create Org User",
|
||||
"actionUpdateOrg": "Update Organization",
|
||||
"actionUpdateUser": "Update User",
|
||||
"actionGetUser": "Get User",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Delete Site",
|
||||
"actionGetSite": "Get Site",
|
||||
"actionListSites": "List Sites",
|
||||
"actionApplyBlueprint": "Apply Blueprint",
|
||||
"setupToken": "Setup Token",
|
||||
"setupTokenDescription": "Enter the setup token from the server console.",
|
||||
"setupTokenRequired": "Setup token is required",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Navigation Menu",
|
||||
"navbarDescription": "Main navigation menu for the application",
|
||||
"navbarDocsLink": "Documentation",
|
||||
"commercialEdition": "Commercial Edition",
|
||||
"otpErrorEnable": "Unable to enable 2FA",
|
||||
"otpErrorEnableDescription": "An error occurred while enabling 2FA",
|
||||
"otpSetupCheckCode": "Please enter a 6-digit code",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "All Users",
|
||||
"sidebarIdentityProviders": "Identity Providers",
|
||||
"sidebarLicense": "License",
|
||||
"sidebarClients": "Clients (Beta)",
|
||||
"sidebarClients": "Clients",
|
||||
"sidebarDomains": "Domains",
|
||||
"enableDockerSocket": "Enable Docker Socket",
|
||||
"enableDockerSocketDescription": "Enable Docker Socket discovery for populating container information. Socket path must be provided to Newt.",
|
||||
"sidebarBluePrints": "Blueprints",
|
||||
"blueprints": "Blueprints",
|
||||
"blueprintsDescription": "Apply declarative configurations and view previous runs",
|
||||
"blueprintAdd": "Add Blueprint",
|
||||
"blueprintGoBack": "See all Blueprints",
|
||||
"blueprintCreate": "Create Blueprint",
|
||||
"blueprintCreateDescription2": "Follow the steps below to create and apply a new blueprint",
|
||||
"blueprintDetails": "Blueprint Details",
|
||||
"blueprintDetailsDescription": "See the result of the applied blueprint and any errors that occurred",
|
||||
"blueprintInfo": "Blueprint Information",
|
||||
"message": "Message",
|
||||
"blueprintContentsDescription": "Define the YAML content describing your infrastructure",
|
||||
"blueprintErrorCreateDescription": "An error occurred when applying the blueprint",
|
||||
"blueprintErrorCreate": "Error creating blueprint",
|
||||
"searchBlueprintProgress": "Search blueprints...",
|
||||
"appliedAt": "Applied At",
|
||||
"source": "Source",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Learn More",
|
||||
"viewDockerContainers": "View Docker Containers",
|
||||
"containersIn": "Containers in {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Create Domain",
|
||||
"domainCreatedDescription": "Domain created successfully",
|
||||
"domainDeletedDescription": "Domain deleted successfully",
|
||||
"domainQuestionRemove": "Are you sure you want to remove the domain {domain} from your account?",
|
||||
"domainQuestionRemove": "Are you sure you want to remove the domain from your account?",
|
||||
"domainMessageRemove": "Once removed, the domain will no longer be associated with your account.",
|
||||
"domainMessageConfirm": "To confirm, please type the domain name below.",
|
||||
"domainConfirmDelete": "Confirm Delete Domain",
|
||||
"domainDelete": "Delete Domain",
|
||||
"domain": "Domain",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Update Available",
|
||||
"newtUpdateAvailableInfo": "A new version of Newt is available. Please update to the latest version for the best experience.",
|
||||
"domainPickerEnterDomain": "Domain",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com, or just myapp",
|
||||
"domainPickerPlaceholder": "myapp.example.com",
|
||||
"domainPickerDescription": "Enter the full domain of the resource to see available options.",
|
||||
"domainPickerDescriptionSaas": "Enter a full domain, subdomain, or just a name to see available options",
|
||||
"domainPickerTabAll": "All",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Subdomain: {subdomain}",
|
||||
"domainPickerNamespace": "Namespace: {namespace}",
|
||||
"domainPickerShowMore": "Show More",
|
||||
"regionSelectorTitle": "Select Region",
|
||||
"regionSelectorInfo": "Selecting a region helps us provide better performance for your location. You do not have to be in the same region as your server.",
|
||||
"regionSelectorPlaceholder": "Choose a region",
|
||||
"regionSelectorComingSoon": "Coming Soon",
|
||||
"billingLoadingSubscription": "Loading subscription...",
|
||||
"billingFreeTier": "Free Tier",
|
||||
"billingWarningOverLimit": "Warning: You have exceeded one or more usage limits. Your sites will not connect until you modify your subscription or adjust your usage.",
|
||||
"billingUsageLimitsOverview": "Usage Limits Overview",
|
||||
"billingMonitorUsage": "Monitor your usage against configured limits. If you need limits increased please contact us support@pangolin.net.",
|
||||
"billingDataUsage": "Data Usage",
|
||||
"billingOnlineTime": "Site Online Time",
|
||||
"billingUsers": "Active Users",
|
||||
"billingDomains": "Active Domains",
|
||||
"billingRemoteExitNodes": "Active Self-hosted Nodes",
|
||||
"billingNoLimitConfigured": "No limit configured",
|
||||
"billingEstimatedPeriod": "Estimated Billing Period",
|
||||
"billingIncludedUsage": "Included Usage",
|
||||
"billingIncludedUsageDescription": "Usage included with your current subscription plan",
|
||||
"billingFreeTierIncludedUsage": "Free tier usage allowances",
|
||||
"billingIncluded": "included",
|
||||
"billingEstimatedTotal": "Estimated Total:",
|
||||
"billingNotes": "Notes",
|
||||
"billingEstimateNote": "This is an estimate based on your current usage.",
|
||||
"billingActualChargesMayVary": "Actual charges may vary.",
|
||||
"billingBilledAtEnd": "You will be billed at the end of the billing period.",
|
||||
"billingModifySubscription": "Modify Subscription",
|
||||
"billingStartSubscription": "Start Subscription",
|
||||
"billingRecurringCharge": "Recurring Charge",
|
||||
"billingManageSubscriptionSettings": "Manage your subscription settings and preferences",
|
||||
"billingNoActiveSubscription": "You don't have an active subscription. Start your subscription to increase usage limits.",
|
||||
"billingFailedToLoadSubscription": "Failed to load subscription",
|
||||
"billingFailedToLoadUsage": "Failed to load usage",
|
||||
"billingFailedToGetCheckoutUrl": "Failed to get checkout URL",
|
||||
"billingPleaseTryAgainLater": "Please try again later.",
|
||||
"billingCheckoutError": "Checkout Error",
|
||||
"billingFailedToGetPortalUrl": "Failed to get portal URL",
|
||||
"billingPortalError": "Portal Error",
|
||||
"billingDataUsageInfo": "You're charged for all data transferred through your secure tunnels when connected to the cloud. This includes both incoming and outgoing traffic across all your sites. When you reach your limit, your sites will disconnect until you upgrade your plan or reduce usage. Data is not charged when using nodes.",
|
||||
"billingOnlineTimeInfo": "You're charged based on how long your sites stay connected to the cloud. For example, 44,640 minutes equals one site running 24/7 for a full month. When you reach your limit, your sites will disconnect until you upgrade your plan or reduce usage. Time is not charged when using nodes.",
|
||||
"billingUsersInfo": "You're charged for each user in your organization. Billing is calculated daily based on the number of active user accounts in your org.",
|
||||
"billingDomainInfo": "You're charged for each domain in your organization. Billing is calculated daily based on the number of active domain accounts in your org.",
|
||||
"billingRemoteExitNodesInfo": "You're charged for each managed Node in your organization. Billing is calculated daily based on the number of active managed Nodes in your org.",
|
||||
"domainNotFound": "Domain Not Found",
|
||||
"domainNotFoundDescription": "This resource is disabled because the domain no longer exists our system. Please set a new domain for this resource.",
|
||||
"failed": "Failed",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "There was a problem using your security key. Please try again.",
|
||||
"twoFactorRequired": "Two-factor authentication is required to register a security key.",
|
||||
"twoFactor": "Two-Factor Authentication",
|
||||
"twoFactorAuthentication": "Two-Factor Authentication",
|
||||
"twoFactorDescription": "This organization requires two-factor authentication.",
|
||||
"enableTwoFactor": "Enable Two-Factor Authentication",
|
||||
"organizationSecurityPolicy": "Organization Security Policy",
|
||||
"organizationSecurityPolicyDescription": "This organization has security requirements that must be met before you can access it",
|
||||
"securityRequirements": "Security Requirements",
|
||||
"allRequirementsMet": "All requirements have been met",
|
||||
"completeRequirementsToContinue": "Complete the requirements below to continue accessing this organization",
|
||||
"youCanNowAccessOrganization": "You can now access this organization",
|
||||
"reauthenticationRequired": "Session Length",
|
||||
"reauthenticationDescription": "This organization requires you to log in every {maxDays} days.",
|
||||
"reauthenticationDescriptionHours": "This organization requires you to log in every {maxHours} hours.",
|
||||
"reauthenticateNow": "Log In Again",
|
||||
"adminEnabled2FaOnYourAccount": "Your administrator has enabled two-factor authentication for {email}. Please complete the setup process to continue.",
|
||||
"continueToApplication": "Continue to Application",
|
||||
"securityKeyAdd": "Add Security Key",
|
||||
"securityKeyRegisterTitle": "Register New Security Key",
|
||||
"securityKeyRegisterDescription": "Connect your security key and enter a name to identify it",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "DNS changes may take some time to propagate across the internet. This can take anywhere from a few minutes to 48 hours, depending on your DNS provider and TTL settings.",
|
||||
"resourcePortRequired": "Port number is required for non-HTTP resources",
|
||||
"resourcePortNotAllowed": "Port number should not be set for HTTP resources",
|
||||
"billingPricingCalculatorLink": "Pricing Calculator",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "I agree to the",
|
||||
"termsOfService": "terms of service",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "External Proxy Enabled",
|
||||
"addNewTarget": "Add New Target",
|
||||
"targetsList": "Targets List",
|
||||
"advancedMode": "Advanced Mode",
|
||||
"targetErrorDuplicateTargetFound": "Duplicate target found",
|
||||
"healthCheckHealthy": "Healthy",
|
||||
"healthCheckUnhealthy": "Unhealthy",
|
||||
"healthCheckUnknown": "Unknown",
|
||||
"healthCheck": "Health Check",
|
||||
"configureHealthCheck": "Configure Health Check",
|
||||
"configureHealthCheckDescription": "Set up health monitoring for {target}",
|
||||
"enableHealthChecks": "Enable Health Checks",
|
||||
"enableHealthChecksDescription": "Monitor the health of this target. You can monitor a different endpoint than the target if required.",
|
||||
"healthScheme": "Method",
|
||||
"healthSelectScheme": "Select Method",
|
||||
"healthCheckPath": "Path",
|
||||
"healthHostname": "IP / Host",
|
||||
"healthPort": "Port",
|
||||
"healthCheckPathDescription": "The path to check for health status.",
|
||||
"healthyIntervalSeconds": "Healthy Interval",
|
||||
"unhealthyIntervalSeconds": "Unhealthy Interval",
|
||||
"IntervalSeconds": "Healthy Interval",
|
||||
"timeoutSeconds": "Timeout",
|
||||
"timeIsInSeconds": "Time is in seconds",
|
||||
"retryAttempts": "Retry Attempts",
|
||||
"expectedResponseCodes": "Expected Response Codes",
|
||||
"expectedResponseCodesDescription": "HTTP status code that indicates healthy status. If left blank, 200-300 is considered healthy.",
|
||||
"customHeaders": "Custom Headers",
|
||||
"customHeadersDescription": "Headers new line separated: Header-Name: value",
|
||||
"headersValidationError": "Headers must be in the format: Header-Name: value",
|
||||
"saveHealthCheck": "Save Health Check",
|
||||
"healthCheckSaved": "Health Check Saved",
|
||||
"healthCheckSavedDescription": "Health check configuration has been saved successfully",
|
||||
"healthCheckError": "Health Check Error",
|
||||
"healthCheckErrorDescription": "An error occurred while saving the health check configuration",
|
||||
"healthCheckPathRequired": "Health check path is required",
|
||||
"healthCheckMethodRequired": "HTTP method is required",
|
||||
"healthCheckIntervalMin": "Check interval must be at least 5 seconds",
|
||||
"healthCheckTimeoutMin": "Timeout must be at least 1 second",
|
||||
"healthCheckRetryMin": "Retry attempts must be at least 1",
|
||||
"httpMethod": "HTTP Method",
|
||||
"selectHttpMethod": "Select HTTP method",
|
||||
"domainPickerSubdomainLabel": "Subdomain",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Enter a subdomain to search and select from available free domains.",
|
||||
"domainPickerFreeDomains": "Free Domains",
|
||||
"domainPickerSearchForAvailableDomains": "Search for available domains",
|
||||
"domainPickerNotWorkSelfHosted": "Note: Free provided domains are not available for self-hosted instances right now.",
|
||||
"resourceDomain": "Domain",
|
||||
"resourceEditDomain": "Edit Domain",
|
||||
"siteName": "Site Name",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protocol",
|
||||
"editInternalResourceDialogSitePort": "Site Port",
|
||||
"editInternalResourceDialogTargetConfiguration": "Target Configuration",
|
||||
"editInternalResourceDialogDestinationIP": "Destination IP",
|
||||
"editInternalResourceDialogDestinationPort": "Destination Port",
|
||||
"editInternalResourceDialogCancel": "Cancel",
|
||||
"editInternalResourceDialogSaveResource": "Save Resource",
|
||||
"editInternalResourceDialogSuccess": "Success",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Site Port",
|
||||
"createInternalResourceDialogSitePortDescription": "Use this port to access the resource on the site when connected with a client.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Target Configuration",
|
||||
"createInternalResourceDialogDestinationIP": "Destination IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "The IP address of the resource on the site's network.",
|
||||
"createInternalResourceDialogDestinationPort": "Destination Port",
|
||||
"createInternalResourceDialogDestinationIPDescription": "The IP or hostname address of the resource on the site's network.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "The port on the destination IP where the resource is accessible.",
|
||||
"createInternalResourceDialogCancel": "Cancel",
|
||||
"createInternalResourceDialogCreateResource": "Create Resource",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Auto Login Error",
|
||||
"autoLoginErrorNoRedirectUrl": "No redirect URL received from the identity provider.",
|
||||
"autoLoginErrorGeneratingUrl": "Failed to generate authentication URL.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Remote Nodes",
|
||||
"remoteExitNodeDescription": "Self-host one or more remote nodes to extend your network connectivity and reduce reliance on the cloud",
|
||||
"remoteExitNodes": "Nodes",
|
||||
"searchRemoteExitNodes": "Search nodes...",
|
||||
"remoteExitNodeAdd": "Add Node",
|
||||
"remoteExitNodeErrorDelete": "Error deleting node",
|
||||
"remoteExitNodeQuestionRemove": "Are you sure you want to remove the node from the organization?",
|
||||
"remoteExitNodeMessageRemove": "Once removed, the node will no longer be accessible.",
|
||||
"remoteExitNodeConfirmDelete": "Confirm Delete Node",
|
||||
"remoteExitNodeDelete": "Delete Node",
|
||||
"sidebarRemoteExitNodes": "Remote Nodes",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Create Node",
|
||||
"description": "Create a new node to extend your network connectivity",
|
||||
"viewAllButton": "View All Nodes",
|
||||
"strategy": {
|
||||
"title": "Creation Strategy",
|
||||
"description": "Choose this to manually configure your node or generate new credentials.",
|
||||
"adopt": {
|
||||
"title": "Adopt Node",
|
||||
"description": "Choose this if you already have the credentials for the node."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Generate Keys",
|
||||
"description": "Choose this if you want to generate new keys for the node"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Adopt Existing Node",
|
||||
"description": "Enter the credentials of the existing node you want to adopt",
|
||||
"nodeIdLabel": "Node ID",
|
||||
"nodeIdDescription": "The ID of the existing node you want to adopt",
|
||||
"secretLabel": "Secret",
|
||||
"secretDescription": "The secret key of the existing node",
|
||||
"submitButton": "Adopt Node"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Generated Credentials",
|
||||
"description": "Use these generated credentials to configure your node",
|
||||
"nodeIdTitle": "Node ID",
|
||||
"secretTitle": "Secret",
|
||||
"saveCredentialsTitle": "Add Credentials to Config",
|
||||
"saveCredentialsDescription": "Add these credentials to your self-hosted Pangolin node configuration file to complete the connection.",
|
||||
"submitButton": "Create Node"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "Node ID and Secret are required when adopting an existing node"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Failed to load defaults",
|
||||
"defaultsNotLoaded": "Defaults not loaded",
|
||||
"createFailed": "Failed to create node"
|
||||
},
|
||||
"success": {
|
||||
"created": "Node created successfully"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Node Selection",
|
||||
"remoteExitNodeSelectionDescription": "Select a node to route traffic through for this local site",
|
||||
"remoteExitNodeRequired": "A node must be selected for local sites",
|
||||
"noRemoteExitNodesAvailable": "No Nodes Available",
|
||||
"noRemoteExitNodesAvailableDescription": "No nodes are available for this organization. Create a node first to use local sites.",
|
||||
"exitNode": "Exit Node",
|
||||
"country": "Country",
|
||||
"rulesMatchCountry": "Currently based on source IP",
|
||||
"managedSelfHosted": {
|
||||
"title": "Managed Self-Hosted",
|
||||
"description": "More reliable and low-maintenance self-hosted Pangolin server with extra bells and whistles",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Convert This Node to Managed Self-Hosted"
|
||||
},
|
||||
"internationaldomaindetected": "International Domain Detected",
|
||||
"willbestoredas": "Will be stored as:"
|
||||
}
|
||||
"willbestoredas": "Will be stored as:",
|
||||
"roleMappingDescription": "Determine how roles are assigned to users when they sign in when Auto Provision is enabled.",
|
||||
"selectRole": "Select a Role",
|
||||
"roleMappingExpression": "Expression",
|
||||
"selectRolePlaceholder": "Choose a role",
|
||||
"selectRoleDescription": "Select a role to assign to all users from this identity provider",
|
||||
"roleMappingExpressionDescription": "Enter a JMESPath expression to extract role information from the ID token",
|
||||
"idpTenantIdRequired": "Tenant ID is required",
|
||||
"invalidValue": "Invalid value",
|
||||
"idpTypeLabel": "Identity Provider Type",
|
||||
"roleMappingExpressionPlaceholder": "e.g., contains(groups, 'admin') && 'Admin' || 'Member'",
|
||||
"idpGoogleConfiguration": "Google Configuration",
|
||||
"idpGoogleConfigurationDescription": "Configure your Google OAuth2 credentials",
|
||||
"idpGoogleClientIdDescription": "Your Google OAuth2 Client ID",
|
||||
"idpGoogleClientSecretDescription": "Your Google OAuth2 Client Secret",
|
||||
"idpAzureConfiguration": "Azure Entra ID Configuration",
|
||||
"idpAzureConfigurationDescription": "Configure your Azure Entra ID OAuth2 credentials",
|
||||
"idpTenantId": "Tenant ID",
|
||||
"idpTenantIdPlaceholder": "your-tenant-id",
|
||||
"idpAzureTenantIdDescription": "Your Azure tenant ID (found in Azure Active Directory overview)",
|
||||
"idpAzureClientIdDescription": "Your Azure App Registration Client ID",
|
||||
"idpAzureClientSecretDescription": "Your Azure App Registration Client Secret",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Google Configuration",
|
||||
"idpAzureConfigurationTitle": "Azure Entra ID Configuration",
|
||||
"idpTenantIdLabel": "Tenant ID",
|
||||
"idpAzureClientIdDescription2": "Your Azure App Registration Client ID",
|
||||
"idpAzureClientSecretDescription2": "Your Azure App Registration Client Secret",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC provider",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Subnet",
|
||||
"subnetDescription": "The subnet for this organization's network configuration.",
|
||||
"authPage": "Auth Page",
|
||||
"authPageDescription": "Configure the auth page for your organization",
|
||||
"authPageDomain": "Auth Page Domain",
|
||||
"noDomainSet": "No domain set",
|
||||
"changeDomain": "Change Domain",
|
||||
"selectDomain": "Select Domain",
|
||||
"restartCertificate": "Restart Certificate",
|
||||
"editAuthPageDomain": "Edit Auth Page Domain",
|
||||
"setAuthPageDomain": "Set Auth Page Domain",
|
||||
"failedToFetchCertificate": "Failed to fetch certificate",
|
||||
"failedToRestartCertificate": "Failed to restart certificate",
|
||||
"addDomainToEnableCustomAuthPages": "Add a domain to enable custom authentication pages for your organization",
|
||||
"selectDomainForOrgAuthPage": "Select a domain for the organization's authentication page",
|
||||
"domainPickerProvidedDomain": "Provided Domain",
|
||||
"domainPickerFreeProvidedDomain": "Free Provided Domain",
|
||||
"domainPickerVerified": "Verified",
|
||||
"domainPickerUnverified": "Unverified",
|
||||
"domainPickerInvalidSubdomainStructure": "This subdomain contains invalid characters or structure. It will be sanitized automatically when you save.",
|
||||
"domainPickerError": "Error",
|
||||
"domainPickerErrorLoadDomains": "Failed to load organization domains",
|
||||
"domainPickerErrorCheckAvailability": "Failed to check domain availability",
|
||||
"domainPickerInvalidSubdomain": "Invalid subdomain",
|
||||
"domainPickerInvalidSubdomainRemoved": "The input \"{sub}\" was removed because it's not valid.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" could not be made valid for {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Subdomain sanitized",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" was corrected to \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Sign in to your organization",
|
||||
"orgAuthChooseIdpDescription": "Choose your identity provider to continue",
|
||||
"orgAuthNoIdpConfigured": "This organization doesn't have any identity providers configured. You can log in with your Pangolin identity instead.",
|
||||
"orgAuthSignInWithPangolin": "Sign in with Pangolin",
|
||||
"subscriptionRequiredToUse": "A subscription is required to use this feature.",
|
||||
"idpDisabled": "Identity providers are disabled.",
|
||||
"orgAuthPageDisabled": "Organization auth page is disabled.",
|
||||
"domainRestartedDescription": "Domain verification restarted successfully",
|
||||
"resourceAddEntrypointsEditFile": "Edit file: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Edit file: docker-compose.yml",
|
||||
"emailVerificationRequired": "Email verification is required. Please log in again via {dashboardUrl}/auth/login complete this step. Then, come back here.",
|
||||
"twoFactorSetupRequired": "Two-factor authentication setup is required. Please log in again via {dashboardUrl}/auth/login complete this step. Then, come back here.",
|
||||
"additionalSecurityRequired": "Additional Security Required",
|
||||
"organizationRequiresAdditionalSteps": "This organization requires additional security steps before you can access resources.",
|
||||
"completeTheseSteps": "Complete these steps",
|
||||
"enableTwoFactorAuthentication": "Enable two-factor authentication",
|
||||
"completeSecuritySteps": "Complete Security Steps",
|
||||
"securitySettings": "Security Settings",
|
||||
"securitySettingsDescription": "Configure security policies for your organization",
|
||||
"requireTwoFactorForAllUsers": "Require Two-Factor Authentication for All Users",
|
||||
"requireTwoFactorDescription": "When enabled, all internal users in this organization must have two-factor authentication enabled to access the organization.",
|
||||
"requireTwoFactorDisabledDescription": "This feature requires a valid license (Enterprise) or active subscription (SaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "You must enable two-factor authentication for your account before enforcing it for all users",
|
||||
"maxSessionLength": "Maximum Session Length",
|
||||
"maxSessionLengthDescription": "Set the maximum duration for user sessions. After this time, users will need to re-authenticate.",
|
||||
"maxSessionLengthDisabledDescription": "This feature requires a valid license (Enterprise) or active subscription (SaaS)",
|
||||
"selectSessionLength": "Select session length",
|
||||
"unenforced": "Unenforced",
|
||||
"1Hour": "1 hour",
|
||||
"3Hours": "3 hours",
|
||||
"6Hours": "6 hours",
|
||||
"12Hours": "12 hours",
|
||||
"1DaySession": "1 day",
|
||||
"3Days": "3 days",
|
||||
"7Days": "7 days",
|
||||
"14Days": "14 days",
|
||||
"30DaysSession": "30 days",
|
||||
"90DaysSession": "90 days",
|
||||
"180DaysSession": "180 days",
|
||||
"passwordExpiryDays": "Password Expiry",
|
||||
"editPasswordExpiryDescription": "Set the number of days before users are required to change their password.",
|
||||
"selectPasswordExpiry": "Select password expiry",
|
||||
"30Days": "30 days",
|
||||
"1Day": "1 day",
|
||||
"60Days": "60 days",
|
||||
"90Days": "90 days",
|
||||
"180Days": "180 days",
|
||||
"1Year": "1 year",
|
||||
"subscriptionBadge": "Subscription Required",
|
||||
"securityPolicyChangeWarning": "Security Policy Change Warning",
|
||||
"securityPolicyChangeDescription": "You are about to change security policy settings. After saving, you may need to reauthenticate to comply with these policy updates. All users who are not compliant will also need to reauthenticate.",
|
||||
"securityPolicyChangeConfirmMessage": "I confirm",
|
||||
"securityPolicyChangeWarningText": "This will affect all users in the organization",
|
||||
"authPageErrorUpdateMessage": "An error occurred while updating the auth page settings",
|
||||
"authPageErrorUpdate": "Unable to update auth page",
|
||||
"authPageUpdated": "Auth page updated successfully",
|
||||
"healthCheckNotAvailable": "Local",
|
||||
"rewritePath": "Rewrite Path",
|
||||
"rewritePathDescription": "Optionally rewrite the path before forwarding to the target.",
|
||||
"continueToApplication": "Continue to application",
|
||||
"checkingInvite": "Checking Invite",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Remove Header Auth",
|
||||
"resourceHeaderAuthRemoveDescription": "Header authentication removed successfully.",
|
||||
"resourceErrorHeaderAuthRemove": "Failed to remove Header Authentication",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Could not remove header authentication for the resource.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Header Authentication Enabled",
|
||||
"resourceHeaderAuthProtectionDisabled": "Header Authentication Disabled",
|
||||
"headerAuthRemove": "Remove Header Auth",
|
||||
"headerAuthAdd": "Add Header Auth",
|
||||
"resourceErrorHeaderAuthSetup": "Failed to set Header Authentication",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Could not set header authentication for the resource.",
|
||||
"resourceHeaderAuthSetup": "Header Authentication set successfully",
|
||||
"resourceHeaderAuthSetupDescription": "Header authentication has been successfully set.",
|
||||
"resourceHeaderAuthSetupTitle": "Set Header Authentication",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Set the basic auth credentials (username and password) to protect this resource with HTTP Header Authentication. Access it using the format https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Set Header Authentication",
|
||||
"actionSetResourceHeaderAuth": "Set Header Authentication",
|
||||
"enterpriseEdition": "Enterprise Edition",
|
||||
"unlicensed": "Unlicensed",
|
||||
"beta": "Beta",
|
||||
"manageClients": "Manage Clients",
|
||||
"manageClientsDescription": "Clients are devices that can connect to your sites",
|
||||
"licenseTableValidUntil": "Valid Until",
|
||||
"saasLicenseKeysSettingsTitle": "Enterprise Licenses",
|
||||
"saasLicenseKeysSettingsDescription": "Generate and manage Enterprise license keys for self-hosted Pangolin instances",
|
||||
"sidebarEnterpriseLicenses": "Licenses",
|
||||
"generateLicenseKey": "Generate License Key",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Please enter a valid email address",
|
||||
"useCaseTypeRequired": "Please select a use case type",
|
||||
"firstNameRequired": "First name is required",
|
||||
"lastNameRequired": "Last name is required",
|
||||
"primaryUseRequired": "Please describe your primary use",
|
||||
"jobTitleRequiredBusiness": "Job title is required for business use",
|
||||
"industryRequiredBusiness": "Industry is required for business use",
|
||||
"stateProvinceRegionRequired": "State/Province/Region is required",
|
||||
"postalZipCodeRequired": "Postal/ZIP Code is required",
|
||||
"companyNameRequiredBusiness": "Company name is required for business use",
|
||||
"countryOfResidenceRequiredBusiness": "Country of residence is required for business use",
|
||||
"countryRequiredPersonal": "Country is required for personal use",
|
||||
"agreeToTermsRequired": "You must agree to the terms",
|
||||
"complianceConfirmationRequired": "You must confirm compliance with the Fossorial Commercial License"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Personal Use",
|
||||
"description": "For individual, non-commercial use such as learning, personal projects, or experimentation."
|
||||
},
|
||||
"business": {
|
||||
"title": "Business Use",
|
||||
"description": "For use within organizations, companies, or commercial or revenue-generating activities."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Email & License Type",
|
||||
"description": "Enter your email and choose your license type"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Personal Information",
|
||||
"description": "Tell us about yourself"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Contact Information",
|
||||
"description": "Your contact details"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Terms & Generate",
|
||||
"description": "Review and accept terms to generate your license"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Usage Disclosure",
|
||||
"description": "Select the license tier that accurately reflects your intended use. The Personal License permits free use of the Software for individual, non-commercial or small-scale commercial activities with annual gross revenue under $100,000 USD. Any use beyond these limits — including use within a business, organization, or other revenue-generating environment — requires a valid Enterprise License and payment of the applicable licensing fee. All users, whether Personal or Enterprise, must comply with the Fossorial Commercial License Terms."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Trial Period Information",
|
||||
"description": "This License Key enables Enterprise features for a 7-day evaluation period. Continued access to Paid Features beyond the evaluation period requires activation under a valid Personal or Enterprise License. For Enterprise licensing, contact sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Are you using Pangolin for personal or business use?",
|
||||
"firstName": "First Name",
|
||||
"lastName": "Last Name",
|
||||
"jobTitle": "Job Title",
|
||||
"primaryUseQuestion": "What do you primarily plan to use Pangolin for?",
|
||||
"industryQuestion": "What is your industry?",
|
||||
"prospectiveUsersQuestion": "How many prospective users do you expect to have?",
|
||||
"prospectiveSitesQuestion": "How many prospective sites (tunnels) do you expect to have?",
|
||||
"companyName": "Company name",
|
||||
"countryOfResidence": "Country of residence",
|
||||
"stateProvinceRegion": "State / Province / Region",
|
||||
"postalZipCode": "Postal / ZIP Code",
|
||||
"companyWebsite": "Company website",
|
||||
"companyPhoneNumber": "Company phone number",
|
||||
"country": "Country",
|
||||
"phoneNumberOptional": "Phone number (optional)",
|
||||
"complianceConfirmation": "I confirm that the information I provided is accurate and that I am in compliance with the Fossorial Commercial License. Reporting inaccurate information or misidentifying use of the product is a violation of the license and may result in your key getting revoked."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Close",
|
||||
"previous": "Previous",
|
||||
"next": "Next",
|
||||
"generateLicenseKey": "Generate License Key"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "License key generated successfully",
|
||||
"description": "Your license key has been generated and is ready to use."
|
||||
},
|
||||
"error": {
|
||||
"title": "Failed to generate license key",
|
||||
"description": "An error occurred while generating the license key."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Priority",
|
||||
"priorityDescription": "Higher priority routes are evaluated first. Priority = 100 means automatic ordering (system decides). Use another number to enforce manual priority.",
|
||||
"instanceName": "Instance Name",
|
||||
"pathMatchModalTitle": "Configure Path Matching",
|
||||
"pathMatchModalDescription": "Set up how incoming requests should be matched based on their path.",
|
||||
"pathMatchType": "Match Type",
|
||||
"pathMatchPrefix": "Prefix",
|
||||
"pathMatchExact": "Exact",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Path Value",
|
||||
"clear": "Clear",
|
||||
"saveChanges": "Save Changes",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/path",
|
||||
"pathMatchPrefixHelp": "Example: /api matches /api, /api/users, etc.",
|
||||
"pathMatchExactHelp": "Example: /api matches only /api",
|
||||
"pathMatchRegexHelp": "Example: ^/api/.* matches /api/anything",
|
||||
"pathRewriteModalTitle": "Configure Path Rewriting",
|
||||
"pathRewriteModalDescription": "Transform the matched path before forwarding to the target.",
|
||||
"pathRewriteType": "Rewrite Type",
|
||||
"pathRewritePrefixOption": "Prefix - Replace prefix",
|
||||
"pathRewriteExactOption": "Exact - Replace entire path",
|
||||
"pathRewriteRegexOption": "Regex - Pattern replacement",
|
||||
"pathRewriteStripPrefixOption": "Strip Prefix - Remove prefix",
|
||||
"pathRewriteValue": "Rewrite Value",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "Replace the matched prefix with this value",
|
||||
"pathRewriteExactHelp": "Replace the entire path with this value when the path matches exactly",
|
||||
"pathRewriteRegexHelp": "Use capture groups like $1, $2 for replacement",
|
||||
"pathRewriteStripPrefixHelp": "Leave empty to strip prefix or provide new prefix",
|
||||
"pathRewritePrefix": "Prefix",
|
||||
"pathRewriteExact": "Exact",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Strip",
|
||||
"pathRewriteStripLabel": "strip",
|
||||
"sidebarEnableEnterpriseLicense": "Enable Enterprise License",
|
||||
"cannotbeUndone": "This can not be undone.",
|
||||
"toConfirm": "to confirm",
|
||||
"deleteClientQuestion": "Are you sure you want to remove the client from the site and organization?",
|
||||
"clientMessageRemove": "Once removed, the client will no longer be able to connect to the site.",
|
||||
"sidebarLogs": "Logs",
|
||||
"request": "Request",
|
||||
"logs": "Logs",
|
||||
"logsSettingsDescription": "Monitor logs collected from this orginization",
|
||||
"searchLogs": "Search logs...",
|
||||
"action": "Action",
|
||||
"actor": "Actor",
|
||||
"timestamp": "Timestamp",
|
||||
"accessLogs": "Access Logs",
|
||||
"exportCsv": "Export CSV",
|
||||
"actorId": "Actor ID",
|
||||
"allowedByRule": "Allowed by Rule",
|
||||
"allowedNoAuth": "Allowed No Auth",
|
||||
"validAccessToken": "Valid Access Token",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Valid Password",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Resource Blocked",
|
||||
"droppedByRule": "Dropped by Rule",
|
||||
"noSessions": "No Sessions",
|
||||
"temporaryRequestToken": "Temporary Request Token",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Reason",
|
||||
"requestLogs": "Request Logs",
|
||||
"host": "Host",
|
||||
"location": "Location",
|
||||
"actionLogs": "Action Logs",
|
||||
"sidebarLogsRequest": "Request Logs",
|
||||
"sidebarLogsAccess": "Access Logs",
|
||||
"sidebarLogsAction": "Action Logs",
|
||||
"logRetention": "Log Retention",
|
||||
"logRetentionDescription": "Manage how long different types of logs are retained for this organization or disable them",
|
||||
"requestLogsDescription": "View detailed request logs for resources in this organization",
|
||||
"logRetentionRequestLabel": "Request Log Retention",
|
||||
"logRetentionRequestDescription": "How long to retain request logs",
|
||||
"logRetentionAccessLabel": "Access Log Retention",
|
||||
"logRetentionAccessDescription": "How long to retain access logs",
|
||||
"logRetentionActionLabel": "Action Log Retention",
|
||||
"logRetentionActionDescription": "How long to retain action logs",
|
||||
"logRetentionDisabled": "Disabled",
|
||||
"logRetention3Days": "3 days",
|
||||
"logRetention7Days": "7 days",
|
||||
"logRetention14Days": "14 days",
|
||||
"logRetention30Days": "30 days",
|
||||
"logRetention90Days": "90 days",
|
||||
"logRetentionForever": "Forever",
|
||||
"actionLogsDescription": "View a history of actions performed in this organization",
|
||||
"accessLogsDescription": "View access auth requests for resources in this organization",
|
||||
"licenseRequiredToUse": "An Enterprise license is required to use this feature.",
|
||||
"certResolver": "Certificate Resolver",
|
||||
"certResolverDescription": "Select the certificate resolver to use for this resource.",
|
||||
"selectCertResolver": "Select Certificate Resolver",
|
||||
"enterCustomResolver": "Enter Custom Resolver",
|
||||
"preferWildcardCert": "Prefer Wildcard Certificate",
|
||||
"unverified": "Unverified",
|
||||
"domainSetting": "Domain Settings",
|
||||
"domainSettingDescription": "Configure settings for your domain",
|
||||
"preferWildcardCertDescription": "Attempt to generate a wildcard certificate (require a properly configured certificate resolver).",
|
||||
"recordName": "Record Name",
|
||||
"auto": "Auto",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "How to Add Records",
|
||||
"dnsRecord": "DNS Records",
|
||||
"required": "Required",
|
||||
"domainSettingsUpdated": "Domain settings updated successfully",
|
||||
"orgOrDomainIdMissing": "Organization or Domain ID is missing",
|
||||
"loadingDNSRecords": "Loading DNS records...",
|
||||
"olmUpdateAvailableInfo": "An updated version of Olm is available. Please update to the latest version for the best experience.",
|
||||
"client": "Client",
|
||||
"proxyProtocol": "Proxy Protocol Settings",
|
||||
"proxyProtocolDescription": "Configure Proxy Protocol to preserve client IP addresses for TCP/UDP services.",
|
||||
"enableProxyProtocol": "Enable Proxy Protocol",
|
||||
"proxyProtocolInfo": "Preserve client IP addresses for TCP/UDP backends",
|
||||
"proxyProtocolVersion": "Proxy Protocol Version",
|
||||
"version1": " Version 1 (Recommended)",
|
||||
"version2": "Version 2",
|
||||
"versionDescription": "Version 1 is text-based and widely supported. Version 2 is binary and more efficient but less compatible. Make sure servers transport is added to dynamic config.",
|
||||
"warning": "Warning",
|
||||
"proxyProtocolWarning": "Your backend application must be configured to accept Proxy Protocol connections. If your backend doesn't support Proxy Protocol, enabling this will break all connections so only enable this if you know what you're doing. Make sure to configure your backend to trust Proxy Protocol headers from Traefik.",
|
||||
"restarting": "Restarting...",
|
||||
"manual": "Manual",
|
||||
"messageSupport": "Message Support",
|
||||
"supportNotAvailableTitle": "Support Not Available",
|
||||
"supportNotAvailableDescription": "Support is not available right now. You can send an email to support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Support Request Sent",
|
||||
"supportRequestSentDescription": "Your message has been sent successfully.",
|
||||
"supportRequestFailedTitle": "Failed to Send Request",
|
||||
"supportRequestFailedDescription": "An error occurred while sending your support request.",
|
||||
"supportSubjectRequired": "Subject is required",
|
||||
"supportSubjectMaxLength": "Subject must be 255 characters or less",
|
||||
"supportMessageRequired": "Message is required",
|
||||
"supportReplyTo": "Reply To",
|
||||
"supportSubject": "Subject",
|
||||
"supportSubjectPlaceholder": "Enter subject",
|
||||
"supportMessage": "Message",
|
||||
"supportMessagePlaceholder": "Enter your message",
|
||||
"supportSending": "Sending...",
|
||||
"supportSend": "Send",
|
||||
"supportMessageSent": "Message Sent!",
|
||||
"supportWillContact": "We'll be in touch shortly!",
|
||||
"selectLogRetention": "Select log retention",
|
||||
"showColumns": "Show Columns",
|
||||
"hideColumns": "Hide Columns",
|
||||
"columnVisibility": "Column Visibility",
|
||||
"toggleColumn": "Toggle {columnName} column",
|
||||
"allColumns": "All Columns",
|
||||
"defaultColumns": "Default Columns",
|
||||
"customizeView": "Customize View",
|
||||
"viewOptions": "View Options",
|
||||
"selectAll": "Select All",
|
||||
"selectNone": "Select None",
|
||||
"selectedResources": "Selected Resources",
|
||||
"enableSelected": "Enable Selected",
|
||||
"disableSelected": "Disable Selected",
|
||||
"checkSelectedStatus": "Check Status of Selected"
|
||||
}
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "Editar",
|
||||
"siteConfirmDelete": "Confirmar Borrar Sitio",
|
||||
"siteDelete": "Eliminar sitio",
|
||||
"siteMessageRemove": "Una vez eliminado, el sitio ya no será accesible. Todos los recursos y objetivos asociados con el sitio también serán eliminados.",
|
||||
"siteMessageConfirm": "Para confirmar, por favor escriba el nombre del sitio a continuación.",
|
||||
"siteQuestionRemove": "¿Está seguro de que desea eliminar el sitio {selectedSite} de la organización?",
|
||||
"siteMessageRemove": "Una vez eliminado, el sitio ya no será accesible. Todos los objetivos asociados con el sitio también serán eliminados.",
|
||||
"siteQuestionRemove": "¿Está seguro que desea eliminar el sitio de la organización?",
|
||||
"siteManageSites": "Administrar Sitios",
|
||||
"siteDescription": "Permitir conectividad a tu red a través de túneles seguros",
|
||||
"siteCreate": "Crear sitio",
|
||||
@@ -67,7 +66,7 @@
|
||||
"siteDocker": "Expandir para detalles de despliegue de Docker",
|
||||
"toggle": "Cambiar",
|
||||
"dockerCompose": "Componer Docker",
|
||||
"dockerRun": "Docker Run",
|
||||
"dockerRun": "Ejecutar Docker",
|
||||
"siteLearnLocal": "Los sitios locales no tienen túnel, aprender más",
|
||||
"siteConfirmCopy": "He copiado la configuración",
|
||||
"searchSitesProgress": "Buscar sitios...",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Utilice cualquier cliente Wirex Guard para establecer un túnel. Se requiere una configuración manual de NAT.",
|
||||
"siteWgDescriptionSaas": "Utilice cualquier cliente de WireGuard para establecer un túnel. Se requiere configuración manual de NAT. SOLO FUNCIONA EN NODOS AUTOGESTIONADOS",
|
||||
"siteLocalDescription": "Solo recursos locales. Sin túneles.",
|
||||
"siteLocalDescriptionSaas": "Solo recursos locales. Sin túneles. SOLO FUNCIONA EN NODOS AUTOGESTIONADOS",
|
||||
"siteLocalDescriptionSaas": "Solo recursos locales. No hay túneles. Sólo disponible en nodos remotos.",
|
||||
"siteSeeAll": "Ver todos los sitios",
|
||||
"siteTunnelDescription": "Determina cómo quieres conectarte a tu sitio",
|
||||
"siteNewtCredentials": "Credenciales nuevas",
|
||||
@@ -132,7 +131,7 @@
|
||||
"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.",
|
||||
"shareSeeOnce": "Sólo podrá ver este enlace una vez. Asegúrese de copiarlo.",
|
||||
"shareSeeOnce": "Sólo podrás ver este enlace una vez. Asegúrate de copiarlo.",
|
||||
"shareAccessHint": "Cualquiera con este enlace puede acceder al recurso. Compártelo con cuidado.",
|
||||
"shareTokenUsage": "Ver Uso de Token de Acceso",
|
||||
"createLink": "Crear enlace",
|
||||
@@ -154,8 +153,7 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "Para confirmar, por favor escriba el nombre del recurso a continuación.",
|
||||
"resourceQuestionRemove": "¿Está seguro de que desea eliminar el recurso {selectedResource} de la organización?",
|
||||
"resourceQuestionRemove": "¿Está seguro que desea eliminar el recurso de la organización?",
|
||||
"resourceHTTP": "HTTPS Recurso",
|
||||
"resourceHTTPDescription": "Solicitudes de proxy a tu aplicación sobre HTTPS usando un subdominio o dominio base.",
|
||||
"resourceRaw": "Recurso TCP/UDP sin procesar",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Seleccionar sitio",
|
||||
"siteSearch": "Buscar sitio",
|
||||
"siteNotFound": "Sitio no encontrado.",
|
||||
"selectCountry": "Seleccionar país",
|
||||
"searchCountries": "Buscar países...",
|
||||
"noCountryFound": "Ningún país encontrado.",
|
||||
"siteSelectionDescription": "Este sitio proporcionará conectividad al objetivo.",
|
||||
"resourceType": "Tipo de recurso",
|
||||
"resourceTypeDescription": "Determina cómo quieres acceder a tu recurso",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Dominio base",
|
||||
"subdomnainDescription": "El subdominio al que su recurso será accesible.",
|
||||
"resourceRawSettings": "Configuración TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configurar cómo se accederá a su recurso a través de TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configure cómo se accederá a su recurso a través de TCP/UDP. Mapeas el recurso a un puerto en el servidor Pangolin host, así puedes acceder al recurso desde el servidor-public-ip:mapped-port.",
|
||||
"protocol": "Protocolo",
|
||||
"protocolSelect": "Seleccionar un protocolo",
|
||||
"resourcePortNumber": "Número de puerto",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Confirmar eliminación de organización",
|
||||
"orgMessageRemove": "Esta acción es irreversible y eliminará todos los datos asociados.",
|
||||
"orgMessageConfirm": "Para confirmar, por favor escriba el nombre de la organización a continuación.",
|
||||
"orgQuestionRemove": "¿Está seguro que desea eliminar la organización {selectedOrg}?",
|
||||
"orgQuestionRemove": "¿Está seguro que desea eliminar la organización?",
|
||||
"orgUpdated": "Organización actualizada",
|
||||
"orgUpdatedDescription": "La organización ha sido actualizada.",
|
||||
"orgErrorUpdate": "Error al actualizar la organización",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Generar clave API",
|
||||
"apiKeysErrorDelete": "Error al eliminar la clave API",
|
||||
"apiKeysErrorDeleteMessage": "Error al eliminar la clave API",
|
||||
"apiKeysQuestionRemove": "¿Está seguro de que desea eliminar la clave de API {selectedApiKey} de la organización?",
|
||||
"apiKeysQuestionRemove": "¿Está seguro que desea eliminar la clave API de la organización?",
|
||||
"apiKeysMessageRemove": "Una vez eliminada, la clave API ya no podrá ser utilizada.",
|
||||
"apiKeysMessageConfirm": "Para confirmar, por favor escriba el nombre de la clave API a continuación.",
|
||||
"apiKeysDeleteConfirm": "Confirmar Borrar Clave API",
|
||||
"apiKeysDelete": "Borrar Clave API",
|
||||
"apiKeysManage": "Administrar claves API",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Confirmar Borrar Usuario",
|
||||
"userDeleteServer": "Eliminar usuario del servidor",
|
||||
"userMessageRemove": "El usuario será eliminado de todas las organizaciones y será eliminado completamente del servidor.",
|
||||
"userMessageConfirm": "Para confirmar, por favor escriba el nombre del usuario a continuación.",
|
||||
"userQuestionRemove": "¿Está seguro que desea eliminar permanentemente {selectedUser} del servidor?",
|
||||
"userQuestionRemove": "¿Está seguro que desea eliminar permanentemente al usuario del servidor?",
|
||||
"licenseKey": "Clave de licencia",
|
||||
"valid": "Válido",
|
||||
"numberOfSites": "Número de sitios",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Ver Términos de suscripción y licencia comercial",
|
||||
"licenseMessageRemove": "Esto eliminará la clave de licencia y todos los permisos asociados otorgados por ella.",
|
||||
"licenseMessageConfirm": "Para confirmar, por favor escriba la clave de licencia a continuación.",
|
||||
"licenseQuestionRemove": "¿Está seguro que desea eliminar la clave de licencia {selectedKey}?",
|
||||
"licenseQuestionRemove": "¿Está seguro que desea eliminar la clave de licencia?",
|
||||
"licenseKeyDelete": "Eliminar clave de licencia",
|
||||
"licenseKeyDeleteConfirm": "Confirmar eliminar clave de licencia",
|
||||
"licenseTitle": "Administrar estado de licencia",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Ocurrió un error mientras se eliminaba la invitación.",
|
||||
"inviteRemoved": "Invitación eliminada",
|
||||
"inviteRemovedDescription": "La invitación para {email} ha sido eliminada.",
|
||||
"inviteQuestionRemove": "¿Está seguro de que desea eliminar la invitación {email}?",
|
||||
"inviteQuestionRemove": "¿Está seguro de que desea eliminar la invitación?",
|
||||
"inviteMessageRemove": "Una vez eliminada, esta invitación ya no será válida. Siempre puede volver a invitar al usuario más tarde.",
|
||||
"inviteMessageConfirm": "Para confirmar, por favor escriba la dirección de correo electrónico de la invitación a continuación.",
|
||||
"inviteQuestionRegenerate": "¿Estás seguro de que quieres regenerar la invitación para {email}? Esto revocará la invitación anterior.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Ocurrió un error mientras se eliminaba el usuario.",
|
||||
"userOrgRemoved": "Usuario eliminado",
|
||||
"userOrgRemovedDescription": "El usuario {email} ha sido eliminado de la organización.",
|
||||
"userQuestionOrgRemove": "¿Estás seguro de que quieres eliminar {email} de la organización?",
|
||||
"userQuestionOrgRemove": "¿Está seguro que desea eliminar este usuario de la organización?",
|
||||
"userMessageOrgRemove": "Una vez eliminado, este usuario ya no tendrá acceso a la organización. Siempre puede volver a invitarlos más tarde, pero tendrán que aceptar la invitación de nuevo.",
|
||||
"userMessageOrgConfirm": "Para confirmar, por favor escriba el nombre del usuario a continuación.",
|
||||
"userRemoveOrgConfirm": "Confirmar eliminar usuario",
|
||||
"userRemoveOrg": "Eliminar usuario de la organización",
|
||||
"users": "Usuarios",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Ocurrió un error mientras se añadía el usuario al rol.",
|
||||
"userSaved": "Usuario guardado",
|
||||
"userSavedDescription": "El usuario ha sido actualizado.",
|
||||
"autoProvisioned": "Auto asegurado",
|
||||
"autoProvisionedDescription": "Permitir a este usuario ser administrado automáticamente por el proveedor de identidad",
|
||||
"accessControlsDescription": "Administrar lo que este usuario puede acceder y hacer en la organización",
|
||||
"accessControlsSubmit": "Guardar controles de acceso",
|
||||
"roles": "Roles",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Creado el",
|
||||
"proxyErrorInvalidHeader": "Valor de cabecera de host personalizado no válido. Utilice el formato de nombre de dominio, o guarde en blanco para desestablecer cabecera de host personalizada.",
|
||||
"proxyErrorTls": "Nombre de servidor TLS inválido. Utilice el formato de nombre de dominio o guarde en blanco para eliminar el nombre de servidor TLS.",
|
||||
"proxyEnableSSL": "Habilitar SSL (https)",
|
||||
"proxyEnableSSL": "Activar SSL",
|
||||
"proxyEnableSSLDescription": "Activa el cifrado SSL/TLS para conexiones seguras HTTPS a tus objetivos.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Configurar objetivos",
|
||||
"targetErrorFetch": "Error al recuperar los objetivos",
|
||||
"targetErrorFetchDescription": "Se ha producido un error al recuperar los objetivos",
|
||||
"siteErrorFetch": "No se pudo obtener el recurso",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Configuración de conexión segura",
|
||||
"targetTlsSettingsDescription": "Configurar ajustes SSL/TLS para su recurso",
|
||||
"targetTlsSettingsAdvanced": "Ajustes avanzados de TLS",
|
||||
"targetTlsSni": "Nombre del servidor TLS (SNI)",
|
||||
"targetTlsSni": "Nombre del servidor TLS",
|
||||
"targetTlsSniDescription": "El nombre del servidor TLS a usar para SNI. Deje en blanco para usar el valor predeterminado.",
|
||||
"targetTlsSubmit": "Guardar ajustes",
|
||||
"targets": "Configuración de objetivos",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Mantener conexiones en el mismo objetivo de backend para toda su sesión.",
|
||||
"methodSelect": "Seleccionar método",
|
||||
"targetSubmit": "Añadir destino",
|
||||
"targetNoOne": "No hay objetivos. Agregue un objetivo usando el formulario.",
|
||||
"targetNoOne": "Este recurso no tiene ningún objetivo. Agrega un objetivo para configurar dónde enviar peticiones al backend.",
|
||||
"targetNoOneDescription": "Si se añade más de un objetivo anterior se activará el balance de carga.",
|
||||
"targetsSubmit": "Guardar objetivos",
|
||||
"addTarget": "Añadir destino",
|
||||
"targetErrorInvalidIp": "Dirección IP inválida",
|
||||
"targetErrorInvalidIpDescription": "Por favor, introduzca una dirección IP válida o nombre de host",
|
||||
"targetErrorInvalidPort": "Puerto inválido",
|
||||
"targetErrorInvalidPortDescription": "Por favor, introduzca un número de puerto válido",
|
||||
"targetErrorNoSite": "Ningún sitio seleccionado",
|
||||
"targetErrorNoSiteDescription": "Por favor, seleccione un sitio para el objetivo",
|
||||
"targetCreated": "Objetivo creado",
|
||||
"targetCreatedDescription": "El objetivo se ha creado correctamente",
|
||||
"targetErrorCreate": "Error al crear el objetivo",
|
||||
"targetErrorCreateDescription": "Se ha producido un error al crear el objetivo",
|
||||
"save": "Guardar",
|
||||
"proxyAdditional": "Ajustes adicionales del proxy",
|
||||
"proxyAdditionalDescription": "Configura cómo tu recurso maneja la configuración del proxy",
|
||||
"proxyCustomHeader": "Cabecera de host personalizada",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Formato de dirección IP inválido",
|
||||
"ipAddressErrorInvalidOctet": "Octet de dirección IP no válido",
|
||||
"path": "Ruta",
|
||||
"matchPath": "Coincidir ruta",
|
||||
"ipAddressRange": "Rango IP",
|
||||
"rulesErrorFetch": "Error al obtener las reglas",
|
||||
"rulesErrorFetchDescription": "Se ha producido un error al recuperar las reglas",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Admin Servidor - Pangolin",
|
||||
"licenseTierProfessional": "Licencia profesional",
|
||||
"licenseTierEnterprise": "Licencia Enterprise",
|
||||
"licenseTierCommercial": "Licencia comercial",
|
||||
"licenseTierPersonal": "Licencia personal",
|
||||
"licensed": "Licenciado",
|
||||
"yes": "Sí",
|
||||
"no": "Nu",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Ver y administrar proveedores de identidad en el sistema",
|
||||
"idpDeletedDescription": "Proveedor de identidad eliminado correctamente",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "¿Está seguro que desea eliminar permanentemente el proveedor de identidad {name}?",
|
||||
"idpQuestionRemove": "¿Está seguro que desea eliminar permanentemente el proveedor de identidad?",
|
||||
"idpMessageRemove": "Esto eliminará el proveedor de identidad y todas las configuraciones asociadas. Los usuarios que se autentifiquen a través de este proveedor ya no podrán iniciar sesión.",
|
||||
"idpMessageConfirm": "Para confirmar, por favor escriba el nombre del proveedor de identidad a continuación.",
|
||||
"idpConfirmDelete": "Confirmar eliminar proveedor de identidad",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Un nombre mostrado para este proveedor de identidad",
|
||||
"idpAutoProvisionUsers": "Auto-Provisión de Usuarios",
|
||||
"idpAutoProvisionUsersDescription": "Cuando está habilitado, los usuarios serán creados automáticamente en el sistema al iniciar sesión con la capacidad de asignar a los usuarios a roles y organizaciones.",
|
||||
"licenseBadge": "Profesional",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Tipo de proveedor",
|
||||
"idpTypeDescription": "Seleccione el tipo de proveedor de identidad que desea configurar",
|
||||
"idpOidcConfigure": "Configuración OAuth2/OIDC",
|
||||
@@ -811,7 +827,7 @@
|
||||
"redirectUrl": "URL de redirección",
|
||||
"redirectUrlAbout": "Acerca de la URL de redirección",
|
||||
"redirectUrlAboutDescription": "Esta es la URL a la que los usuarios serán redireccionados después de la autenticación. Necesitas configurar esta URL en la configuración de tu proveedor de identidad.",
|
||||
"pangolinAuth": "Auth - Pangolin",
|
||||
"pangolinAuth": "Autenticación - Pangolin",
|
||||
"verificationCodeLengthRequirements": "Tu código de verificación debe tener 8 caracteres.",
|
||||
"errorOccurred": "Se ha producido un error",
|
||||
"emailErrorVerify": "No se pudo verificar el email:",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Revisa tu correo electrónico para ver el código de restablecimiento.",
|
||||
"passwordNew": "Nueva contraseña",
|
||||
"passwordNewConfirm": "Confirmar nueva contraseña",
|
||||
"changePassword": "Cambiar Contraseña",
|
||||
"changePasswordDescription": "Actualizar la contraseña de tu cuenta",
|
||||
"oldPassword": "Contraseña Actual",
|
||||
"newPassword": "Nueva Contraseña",
|
||||
"confirmNewPassword": "Confirme Nueva Contraseña",
|
||||
"changePasswordError": "Error al cambiar la contraseña",
|
||||
"changePasswordErrorDescription": "Se ha producido un error al cambiar la contraseña",
|
||||
"changePasswordSuccess": "La contraseña ha sido cambiada correctamente",
|
||||
"changePasswordSuccessDescription": "Su contraseña ha sido actualizada correctamente",
|
||||
"passwordExpiryRequired": "Contraseña con caducidad requerida",
|
||||
"passwordExpiryDescription": "Esta organización requiere que cambies tu contraseña cada {maxDays} días.",
|
||||
"changePasswordNow": "Cambiar Contraseña Ahora",
|
||||
"pincodeAuth": "Código de autenticación",
|
||||
"pincodeSubmit2": "Enviar código",
|
||||
"passwordResetSubmit": "Reiniciar Solicitud",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Edición Profesional requerida",
|
||||
"licenseTierProfessionalRequiredDescription": "Esta característica sólo está disponible en la Edición Profesional.",
|
||||
"actionGetOrg": "Obtener organización",
|
||||
"updateOrgUser": "Actualizar usuario Org",
|
||||
"createOrgUser": "Crear usuario Org",
|
||||
"actionUpdateOrg": "Actualizar organización",
|
||||
"actionUpdateUser": "Actualizar usuario",
|
||||
"actionGetUser": "Obtener usuario",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Eliminar sitio",
|
||||
"actionGetSite": "Obtener sitio",
|
||||
"actionListSites": "Listar sitios",
|
||||
"actionApplyBlueprint": "Aplicar plano",
|
||||
"setupToken": "Configuración de token",
|
||||
"setupTokenDescription": "Ingrese el token de configuración desde la consola del servidor.",
|
||||
"setupTokenRequired": "Se requiere el token de configuración",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Menú de navegación",
|
||||
"navbarDescription": "Menú de navegación principal para la aplicación",
|
||||
"navbarDocsLink": "Documentación",
|
||||
"commercialEdition": "Edición Comercial",
|
||||
"otpErrorEnable": "No se puede habilitar 2FA",
|
||||
"otpErrorEnableDescription": "Se ha producido un error al habilitar 2FA",
|
||||
"otpSetupCheckCode": "Por favor, introduzca un código de 6 dígitos",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Todos los usuarios",
|
||||
"sidebarIdentityProviders": "Proveedores de identidad",
|
||||
"sidebarLicense": "Licencia",
|
||||
"sidebarClients": "Clientes (Beta)",
|
||||
"sidebarClients": "Clientes",
|
||||
"sidebarDomains": "Dominios",
|
||||
"enableDockerSocket": "Habilitar conector Docker",
|
||||
"enableDockerSocketDescription": "Habilitar el descubrimiento de Docker Socket para completar la información del contenedor. La ruta del socket debe proporcionarse a Newt.",
|
||||
"sidebarBluePrints": "Planos",
|
||||
"blueprints": "Planos",
|
||||
"blueprintsDescription": "Aplicar configuraciones declarativas y ver ejecuciones anteriores",
|
||||
"blueprintAdd": "Añadir plano",
|
||||
"blueprintGoBack": "Ver todos los Planos",
|
||||
"blueprintCreate": "Crear Plano",
|
||||
"blueprintCreateDescription2": "Siga los siguientes pasos para crear y aplicar un nuevo plano",
|
||||
"blueprintDetails": "Detalles del plano",
|
||||
"blueprintDetailsDescription": "Ver el resultado del plano aplicado y cualquier error que haya ocurrido",
|
||||
"blueprintInfo": "Información del plano",
|
||||
"message": "Mensaje",
|
||||
"blueprintContentsDescription": "Defina el contenido YAML describiendo su infraestructura",
|
||||
"blueprintErrorCreateDescription": "Se ha producido un error al aplicar el plano",
|
||||
"blueprintErrorCreate": "Error al crear el plano",
|
||||
"searchBlueprintProgress": "Buscar planos...",
|
||||
"appliedAt": "Aplicado en",
|
||||
"source": "Fuente",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Saber más",
|
||||
"viewDockerContainers": "Ver contenedores Docker",
|
||||
"containersIn": "Contenedores en {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Crear dominio",
|
||||
"domainCreatedDescription": "Dominio creado con éxito",
|
||||
"domainDeletedDescription": "Dominio eliminado exitosamente",
|
||||
"domainQuestionRemove": "¿Está seguro de que desea eliminar el dominio {domain} de su cuenta?",
|
||||
"domainQuestionRemove": "¿Está seguro que desea eliminar el dominio de su cuenta?",
|
||||
"domainMessageRemove": "Una vez eliminado, el dominio ya no estará asociado con su cuenta.",
|
||||
"domainMessageConfirm": "Para confirmar, por favor escriba el nombre del dominio abajo.",
|
||||
"domainConfirmDelete": "Confirmar eliminación del dominio",
|
||||
"domainDelete": "Eliminar dominio",
|
||||
"domain": "Dominio",
|
||||
@@ -1211,7 +1259,7 @@
|
||||
"billing": "Facturación",
|
||||
"orgBillingDescription": "Gestiona tu información de facturación y suscripciones",
|
||||
"github": "GitHub",
|
||||
"pangolinHosted": "Pangolin Hosted",
|
||||
"pangolinHosted": "Pangolin Alojado",
|
||||
"fossorial": "Fossorial",
|
||||
"completeAccountSetup": "Completar configuración de cuenta",
|
||||
"completeAccountSetupDescription": "Establece tu contraseña para comenzar",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Nueva actualización disponible",
|
||||
"newtUpdateAvailableInfo": "Hay una nueva versión de Newt disponible. Actualice a la última versión para la mejor experiencia.",
|
||||
"domainPickerEnterDomain": "Dominio",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.miDominio.com, o solo myapp",
|
||||
"domainPickerPlaceholder": "miapp.ejemplo.com",
|
||||
"domainPickerDescription": "Ingresa el dominio completo del recurso para ver las opciones disponibles.",
|
||||
"domainPickerDescriptionSaas": "Ingresa un dominio completo, subdominio o simplemente un nombre para ver las opciones disponibles",
|
||||
"domainPickerTabAll": "Todo",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Subdominio: {subdomain}",
|
||||
"domainPickerNamespace": "Espacio de nombres: {namespace}",
|
||||
"domainPickerShowMore": "Mostrar más",
|
||||
"regionSelectorTitle": "Seleccionar Región",
|
||||
"regionSelectorInfo": "Seleccionar una región nos ayuda a brindar un mejor rendimiento para tu ubicación. No tienes que estar en la misma región que tu servidor.",
|
||||
"regionSelectorPlaceholder": "Elige una región",
|
||||
"regionSelectorComingSoon": "Próximamente",
|
||||
"billingLoadingSubscription": "Cargando suscripción...",
|
||||
"billingFreeTier": "Nivel Gratis",
|
||||
"billingWarningOverLimit": "Advertencia: Has excedido uno o más límites de uso. Tus sitios no se conectarán hasta que modifiques tu suscripción o ajustes tu uso.",
|
||||
"billingUsageLimitsOverview": "Descripción general de los límites de uso",
|
||||
"billingMonitorUsage": "Monitorea tu uso comparado con los límites configurados. Si necesitas que aumenten los límites, contáctanos a soporte@pangolin.net.",
|
||||
"billingDataUsage": "Uso de datos",
|
||||
"billingOnlineTime": "Tiempo en línea del sitio",
|
||||
"billingUsers": "Usuarios activos",
|
||||
"billingDomains": "Dominios activos",
|
||||
"billingRemoteExitNodes": "Nodos autogestionados activos",
|
||||
"billingNoLimitConfigured": "No se ha configurado ningún límite",
|
||||
"billingEstimatedPeriod": "Período de facturación estimado",
|
||||
"billingIncludedUsage": "Uso incluido",
|
||||
"billingIncludedUsageDescription": "Uso incluido con su plan de suscripción actual",
|
||||
"billingFreeTierIncludedUsage": "Permisos de uso del nivel gratuito",
|
||||
"billingIncluded": "incluido",
|
||||
"billingEstimatedTotal": "Total Estimado:",
|
||||
"billingNotes": "Notas",
|
||||
"billingEstimateNote": "Esta es una estimación basada en tu uso actual.",
|
||||
"billingActualChargesMayVary": "Los cargos reales pueden variar.",
|
||||
"billingBilledAtEnd": "Se te facturará al final del período de facturación.",
|
||||
"billingModifySubscription": "Modificar Suscripción",
|
||||
"billingStartSubscription": "Iniciar Suscripción",
|
||||
"billingRecurringCharge": "Cargo Recurrente",
|
||||
"billingManageSubscriptionSettings": "Administra la configuración y preferencias de tu suscripción",
|
||||
"billingNoActiveSubscription": "No tienes una suscripción activa. Inicia tu suscripción para aumentar los límites de uso.",
|
||||
"billingFailedToLoadSubscription": "Error al cargar la suscripción",
|
||||
"billingFailedToLoadUsage": "Error al cargar el uso",
|
||||
"billingFailedToGetCheckoutUrl": "Error al obtener la URL de pago",
|
||||
"billingPleaseTryAgainLater": "Por favor, inténtelo de nuevo más tarde.",
|
||||
"billingCheckoutError": "Error de pago",
|
||||
"billingFailedToGetPortalUrl": "Error al obtener la URL del portal",
|
||||
"billingPortalError": "Error del portal",
|
||||
"billingDataUsageInfo": "Se le cobran todos los datos transferidos a través de sus túneles seguros cuando se conectan a la nube. Esto incluye tanto tráfico entrante como saliente a través de todos sus sitios. Cuando alcance su límite, sus sitios se desconectarán hasta que actualice su plan o reduzca el uso. Los datos no se cargan cuando se usan nodos.",
|
||||
"billingOnlineTimeInfo": "Se te cobrará en función del tiempo que tus sitios permanezcan conectados a la nube. Por ejemplo, 44.640 minutos equivale a un sitio que funciona 24/7 durante un mes completo. Cuando alcance su límite, sus sitios se desconectarán hasta que mejore su plan o reduzca el uso. No se cargará el tiempo al usar nodos.",
|
||||
"billingUsersInfo": "Se te cobra por cada usuario en tu organización. La facturación se calcula diariamente según la cantidad de cuentas de usuario activas en tu organización.",
|
||||
"billingDomainInfo": "Se te cobra por cada dominio en tu organización. La facturación se calcula diariamente según la cantidad de cuentas de dominio activas en tu organización.",
|
||||
"billingRemoteExitNodesInfo": "Se te cobra por cada nodo gestionado en tu organización. La facturación se calcula diariamente según la cantidad de nodos gestionados activos en tu organización.",
|
||||
"domainNotFound": "Dominio no encontrado",
|
||||
"domainNotFoundDescription": "Este recurso está deshabilitado porque el dominio ya no existe en nuestro sistema. Por favor, establece un nuevo dominio para este recurso.",
|
||||
"failed": "Fallido",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Hubo un problema al usar tu llave de seguridad. Por favor, inténtalo de nuevo.",
|
||||
"twoFactorRequired": "Se requiere autenticación de dos factores para registrar una llave de seguridad.",
|
||||
"twoFactor": "Autenticación de dos factores",
|
||||
"twoFactorAuthentication": "Autenticación de Dos Factores",
|
||||
"twoFactorDescription": "Esta organización requiere autenticación de dos factores.",
|
||||
"enableTwoFactor": "Habilitar autenticación de dos factores",
|
||||
"organizationSecurityPolicy": "Política de Seguridad de la Organización",
|
||||
"organizationSecurityPolicyDescription": "Esta organización tiene requisitos de seguridad que deben cumplirse antes de poder acceder a ella",
|
||||
"securityRequirements": "Requisitos de seguridad",
|
||||
"allRequirementsMet": "Todos los requisitos han sido cumplidos",
|
||||
"completeRequirementsToContinue": "Completa los siguientes requisitos para seguir accediendo a esta organización",
|
||||
"youCanNowAccessOrganization": "Ahora puedes acceder a esta organización",
|
||||
"reauthenticationRequired": "Longitud de la sesión",
|
||||
"reauthenticationDescription": "Esta organización requiere que inicies sesión cada {maxDays} días.",
|
||||
"reauthenticationDescriptionHours": "Esta organización requiere que inicies sesión cada {maxHours} horas.",
|
||||
"reauthenticateNow": "Iniciar sesión de nuevo",
|
||||
"adminEnabled2FaOnYourAccount": "Su administrador ha habilitado la autenticación de dos factores para {email}. Por favor, complete el proceso de configuración para continuar.",
|
||||
"continueToApplication": "Continuar a la aplicación",
|
||||
"securityKeyAdd": "Agregar llave de seguridad",
|
||||
"securityKeyRegisterTitle": "Registrar nueva llave de seguridad",
|
||||
"securityKeyRegisterDescription": "Conecta tu llave de seguridad y escribe un nombre para identificarla",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "Los cambios de DNS pueden tardar un tiempo en propagarse a través de internet. Esto puede tardar desde unos pocos minutos hasta 48 horas, dependiendo de tu proveedor de DNS y la configuración de TTL.",
|
||||
"resourcePortRequired": "Se requiere número de puerto para recursos no HTTP",
|
||||
"resourcePortNotAllowed": "El número de puerto no debe establecerse para recursos HTTP",
|
||||
"billingPricingCalculatorLink": "Calculadora de Precios",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Estoy de acuerdo con los",
|
||||
"termsOfService": "términos del servicio",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Proxy externo habilitado",
|
||||
"addNewTarget": "Agregar nuevo destino",
|
||||
"targetsList": "Lista de destinos",
|
||||
"advancedMode": "Modo avanzado",
|
||||
"targetErrorDuplicateTargetFound": "Se encontró un destino duplicado",
|
||||
"healthCheckHealthy": "Saludable",
|
||||
"healthCheckUnhealthy": "No saludable",
|
||||
"healthCheckUnknown": "Desconocido",
|
||||
"healthCheck": "Chequeo de salud",
|
||||
"configureHealthCheck": "Configurar Chequeo de Salud",
|
||||
"configureHealthCheckDescription": "Configura la monitorización de salud para {target}",
|
||||
"enableHealthChecks": "Activar Chequeos de Salud",
|
||||
"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",
|
||||
"healthCheckPath": "Ruta",
|
||||
"healthHostname": "IP / Nombre del host",
|
||||
"healthPort": "Puerto",
|
||||
"healthCheckPathDescription": "La ruta para comprobar el estado de salud.",
|
||||
"healthyIntervalSeconds": "Intervalo Saludable",
|
||||
"unhealthyIntervalSeconds": "Intervalo No Saludable",
|
||||
"IntervalSeconds": "Intervalo Saludable",
|
||||
"timeoutSeconds": "Tiempo de Espera",
|
||||
"timeIsInSeconds": "El tiempo está en segundos",
|
||||
"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.",
|
||||
"customHeaders": "Cabeceras personalizadas",
|
||||
"customHeadersDescription": "Nueva línea de cabeceras separada: Nombre de cabecera: valor",
|
||||
"headersValidationError": "Los encabezados deben estar en el formato: Nombre de cabecera: valor.",
|
||||
"saveHealthCheck": "Guardar Chequeo de Salud",
|
||||
"healthCheckSaved": "Chequeo de Salud Guardado",
|
||||
"healthCheckSavedDescription": "La configuración del chequeo de salud se ha guardado correctamente",
|
||||
"healthCheckError": "Error en el Chequeo de Salud",
|
||||
"healthCheckErrorDescription": "Ocurrió un error al guardar la configuración del chequeo de salud",
|
||||
"healthCheckPathRequired": "Se requiere la ruta del chequeo de salud",
|
||||
"healthCheckMethodRequired": "Se requiere el método HTTP",
|
||||
"healthCheckIntervalMin": "El intervalo de comprobación debe ser de al menos 5 segundos",
|
||||
"healthCheckTimeoutMin": "El tiempo de espera debe ser de al menos 1 segundo",
|
||||
"healthCheckRetryMin": "Los intentos de reintento deben ser de al menos 1",
|
||||
"httpMethod": "Método HTTP",
|
||||
"selectHttpMethod": "Seleccionar método HTTP",
|
||||
"domainPickerSubdomainLabel": "Subdominio",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Ingrese un subdominio para buscar y seleccionar entre dominios gratuitos disponibles.",
|
||||
"domainPickerFreeDomains": "Dominios gratuitos",
|
||||
"domainPickerSearchForAvailableDomains": "Buscar dominios disponibles",
|
||||
"domainPickerNotWorkSelfHosted": "Nota: Los dominios gratuitos proporcionados no están disponibles para instancias autogestionadas por ahora.",
|
||||
"resourceDomain": "Dominio",
|
||||
"resourceEditDomain": "Editar dominio",
|
||||
"siteName": "Nombre del sitio",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protocolo",
|
||||
"editInternalResourceDialogSitePort": "Puerto del sitio",
|
||||
"editInternalResourceDialogTargetConfiguration": "Configuración de objetivos",
|
||||
"editInternalResourceDialogDestinationIP": "IP de destino",
|
||||
"editInternalResourceDialogDestinationPort": "Puerto de destino",
|
||||
"editInternalResourceDialogCancel": "Cancelar",
|
||||
"editInternalResourceDialogSaveResource": "Guardar recurso",
|
||||
"editInternalResourceDialogSuccess": "Éxito",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Puerto del sitio",
|
||||
"createInternalResourceDialogSitePortDescription": "Use este puerto para acceder al recurso en el sitio cuando se conecta con un cliente.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Configuración de objetivos",
|
||||
"createInternalResourceDialogDestinationIP": "IP de destino",
|
||||
"createInternalResourceDialogDestinationIPDescription": "La dirección IP del recurso en la red del sitio.",
|
||||
"createInternalResourceDialogDestinationPort": "Puerto de destino",
|
||||
"createInternalResourceDialogDestinationIPDescription": "La dirección IP o nombre de host del recurso en la red del sitio.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "El puerto en la IP de destino donde el recurso es accesible.",
|
||||
"createInternalResourceDialogCancel": "Cancelar",
|
||||
"createInternalResourceDialogCreateResource": "Crear recurso",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Error de inicio de sesión automático",
|
||||
"autoLoginErrorNoRedirectUrl": "No se recibió URL de redirección del proveedor de identidad.",
|
||||
"autoLoginErrorGeneratingUrl": "Error al generar URL de autenticación.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Nodos remotos",
|
||||
"remoteExitNodeDescription": "Autoalojar uno o más nodos remotos para extender la conectividad de red y reducir la dependencia de la nube",
|
||||
"remoteExitNodes": "Nodos",
|
||||
"searchRemoteExitNodes": "Buscar nodos...",
|
||||
"remoteExitNodeAdd": "Añadir Nodo",
|
||||
"remoteExitNodeErrorDelete": "Error al eliminar el nodo",
|
||||
"remoteExitNodeQuestionRemove": "¿Está seguro que desea eliminar el nodo de la organización?",
|
||||
"remoteExitNodeMessageRemove": "Una vez eliminado, el nodo ya no será accesible.",
|
||||
"remoteExitNodeConfirmDelete": "Confirmar eliminar nodo",
|
||||
"remoteExitNodeDelete": "Eliminar Nodo",
|
||||
"sidebarRemoteExitNodes": "Nodos remotos",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Crear Nodo",
|
||||
"description": "Crear un nuevo nodo para extender la conectividad de red",
|
||||
"viewAllButton": "Ver todos los nodos",
|
||||
"strategy": {
|
||||
"title": "Estrategia de Creación",
|
||||
"description": "Elija esto para configurar manualmente su nodo o generar nuevas credenciales.",
|
||||
"adopt": {
|
||||
"title": "Adoptar Nodo",
|
||||
"description": "Elija esto si ya tiene las credenciales para el nodo."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Generar Claves",
|
||||
"description": "Elija esto si desea generar nuevas claves para el nodo"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Adoptar Nodo Existente",
|
||||
"description": "Introduzca las credenciales del nodo existente que desea adoptar",
|
||||
"nodeIdLabel": "ID del nodo",
|
||||
"nodeIdDescription": "El ID del nodo existente que desea adoptar",
|
||||
"secretLabel": "Secreto",
|
||||
"secretDescription": "La clave secreta del nodo existente",
|
||||
"submitButton": "Adoptar Nodo"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Credenciales Generadas",
|
||||
"description": "Utilice estas credenciales generadas para configurar su nodo",
|
||||
"nodeIdTitle": "ID del nodo",
|
||||
"secretTitle": "Secreto",
|
||||
"saveCredentialsTitle": "Agregar Credenciales a la Configuración",
|
||||
"saveCredentialsDescription": "Agrega estas credenciales a tu archivo de configuración del nodo Pangolin autogestionado para completar la conexión.",
|
||||
"submitButton": "Crear Nodo"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "El ID del nodo y el secreto son necesarios al adoptar un nodo existente"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Falló al cargar los valores predeterminados",
|
||||
"defaultsNotLoaded": "Valores predeterminados no cargados",
|
||||
"createFailed": "Error al crear el nodo"
|
||||
},
|
||||
"success": {
|
||||
"created": "Nodo creado correctamente"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Selección de nodo",
|
||||
"remoteExitNodeSelectionDescription": "Seleccione un nodo a través del cual enrutar el tráfico para este sitio local",
|
||||
"remoteExitNodeRequired": "Un nodo debe ser seleccionado para sitios locales",
|
||||
"noRemoteExitNodesAvailable": "No hay nodos disponibles",
|
||||
"noRemoteExitNodesAvailableDescription": "No hay nodos disponibles para esta organización. Crea un nodo primero para usar sitios locales.",
|
||||
"exitNode": "Nodo de Salida",
|
||||
"country": "País",
|
||||
"rulesMatchCountry": "Actualmente basado en IP de origen",
|
||||
"managedSelfHosted": {
|
||||
"title": "Autogestionado",
|
||||
"description": "Servidor Pangolin autoalojado más fiable y de bajo mantenimiento con campanas y silbidos extra",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Convierte este nodo a autoalojado administrado"
|
||||
},
|
||||
"internationaldomaindetected": "Dominio Internacional detectado",
|
||||
"willbestoredas": "Se almacenará como:"
|
||||
}
|
||||
"willbestoredas": "Se almacenará como:",
|
||||
"roleMappingDescription": "Determinar cómo se asignan los roles a los usuarios cuando se registran cuando está habilitada la provisión automática.",
|
||||
"selectRole": "Seleccione un rol",
|
||||
"roleMappingExpression": "Expresión",
|
||||
"selectRolePlaceholder": "Elija un rol",
|
||||
"selectRoleDescription": "Seleccione un rol para asignar a todos los usuarios de este proveedor de identidad",
|
||||
"roleMappingExpressionDescription": "Introduzca una expresión JMESPath para extraer información de rol del token de ID",
|
||||
"idpTenantIdRequired": "El ID del cliente es obligatorio",
|
||||
"invalidValue": "Valor inválido",
|
||||
"idpTypeLabel": "Tipo de proveedor de identidad",
|
||||
"roleMappingExpressionPlaceholder": "e.g., contiene(grupos, 'administrador') && 'administrador' || 'miembro'",
|
||||
"idpGoogleConfiguration": "Configuración de Google",
|
||||
"idpGoogleConfigurationDescription": "Configura tus credenciales de Google OAuth2",
|
||||
"idpGoogleClientIdDescription": "Tu ID de cliente de Google OAuth2",
|
||||
"idpGoogleClientSecretDescription": "Tu secreto de cliente de Google OAuth2",
|
||||
"idpAzureConfiguration": "Configuración de Azure Entra ID",
|
||||
"idpAzureConfigurationDescription": "Configure sus credenciales de Azure Entra ID OAuth2",
|
||||
"idpTenantId": "ID del inquilino",
|
||||
"idpTenantIdPlaceholder": "su-inquilino-id",
|
||||
"idpAzureTenantIdDescription": "Su ID de inquilino de Azure (encontrado en el resumen de Azure Active Directory)",
|
||||
"idpAzureClientIdDescription": "Tu ID de Cliente de Registro de Azure App",
|
||||
"idpAzureClientSecretDescription": "Tu Azure App Registro Cliente secreto",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Configuración de Google",
|
||||
"idpAzureConfigurationTitle": "Configuración de Azure Entra ID",
|
||||
"idpTenantIdLabel": "ID del inquilino",
|
||||
"idpAzureClientIdDescription2": "Tu ID de Cliente de Registro de Azure App",
|
||||
"idpAzureClientSecretDescription2": "Tu Azure App Registro Cliente secreto",
|
||||
"idpGoogleDescription": "Proveedor OAuth2/OIDC de Google",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Subred",
|
||||
"subnetDescription": "La subred para la configuración de red de esta organización.",
|
||||
"authPage": "Página Auth",
|
||||
"authPageDescription": "Configurar la página de autenticación de su organización",
|
||||
"authPageDomain": "Dominio de la página Auth",
|
||||
"noDomainSet": "Ningún dominio establecido",
|
||||
"changeDomain": "Cambiar dominio",
|
||||
"selectDomain": "Seleccionar dominio",
|
||||
"restartCertificate": "Reiniciar certificado",
|
||||
"editAuthPageDomain": "Editar dominio Auth Page",
|
||||
"setAuthPageDomain": "Establecer dominio Auth Page",
|
||||
"failedToFetchCertificate": "Error al obtener el certificado",
|
||||
"failedToRestartCertificate": "Error al reiniciar el certificado",
|
||||
"addDomainToEnableCustomAuthPages": "Añadir un dominio para habilitar páginas de autenticación personalizadas para su organización",
|
||||
"selectDomainForOrgAuthPage": "Seleccione un dominio para la página de autenticación de la organización",
|
||||
"domainPickerProvidedDomain": "Dominio proporcionado",
|
||||
"domainPickerFreeProvidedDomain": "Dominio proporcionado gratis",
|
||||
"domainPickerVerified": "Verificado",
|
||||
"domainPickerUnverified": "Sin verificar",
|
||||
"domainPickerInvalidSubdomainStructure": "Este subdominio contiene caracteres o estructura no válidos. Se limpiará automáticamente al guardar.",
|
||||
"domainPickerError": "Error",
|
||||
"domainPickerErrorLoadDomains": "Error al cargar los dominios de la organización",
|
||||
"domainPickerErrorCheckAvailability": "No se pudo comprobar la disponibilidad del dominio",
|
||||
"domainPickerInvalidSubdomain": "Subdominio inválido",
|
||||
"domainPickerInvalidSubdomainRemoved": "La entrada \"{sub}\" fue eliminada porque no es válida.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "No se ha podido hacer válido \"{sub}\" para {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Subdominio saneado",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" fue corregido a \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Inicia sesión en tu organización",
|
||||
"orgAuthChooseIdpDescription": "Elige tu proveedor de identidad para continuar",
|
||||
"orgAuthNoIdpConfigured": "Esta organización no tiene ningún proveedor de identidad configurado. En su lugar puedes iniciar sesión con tu identidad de Pangolin.",
|
||||
"orgAuthSignInWithPangolin": "Iniciar sesión con Pangolin",
|
||||
"subscriptionRequiredToUse": "Se requiere una suscripción para utilizar esta función.",
|
||||
"idpDisabled": "Los proveedores de identidad están deshabilitados.",
|
||||
"orgAuthPageDisabled": "La página de autenticación de la organización está deshabilitada.",
|
||||
"domainRestartedDescription": "Verificación de dominio reiniciada con éxito",
|
||||
"resourceAddEntrypointsEditFile": "Editar archivo: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Editar archivo: docker-compose.yml",
|
||||
"emailVerificationRequired": "Se requiere verificación de correo electrónico. Por favor, inicie sesión de nuevo a través de {dashboardUrl}/auth/login complete este paso. Luego, vuelva aquí.",
|
||||
"twoFactorSetupRequired": "La configuración de autenticación de doble factor es requerida. Por favor, inicia sesión de nuevo a través de {dashboardUrl}/auth/login completa este paso. Luego, vuelve aquí.",
|
||||
"additionalSecurityRequired": "Seguridad adicional requerida",
|
||||
"organizationRequiresAdditionalSteps": "Esta organización requiere pasos de seguridad adicionales antes de poder acceder a los recursos.",
|
||||
"completeTheseSteps": "Completa estos pasos",
|
||||
"enableTwoFactorAuthentication": "Habilitar autenticación de doble factor",
|
||||
"completeSecuritySteps": "Pasos de seguridad completos",
|
||||
"securitySettings": "Ajustes de seguridad",
|
||||
"securitySettingsDescription": "Configurar políticas de seguridad para su organización",
|
||||
"requireTwoFactorForAllUsers": "Requiere autenticación de doble factor para todos los usuarios",
|
||||
"requireTwoFactorDescription": "Cuando está activado, todos los usuarios internos de esta organización deben tener habilitada la autenticación de dos factores para acceder a la organización.",
|
||||
"requireTwoFactorDisabledDescription": "Esta característica requiere una licencia válida (Enterprise) o una suscripción activa (SaBudget)",
|
||||
"requireTwoFactorCannotEnableDescription": "Debes habilitar la autenticación de doble factor para tu cuenta antes de aplicarla a todos los usuarios",
|
||||
"maxSessionLength": "Longitud máxima de la sesión",
|
||||
"maxSessionLengthDescription": "Establecer la duración máxima de las sesiones de usuario. Después de este tiempo, los usuarios tendrán que volver a autenticarse.",
|
||||
"maxSessionLengthDisabledDescription": "Esta característica requiere una licencia válida (Enterprise) o una suscripción activa (SaBudget)",
|
||||
"selectSessionLength": "Seleccionar duración de sesión",
|
||||
"unenforced": "No aplicado",
|
||||
"1Hour": "1 hora",
|
||||
"3Hours": "3 horas",
|
||||
"6Hours": "6 horas",
|
||||
"12Hours": "12 horas",
|
||||
"1DaySession": "1 día",
|
||||
"3Days": "3 días",
|
||||
"7Days": "7 días",
|
||||
"14Days": "14 días",
|
||||
"30DaysSession": "30 días",
|
||||
"90DaysSession": "90 días",
|
||||
"180DaysSession": "180 días",
|
||||
"passwordExpiryDays": "Caduca la contraseña",
|
||||
"editPasswordExpiryDescription": "Establecer el número de días antes de que los usuarios tengan que cambiar su contraseña.",
|
||||
"selectPasswordExpiry": "Seleccione la contraseña expirada",
|
||||
"30Days": "30 días",
|
||||
"1Day": "1 día",
|
||||
"60Days": "60 días",
|
||||
"90Days": "90 días",
|
||||
"180Days": "180 días",
|
||||
"1Year": "1 año",
|
||||
"subscriptionBadge": "Suscripción requerida",
|
||||
"securityPolicyChangeWarning": "Advertencia de cambio de política de seguridad",
|
||||
"securityPolicyChangeDescription": "Está a punto de cambiar la configuración de la política de seguridad. Después de guardar, puede que necesite volver a autenticarse para cumplir con estas actualizaciones de política. Todos los usuarios que no cumplan con los requisitos también tendrán que volver a autenticarse.",
|
||||
"securityPolicyChangeConfirmMessage": "Confirmo",
|
||||
"securityPolicyChangeWarningText": "Esto afectará a todos los usuarios de la organización",
|
||||
"authPageErrorUpdateMessage": "Ocurrió un error mientras se actualizaban los ajustes de la página auth",
|
||||
"authPageErrorUpdate": "No se puede actualizar la página de autenticación",
|
||||
"authPageUpdated": "Página auth actualizada correctamente",
|
||||
"healthCheckNotAvailable": "Local",
|
||||
"rewritePath": "Reescribir Ruta",
|
||||
"rewritePathDescription": "Opcionalmente reescribe la ruta antes de reenviar al destino.",
|
||||
"continueToApplication": "Continuar a la aplicación",
|
||||
"checkingInvite": "Comprobando invitación",
|
||||
"setResourceHeaderAuth": "set-Resource HeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Eliminar Auth del Encabezado",
|
||||
"resourceHeaderAuthRemoveDescription": "Autenticación de cabecera eliminada correctamente.",
|
||||
"resourceErrorHeaderAuthRemove": "Error al eliminar autenticación de cabecera",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "No se pudo eliminar la autenticación de cabecera del recurso.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Autenticación de cabecera habilitada",
|
||||
"resourceHeaderAuthProtectionDisabled": "Autenticación de cabecera desactivada",
|
||||
"headerAuthRemove": "Eliminar Auth del Encabezado",
|
||||
"headerAuthAdd": "Añadir autenticación de cabecera",
|
||||
"resourceErrorHeaderAuthSetup": "Error al establecer autenticación de cabecera",
|
||||
"resourceErrorHeaderAuthSetupDescription": "No se pudo establecer autenticación de cabecera para el recurso.",
|
||||
"resourceHeaderAuthSetup": "Autenticación de cabecera establecida correctamente",
|
||||
"resourceHeaderAuthSetupDescription": "La autenticación de cabecera se ha establecido correctamente.",
|
||||
"resourceHeaderAuthSetupTitle": "Establecer autenticación de cabecera",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Establezca las credenciales básicas de autenticación (nombre de usuario y contraseña) para proteger este recurso con autenticación de HTTP Header. Acceda a él usando el formato https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Establecer autenticación de cabecera",
|
||||
"actionSetResourceHeaderAuth": "Establecer autenticación de cabecera",
|
||||
"enterpriseEdition": "Edición corporativa",
|
||||
"unlicensed": "Sin licencia",
|
||||
"beta": "Beta",
|
||||
"manageClients": "Administrar clientes",
|
||||
"manageClientsDescription": "Los clientes son dispositivos que pueden conectarse a sus sitios",
|
||||
"licenseTableValidUntil": "Válido hasta",
|
||||
"saasLicenseKeysSettingsTitle": "Licencias empresariales",
|
||||
"saasLicenseKeysSettingsDescription": "Generar y administrar claves de licencia Enterprise para instancias Pangolin autoalojadas",
|
||||
"sidebarEnterpriseLicenses": "Licencias",
|
||||
"generateLicenseKey": "Generar clave de licencia",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Por favor, introduzca una dirección de correo válida",
|
||||
"useCaseTypeRequired": "Por favor, seleccione un tipo de caso de uso",
|
||||
"firstNameRequired": "El nombre es obligatorio",
|
||||
"lastNameRequired": "Se requiere apellido",
|
||||
"primaryUseRequired": "Por favor describa su uso principal",
|
||||
"jobTitleRequiredBusiness": "El título de la tarea es obligatorio para uso empresarial",
|
||||
"industryRequiredBusiness": "La industria es necesaria para uso comercial",
|
||||
"stateProvinceRegionRequired": "Se requiere estado/Province/región",
|
||||
"postalZipCodeRequired": "Código Postal/ZIP es requerido",
|
||||
"companyNameRequiredBusiness": "El nombre de la empresa es obligatorio para uso comercial",
|
||||
"countryOfResidenceRequiredBusiness": "El país de residencia es obligatorio para uso de negocios",
|
||||
"countryRequiredPersonal": "El país es obligatorio para uso personal",
|
||||
"agreeToTermsRequired": "Debe aceptar los términos",
|
||||
"complianceConfirmationRequired": "Debe confirmar el cumplimiento de la Licencia Comercial Fossorial"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Uso personal",
|
||||
"description": "Para uso individual y no comercial, tales como aprendizaje, proyectos personales o experimentación."
|
||||
},
|
||||
"business": {
|
||||
"title": "Uso de Negocio",
|
||||
"description": "Para uso dentro de organizaciones, empresas o actividades comerciales o generadoras de ingresos."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Email y tipo de licencia",
|
||||
"description": "Introduzca su correo electrónico y elija su tipo de licencia"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Información Personal",
|
||||
"description": "Cuéntanos acerca de ti"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Información de contacto",
|
||||
"description": "Sus datos de contacto"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Términos y Generar",
|
||||
"description": "Revisar y aceptar términos para generar su licencia"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Divulgación de uso",
|
||||
"description": "Seleccione el nivel de licencia que refleje con precisión su uso previsto. La Licencia Personal permite el uso libre del Software para actividades comerciales individuales, no comerciales o de pequeña escala con ingresos brutos anuales inferiores a $100,000 USD. Cualquier uso más allá de estos límites — incluyendo el uso dentro de una empresa, organización, u otro entorno de generación de ingresos — requiere una Licencia Empresarial válida y el pago de la cuota de licencia aplicable. Todos los usuarios, ya sean personales o empresariales, deben cumplir con las Condiciones de Licencia Comercial Fossorial."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Información del período de prueba",
|
||||
"description": "Esta Clave de Licencia permite las funciones de la Empresa durante un período de evaluación de 7 días. El acceso continuado a las características de pago más allá del período de evaluación requiere una activación bajo una Licencia Personal o Empresarial válida. Para licencias de la Empresa, póngase en contacto con sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "¿Estás usando Pangolin para uso personal o de negocios?",
|
||||
"firstName": "Nombre",
|
||||
"lastName": "Apellido",
|
||||
"jobTitle": "Trabajo",
|
||||
"primaryUseQuestion": "¿Para qué planeas usar principalmente Pangolin?",
|
||||
"industryQuestion": "¿Cuál es su industria?",
|
||||
"prospectiveUsersQuestion": "¿Cuántos usuarios potenciales esperas tener?",
|
||||
"prospectiveSitesQuestion": "¿Cuántos sitios potenciales (túneles) esperas tener?",
|
||||
"companyName": "Nombre de la empresa",
|
||||
"countryOfResidence": "País de residencia",
|
||||
"stateProvinceRegion": "Estado / Province / Región",
|
||||
"postalZipCode": "Código postal",
|
||||
"companyWebsite": "Sitio web de la empresa",
|
||||
"companyPhoneNumber": "Número de teléfono de la empresa",
|
||||
"country": "País",
|
||||
"phoneNumberOptional": "Número de teléfono (opcional)",
|
||||
"complianceConfirmation": "Confirmo que la información que he proporcionado es exacta y que estoy en conformidad con la Licencia Comercial Fossorial. Informar de información inexacta o identificar mal el uso del producto es una violación de la licencia y puede resultar en que su clave sea revocada."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Cerrar",
|
||||
"previous": "Anterior",
|
||||
"next": "Siguiente",
|
||||
"generateLicenseKey": "Generar clave de licencia"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Clave de licencia generada con éxito",
|
||||
"description": "Su clave de licencia ha sido generada y está lista para usar."
|
||||
},
|
||||
"error": {
|
||||
"title": "Error al generar la clave de licencia",
|
||||
"description": "Se ha producido un error al generar la clave de licencia."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Prioridad",
|
||||
"priorityDescription": "Las rutas de prioridad más alta son evaluadas primero. Prioridad = 100 significa orden automático (decisiones del sistema). Utilice otro número para hacer cumplir la prioridad manual.",
|
||||
"instanceName": "Nombre de instancia",
|
||||
"pathMatchModalTitle": "Configurar ruta coincidente",
|
||||
"pathMatchModalDescription": "Configurar cómo deben coincidir las peticiones entrantes en función de su ruta.",
|
||||
"pathMatchType": "Tipo de partida",
|
||||
"pathMatchPrefix": "Prefijo",
|
||||
"pathMatchExact": "Exacto",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Valor de ruta",
|
||||
"clear": "Claro",
|
||||
"saveChanges": "Guardar Cambios",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/ruta",
|
||||
"pathMatchPrefixHelp": "Ejemplo: /api coincide con /api, /api/users, etc.",
|
||||
"pathMatchExactHelp": "Ejemplo: /api coincide sólo con /api",
|
||||
"pathMatchRegexHelp": "Ejemplo: ^/api/.* coincide con /api/anything",
|
||||
"pathRewriteModalTitle": "Configurar ruta de reescritura",
|
||||
"pathRewriteModalDescription": "Transforma la ruta coincidente antes de reenviarla al objetivo.",
|
||||
"pathRewriteType": "Tipo de reescritura",
|
||||
"pathRewritePrefixOption": "Prefijo - Reemplazar prefijo",
|
||||
"pathRewriteExactOption": "Exacto - Reemplazar toda la ruta",
|
||||
"pathRewriteRegexOption": "Regex - Reemplazo de patrón",
|
||||
"pathRewriteStripPrefixOption": "Prefijo de clip - Quitar prefijo",
|
||||
"pathRewriteValue": "Reescribir valor",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "Reemplazar el prefijo coincidente con este valor",
|
||||
"pathRewriteExactHelp": "Reemplaza toda la ruta con este valor cuando la ruta coincida exactamente",
|
||||
"pathRewriteRegexHelp": "Usar grupos de captura como $1, $2 para reemplazar",
|
||||
"pathRewriteStripPrefixHelp": "Dejar en blanco para el prefijo strip o proporcionar un nuevo prefijo",
|
||||
"pathRewritePrefix": "Prefijo",
|
||||
"pathRewriteExact": "Exacto",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Clip",
|
||||
"pathRewriteStripLabel": "clip",
|
||||
"sidebarEnableEnterpriseLicense": "Activar licencia corporativa",
|
||||
"cannotbeUndone": "Esto no se puede deshacer.",
|
||||
"toConfirm": "confirmar",
|
||||
"deleteClientQuestion": "¿Está seguro que desea eliminar el cliente del sitio y la organización?",
|
||||
"clientMessageRemove": "Una vez eliminado, el cliente ya no podrá conectarse al sitio.",
|
||||
"sidebarLogs": "Registros",
|
||||
"request": "Solicitud",
|
||||
"logs": "Registros",
|
||||
"logsSettingsDescription": "Monitorear registros recogidos de esta orginización",
|
||||
"searchLogs": "Buscar registros...",
|
||||
"action": "Accin",
|
||||
"actor": "Actor",
|
||||
"timestamp": "Timestamp",
|
||||
"accessLogs": "Registros de acceso",
|
||||
"exportCsv": "Exportar CSV",
|
||||
"actorId": "ID de Actor",
|
||||
"allowedByRule": "Permitido por regla",
|
||||
"allowedNoAuth": "No se permite autorización",
|
||||
"validAccessToken": "Token de Acceso Válido",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Contraseña válida",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Recurso bloqueado",
|
||||
"droppedByRule": "Soltado por regla",
|
||||
"noSessions": "No hay sesiones",
|
||||
"temporaryRequestToken": "Token de solicitud temporal",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Razón",
|
||||
"requestLogs": "Registros de Solicitud",
|
||||
"host": "Anfitrión",
|
||||
"location": "Ubicación",
|
||||
"actionLogs": "Registros de acción",
|
||||
"sidebarLogsRequest": "Registros de Solicitud",
|
||||
"sidebarLogsAccess": "Registros de acceso",
|
||||
"sidebarLogsAction": "Registros de acción",
|
||||
"logRetention": "Retención de Log",
|
||||
"logRetentionDescription": "Administrar cuánto tiempo se conservan los diferentes tipos de registros para esta organización o desactivarlos",
|
||||
"requestLogsDescription": "Ver registros de solicitudes detallados para los recursos de esta organización",
|
||||
"logRetentionRequestLabel": "Retención de Registro de Solicitud",
|
||||
"logRetentionRequestDescription": "Cuánto tiempo conservar los registros de solicitudes",
|
||||
"logRetentionAccessLabel": "Retención de Log de Acceso",
|
||||
"logRetentionAccessDescription": "Cuánto tiempo retener los registros de acceso",
|
||||
"logRetentionActionLabel": "Retención de registro de acción",
|
||||
"logRetentionActionDescription": "Cuánto tiempo retener los registros de acción",
|
||||
"logRetentionDisabled": "Deshabilitado",
|
||||
"logRetention3Days": "3 días",
|
||||
"logRetention7Days": "7 días",
|
||||
"logRetention14Days": "14 días",
|
||||
"logRetention30Days": "30 días",
|
||||
"logRetention90Days": "90 días",
|
||||
"logRetentionForever": "Para siempre",
|
||||
"actionLogsDescription": "Ver un historial de acciones realizadas en esta organización",
|
||||
"accessLogsDescription": "Ver solicitudes de acceso a los recursos de esta organización",
|
||||
"licenseRequiredToUse": "Se requiere una licencia Enterprise para utilizar esta función.",
|
||||
"certResolver": "Resolver certificado",
|
||||
"certResolverDescription": "Seleccione la resolución de certificados a utilizar para este recurso.",
|
||||
"selectCertResolver": "Seleccionar Resolver Certificado",
|
||||
"enterCustomResolver": "Introducir resolución personalizada",
|
||||
"preferWildcardCert": "Certificado de comodín preferido",
|
||||
"unverified": "Sin verificar",
|
||||
"domainSetting": "Ajustes de dominio",
|
||||
"domainSettingDescription": "Configurar ajustes para tu dominio",
|
||||
"preferWildcardCertDescription": "Intento de generar un certificado comodín (requiere una resolución de certificados correctamente configurada).",
|
||||
"recordName": "Nombre del registro",
|
||||
"auto": "Auto",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Cómo añadir registros",
|
||||
"dnsRecord": "Registros DNS",
|
||||
"required": "Requerido",
|
||||
"domainSettingsUpdated": "Configuración de dominio actualizada correctamente",
|
||||
"orgOrDomainIdMissing": "Falta el ID de organización o dominio",
|
||||
"loadingDNSRecords": "Cargando registros DNS...",
|
||||
"olmUpdateAvailableInfo": "Una versión actualizada de Olm está disponible. Por favor, actualice a la última versión para obtener la mejor experiencia.",
|
||||
"client": "Cliente",
|
||||
"proxyProtocol": "Configuración del Protocolo Proxy",
|
||||
"proxyProtocolDescription": "Configurar el protocolo de proxy para preservar las direcciones IP del cliente para los servicios TCP/UDP.",
|
||||
"enableProxyProtocol": "Habilitar protocolo proxy",
|
||||
"proxyProtocolInfo": "Conservar direcciones IP del cliente para backends TCP/UDP",
|
||||
"proxyProtocolVersion": "Versión del Protocolo Proxy",
|
||||
"version1": " Versión 1 (Recomendado)",
|
||||
"version2": "Versión 2",
|
||||
"versionDescription": "La versión 1 está basada en texto y es ampliamente soportada. La versión 2 es binaria y más eficiente pero menos compatible.",
|
||||
"warning": "Advertencia",
|
||||
"proxyProtocolWarning": "Su aplicación de backend debe estar configurada para aceptar conexiones Proxy Protocol. Si su backend no soporta Proxy Protocol, habilitando esto romperá todas las conexiones. Asegúrese de configurar su backend para que confíe en las cabeceras del protocolo Proxy de Traefik.",
|
||||
"restarting": "Reiniciando...",
|
||||
"manual": "Manual",
|
||||
"messageSupport": "Soporte de mensajes",
|
||||
"supportNotAvailableTitle": "Soporte no disponible",
|
||||
"supportNotAvailableDescription": "El soporte no está disponible en este momento. Puedes enviar un correo electrónico a support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Solicitud de soporte enviada",
|
||||
"supportRequestSentDescription": "Su mensaje ha sido enviado con éxito.",
|
||||
"supportRequestFailedTitle": "Error al enviar la solicitud",
|
||||
"supportRequestFailedDescription": "Se ha producido un error al enviar su solicitud de soporte.",
|
||||
"supportSubjectRequired": "El asunto es obligatorio",
|
||||
"supportSubjectMaxLength": "El asunto debe tener 255 caracteres o menos",
|
||||
"supportMessageRequired": "El mensaje es obligatorio",
|
||||
"supportReplyTo": "Responder a",
|
||||
"supportSubject": "Asunto",
|
||||
"supportSubjectPlaceholder": "Introducir asunto",
|
||||
"supportMessage": "Mensaje",
|
||||
"supportMessagePlaceholder": "Introduce tu mensaje",
|
||||
"supportSending": "Enviando...",
|
||||
"supportSend": "Enviar",
|
||||
"supportMessageSent": "¡Mensaje enviado!",
|
||||
"supportWillContact": "¡Estaremos en contacto en breve!",
|
||||
"selectLogRetention": "Seleccionar retención de registro",
|
||||
"showColumns": "Mostrar columnas",
|
||||
"hideColumns": "Ocultar columnas",
|
||||
"columnVisibility": "Visibilidad de la columna",
|
||||
"toggleColumn": "Cambiar columna {columnName}",
|
||||
"allColumns": "Todas las columnas",
|
||||
"defaultColumns": "Columnas por defecto",
|
||||
"customizeView": "Personalizar vista",
|
||||
"viewOptions": "Ver opciones",
|
||||
"selectAll": "Seleccionar todo",
|
||||
"selectNone": "No seleccionar",
|
||||
"selectedResources": "Recursos seleccionados",
|
||||
"enableSelected": "Habilitar seleccionados",
|
||||
"disableSelected": "Desactivar Seleccionado",
|
||||
"checkSelectedStatus": "Comprobar el estado de selección"
|
||||
}
|
||||
@@ -10,20 +10,20 @@
|
||||
"setupErrorIdentifier": "L'ID de l'organisation est déjà pris. Veuillez en choisir un autre.",
|
||||
"componentsErrorNoMemberCreate": "Vous n'êtes actuellement membre d'aucune organisation. Créez une organisation pour commencer.",
|
||||
"componentsErrorNoMember": "Vous n'êtes actuellement membre d'aucune organisation.",
|
||||
"welcome": "Bienvenue à Pangolin",
|
||||
"welcome": "Bienvenue sur Pangolin !",
|
||||
"welcomeTo": "Bienvenue chez",
|
||||
"componentsCreateOrg": "Créer une organisation",
|
||||
"componentsMember": "Vous êtes membre de {count, plural, =0 {aucune organisation} one {une organisation} other {# organisations}}.",
|
||||
"componentsInvalidKey": "Clés de licence invalides ou expirées détectées. Suivez les conditions de licence pour continuer à utiliser toutes les fonctionnalités.",
|
||||
"dismiss": "Refuser",
|
||||
"componentsLicenseViolation": "Violation de licence : Ce serveur utilise des sites {usedSites} qui dépassent la limite autorisée des sites {maxSites} . Suivez les conditions de licence pour continuer à utiliser toutes les fonctionnalités.",
|
||||
"componentsInvalidKey": "Clés de licence invalides ou expirées détectées. Veuillez respecter les conditions de licence pour continuer à utiliser toutes les fonctionnalités.",
|
||||
"dismiss": "Rejeter",
|
||||
"componentsLicenseViolation": "Violation de licence : ce serveur utilise {usedSites} sites, ce qui dépasse la limite autorisée de {maxSites} sites. Respectez les conditions de licence pour continuer à utiliser toutes les fonctionnalités.",
|
||||
"componentsSupporterMessage": "Merci de soutenir Pangolin en tant que {tier}!",
|
||||
"inviteErrorNotValid": "Nous sommes désolés, mais il semble que l'invitation que vous essayez d'accéder n'ait pas été acceptée ou n'est plus valide.",
|
||||
"inviteErrorUser": "Nous sommes désolés, mais il semble que l'invitation que vous essayez d'accéder ne soit pas pour cet utilisateur.",
|
||||
"inviteLoginUser": "Assurez-vous que vous êtes bien connecté en tant qu'utilisateur correct.",
|
||||
"inviteErrorNoUser": "Nous sommes désolés, mais il semble que l'invitation que vous essayez d'accéder ne soit pas pour un utilisateur qui existe.",
|
||||
"inviteErrorNotValid": "Nous sommes désolés, mais il semble que l'invitation à laquelle vous essayez d'accéder n'ait pas été acceptée ou ne soit plus valide.",
|
||||
"inviteErrorUser": "Nous sommes désolés, mais il semble que l'invitation à laquelle vous essayez d'accéder ne soit pas pour cet utilisateur.",
|
||||
"inviteLoginUser": "Veuillez vous assurer que vous êtes connecté avec le bon utilisateur.",
|
||||
"inviteErrorNoUser": "Nous sommes désolés, mais il semble que l'invitation à laquelle vous essayez d'accéder ne concerne pas un utilisateur existant.",
|
||||
"inviteCreateUser": "Veuillez d'abord créer un compte.",
|
||||
"goHome": "Retour à la maison",
|
||||
"goHome": "Retour à l'accueil",
|
||||
"inviteLogInOtherUser": "Se connecter en tant qu'utilisateur différent",
|
||||
"createAnAccount": "Créer un compte",
|
||||
"inviteNotAccepted": "Invitation non acceptée",
|
||||
@@ -39,17 +39,16 @@
|
||||
"online": "En ligne",
|
||||
"offline": "Hors ligne",
|
||||
"site": "Site",
|
||||
"dataIn": "Données dans",
|
||||
"dataOut": "Données épuisées",
|
||||
"dataIn": "Données entrantes",
|
||||
"dataOut": "Données sortantes",
|
||||
"connectionType": "Type de connexion",
|
||||
"tunnelType": "Type de tunnel",
|
||||
"local": "Locale",
|
||||
"edit": "Editer",
|
||||
"edit": "Éditer",
|
||||
"siteConfirmDelete": "Confirmer la suppression du site",
|
||||
"siteDelete": "Supprimer le site",
|
||||
"siteMessageRemove": "Une fois supprimé, le site ne sera plus accessible. Toutes les ressources et cibles associées au site seront également supprimées.",
|
||||
"siteMessageConfirm": "Pour confirmer, veuillez saisir le nom du site ci-dessous.",
|
||||
"siteQuestionRemove": "Êtes-vous sûr de vouloir supprimer le site {selectedSite} de l'organisation ?",
|
||||
"siteMessageRemove": "Une fois supprimé, le site ne sera plus accessible. Toutes les cibles associées au site seront également supprimées.",
|
||||
"siteQuestionRemove": "Êtes-vous sûr de vouloir supprimer le site de l'organisation ?",
|
||||
"siteManageSites": "Gérer les sites",
|
||||
"siteDescription": "Autoriser la connectivité à votre réseau via des tunnels sécurisés",
|
||||
"siteCreate": "Créer un site",
|
||||
@@ -64,11 +63,11 @@
|
||||
"siteLearnNewt": "Apprenez à installer Newt sur votre système",
|
||||
"siteSeeConfigOnce": "Vous ne pourrez voir la configuration qu'une seule fois.",
|
||||
"siteLoadWGConfig": "Chargement de la configuration WireGuard...",
|
||||
"siteDocker": "Développer les détails du déploiement Docker",
|
||||
"siteDocker": "Développer pour obtenir plus de détails sur le déploiement Docker",
|
||||
"toggle": "Activer/désactiver",
|
||||
"dockerCompose": "Composition Docker",
|
||||
"dockerRun": "Exécution Docker",
|
||||
"siteLearnLocal": "Les sites locaux ne tunnel, en savoir plus",
|
||||
"siteLearnLocal": "Les sites locaux ne font pas de tunnel, en savoir plus",
|
||||
"siteConfirmCopy": "J'ai copié la configuration",
|
||||
"searchSitesProgress": "Rechercher des sites...",
|
||||
"siteAdd": "Ajouter un site",
|
||||
@@ -79,7 +78,7 @@
|
||||
"operatingSystem": "Système d'exploitation",
|
||||
"commands": "Commandes",
|
||||
"recommended": "Recommandé",
|
||||
"siteNewtDescription": "Pour une meilleure expérience d'utilisateur, utilisez Newt. Il utilise WireGuard sous le capot et vous permet d'adresser vos ressources privées par leur adresse LAN sur votre réseau privé à partir du tableau de bord Pangolin.",
|
||||
"siteNewtDescription": "Pour une meilleure expérience d'utilisateur, utilisez Newt. Il utilise WireGuard sous le capot et vous permet de vous connecter à vos ressources privées par leur adresse LAN sur votre réseau privé à partir du tableau de bord Pangolin.",
|
||||
"siteRunsInDocker": "Exécute dans Docker",
|
||||
"siteRunsInShell": "Exécute en shell sur macOS, Linux et Windows",
|
||||
"siteErrorDelete": "Erreur lors de la suppression du site",
|
||||
@@ -94,9 +93,9 @@
|
||||
"siteNewtTunnelDescription": "La façon la plus simple de créer un point d'entrée dans votre réseau. Pas de configuration supplémentaire.",
|
||||
"siteWg": "WireGuard basique",
|
||||
"siteWgDescription": "Utilisez n'importe quel client WireGuard pour établir un tunnel. Configuration NAT manuelle requise.",
|
||||
"siteWgDescriptionSaas": "Utilisez n'importe quel client WireGuard pour établir un tunnel. Configuration NAT manuelle requise. FONCTIONNE UNIQUEMENT SUR DES NŒUDS AUTONOMES",
|
||||
"siteWgDescriptionSaas": "Utilisez n'importe quel client WireGuard pour établir un tunnel. Configuration NAT manuelle requise. FONCTIONNE UNIQUEMENT SUR DES NŒUDS AUTONOMES.",
|
||||
"siteLocalDescription": "Ressources locales seulement. Pas de tunneling.",
|
||||
"siteLocalDescriptionSaas": "Ressources locales uniquement. Pas de tunneling. FONCTIONNE UNIQUEMENT SUR DES NŒUDS AUTONOMES",
|
||||
"siteLocalDescriptionSaas": "Ressources locales uniquement. Pas de tunneling. Disponible uniquement sur les nœuds distants.",
|
||||
"siteSeeAll": "Voir tous les sites",
|
||||
"siteTunnelDescription": "Déterminez comment vous voulez vous connecter à votre site",
|
||||
"siteNewtCredentials": "Identifiants Newt",
|
||||
@@ -131,9 +130,9 @@
|
||||
"shareTitleOptional": "Titre (facultatif)",
|
||||
"expireIn": "Expire dans",
|
||||
"neverExpire": "N'expire jamais",
|
||||
"shareExpireDescription": "Le temps d'expiration est combien de temps le lien sera utilisable et fournira un accès à la ressource. Après cette période, le lien ne fonctionnera plus et les utilisateurs qui ont utilisé ce lien perdront l'accès à la ressource.",
|
||||
"shareSeeOnce": "Vous ne pourrez voir ce lien. Assurez-vous de le copier.",
|
||||
"shareAccessHint": "N'importe qui avec ce lien peut accéder à la ressource. Partagez-le avec soin.",
|
||||
"shareExpireDescription": "La durée 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.",
|
||||
"shareSeeOnce": "Vous ne pourrez voir ce lien qu'une seule fois. Assurez-vous de le copier.",
|
||||
"shareAccessHint": "N'importe qui avec ce lien peut accéder à la ressource. Partagez-le avec précaution.",
|
||||
"shareTokenUsage": "Voir Utilisation du jeton d'accès",
|
||||
"createLink": "Créer un lien",
|
||||
"resourcesNotFound": "Aucune ressource trouvée",
|
||||
@@ -154,12 +153,11 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "Pour confirmer, veuillez saisir le nom de la ressource ci-dessous.",
|
||||
"resourceQuestionRemove": "Êtes-vous sûr de vouloir supprimer la ressource {selectedResource} de l'organisation ?",
|
||||
"resourceQuestionRemove": "Êtes-vous sûr de vouloir supprimer la ressource de l'organisation ?",
|
||||
"resourceHTTP": "Ressource HTTPS",
|
||||
"resourceHTTPDescription": "Requêtes de proxy à votre application via HTTPS en utilisant un sous-domaine ou un domaine de base.",
|
||||
"resourceHTTPDescription": "Requêtes de proxy vers votre application via HTTPS en utilisant un sous-domaine ou un domaine de base.",
|
||||
"resourceRaw": "Ressource TCP/UDP brute",
|
||||
"resourceRawDescription": "Demandes de proxy à votre application via TCP/UDP en utilisant un numéro de port.",
|
||||
"resourceRawDescription": "Demandes de proxy vers votre application via TCP/UDP en utilisant un numéro de port.",
|
||||
"resourceCreate": "Créer une ressource",
|
||||
"resourceCreateDescription": "Suivez les étapes ci-dessous pour créer une nouvelle ressource",
|
||||
"resourceSeeAll": "Voir toutes les ressources",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Sélectionner un site",
|
||||
"siteSearch": "Chercher un site",
|
||||
"siteNotFound": "Aucun site trouvé.",
|
||||
"selectCountry": "Sélectionnez un pays",
|
||||
"searchCountries": "Recherchez des pays...",
|
||||
"noCountryFound": "Aucun pays trouvé.",
|
||||
"siteSelectionDescription": "Ce site fournira la connectivité à la cible.",
|
||||
"resourceType": "Type de ressource",
|
||||
"resourceTypeDescription": "Déterminer comment vous voulez accéder à votre ressource",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Domaine de base",
|
||||
"subdomnainDescription": "Le sous-domaine où votre ressource sera accessible.",
|
||||
"resourceRawSettings": "Paramètres TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP. Vous mappez la ressource à un port sur le serveur Pangolin, de sorte que vous puissiez accéder à la ressource depuis server-public-ip:mapped-port.",
|
||||
"protocol": "Protocole",
|
||||
"protocolSelect": "Sélectionner un protocole",
|
||||
"resourcePortNumber": "Numéro de port",
|
||||
@@ -205,7 +206,7 @@
|
||||
"resourceSetting": "Réglages {resourceName}",
|
||||
"alwaysAllow": "Toujours autoriser",
|
||||
"alwaysDeny": "Toujours refuser",
|
||||
"passToAuth": "Paser à l'authentification",
|
||||
"passToAuth": "Passer à l'authentification",
|
||||
"orgSettingsDescription": "Configurer les paramètres généraux de votre organisation",
|
||||
"orgGeneralSettings": "Paramètres de l'organisation",
|
||||
"orgGeneralSettingsDescription": "Gérer les détails et la configuration de votre organisation",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Confirmer la suppression de l'organisation",
|
||||
"orgMessageRemove": "Cette action est irréversible et supprimera toutes les données associées.",
|
||||
"orgMessageConfirm": "Pour confirmer, veuillez saisir le nom de l'organisation ci-dessous.",
|
||||
"orgQuestionRemove": "Êtes-vous sûr de vouloir supprimer l'organisation {selectedOrg}?",
|
||||
"orgQuestionRemove": "Êtes-vous sûr de vouloir supprimer l'organisation ?",
|
||||
"orgUpdated": "Organisation mise à jour",
|
||||
"orgUpdatedDescription": "L'organisation a été mise à jour.",
|
||||
"orgErrorUpdate": "Échec de la mise à jour de l'organisation",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Générer une clé API",
|
||||
"apiKeysErrorDelete": "Erreur lors de la suppression de la clé API",
|
||||
"apiKeysErrorDeleteMessage": "Erreur lors de la suppression de la clé API",
|
||||
"apiKeysQuestionRemove": "Êtes-vous sûr de vouloir supprimer la clé API {selectedApiKey} de l'organisation ?",
|
||||
"apiKeysQuestionRemove": "Êtes-vous sûr de vouloir supprimer la clé API de l'organisation ?",
|
||||
"apiKeysMessageRemove": "Une fois supprimée, la clé API ne pourra plus être utilisée.",
|
||||
"apiKeysMessageConfirm": "Pour confirmer, veuillez saisir le nom de la clé API ci-dessous.",
|
||||
"apiKeysDeleteConfirm": "Confirmer la suppression de la clé API",
|
||||
"apiKeysDelete": "Supprimer la clé API",
|
||||
"apiKeysManage": "Gérer les clés API",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Confirmer la suppression de l'utilisateur",
|
||||
"userDeleteServer": "Supprimer l'utilisateur du serveur",
|
||||
"userMessageRemove": "L'utilisateur sera retiré de toutes les organisations et sera complètement retiré du serveur.",
|
||||
"userMessageConfirm": "Pour confirmer, veuillez saisir le nom de l'utilisateur ci-dessous.",
|
||||
"userQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement {selectedUser} du serveur?",
|
||||
"userQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement l'utilisateur du serveur?",
|
||||
"licenseKey": "Clé de licence",
|
||||
"valid": "Valide",
|
||||
"numberOfSites": "Nombre de sites",
|
||||
@@ -336,14 +335,14 @@
|
||||
"fossorialLicense": "Voir les conditions de licence commerciale et d'abonnement Fossorial",
|
||||
"licenseMessageRemove": "Cela supprimera la clé de licence et toutes les autorisations qui lui sont associées.",
|
||||
"licenseMessageConfirm": "Pour confirmer, veuillez saisir la clé de licence ci-dessous.",
|
||||
"licenseQuestionRemove": "Êtes-vous sûr de vouloir supprimer la clé de licence {selectedKey}?",
|
||||
"licenseQuestionRemove": "Êtes-vous sûr de vouloir supprimer la clé de licence ?",
|
||||
"licenseKeyDelete": "Supprimer la clé de licence",
|
||||
"licenseKeyDeleteConfirm": "Confirmer la suppression de la clé de licence",
|
||||
"licenseTitle": "Gérer le statut de la licence",
|
||||
"licenseTitleDescription": "Voir et gérer les clés de licence dans le système",
|
||||
"licenseHost": "Licence Hôte",
|
||||
"licenseHostDescription": "Gérer la clé de licence principale de l'hôte.",
|
||||
"licensedNot": "Non licencié",
|
||||
"licensedNot": "Pas de licence",
|
||||
"hostId": "ID de l'hôte",
|
||||
"licenseReckeckAll": "Revérifier toutes les clés",
|
||||
"licenseSiteUsage": "Utilisation des sites",
|
||||
@@ -351,7 +350,7 @@
|
||||
"licenseNoSiteLimit": "Il n'y a pas de limite sur le nombre de sites utilisant un hôte non autorisé.",
|
||||
"licensePurchase": "Acheter une licence",
|
||||
"licensePurchaseSites": "Acheter des sites supplémentaires",
|
||||
"licenseSitesUsedMax": "{usedSites} des sites {maxSites} utilisés",
|
||||
"licenseSitesUsedMax": "{usedSites} des {maxSites} sites utilisés",
|
||||
"licenseSitesUsed": "{count, plural, =0 {# sites} one {# site} other {# sites}} dans le système.",
|
||||
"licensePurchaseDescription": "Choisissez le nombre de sites que vous voulez {selectedMode, select, license {achetez une licence. Vous pouvez toujours ajouter plus de sites plus tard.} other {ajouter à votre licence existante.}}",
|
||||
"licenseFee": "Frais de licence",
|
||||
@@ -369,10 +368,10 @@
|
||||
"inviteRemoveErrorDescription": "Une erreur s'est produite lors de la suppression de l'invitation.",
|
||||
"inviteRemoved": "Invitation supprimée",
|
||||
"inviteRemovedDescription": "L'invitation pour {email} a été supprimée.",
|
||||
"inviteQuestionRemove": "Êtes-vous sûr de vouloir supprimer l'invitation {email}?",
|
||||
"inviteQuestionRemove": "Êtes-vous sûr de vouloir supprimer l'invitation?",
|
||||
"inviteMessageRemove": "Une fois supprimée, cette invitation ne sera plus valide. Vous pourrez toujours réinviter l'utilisateur plus tard.",
|
||||
"inviteMessageConfirm": "Pour confirmer, veuillez saisir l'adresse e-mail de l'invitation ci-dessous.",
|
||||
"inviteQuestionRegenerate": "Êtes-vous sûr de vouloir régénérer l'invitation {email}? Cela révoquera l'invitation précédente.",
|
||||
"inviteQuestionRegenerate": "Êtes-vous sûr de vouloir régénérer l'invitation pour {email}? Cela révoquera l'invitation précédente.",
|
||||
"inviteRemoveConfirm": "Confirmer la suppression de l'invitation",
|
||||
"inviteRegenerated": "Invitation régénérée",
|
||||
"inviteSent": "Une nouvelle invitation a été envoyée à {email}.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Une erreur s'est produite lors de la suppression de l'utilisateur.",
|
||||
"userOrgRemoved": "Utilisateur supprimé",
|
||||
"userOrgRemovedDescription": "L'utilisateur {email} a été retiré de l'organisation.",
|
||||
"userQuestionOrgRemove": "Êtes-vous sûr de vouloir retirer {email} de l'organisation ?",
|
||||
"userQuestionOrgRemove": "Êtes-vous sûr de vouloir supprimer cet utilisateur de l'organisation ?",
|
||||
"userMessageOrgRemove": "Une fois retiré, cet utilisateur n'aura plus accès à l'organisation. Vous pouvez toujours le réinviter plus tard, mais il devra accepter l'invitation à nouveau.",
|
||||
"userMessageOrgConfirm": "Pour confirmer, veuillez saisir le nom de l'utilisateur ci-dessous.",
|
||||
"userRemoveOrgConfirm": "Confirmer la suppression de l'utilisateur",
|
||||
"userRemoveOrg": "Retirer l'utilisateur de l'organisation",
|
||||
"users": "Utilisateurs",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Une erreur s'est produite lors de l'ajout de l'utilisateur au rôle.",
|
||||
"userSaved": "Utilisateur enregistré",
|
||||
"userSavedDescription": "L'utilisateur a été mis à jour.",
|
||||
"autoProvisioned": "Auto-provisionné",
|
||||
"autoProvisionedDescription": "Permettre à cet utilisateur d'être géré automatiquement par le fournisseur d'identité",
|
||||
"accessControlsDescription": "Gérer ce que cet utilisateur peut accéder et faire dans l'organisation",
|
||||
"accessControlsSubmit": "Enregistrer les contrôles d'accès",
|
||||
"roles": "Rôles",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Créé le",
|
||||
"proxyErrorInvalidHeader": "Valeur d'en-tête Host personnalisée invalide. Utilisez le format de nom de domaine, ou laissez vide pour désactiver l'en-tête Host personnalisé.",
|
||||
"proxyErrorTls": "Nom de serveur TLS invalide. Utilisez le format de nom de domaine, ou laissez vide pour supprimer le nom de serveur TLS.",
|
||||
"proxyEnableSSL": "Activer SSL (https)",
|
||||
"proxyEnableSSL": "Activer SSL",
|
||||
"proxyEnableSSLDescription": "Activez le cryptage SSL/TLS pour des connexions HTTPS sécurisées vers vos cibles.",
|
||||
"target": "Cible",
|
||||
"configureTarget": "Configurer les cibles",
|
||||
"targetErrorFetch": "Échec de la récupération des cibles",
|
||||
"targetErrorFetchDescription": "Une erreur s'est produite lors de la récupération des cibles",
|
||||
"siteErrorFetch": "Échec de la récupération de la ressource",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Configuration sécurisée de connexion",
|
||||
"targetTlsSettingsDescription": "Configurer les paramètres SSL/TLS pour votre ressource",
|
||||
"targetTlsSettingsAdvanced": "Paramètres TLS avancés",
|
||||
"targetTlsSni": "Nom de serveur TLS (SNI)",
|
||||
"targetTlsSni": "Nom du serveur TLS",
|
||||
"targetTlsSniDescription": "Le nom de serveur TLS à utiliser pour SNI. Laissez vide pour utiliser la valeur par défaut.",
|
||||
"targetTlsSubmit": "Enregistrer les paramètres",
|
||||
"targets": "Configuration des cibles",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Maintenir les connexions sur la même cible backend pendant toute leur session.",
|
||||
"methodSelect": "Sélectionner la méthode",
|
||||
"targetSubmit": "Ajouter une cible",
|
||||
"targetNoOne": "Aucune cible. Ajoutez une cible en utilisant le formulaire.",
|
||||
"targetNoOne": "Cette ressource n'a aucune cible. Ajoutez une cible pour configurer où envoyer des requêtes à votre backend.",
|
||||
"targetNoOneDescription": "L'ajout de plus d'une cible ci-dessus activera l'équilibrage de charge.",
|
||||
"targetsSubmit": "Enregistrer les cibles",
|
||||
"addTarget": "Ajouter une cible",
|
||||
"targetErrorInvalidIp": "Adresse IP invalide",
|
||||
"targetErrorInvalidIpDescription": "Veuillez entrer une adresse IP ou un nom d'hôte valide",
|
||||
"targetErrorInvalidPort": "Port invalide",
|
||||
"targetErrorInvalidPortDescription": "Veuillez entrer un numéro de port valide",
|
||||
"targetErrorNoSite": "Aucun site sélectionné",
|
||||
"targetErrorNoSiteDescription": "Veuillez sélectionner un site pour la cible",
|
||||
"targetCreated": "Cible créée",
|
||||
"targetCreatedDescription": "La cible a été créée avec succès",
|
||||
"targetErrorCreate": "Impossible de créer la cible",
|
||||
"targetErrorCreateDescription": "Une erreur s'est produite lors de la création de la cible",
|
||||
"save": "Enregistrer",
|
||||
"proxyAdditional": "Paramètres de proxy supplémentaires",
|
||||
"proxyAdditionalDescription": "Configurer la façon dont votre ressource gère les paramètres de proxy",
|
||||
"proxyCustomHeader": "En-tête Host personnalisé",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Format d'adresse IP invalide",
|
||||
"ipAddressErrorInvalidOctet": "Octet d'adresse IP invalide",
|
||||
"path": "Chemin",
|
||||
"matchPath": "Chemin de correspondance",
|
||||
"ipAddressRange": "Plage IP",
|
||||
"rulesErrorFetch": "Échec de la récupération des règles",
|
||||
"rulesErrorFetchDescription": "Une erreur s'est produite lors de la récupération des règles",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Admin Serveur - Pangolin",
|
||||
"licenseTierProfessional": "Licence Professionnelle",
|
||||
"licenseTierEnterprise": "Licence Entreprise",
|
||||
"licenseTierCommercial": "Licence commerciale",
|
||||
"licenseTierPersonal": "Licence personnelle",
|
||||
"licensed": "Sous licence",
|
||||
"yes": "Oui",
|
||||
"no": "Non",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Voir et gérer les fournisseurs d'identité dans le système",
|
||||
"idpDeletedDescription": "Fournisseur d'identité supprimé avec succès",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement le fournisseur d'identité {name}?",
|
||||
"idpQuestionRemove": "Êtes-vous sûr de vouloir supprimer définitivement le fournisseur d'identité?",
|
||||
"idpMessageRemove": "Cela supprimera le fournisseur d'identité et toutes les configurations associées. Les utilisateurs qui s'authentifient via ce fournisseur ne pourront plus se connecter.",
|
||||
"idpMessageConfirm": "Pour confirmer, veuillez saisir le nom du fournisseur d'identité ci-dessous.",
|
||||
"idpConfirmDelete": "Confirmer la suppression du fournisseur d'identité",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Un nom d'affichage pour ce fournisseur d'identité",
|
||||
"idpAutoProvisionUsers": "Approvisionnement automatique des utilisateurs",
|
||||
"idpAutoProvisionUsersDescription": "Lorsque cette option est activée, les utilisateurs seront automatiquement créés dans le système lors de leur première connexion avec la possibilité de mapper les utilisateurs aux rôles et aux organisations.",
|
||||
"licenseBadge": "Professionnel",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Type de fournisseur",
|
||||
"idpTypeDescription": "Sélectionnez le type de fournisseur d'identité que vous souhaitez configurer",
|
||||
"idpOidcConfigure": "Configuration OAuth2/OIDC",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Vérifiez votre e-mail pour le code de réinitialisation.",
|
||||
"passwordNew": "Nouveau mot de passe",
|
||||
"passwordNewConfirm": "Confirmer le nouveau mot de passe",
|
||||
"changePassword": "Changer le mot de passe",
|
||||
"changePasswordDescription": "Mettre à jour le mot de passe de votre compte",
|
||||
"oldPassword": "Mot de passe actuel",
|
||||
"newPassword": "Nouveau mot de passe",
|
||||
"confirmNewPassword": "Confirmer le nouveau mot de passe",
|
||||
"changePasswordError": "Impossible de changer le mot de passe",
|
||||
"changePasswordErrorDescription": "Une erreur s'est produite lors de la modification de votre mot de passe",
|
||||
"changePasswordSuccess": "Mot de passe modifié avec succès",
|
||||
"changePasswordSuccessDescription": "Votre mot de passe a été mis à jour avec succès",
|
||||
"passwordExpiryRequired": "Expiration du mot de passe requise",
|
||||
"passwordExpiryDescription": "Cette organisation vous demande de changer votre mot de passe tous les {maxDays} jours.",
|
||||
"changePasswordNow": "Changer le mot de passe maintenant",
|
||||
"pincodeAuth": "Code d'authentification",
|
||||
"pincodeSubmit2": "Soumettre le code",
|
||||
"passwordResetSubmit": "Demander la réinitialisation",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Édition Professionnelle Requise",
|
||||
"licenseTierProfessionalRequiredDescription": "Cette fonctionnalité n'est disponible que dans l'Édition Professionnelle.",
|
||||
"actionGetOrg": "Obtenir l'organisation",
|
||||
"updateOrgUser": "Mise à jour de l'utilisateur Org",
|
||||
"createOrgUser": "Créer un utilisateur Org",
|
||||
"actionUpdateOrg": "Mettre à jour l'organisation",
|
||||
"actionUpdateUser": "Mettre à jour l'utilisateur",
|
||||
"actionGetUser": "Obtenir l'utilisateur",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Supprimer un site",
|
||||
"actionGetSite": "Obtenir un site",
|
||||
"actionListSites": "Lister les sites",
|
||||
"actionApplyBlueprint": "Appliquer le Plan",
|
||||
"setupToken": "Jeton de configuration",
|
||||
"setupTokenDescription": "Entrez le jeton de configuration depuis la console du serveur.",
|
||||
"setupTokenRequired": "Le jeton de configuration est requis.",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Menu de navigation",
|
||||
"navbarDescription": "Menu de navigation principal de l'application",
|
||||
"navbarDocsLink": "Documentation",
|
||||
"commercialEdition": "Édition Commerciale",
|
||||
"otpErrorEnable": "Impossible d'activer l'A2F",
|
||||
"otpErrorEnableDescription": "Une erreur s'est produite lors de l'activation de l'A2F",
|
||||
"otpSetupCheckCode": "Veuillez entrer un code à 6 chiffres",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Tous les utilisateurs",
|
||||
"sidebarIdentityProviders": "Fournisseurs d'identité",
|
||||
"sidebarLicense": "Licence",
|
||||
"sidebarClients": "Clients (Bêta)",
|
||||
"sidebarClients": "Clients",
|
||||
"sidebarDomains": "Domaines",
|
||||
"enableDockerSocket": "Activer Docker Socket",
|
||||
"enableDockerSocketDescription": "Activer la découverte Docker Socket pour remplir les informations du conteneur. Le chemin du socket doit être fourni à Newt.",
|
||||
"sidebarBluePrints": "Plans",
|
||||
"blueprints": "Plans",
|
||||
"blueprintsDescription": "Appliquer les configurations déclaratives et afficher les exécutions précédentes",
|
||||
"blueprintAdd": "Ajouter un Plan",
|
||||
"blueprintGoBack": "Voir tous les plans",
|
||||
"blueprintCreate": "Créer un Plan",
|
||||
"blueprintCreateDescription2": "Suivez les étapes ci-dessous pour créer et appliquer un nouveau plan",
|
||||
"blueprintDetails": "Détails du Plan",
|
||||
"blueprintDetailsDescription": "Voir le résultat du plan appliqué et les erreurs qui se sont produites",
|
||||
"blueprintInfo": "Informations sur le Plan",
|
||||
"message": "Message",
|
||||
"blueprintContentsDescription": "Définissez le contenu YAML décrivant votre infrastructure",
|
||||
"blueprintErrorCreateDescription": "Une erreur s'est produite lors de l'application du plan",
|
||||
"blueprintErrorCreate": "Erreur lors de la création du plan",
|
||||
"searchBlueprintProgress": "Rechercher des plans...",
|
||||
"appliedAt": "Appliqué à",
|
||||
"source": "Source",
|
||||
"contents": "Contenus",
|
||||
"parsedContents": "Contenu analysé (lecture seule)",
|
||||
"enableDockerSocket": "Activer le Plan Docker",
|
||||
"enableDockerSocketDescription": "Activer le ramassage d'étiquettes de socket Docker pour les étiquettes de plan. Le chemin de socket doit être fourni à Newt.",
|
||||
"enableDockerSocketLink": "En savoir plus",
|
||||
"viewDockerContainers": "Voir les conteneurs Docker",
|
||||
"containersIn": "Conteneurs en {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Créer un domaine",
|
||||
"domainCreatedDescription": "Domaine créé avec succès",
|
||||
"domainDeletedDescription": "Domaine supprimé avec succès",
|
||||
"domainQuestionRemove": "Êtes-vous sûr de vouloir supprimer le domaine {domain} de votre compte ?",
|
||||
"domainQuestionRemove": "Êtes-vous sûr de vouloir supprimer le domaine de votre compte ?",
|
||||
"domainMessageRemove": "Une fois supprimé, le domaine ne sera plus associé à votre compte.",
|
||||
"domainMessageConfirm": "Pour confirmer, veuillez taper le nom du domaine ci-dessous.",
|
||||
"domainConfirmDelete": "Confirmer la suppression du domaine",
|
||||
"domainDelete": "Supprimer le domaine",
|
||||
"domain": "Domaine",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Mise à jour disponible",
|
||||
"newtUpdateAvailableInfo": "Une nouvelle version de Newt est disponible. Veuillez mettre à jour vers la dernière version pour une meilleure expérience.",
|
||||
"domainPickerEnterDomain": "Domaine",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com, ou simplement myapp",
|
||||
"domainPickerPlaceholder": "monapp.exemple.com",
|
||||
"domainPickerDescription": "Entrez le domaine complet de la ressource pour voir les options disponibles.",
|
||||
"domainPickerDescriptionSaas": "Entrez un domaine complet, un sous-domaine ou juste un nom pour voir les options disponibles",
|
||||
"domainPickerTabAll": "Tous",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Sous-domaine : {subdomain}",
|
||||
"domainPickerNamespace": "Espace de noms : {namespace}",
|
||||
"domainPickerShowMore": "Afficher plus",
|
||||
"regionSelectorTitle": "Sélectionner Région",
|
||||
"regionSelectorInfo": "Sélectionner une région nous aide à offrir de meilleures performances pour votre localisation. Vous n'avez pas besoin d'être dans la même région que votre serveur.",
|
||||
"regionSelectorPlaceholder": "Choisissez une région",
|
||||
"regionSelectorComingSoon": "Bientôt disponible",
|
||||
"billingLoadingSubscription": "Chargement de l'abonnement...",
|
||||
"billingFreeTier": "Niveau gratuit",
|
||||
"billingWarningOverLimit": "Attention : Vous avez dépassé une ou plusieurs limites d'utilisation. Vos sites ne se connecteront pas tant que vous n'avez pas modifié votre abonnement ou ajusté votre utilisation.",
|
||||
"billingUsageLimitsOverview": "Vue d'ensemble des limites d'utilisation",
|
||||
"billingMonitorUsage": "Surveillez votre consommation par rapport aux limites configurées. Si vous avez besoin d'une augmentation des limites, veuillez nous contacter à support@pangolin.net.",
|
||||
"billingDataUsage": "Utilisation des données",
|
||||
"billingOnlineTime": "Temps en ligne du site",
|
||||
"billingUsers": "Utilisateurs actifs",
|
||||
"billingDomains": "Domaines actifs",
|
||||
"billingRemoteExitNodes": "Nœuds auto-hébergés actifs",
|
||||
"billingNoLimitConfigured": "Aucune limite configurée",
|
||||
"billingEstimatedPeriod": "Période de facturation estimée",
|
||||
"billingIncludedUsage": "Utilisation incluse",
|
||||
"billingIncludedUsageDescription": "Utilisation incluse dans votre plan d'abonnement actuel",
|
||||
"billingFreeTierIncludedUsage": "Tolérances d'utilisation du niveau gratuit",
|
||||
"billingIncluded": "inclus",
|
||||
"billingEstimatedTotal": "Total estimé :",
|
||||
"billingNotes": "Notes",
|
||||
"billingEstimateNote": "Ceci est une estimation basée sur votre utilisation actuelle.",
|
||||
"billingActualChargesMayVary": "Les frais réels peuvent varier.",
|
||||
"billingBilledAtEnd": "Vous serez facturé à la fin de la période de facturation.",
|
||||
"billingModifySubscription": "Modifier l'abonnement",
|
||||
"billingStartSubscription": "Démarrer l'abonnement",
|
||||
"billingRecurringCharge": "Frais récurrents",
|
||||
"billingManageSubscriptionSettings": "Gérez les paramètres et préférences de votre abonnement",
|
||||
"billingNoActiveSubscription": "Vous n'avez pas d'abonnement actif. Commencez votre abonnement pour augmenter les limites d'utilisation.",
|
||||
"billingFailedToLoadSubscription": "Échec du chargement de l'abonnement",
|
||||
"billingFailedToLoadUsage": "Échec du chargement de l'utilisation",
|
||||
"billingFailedToGetCheckoutUrl": "Échec pour obtenir l'URL de paiement",
|
||||
"billingPleaseTryAgainLater": "Veuillez réessayer plus tard.",
|
||||
"billingCheckoutError": "Erreur de paiement",
|
||||
"billingFailedToGetPortalUrl": "Échec pour obtenir l'URL du portail",
|
||||
"billingPortalError": "Erreur du portail",
|
||||
"billingDataUsageInfo": "Vous êtes facturé pour toutes les données transférées via vos tunnels sécurisés lorsque vous êtes connecté au cloud. Cela inclut le trafic entrant et sortant sur tous vos sites. Lorsque vous atteignez votre limite, vos sites se déconnecteront jusqu'à ce que vous mettiez à niveau votre plan ou réduisiez l'utilisation. Les données ne sont pas facturées lors de l'utilisation de nœuds.",
|
||||
"billingOnlineTimeInfo": "Vous êtes facturé en fonction de la durée de connexion de vos sites au cloud. Par exemple, 44 640 minutes équivaut à un site fonctionnant 24/7 pendant un mois complet. Lorsque vous atteignez votre limite, vos sites se déconnecteront jusqu'à ce que vous mettiez à niveau votre forfait ou réduisiez votre consommation. Le temps n'est pas facturé lors de l'utilisation de nœuds.",
|
||||
"billingUsersInfo": "Vous êtes facturé pour chaque utilisateur dans votre organisation. La facturation est calculée quotidiennement en fonction du nombre de comptes utilisateurs actifs dans votre organisation.",
|
||||
"billingDomainInfo": "Vous êtes facturé pour chaque domaine dans votre organisation. La facturation est calculée quotidiennement en fonction du nombre de comptes de domaine actifs dans votre organisation.",
|
||||
"billingRemoteExitNodesInfo": "Vous êtes facturé pour chaque nœud géré dans votre organisation. La facturation est calculée quotidiennement en fonction du nombre de nœuds gérés actifs dans votre organisation.",
|
||||
"domainNotFound": "Domaine introuvable",
|
||||
"domainNotFoundDescription": "Cette ressource est désactivée car le domaine n'existe plus dans notre système. Veuillez définir un nouveau domaine pour cette ressource.",
|
||||
"failed": "Échec",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Un problème est survenu avec votre clé de sécurité. Veuillez réessayer.",
|
||||
"twoFactorRequired": "L'authentification à deux facteurs est requise pour enregistrer une clé de sécurité.",
|
||||
"twoFactor": "Authentification à deux facteurs",
|
||||
"twoFactorAuthentication": "Authentification à deux facteurs",
|
||||
"twoFactorDescription": "Cette organisation nécessite une authentification à deux facteurs.",
|
||||
"enableTwoFactor": "Activer l'authentification à deux facteurs",
|
||||
"organizationSecurityPolicy": "Politique de sécurité de l'organisation",
|
||||
"organizationSecurityPolicyDescription": "Cette organisation a des exigences de sécurité qui doivent être remplies avant que vous puissiez y accéder",
|
||||
"securityRequirements": "Exigences de sécurité",
|
||||
"allRequirementsMet": "Toutes les conditions ont été remplies",
|
||||
"completeRequirementsToContinue": "Remplissez les conditions ci-dessous pour continuer à accéder à cette organisation",
|
||||
"youCanNowAccessOrganization": "Vous pouvez maintenant accéder à cette organisation",
|
||||
"reauthenticationRequired": "Durée de la session",
|
||||
"reauthenticationDescription": "Cette organisation vous demande de vous connecter tous les {maxDays} jours.",
|
||||
"reauthenticationDescriptionHours": "Cette organisation vous demande de vous connecter toutes les {maxHours} heures.",
|
||||
"reauthenticateNow": "Reconnectez-vous",
|
||||
"adminEnabled2FaOnYourAccount": "Votre administrateur a activé l'authentification à deux facteurs pour {email}. Veuillez terminer le processus d'installation pour continuer.",
|
||||
"continueToApplication": "Continuer vers l'application",
|
||||
"securityKeyAdd": "Ajouter une clé de sécurité",
|
||||
"securityKeyRegisterTitle": "Enregistrer une nouvelle clé de sécurité",
|
||||
"securityKeyRegisterDescription": "Connectez votre clé de sécurité et saisissez un nom pour l'identifier",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "Les modifications DNS peuvent mettre du temps à se propager sur internet. Cela peut prendre de quelques minutes à 48 heures selon votre fournisseur DNS et les réglages TTL.",
|
||||
"resourcePortRequired": "Le numéro de port est requis pour les ressources non-HTTP",
|
||||
"resourcePortNotAllowed": "Le numéro de port ne doit pas être défini pour les ressources HTTP",
|
||||
"billingPricingCalculatorLink": "Calculateur de prix",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Je suis d'accord avec",
|
||||
"termsOfService": "les conditions d'utilisation",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Proxy externe activé",
|
||||
"addNewTarget": "Ajouter une nouvelle cible",
|
||||
"targetsList": "Liste des cibles",
|
||||
"advancedMode": "Mode Avancé",
|
||||
"targetErrorDuplicateTargetFound": "Cible en double trouvée",
|
||||
"healthCheckHealthy": "Sain",
|
||||
"healthCheckUnhealthy": "En mauvaise santé",
|
||||
"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}",
|
||||
"enableHealthChecks": "Activer les vérifications de santé",
|
||||
"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",
|
||||
"healthCheckPath": "Chemin d'accès",
|
||||
"healthHostname": "IP / Hôte",
|
||||
"healthPort": "Port",
|
||||
"healthCheckPathDescription": "Le chemin à vérifier pour le statut de santé.",
|
||||
"healthyIntervalSeconds": "Intervalle sain",
|
||||
"unhealthyIntervalSeconds": "Intervalle en mauvaise santé",
|
||||
"IntervalSeconds": "Intervalle sain",
|
||||
"timeoutSeconds": "Délai",
|
||||
"timeIsInSeconds": "Le temps est exprimé en secondes",
|
||||
"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.",
|
||||
"customHeaders": "En-têtes personnalisés",
|
||||
"customHeadersDescription": "En-têtes séparés par une nouvelle ligne: En-nom: valeur",
|
||||
"headersValidationError": "Les entêtes doivent être au format : Header-Name: valeur.",
|
||||
"saveHealthCheck": "Sauvegarder la vérification de l'état de santé",
|
||||
"healthCheckSaved": "Vérification de l'état de santé enregistrée",
|
||||
"healthCheckSavedDescription": "La configuration de la vérification de l'état de santé a été enregistrée avec succès",
|
||||
"healthCheckError": "Erreur de vérification de l'état de santé",
|
||||
"healthCheckErrorDescription": "Une erreur s'est produite lors de l'enregistrement de la configuration de la vérification de l'état de santé",
|
||||
"healthCheckPathRequired": "Le chemin de vérification de l'état de santé est requis",
|
||||
"healthCheckMethodRequired": "La méthode HTTP est requise",
|
||||
"healthCheckIntervalMin": "L'intervalle de vérification doit être d'au moins 5 secondes",
|
||||
"healthCheckTimeoutMin": "Le délai doit être d'au moins 1 seconde",
|
||||
"healthCheckRetryMin": "Les tentatives de réessai doivent être d'au moins 1",
|
||||
"httpMethod": "Méthode HTTP",
|
||||
"selectHttpMethod": "Sélectionnez la méthode HTTP",
|
||||
"domainPickerSubdomainLabel": "Sous-domaine",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Entrez un sous-domaine pour rechercher et sélectionner parmi les domaines gratuits disponibles.",
|
||||
"domainPickerFreeDomains": "Domaines gratuits",
|
||||
"domainPickerSearchForAvailableDomains": "Rechercher des domaines disponibles",
|
||||
"domainPickerNotWorkSelfHosted": "Remarque : Les domaines fournis gratuitement ne sont pas disponibles pour les instances auto-hébergées pour le moment.",
|
||||
"resourceDomain": "Domaine",
|
||||
"resourceEditDomain": "Modifier le domaine",
|
||||
"siteName": "Nom du site",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protocole",
|
||||
"editInternalResourceDialogSitePort": "Port du site",
|
||||
"editInternalResourceDialogTargetConfiguration": "Configuration de la cible",
|
||||
"editInternalResourceDialogDestinationIP": "IP de destination",
|
||||
"editInternalResourceDialogDestinationPort": "Port de destination",
|
||||
"editInternalResourceDialogCancel": "Abandonner",
|
||||
"editInternalResourceDialogSaveResource": "Enregistrer la ressource",
|
||||
"editInternalResourceDialogSuccess": "Succès",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Port du site",
|
||||
"createInternalResourceDialogSitePortDescription": "Utilisez ce port pour accéder à la ressource sur le site lors de la connexion avec un client.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Configuration de la cible",
|
||||
"createInternalResourceDialogDestinationIP": "IP de destination",
|
||||
"createInternalResourceDialogDestinationIPDescription": "L'adresse IP de la ressource sur le réseau du site.",
|
||||
"createInternalResourceDialogDestinationPort": "Port de destination",
|
||||
"createInternalResourceDialogDestinationIPDescription": "L'adresse IP ou le nom d'hôte de la ressource sur le réseau du site.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "Le port sur l'IP de destination où la ressource est accessible.",
|
||||
"createInternalResourceDialogCancel": "Abandonner",
|
||||
"createInternalResourceDialogCreateResource": "Créer une ressource",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Erreur de connexion automatique",
|
||||
"autoLoginErrorNoRedirectUrl": "Aucune URL de redirection reçue du fournisseur d'identité.",
|
||||
"autoLoginErrorGeneratingUrl": "Échec de la génération de l'URL d'authentification.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Nœuds distants",
|
||||
"remoteExitNodeDescription": "Héberger un ou plusieurs nœuds distants pour étendre votre connectivité réseau et réduire la dépendance sur le cloud",
|
||||
"remoteExitNodes": "Nœuds",
|
||||
"searchRemoteExitNodes": "Rechercher des nœuds...",
|
||||
"remoteExitNodeAdd": "Ajouter un noeud",
|
||||
"remoteExitNodeErrorDelete": "Erreur lors de la suppression du noeud",
|
||||
"remoteExitNodeQuestionRemove": "Êtes-vous sûr de vouloir supprimer le noeud de l'organisation ?",
|
||||
"remoteExitNodeMessageRemove": "Une fois supprimé, le noeud ne sera plus accessible.",
|
||||
"remoteExitNodeConfirmDelete": "Confirmer la suppression du noeud",
|
||||
"remoteExitNodeDelete": "Supprimer le noeud",
|
||||
"sidebarRemoteExitNodes": "Nœuds distants",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Créer un noeud",
|
||||
"description": "Créer un nouveau nœud pour étendre votre connectivité réseau",
|
||||
"viewAllButton": "Voir tous les nœuds",
|
||||
"strategy": {
|
||||
"title": "Stratégie de création",
|
||||
"description": "Choisissez ceci pour configurer manuellement votre nœud ou générer de nouveaux identifiants.",
|
||||
"adopt": {
|
||||
"title": "Adopter un nœud",
|
||||
"description": "Choisissez ceci si vous avez déjà les identifiants pour le noeud."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Générer des clés",
|
||||
"description": "Choisissez ceci si vous voulez générer de nouvelles clés pour le noeud"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Adopter un nœud existant",
|
||||
"description": "Entrez les identifiants du noeud existant que vous souhaitez adopter",
|
||||
"nodeIdLabel": "Nœud ID",
|
||||
"nodeIdDescription": "L'ID du noeud existant que vous voulez adopter",
|
||||
"secretLabel": "Secret",
|
||||
"secretDescription": "La clé secrète du noeud existant",
|
||||
"submitButton": "Noeud d'Adopt"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Informations d'identification générées",
|
||||
"description": "Utilisez ces identifiants générés pour configurer votre noeud",
|
||||
"nodeIdTitle": "Nœud ID",
|
||||
"secretTitle": "Secret",
|
||||
"saveCredentialsTitle": "Ajouter des identifiants à la config",
|
||||
"saveCredentialsDescription": "Ajoutez ces informations d'identification à votre fichier de configuration du nœud Pangolin auto-hébergé pour compléter la connexion.",
|
||||
"submitButton": "Créer un noeud"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "ID de nœud et secret sont requis lors de l'adoption d'un noeud existant"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Échec du chargement des valeurs par défaut",
|
||||
"defaultsNotLoaded": "Valeurs par défaut non chargées",
|
||||
"createFailed": "Impossible de créer le noeud"
|
||||
},
|
||||
"success": {
|
||||
"created": "Noeud créé avec succès"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Sélection du noeud",
|
||||
"remoteExitNodeSelectionDescription": "Sélectionnez un nœud pour acheminer le trafic pour ce site local",
|
||||
"remoteExitNodeRequired": "Un noeud doit être sélectionné pour les sites locaux",
|
||||
"noRemoteExitNodesAvailable": "Aucun noeud disponible",
|
||||
"noRemoteExitNodesAvailableDescription": "Aucun noeud n'est disponible pour cette organisation. Créez d'abord un noeud pour utiliser des sites locaux.",
|
||||
"exitNode": "Nœud de sortie",
|
||||
"country": "Pays",
|
||||
"rulesMatchCountry": "Actuellement basé sur l'IP source",
|
||||
"managedSelfHosted": {
|
||||
"title": "Gestion autonome",
|
||||
"description": "Serveur Pangolin auto-hébergé avec des cloches et des sifflets supplémentaires",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Convertir ce noeud en auto-hébergé géré"
|
||||
},
|
||||
"internationaldomaindetected": "Domaine international détecté",
|
||||
"willbestoredas": "Sera stocké comme :"
|
||||
}
|
||||
"willbestoredas": "Sera stocké comme :",
|
||||
"roleMappingDescription": "Détermine comment les rôles sont assignés aux utilisateurs lorsqu'ils se connectent lorsque la fourniture automatique est activée.",
|
||||
"selectRole": "Sélectionnez un rôle",
|
||||
"roleMappingExpression": "Expression",
|
||||
"selectRolePlaceholder": "Choisir un rôle",
|
||||
"selectRoleDescription": "Sélectionnez un rôle à assigner à tous les utilisateurs de ce fournisseur d'identité",
|
||||
"roleMappingExpressionDescription": "Entrez une expression JMESPath pour extraire les informations du rôle du jeton ID",
|
||||
"idpTenantIdRequired": "L'ID du locataire est requis",
|
||||
"invalidValue": "Valeur non valide",
|
||||
"idpTypeLabel": "Type de fournisseur d'identité",
|
||||
"roleMappingExpressionPlaceholder": "ex: contenu(groupes) && 'admin' || 'membre'",
|
||||
"idpGoogleConfiguration": "Configuration Google",
|
||||
"idpGoogleConfigurationDescription": "Configurer vos identifiants Google OAuth2",
|
||||
"idpGoogleClientIdDescription": "Votre identifiant client Google OAuth2",
|
||||
"idpGoogleClientSecretDescription": "Votre secret client Google OAuth2",
|
||||
"idpAzureConfiguration": "Configuration de l'entra ID Azure",
|
||||
"idpAzureConfigurationDescription": "Configurer vos identifiants OAuth2 Azure Entra",
|
||||
"idpTenantId": "ID du locataire",
|
||||
"idpTenantIdPlaceholder": "votre-locataire-id",
|
||||
"idpAzureTenantIdDescription": "Votre ID de locataire Azure (trouvé dans l'aperçu Azure Active Directory)",
|
||||
"idpAzureClientIdDescription": "Votre ID client d'enregistrement de l'application Azure",
|
||||
"idpAzureClientSecretDescription": "Le secret de votre client d'enregistrement Azure App",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Configuration Google",
|
||||
"idpAzureConfigurationTitle": "Configuration de l'entra ID Azure",
|
||||
"idpTenantIdLabel": "ID du locataire",
|
||||
"idpAzureClientIdDescription2": "Votre ID client d'enregistrement de l'application Azure",
|
||||
"idpAzureClientSecretDescription2": "Le secret de votre client d'enregistrement Azure App",
|
||||
"idpGoogleDescription": "Fournisseur Google OAuth2/OIDC",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Sous-réseau",
|
||||
"subnetDescription": "Le sous-réseau de la configuration réseau de cette organisation.",
|
||||
"authPage": "Page d'authentification",
|
||||
"authPageDescription": "Configurer la page d'authentification de votre organisation",
|
||||
"authPageDomain": "Domaine de la page d'authentification",
|
||||
"noDomainSet": "Aucun domaine défini",
|
||||
"changeDomain": "Changer de domaine",
|
||||
"selectDomain": "Sélectionner un domaine",
|
||||
"restartCertificate": "Redémarrer le certificat",
|
||||
"editAuthPageDomain": "Modifier le domaine de la page d'authentification",
|
||||
"setAuthPageDomain": "Définir le domaine de la page d'authentification",
|
||||
"failedToFetchCertificate": "Impossible de récupérer le certificat",
|
||||
"failedToRestartCertificate": "Échec du redémarrage du certificat",
|
||||
"addDomainToEnableCustomAuthPages": "Ajouter un domaine pour activer les pages d'authentification personnalisées pour votre organisation",
|
||||
"selectDomainForOrgAuthPage": "Sélectionnez un domaine pour la page d'authentification de l'organisation",
|
||||
"domainPickerProvidedDomain": "Domaine fourni",
|
||||
"domainPickerFreeProvidedDomain": "Domaine fourni gratuitement",
|
||||
"domainPickerVerified": "Vérifié",
|
||||
"domainPickerUnverified": "Non vérifié",
|
||||
"domainPickerInvalidSubdomainStructure": "Ce sous-domaine contient des caractères ou une structure non valide. Il sera automatiquement nettoyé lorsque vous enregistrez.",
|
||||
"domainPickerError": "Erreur",
|
||||
"domainPickerErrorLoadDomains": "Impossible de charger les domaines de l'organisation",
|
||||
"domainPickerErrorCheckAvailability": "Impossible de vérifier la disponibilité du domaine",
|
||||
"domainPickerInvalidSubdomain": "Sous-domaine invalide",
|
||||
"domainPickerInvalidSubdomainRemoved": "L'entrée \"{sub}\" a été supprimée car elle n'est pas valide.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "La «{sub}» n'a pas pu être validée pour {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Sous-domaine nettoyé",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" a été corrigé à \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Connectez-vous à votre organisation",
|
||||
"orgAuthChooseIdpDescription": "Choisissez votre fournisseur d'identité pour continuer",
|
||||
"orgAuthNoIdpConfigured": "Cette organisation n'a aucun fournisseur d'identité configuré. Vous pouvez vous connecter avec votre identité Pangolin à la place.",
|
||||
"orgAuthSignInWithPangolin": "Se connecter avec Pangolin",
|
||||
"subscriptionRequiredToUse": "Un abonnement est requis pour utiliser cette fonctionnalité.",
|
||||
"idpDisabled": "Les fournisseurs d'identité sont désactivés.",
|
||||
"orgAuthPageDisabled": "La page d'authentification de l'organisation est désactivée.",
|
||||
"domainRestartedDescription": "La vérification du domaine a été redémarrée avec succès",
|
||||
"resourceAddEntrypointsEditFile": "Modifier le fichier : config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Modifier le fichier : docker-compose.yml",
|
||||
"emailVerificationRequired": "La vérification de l'e-mail est requise. Veuillez vous reconnecter via {dashboardUrl}/auth/login terminé cette étape. Puis revenez ici.",
|
||||
"twoFactorSetupRequired": "La configuration d'authentification à deux facteurs est requise. Veuillez vous reconnecter via {dashboardUrl}/auth/login terminé cette étape. Puis revenez ici.",
|
||||
"additionalSecurityRequired": "Sécurité supplémentaire requise",
|
||||
"organizationRequiresAdditionalSteps": "Cette organisation nécessite des étapes de sécurité supplémentaires avant de pouvoir accéder aux ressources.",
|
||||
"completeTheseSteps": "Compléter ces étapes",
|
||||
"enableTwoFactorAuthentication": "Activer l'authentification à deux facteurs",
|
||||
"completeSecuritySteps": "Compléter les étapes de sécurité",
|
||||
"securitySettings": "Paramètres de sécurité",
|
||||
"securitySettingsDescription": "Configurer les politiques de sécurité de votre organisation",
|
||||
"requireTwoFactorForAllUsers": "Exiger une authentification à deux facteurs pour tous les utilisateurs",
|
||||
"requireTwoFactorDescription": "Lorsque cette option est activée, tous les utilisateurs internes de cette organisation doivent avoir l'authentification à deux facteurs pour accéder à l'organisation.",
|
||||
"requireTwoFactorDisabledDescription": "Cette fonctionnalité nécessite une licence valide (Entreprise) ou un abonnement actif (SaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "Vous devez activer l'authentification à deux facteurs pour votre compte avant de l'appliquer pour tous les utilisateurs",
|
||||
"maxSessionLength": "Longueur maximale de la session",
|
||||
"maxSessionLengthDescription": "Définissez la durée maximale des sessions utilisateur. Après cette période, les utilisateurs devront se ré-authentifier.",
|
||||
"maxSessionLengthDisabledDescription": "Cette fonctionnalité nécessite une licence valide (Entreprise) ou un abonnement actif (SaaS)",
|
||||
"selectSessionLength": "Sélectionnez la durée de la session",
|
||||
"unenforced": "Non appliqué",
|
||||
"1Hour": "1 heure",
|
||||
"3Hours": "3heures",
|
||||
"6Hours": "6 heures",
|
||||
"12Hours": "12 heures",
|
||||
"1DaySession": "1 jour",
|
||||
"3Days": "3 jours",
|
||||
"7Days": "7 jours",
|
||||
"14Days": "14 jours",
|
||||
"30DaysSession": "30 jours",
|
||||
"90DaysSession": "90 jours",
|
||||
"180DaysSession": "180 jours",
|
||||
"passwordExpiryDays": "Expiration du mot de passe",
|
||||
"editPasswordExpiryDescription": "Définissez le nombre de jours avant que les utilisateurs ne soient tenus de changer leur mot de passe.",
|
||||
"selectPasswordExpiry": "Sélectionnez l'expiration du mot de passe",
|
||||
"30Days": "30 jours",
|
||||
"1Day": "1 jour",
|
||||
"60Days": "60 jours",
|
||||
"90Days": "90 jours",
|
||||
"180Days": "180 jours",
|
||||
"1Year": "1 an",
|
||||
"subscriptionBadge": "Abonnement Requis",
|
||||
"securityPolicyChangeWarning": "Avertissement de changement de politique de sécurité",
|
||||
"securityPolicyChangeDescription": "Vous êtes sur le point de modifier les paramètres de la politique de sécurité. Une fois enregistré, vous devrez peut-être vous authentifier à nouveau pour vous conformer à ces mises à jour de règles. Tous les utilisateurs qui ne sont pas conformes devront également se réauthentifier.",
|
||||
"securityPolicyChangeConfirmMessage": "Je confirme",
|
||||
"securityPolicyChangeWarningText": "Cela affectera tous les utilisateurs de l'organisation",
|
||||
"authPageErrorUpdateMessage": "Une erreur s'est produite lors de la mise à jour de la page d\u000027authentification",
|
||||
"authPageErrorUpdate": "Impossible de mettre à jour la page d'authentification",
|
||||
"authPageUpdated": "Page d\u000027authentification mise à jour avec succès",
|
||||
"healthCheckNotAvailable": "Locale",
|
||||
"rewritePath": "Réécrire le chemin",
|
||||
"rewritePathDescription": "Réécrivez éventuellement le chemin avant de le transmettre à la cible.",
|
||||
"continueToApplication": "Continuer vers l'application",
|
||||
"checkingInvite": "Vérification de l'invitation",
|
||||
"setResourceHeaderAuth": "Définir l\\'authentification d\\'en-tête de la ressource",
|
||||
"resourceHeaderAuthRemove": "Supprimer l'authentification de l'en-tête",
|
||||
"resourceHeaderAuthRemoveDescription": "Authentification de l'en-tête supprimée avec succès.",
|
||||
"resourceErrorHeaderAuthRemove": "Échec de la suppression de l'authentification de l'en-tête",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Impossible de supprimer l'authentification de l'en-tête de la ressource.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Authentification de l'en-tête activée",
|
||||
"resourceHeaderAuthProtectionDisabled": "L'authentification de l'en-tête est désactivée",
|
||||
"headerAuthRemove": "Supprimer l'authentification de l'en-tête",
|
||||
"headerAuthAdd": "Ajouter l'authentification de l'en-tête",
|
||||
"resourceErrorHeaderAuthSetup": "Impossible de définir l'authentification de l'en-tête",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Impossible de définir l'authentification de l'en-tête pour la ressource.",
|
||||
"resourceHeaderAuthSetup": "Authentification de l'en-tête définie avec succès",
|
||||
"resourceHeaderAuthSetupDescription": "L'authentification de l'en-tête a été définie avec succès.",
|
||||
"resourceHeaderAuthSetupTitle": "Authentification de l'en-tête",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Définissez les identifiants d'authentification de base (nom d'utilisateur et mot de passe) pour protéger cette ressource avec l'authentification de l'en-tête HTTP. Accédez-y en utilisant le format https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Authentification de l'en-tête",
|
||||
"actionSetResourceHeaderAuth": "Authentification de l'en-tête",
|
||||
"enterpriseEdition": "Édition Entreprise",
|
||||
"unlicensed": "Sans licence",
|
||||
"beta": "Bêta",
|
||||
"manageClients": "Gérer les clients",
|
||||
"manageClientsDescription": "Les clients sont des appareils qui peuvent se connecter à vos sites",
|
||||
"licenseTableValidUntil": "Valable jusqu'au",
|
||||
"saasLicenseKeysSettingsTitle": "Licences Entreprise",
|
||||
"saasLicenseKeysSettingsDescription": "Générer et gérer les clés de licence Entreprise pour les instances Pangolin auto-hébergées",
|
||||
"sidebarEnterpriseLicenses": "Licences",
|
||||
"generateLicenseKey": "Générer une clé de licence",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Veuillez entrer une adresse e-mail valide",
|
||||
"useCaseTypeRequired": "Veuillez sélectionner un type de cas d'utilisation",
|
||||
"firstNameRequired": "Le prénom est requis",
|
||||
"lastNameRequired": "Le nom est requis",
|
||||
"primaryUseRequired": "Veuillez décrire votre utilisation principale",
|
||||
"jobTitleRequiredBusiness": "Le titre du poste est requis pour un usage professionnel",
|
||||
"industryRequiredBusiness": "L'industrie est requise pour une utilisation commerciale",
|
||||
"stateProvinceRegionRequired": "État/Province/Région est obligatoire",
|
||||
"postalZipCodeRequired": "Le code postal est requis",
|
||||
"companyNameRequiredBusiness": "Le nom de la société est requis pour une utilisation commerciale",
|
||||
"countryOfResidenceRequiredBusiness": "Le pays de résidence est requis pour un usage professionnel",
|
||||
"countryRequiredPersonal": "Le pays est requis pour un usage personnel",
|
||||
"agreeToTermsRequired": "Vous devez accepter les conditions",
|
||||
"complianceConfirmationRequired": "Vous devez confirmer le respect de la licence commerciale Fossorial"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Utilisation personnelle",
|
||||
"description": "Pour une utilisation individuelle et non commerciale telle que l'apprentissage, les projets personnels ou l'expérimentation."
|
||||
},
|
||||
"business": {
|
||||
"title": "Utilisation de l'entreprise",
|
||||
"description": "Pour utilisation au sein d’organisations, d’entreprises ou d’activités commerciales ou génératrices de revenus."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Email & Type de licence",
|
||||
"description": "Entrez votre adresse e-mail et choisissez votre type de licence"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Informations personnelles",
|
||||
"description": "Parlez-nous de vous-même"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Coordonnées",
|
||||
"description": "Vos coordonnées"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Termes & Générer",
|
||||
"description": "Examinez et acceptez les conditions pour générer votre licence"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Divulgation d'utilisation",
|
||||
"description": "Sélectionnez le niveau de licence qui correspond exactement à votre utilisation prévue. La Licence Personnelle autorise l'utilisation libre du Logiciel pour des activités commerciales individuelles, non commerciales ou à petite échelle avec un revenu annuel brut inférieur à 100 000 USD. Toute utilisation au-delà de ces limites — y compris l'utilisation au sein d'une entreprise, d'une organisation, ou tout autre environnement générateur de revenus — nécessite une licence d’entreprise valide et le paiement des droits de licence applicables. Tous les utilisateurs, qu'ils soient personnels ou d'entreprise, doivent se conformer aux conditions de licence commerciale Fossorial."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Informations sur la période d'essai",
|
||||
"description": "Cette clé de licence permet aux entreprises de bénéficier de fonctionnalités pour une période d'évaluation de 7 jours. L'accès continu aux fonctionnalités payantes au-delà de la période d'évaluation nécessite une activation sous une licence personnelle ou d'entreprise valide. Pour une licence d'entreprise, contactez sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Utilisez-vous Pangolin à des fins personnelles ou professionnelles?",
|
||||
"firstName": "Prénom",
|
||||
"lastName": "Nom de famille",
|
||||
"jobTitle": "Titre du poste",
|
||||
"primaryUseQuestion": "À quoi comptez-vous avant tout utiliser le Pangolin ?",
|
||||
"industryQuestion": "Quelle est votre industrie?",
|
||||
"prospectiveUsersQuestion": "Combien d'utilisateurs vous attendez-vous à avoir ?",
|
||||
"prospectiveSitesQuestion": "Combien de sites potentiels (tunnels) voulez-vous avoir?",
|
||||
"companyName": "Nom de la société",
|
||||
"countryOfResidence": "Pays de résidence",
|
||||
"stateProvinceRegion": "Etat / Province / Région",
|
||||
"postalZipCode": "Code postal / ZIP",
|
||||
"companyWebsite": "Site web de l'entreprise",
|
||||
"companyPhoneNumber": "Numéro de téléphone de la société",
|
||||
"country": "Pays",
|
||||
"phoneNumberOptional": "Numéro de téléphone (facultatif)",
|
||||
"complianceConfirmation": "Je confirme que les renseignements que j'ai fournis sont exacts et que je suis en conformité avec la licence commerciale Fossorial. Signaler des informations inexactes ou une mauvaise identification de l'utilisation du produit constitue une violation de la licence et peut entraîner la révocation de votre clé."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Fermer",
|
||||
"previous": "Précédent",
|
||||
"next": "Suivant",
|
||||
"generateLicenseKey": "Générer une clé de licence"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Clé de licence générée avec succès",
|
||||
"description": "Votre clé de licence a été générée et est prête à l'emploi."
|
||||
},
|
||||
"error": {
|
||||
"title": "Impossible de générer la clé de licence",
|
||||
"description": "Une erreur s'est produite lors de la génération de la clé de licence."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Priorité",
|
||||
"priorityDescription": "Les routes de haute priorité sont évaluées en premier. La priorité = 100 signifie l'ordre automatique (décision du système). Utilisez un autre nombre pour imposer la priorité manuelle.",
|
||||
"instanceName": "Nom de l'instance",
|
||||
"pathMatchModalTitle": "Configurer le chemin correspondant",
|
||||
"pathMatchModalDescription": "Définissez comment les requêtes entrantes doivent être trouvées en fonction de leur chemin.",
|
||||
"pathMatchType": "Type de correspondance",
|
||||
"pathMatchPrefix": "Préfixe",
|
||||
"pathMatchExact": "Exactement",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Valeur du chemin",
|
||||
"clear": "Nettoyer",
|
||||
"saveChanges": "Enregistrer les modifications",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/chemin d'accès",
|
||||
"pathMatchPrefixHelp": "Exemple: /api correspond à /api, /api/users, etc.",
|
||||
"pathMatchExactHelp": "Exemple: /api ne correspond qu'à /api",
|
||||
"pathMatchRegexHelp": "Exemple: ^/api/.* correspond à /api/anything",
|
||||
"pathRewriteModalTitle": "Configurer la réécriture du chemin",
|
||||
"pathRewriteModalDescription": "Transformez le chemin correspondant avant de l'envoyer à la cible.",
|
||||
"pathRewriteType": "Type de réécriture",
|
||||
"pathRewritePrefixOption": "Préfixe - Remplacer le préfixe",
|
||||
"pathRewriteExactOption": "Exactement - Remplacer le chemin entier",
|
||||
"pathRewriteRegexOption": "Regex - Remplacement de patron",
|
||||
"pathRewriteStripPrefixOption": "Retirer le préfixe - Supprimer le préfixe",
|
||||
"pathRewriteValue": "Réécrire la valeur",
|
||||
"pathRewriteRegexPlaceholder": "/fr/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/fr/new-path",
|
||||
"pathRewritePrefixHelp": "Remplacer le préfixe correspondant par cette valeur",
|
||||
"pathRewriteExactHelp": "Remplacer le chemin entier par cette valeur lorsque le chemin correspond exactement",
|
||||
"pathRewriteRegexHelp": "Utiliser des groupes de capture comme $1, $2 pour le remplacement",
|
||||
"pathRewriteStripPrefixHelp": "Laisser vide pour supprimer le préfixe ou fournir un nouveau préfixe",
|
||||
"pathRewritePrefix": "Préfixe",
|
||||
"pathRewriteExact": "Exactement",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Retirer",
|
||||
"pathRewriteStripLabel": "bande",
|
||||
"sidebarEnableEnterpriseLicense": "Activer la licence Entreprise",
|
||||
"cannotbeUndone": "Cela ne peut pas être annulé.",
|
||||
"toConfirm": "pour confirmer",
|
||||
"deleteClientQuestion": "Êtes-vous sûr de vouloir supprimer le client du site et de l'organisation ?",
|
||||
"clientMessageRemove": "Une fois supprimé, le client ne pourra plus se connecter au site.",
|
||||
"sidebarLogs": "Journaux",
|
||||
"request": "Demander",
|
||||
"logs": "Journaux",
|
||||
"logsSettingsDescription": "Surveiller les logs collectés à partir de cette organisation",
|
||||
"searchLogs": "Rechercher dans les journaux...",
|
||||
"action": "Action",
|
||||
"actor": "Acteur",
|
||||
"timestamp": "Horodatage",
|
||||
"accessLogs": "Journaux d'accès",
|
||||
"exportCsv": "Exporter CSV",
|
||||
"actorId": "ID de l'acteur",
|
||||
"allowedByRule": "Autorisé par la règle",
|
||||
"allowedNoAuth": "Aucune authentification autorisée",
|
||||
"validAccessToken": "Jeton d'accès valide",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Mot de passe valide",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Ressource bloquée",
|
||||
"droppedByRule": "Abandonné par la règle",
|
||||
"noSessions": "Aucune session",
|
||||
"temporaryRequestToken": "Jeton de requête temporaire",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Raison",
|
||||
"requestLogs": "Journal des requêtes",
|
||||
"host": "Hôte",
|
||||
"location": "Localisation",
|
||||
"actionLogs": "Journaux des actions",
|
||||
"sidebarLogsRequest": "Journal des requêtes",
|
||||
"sidebarLogsAccess": "Journaux d'accès",
|
||||
"sidebarLogsAction": "Journaux des actions",
|
||||
"logRetention": "Journaliser la rétention",
|
||||
"logRetentionDescription": "Gérer la durée de conservation des différents types de logs pour cette organisation ou les désactiver",
|
||||
"requestLogsDescription": "Voir les journaux détaillés des requêtes pour les ressources de cette organisation",
|
||||
"logRetentionRequestLabel": "Demander la rétention des journaux",
|
||||
"logRetentionRequestDescription": "Durée de conservation des journaux de requêtes",
|
||||
"logRetentionAccessLabel": "Rétention du journal d'accès",
|
||||
"logRetentionAccessDescription": "Durée de conservation des journaux d'accès",
|
||||
"logRetentionActionLabel": "Retention du journal des actions",
|
||||
"logRetentionActionDescription": "Durée de conservation du journal des actions",
|
||||
"logRetentionDisabled": "Désactivé",
|
||||
"logRetention3Days": "3 jours",
|
||||
"logRetention7Days": "7 jours",
|
||||
"logRetention14Days": "14 jours",
|
||||
"logRetention30Days": "30 jours",
|
||||
"logRetention90Days": "90 jours",
|
||||
"logRetentionForever": "Pour toujours",
|
||||
"actionLogsDescription": "Voir l'historique des actions effectuées dans cette organisation",
|
||||
"accessLogsDescription": "Voir les demandes d'authentification d'accès aux ressources de cette organisation",
|
||||
"licenseRequiredToUse": "Une licence Entreprise est nécessaire pour utiliser cette fonctionnalité.",
|
||||
"certResolver": "Résolveur de certificat",
|
||||
"certResolverDescription": "Sélectionnez le solveur de certificat à utiliser pour cette ressource.",
|
||||
"selectCertResolver": "Sélectionnez le résolveur de certificat",
|
||||
"enterCustomResolver": "Entrez le résolveur personnalisé",
|
||||
"preferWildcardCert": "Préférez le certificat Wildcard",
|
||||
"unverified": "Non vérifié",
|
||||
"domainSetting": "Paramètres de domaine",
|
||||
"domainSettingDescription": "Configurer les paramètres de votre domaine",
|
||||
"preferWildcardCertDescription": "Tentative de génération d'un certificat générique (nécessite un résolveur de certificat correctement configuré).",
|
||||
"recordName": "Nom de l'enregistrement",
|
||||
"auto": "Automatique",
|
||||
"TTL": "TTC",
|
||||
"howToAddRecords": "Comment ajouter des enregistrements",
|
||||
"dnsRecord": "Enregistrements DNS",
|
||||
"required": "Requis",
|
||||
"domainSettingsUpdated": "Paramètres de domaine mis à jour avec succès",
|
||||
"orgOrDomainIdMissing": "L'organisation ou l'identifiant de domaine est manquant",
|
||||
"loadingDNSRecords": "Chargement des enregistrements DNS...",
|
||||
"olmUpdateAvailableInfo": "Une version mise à jour de Olm est disponible. Veuillez mettre à jour vers la dernière version pour la meilleure expérience.",
|
||||
"client": "Client",
|
||||
"proxyProtocol": "Paramètres du protocole proxy",
|
||||
"proxyProtocolDescription": "Configurer le protocole Proxy pour préserver les adresses IP du client pour les services TCP/UDP.",
|
||||
"enableProxyProtocol": "Activer le protocole Proxy",
|
||||
"proxyProtocolInfo": "Conserver les adresses IP du client pour les backends TCP/UDP",
|
||||
"proxyProtocolVersion": "Version du protocole proxy",
|
||||
"version1": " Version 1 (Recommandé)",
|
||||
"version2": "Version 2",
|
||||
"versionDescription": "La version 1 est basée sur du texte et est largement supportée. La version 2 est binaire et plus efficace mais moins compatible.",
|
||||
"warning": "Avertissement",
|
||||
"proxyProtocolWarning": "Votre application backend doit être configurée pour accepter les connexions Proxy Protocol. Si votre backend ne prend pas en charge le protocole Proxy, activer ceci va casser toutes les connexions. Assurez-vous de configurer votre backend pour faire confiance aux en-têtes du protocole Proxy de Traefik.",
|
||||
"restarting": "Redémarrage...",
|
||||
"manual": "Manuelle",
|
||||
"messageSupport": "Soutien aux messages",
|
||||
"supportNotAvailableTitle": "Support non disponible",
|
||||
"supportNotAvailableDescription": "L'assistance n'est pas disponible pour le moment. Vous pouvez envoyer un e-mail à support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Demande de support envoyée",
|
||||
"supportRequestSentDescription": "Votre message a été envoyé avec succès.",
|
||||
"supportRequestFailedTitle": "Échec de l'envoi de la demande",
|
||||
"supportRequestFailedDescription": "Une erreur s'est produite lors de l'envoi de votre demande d'assistance.",
|
||||
"supportSubjectRequired": "Le sujet est requis",
|
||||
"supportSubjectMaxLength": "Le sujet doit être de 255 caractères ou moins",
|
||||
"supportMessageRequired": "Le message est requis",
|
||||
"supportReplyTo": "Répondre à",
|
||||
"supportSubject": "Sujet",
|
||||
"supportSubjectPlaceholder": "Entrez le sujet",
|
||||
"supportMessage": "Message",
|
||||
"supportMessagePlaceholder": "Entrez votre message",
|
||||
"supportSending": "Envoi...",
|
||||
"supportSend": "Envoyer",
|
||||
"supportMessageSent": "Message envoyé !",
|
||||
"supportWillContact": "Nous vous contacterons sous peu!",
|
||||
"selectLogRetention": "Sélectionner la durée de rétention du journal",
|
||||
"showColumns": "Afficher les colonnes",
|
||||
"hideColumns": "Cacher les colonnes",
|
||||
"columnVisibility": "Visibilité des colonnes",
|
||||
"toggleColumn": "Activer/désactiver la colonne {columnName}",
|
||||
"allColumns": "Toutes les colonnes",
|
||||
"defaultColumns": "Colonnes par défaut",
|
||||
"customizeView": "Personnaliser la vue",
|
||||
"viewOptions": "Voir les options",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"selectNone": "Ne rien sélectionner",
|
||||
"selectedResources": "Ressources sélectionnées",
|
||||
"enableSelected": "Activer la sélection",
|
||||
"disableSelected": "Désactiver la sélection",
|
||||
"checkSelectedStatus": "Vérifier le statut de la sélection"
|
||||
}
|
||||
@@ -36,8 +36,8 @@
|
||||
"viewSettings": "Visualizza impostazioni",
|
||||
"delete": "Elimina",
|
||||
"name": "Nome",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
"online": "In linea",
|
||||
"offline": "Non in linea",
|
||||
"site": "Sito",
|
||||
"dataIn": "Dati In",
|
||||
"dataOut": "Dati Fuori",
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "Modifica",
|
||||
"siteConfirmDelete": "Conferma Eliminazione Sito",
|
||||
"siteDelete": "Elimina Sito",
|
||||
"siteMessageRemove": "Una volta rimosso, il sito non sarà più accessibile. Anche tutte le risorse e gli obiettivi associati al sito saranno rimossi.",
|
||||
"siteMessageConfirm": "Per confermare, digita il nome del sito qui sotto.",
|
||||
"siteQuestionRemove": "Sei sicuro di voler rimuovere il sito {selectedSite} dall'organizzazione?",
|
||||
"siteMessageRemove": "Una volta rimosso il sito non sarà più accessibile. Tutti gli obiettivi associati al sito verranno rimossi.",
|
||||
"siteQuestionRemove": "Sei sicuro di voler rimuovere il sito dall'organizzazione?",
|
||||
"siteManageSites": "Gestisci Siti",
|
||||
"siteDescription": "Consenti la connettività alla rete attraverso tunnel sicuri",
|
||||
"siteCreate": "Crea Sito",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Usa qualsiasi client WireGuard per stabilire un tunnel. Impostazione NAT manuale richiesta.",
|
||||
"siteWgDescriptionSaas": "Usa qualsiasi client WireGuard per stabilire un tunnel. Impostazione NAT manuale richiesta. FUNZIONA SOLO SU NODI AUTO-OSPITATI",
|
||||
"siteLocalDescription": "Solo risorse locali. Nessun tunneling.",
|
||||
"siteLocalDescriptionSaas": "Solo risorse locali. Nessun tunneling. FUNZIONA SOLO SU NODI AUTO-OSPITATI",
|
||||
"siteLocalDescriptionSaas": "Solo risorse locali. Nessun tunneling. Disponibile solo su nodi remoti.",
|
||||
"siteSeeAll": "Vedi Tutti I Siti",
|
||||
"siteTunnelDescription": "Determina come vuoi connetterti al tuo sito",
|
||||
"siteNewtCredentials": "Credenziali Newt",
|
||||
@@ -132,7 +131,7 @@
|
||||
"expireIn": "Scadenza In",
|
||||
"neverExpire": "Mai scadere",
|
||||
"shareExpireDescription": "Il tempo di scadenza è 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.",
|
||||
"shareSeeOnce": "Potrai vedere solo questo linkonce. Assicurati di copiarlo.",
|
||||
"shareSeeOnce": "Potrai vedere questo link solo una volta. Assicurati di copiarlo.",
|
||||
"shareAccessHint": "Chiunque abbia questo link può accedere alla risorsa. Condividilo con cura.",
|
||||
"shareTokenUsage": "Vedi Utilizzo Token Di Accesso",
|
||||
"createLink": "Crea Collegamento",
|
||||
@@ -154,8 +153,7 @@
|
||||
"protected": "Protetto",
|
||||
"notProtected": "Non Protetto",
|
||||
"resourceMessageRemove": "Una volta rimossa, la risorsa non sarà più accessibile. Tutti gli obiettivi associati alla risorsa saranno rimossi.",
|
||||
"resourceMessageConfirm": "Per confermare, digita il nome della risorsa qui sotto.",
|
||||
"resourceQuestionRemove": "Sei sicuro di voler rimuovere la risorsa {selectedResource} dall'organizzazione?",
|
||||
"resourceQuestionRemove": "Sei sicuro di voler rimuovere la risorsa dall'organizzazione?",
|
||||
"resourceHTTP": "Risorsa HTTPS",
|
||||
"resourceHTTPDescription": "Richieste proxy alla tua app tramite HTTPS utilizzando un sottodominio o un dominio di base.",
|
||||
"resourceRaw": "Risorsa Raw TCP/UDP",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Seleziona sito",
|
||||
"siteSearch": "Cerca sito",
|
||||
"siteNotFound": "Nessun sito trovato.",
|
||||
"selectCountry": "Seleziona paese",
|
||||
"searchCountries": "Cerca paesi...",
|
||||
"noCountryFound": "Nessun paese trovato.",
|
||||
"siteSelectionDescription": "Questo sito fornirà connettività all'obiettivo.",
|
||||
"resourceType": "Tipo Di Risorsa",
|
||||
"resourceTypeDescription": "Determina come vuoi accedere alla tua risorsa",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Dominio Base",
|
||||
"subdomnainDescription": "Il sottodominio in cui la tua risorsa sarà accessibile.",
|
||||
"resourceRawSettings": "Impostazioni TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configura come accedere alla tua risorsa tramite TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Configura come sarà possibile accedere alla tua risorsa tramite TCP/UDP. Mappare la risorsa a una porta sul server host Pangolin, in modo da poter accedere alla risorsa dal server-public ip:mapped-port.",
|
||||
"protocol": "Protocollo",
|
||||
"protocolSelect": "Seleziona un protocollo",
|
||||
"resourcePortNumber": "Numero Porta",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Conferma Elimina Organizzazione",
|
||||
"orgMessageRemove": "Questa azione è irreversibile e cancellerà tutti i dati associati.",
|
||||
"orgMessageConfirm": "Per confermare, digita il nome dell'organizzazione qui sotto.",
|
||||
"orgQuestionRemove": "Sei sicuro di voler rimuovere l'organizzazione {selectedOrg}?",
|
||||
"orgQuestionRemove": "Sei sicuro di voler rimuovere l'organizzazione?",
|
||||
"orgUpdated": "Organizzazione aggiornata",
|
||||
"orgUpdatedDescription": "L'organizzazione è stata aggiornata.",
|
||||
"orgErrorUpdate": "Impossibile aggiornare l'organizzazione",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Genera Chiave API",
|
||||
"apiKeysErrorDelete": "Errore nell'eliminazione della chiave API",
|
||||
"apiKeysErrorDeleteMessage": "Errore nell'eliminazione della chiave API",
|
||||
"apiKeysQuestionRemove": "Sei sicuro di voler rimuovere la chiave API {selectedApiKey} dall'organizzazione?",
|
||||
"apiKeysQuestionRemove": "Sei sicuro di voler rimuovere la chiave API dall'organizzazione?",
|
||||
"apiKeysMessageRemove": "Una volta rimossa, la chiave API non potrà più essere utilizzata.",
|
||||
"apiKeysMessageConfirm": "Per confermare, digita il nome della chiave API qui sotto.",
|
||||
"apiKeysDeleteConfirm": "Conferma Eliminazione Chiave API",
|
||||
"apiKeysDelete": "Elimina Chiave API",
|
||||
"apiKeysManage": "Gestisci Chiavi API",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Conferma Eliminazione Utente",
|
||||
"userDeleteServer": "Elimina utente dal server",
|
||||
"userMessageRemove": "L'utente verrà rimosso da tutte le organizzazioni ed essere completamente rimosso dal server.",
|
||||
"userMessageConfirm": "Per confermare, digita il nome dell'utente qui sotto.",
|
||||
"userQuestionRemove": "Sei sicuro di voler eliminare definitivamente {selectedUser} dal server?",
|
||||
"userQuestionRemove": "Sei sicuro di voler eliminare definitivamente l'utente dal server?",
|
||||
"licenseKey": "Chiave Di Licenza",
|
||||
"valid": "Valido",
|
||||
"numberOfSites": "Numero di siti",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Visualizza I Termini Di Licenza Commerciale Fossorial E Abbonamento",
|
||||
"licenseMessageRemove": "Questo rimuoverà la chiave di licenza e tutti i permessi associati da essa concessi.",
|
||||
"licenseMessageConfirm": "Per confermare, digitare la chiave di licenza qui sotto.",
|
||||
"licenseQuestionRemove": "Sei sicuro di voler eliminare la chiave di licenza {selectedKey}?",
|
||||
"licenseQuestionRemove": "Sei sicuro di voler eliminare la chiave di licenza?",
|
||||
"licenseKeyDelete": "Elimina Chiave Di Licenza",
|
||||
"licenseKeyDeleteConfirm": "Conferma Elimina Chiave Di Licenza",
|
||||
"licenseTitle": "Gestisci Stato Licenza",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Si è verificato un errore durante la rimozione dell'invito.",
|
||||
"inviteRemoved": "Invito rimosso",
|
||||
"inviteRemovedDescription": "L'invito per {email} è stato rimosso.",
|
||||
"inviteQuestionRemove": "Sei sicuro di voler rimuovere l'invito {email}?",
|
||||
"inviteQuestionRemove": "Sei sicuro di voler rimuovere l'invito?",
|
||||
"inviteMessageRemove": "Una volta rimosso, questo invito non sarà più valido. Puoi sempre reinvitare l'utente in seguito.",
|
||||
"inviteMessageConfirm": "Per confermare, digita l'indirizzo email dell'invito qui sotto.",
|
||||
"inviteQuestionRegenerate": "Sei sicuro di voler rigenerare l'invito {email}? Questo revocherà l'invito precedente.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Si è verificato un errore durante la rimozione dell'utente.",
|
||||
"userOrgRemoved": "Utente rimosso",
|
||||
"userOrgRemovedDescription": "L'utente {email} è stato rimosso dall'organizzazione.",
|
||||
"userQuestionOrgRemove": "Sei sicuro di voler rimuovere {email} dall'organizzazione?",
|
||||
"userQuestionOrgRemove": "Sei sicuro di voler rimuovere questo utente dall'organizzazione?",
|
||||
"userMessageOrgRemove": "Una volta rimosso, questo utente non avrà più accesso all'organizzazione. Puoi sempre reinvitarlo in seguito, ma dovrà accettare nuovamente l'invito.",
|
||||
"userMessageOrgConfirm": "Per confermare, digita il nome dell'utente qui sotto.",
|
||||
"userRemoveOrgConfirm": "Conferma Rimozione Utente",
|
||||
"userRemoveOrg": "Rimuovi Utente dall'Organizzazione",
|
||||
"users": "Utenti",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Si è verificato un errore durante l'aggiunta dell'utente al ruolo.",
|
||||
"userSaved": "Utente salvato",
|
||||
"userSavedDescription": "L'utente è stato aggiornato.",
|
||||
"autoProvisioned": "Auto Provisioned",
|
||||
"autoProvisionedDescription": "Permetti a questo utente di essere gestito automaticamente dal provider di identità",
|
||||
"accessControlsDescription": "Gestisci cosa questo utente può accedere e fare nell'organizzazione",
|
||||
"accessControlsSubmit": "Salva Controlli di Accesso",
|
||||
"roles": "Ruoli",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Creato Il",
|
||||
"proxyErrorInvalidHeader": "Valore dell'intestazione Host personalizzata non valido. Usa il formato nome dominio o salva vuoto per rimuovere l'intestazione Host personalizzata.",
|
||||
"proxyErrorTls": "Nome Server TLS non valido. Usa il formato nome dominio o salva vuoto per rimuovere il Nome Server TLS.",
|
||||
"proxyEnableSSL": "Abilita SSL (https)",
|
||||
"proxyEnableSSL": "Abilita SSL",
|
||||
"proxyEnableSSLDescription": "Abilita la crittografia SSL/TLS per connessioni HTTPS sicure ai tuoi obiettivi.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Configura Obiettivi",
|
||||
"targetErrorFetch": "Impossibile recuperare i target",
|
||||
"targetErrorFetchDescription": "Si è verificato un errore durante il recupero dei target",
|
||||
"siteErrorFetch": "Impossibile recuperare la risorsa",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Configurazione Connessione Sicura",
|
||||
"targetTlsSettingsDescription": "Configura le impostazioni SSL/TLS per la tua risorsa",
|
||||
"targetTlsSettingsAdvanced": "Impostazioni TLS Avanzate",
|
||||
"targetTlsSni": "Nome Server TLS (SNI)",
|
||||
"targetTlsSni": "Nome Server Tls",
|
||||
"targetTlsSniDescription": "Il Nome Server TLS da usare per SNI. Lascia vuoto per usare quello predefinito.",
|
||||
"targetTlsSubmit": "Salva Impostazioni",
|
||||
"targets": "Configurazione Target",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Mantieni le connessioni sullo stesso target backend per l'intera sessione.",
|
||||
"methodSelect": "Seleziona metodo",
|
||||
"targetSubmit": "Aggiungi Target",
|
||||
"targetNoOne": "Nessun target. Aggiungi un target usando il modulo.",
|
||||
"targetNoOne": "Questa risorsa non ha bersagli. Aggiungi un obiettivo per configurare dove inviare le richieste al tuo backend.",
|
||||
"targetNoOneDescription": "L'aggiunta di più di un target abiliterà il bilanciamento del carico.",
|
||||
"targetsSubmit": "Salva Target",
|
||||
"addTarget": "Aggiungi Target",
|
||||
"targetErrorInvalidIp": "Indirizzo IP non valido",
|
||||
"targetErrorInvalidIpDescription": "Inserisci un indirizzo IP o un hostname valido",
|
||||
"targetErrorInvalidPort": "Porta non valida",
|
||||
"targetErrorInvalidPortDescription": "Inserisci un numero di porta valido",
|
||||
"targetErrorNoSite": "Nessun sito selezionato",
|
||||
"targetErrorNoSiteDescription": "Si prega di selezionare un sito per l'obiettivo",
|
||||
"targetCreated": "Destinazione creata",
|
||||
"targetCreatedDescription": "L'obiettivo è stato creato con successo",
|
||||
"targetErrorCreate": "Impossibile creare l'obiettivo",
|
||||
"targetErrorCreateDescription": "Si è verificato un errore durante la creazione del target",
|
||||
"save": "Salva",
|
||||
"proxyAdditional": "Impostazioni Proxy Aggiuntive",
|
||||
"proxyAdditionalDescription": "Configura come la tua risorsa gestisce le impostazioni proxy",
|
||||
"proxyCustomHeader": "Intestazione Host Personalizzata",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Formato indirizzo IP non valido",
|
||||
"ipAddressErrorInvalidOctet": "Ottetto indirizzo IP non valido",
|
||||
"path": "Percorso",
|
||||
"matchPath": "Corrispondenza Tracciato",
|
||||
"ipAddressRange": "Intervallo IP",
|
||||
"rulesErrorFetch": "Impossibile recuperare le regole",
|
||||
"rulesErrorFetchDescription": "Si è verificato un errore durante il recupero delle regole",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Server Admin - Pangolina",
|
||||
"licenseTierProfessional": "Licenza Professional",
|
||||
"licenseTierEnterprise": "Licenza Enterprise",
|
||||
"licenseTierCommercial": "Licenza Commerciale",
|
||||
"licenseTierPersonal": "Licenza Personale",
|
||||
"licensed": "Con Licenza",
|
||||
"yes": "Sì",
|
||||
"no": "No",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Visualizza e gestisci i provider di identità nel sistema",
|
||||
"idpDeletedDescription": "Provider di identità eliminato con successo",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Sei sicuro di voler eliminare definitivamente il provider di identità {name}?",
|
||||
"idpQuestionRemove": "Sei sicuro di voler eliminare definitivamente il provider di identità?",
|
||||
"idpMessageRemove": "Questo rimuoverà il provider di identità e tutte le configurazioni associate. Gli utenti che si autenticano tramite questo provider non potranno più accedere.",
|
||||
"idpMessageConfirm": "Per confermare, digita il nome del provider di identità qui sotto.",
|
||||
"idpConfirmDelete": "Conferma Eliminazione Provider di Identità",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Un nome visualizzato per questo provider di identità",
|
||||
"idpAutoProvisionUsers": "Provisioning Automatico Utenti",
|
||||
"idpAutoProvisionUsersDescription": "Quando abilitato, gli utenti verranno creati automaticamente nel sistema al primo accesso con la possibilità di mappare gli utenti a ruoli e organizzazioni.",
|
||||
"licenseBadge": "Professionista",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Tipo di Provider",
|
||||
"idpTypeDescription": "Seleziona il tipo di provider di identità che desideri configurare",
|
||||
"idpOidcConfigure": "Configurazione OAuth2/OIDC",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Controlla la tua email per il codice di reset.",
|
||||
"passwordNew": "Nuova Password",
|
||||
"passwordNewConfirm": "Conferma Nuova Password",
|
||||
"changePassword": "Cambia Password",
|
||||
"changePasswordDescription": "Aggiorna la password del tuo account",
|
||||
"oldPassword": "Password Attuale",
|
||||
"newPassword": "Nuova Password",
|
||||
"confirmNewPassword": "Conferma Nuova Password",
|
||||
"changePasswordError": "Impossibile cambiare la password",
|
||||
"changePasswordErrorDescription": "Si è verificato un errore durante la modifica della password",
|
||||
"changePasswordSuccess": "Password Cambiata Con Successo",
|
||||
"changePasswordSuccessDescription": "La password è stata aggiornata con successo",
|
||||
"passwordExpiryRequired": "Scadenza Password Richiesta",
|
||||
"passwordExpiryDescription": "Questa organizzazione richiede di cambiare la password ogni {maxDays} giorni.",
|
||||
"changePasswordNow": "Cambia Password Ora",
|
||||
"pincodeAuth": "Codice Autenticatore",
|
||||
"pincodeSubmit2": "Invia Codice",
|
||||
"passwordResetSubmit": "Richiedi Reset",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Edizione Professional Richiesta",
|
||||
"licenseTierProfessionalRequiredDescription": "Questa funzionalità è disponibile solo nell'Edizione Professional.",
|
||||
"actionGetOrg": "Ottieni Organizzazione",
|
||||
"updateOrgUser": "Aggiorna Utente Org",
|
||||
"createOrgUser": "Crea Utente Org",
|
||||
"actionUpdateOrg": "Aggiorna Organizzazione",
|
||||
"actionUpdateUser": "Aggiorna Utente",
|
||||
"actionGetUser": "Ottieni Utente",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Elimina Sito",
|
||||
"actionGetSite": "Ottieni Sito",
|
||||
"actionListSites": "Elenca Siti",
|
||||
"actionApplyBlueprint": "Applica Progetto",
|
||||
"setupToken": "Configura Token",
|
||||
"setupTokenDescription": "Inserisci il token di configurazione dalla console del server.",
|
||||
"setupTokenRequired": "Il token di configurazione è richiesto",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Menu di Navigazione",
|
||||
"navbarDescription": "Menu di navigazione principale dell'applicazione",
|
||||
"navbarDocsLink": "Documentazione",
|
||||
"commercialEdition": "Edizione Commerciale",
|
||||
"otpErrorEnable": "Impossibile abilitare 2FA",
|
||||
"otpErrorEnableDescription": "Si è verificato un errore durante l'abilitazione di 2FA",
|
||||
"otpSetupCheckCode": "Inserisci un codice a 6 cifre",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Tutti Gli Utenti",
|
||||
"sidebarIdentityProviders": "Fornitori Di Identità",
|
||||
"sidebarLicense": "Licenza",
|
||||
"sidebarClients": "Clienti (Beta)",
|
||||
"sidebarClients": "Client",
|
||||
"sidebarDomains": "Domini",
|
||||
"enableDockerSocket": "Abilita Docker Socket",
|
||||
"enableDockerSocketDescription": "Abilita il rilevamento Docker Socket per popolare le informazioni del contenitore. Il percorso del socket deve essere fornito a Newt.",
|
||||
"sidebarBluePrints": "Progetti",
|
||||
"blueprints": "Progetti",
|
||||
"blueprintsDescription": "Applica le configurazioni dichiarative e visualizza le partite precedenti",
|
||||
"blueprintAdd": "Aggiungi Progetto",
|
||||
"blueprintGoBack": "Vedi tutti i progetti",
|
||||
"blueprintCreate": "Crea Progetto",
|
||||
"blueprintCreateDescription2": "Segui i passaggi qui sotto per creare e applicare un nuovo progetto",
|
||||
"blueprintDetails": "Dettagli Progetto",
|
||||
"blueprintDetailsDescription": "Vedere il risultato del progetto applicato e gli eventuali errori verificatisi",
|
||||
"blueprintInfo": "Informazioni Sul Progetto",
|
||||
"message": "Messaggio",
|
||||
"blueprintContentsDescription": "Definisci il contenuto di YAML che descrive la tua infrastruttura",
|
||||
"blueprintErrorCreateDescription": "Si è verificato un errore durante l'applicazione del progetto",
|
||||
"blueprintErrorCreate": "Errore nella creazione del progetto",
|
||||
"searchBlueprintProgress": "Cerca progetti...",
|
||||
"appliedAt": "Applicato Il",
|
||||
"source": "Fonte",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Scopri di più",
|
||||
"viewDockerContainers": "Visualizza Contenitori Docker",
|
||||
"containersIn": "Contenitori in {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Crea Dominio",
|
||||
"domainCreatedDescription": "Dominio creato con successo",
|
||||
"domainDeletedDescription": "Dominio eliminato con successo",
|
||||
"domainQuestionRemove": "Sei sicuro di voler rimuovere il dominio {domain} dal tuo account?",
|
||||
"domainQuestionRemove": "Sei sicuro di voler rimuovere il dominio dal tuo account?",
|
||||
"domainMessageRemove": "Una volta rimosso, il dominio non sarà più associato al tuo account.",
|
||||
"domainMessageConfirm": "Per confermare, digita il nome del dominio qui sotto.",
|
||||
"domainConfirmDelete": "Conferma Eliminazione Dominio",
|
||||
"domainDelete": "Elimina Dominio",
|
||||
"domain": "Dominio",
|
||||
@@ -1212,7 +1260,7 @@
|
||||
"orgBillingDescription": "Gestisci le tue informazioni di fatturazione e abbonamenti",
|
||||
"github": "GitHub",
|
||||
"pangolinHosted": "Pangolin Hosted",
|
||||
"fossorial": "Fossorial",
|
||||
"fossorial": "Fossoriale",
|
||||
"completeAccountSetup": "Completa la Configurazione dell'Account",
|
||||
"completeAccountSetupDescription": "Imposta la tua password per iniziare",
|
||||
"accountSetupSent": "Invieremo un codice di configurazione dell'account a questo indirizzo email.",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Aggiornamento Disponibile",
|
||||
"newtUpdateAvailableInfo": "È disponibile una nuova versione di Newt. Si prega di aggiornare all'ultima versione per la migliore esperienza.",
|
||||
"domainPickerEnterDomain": "Dominio",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com, o semplicemente myapp",
|
||||
"domainPickerPlaceholder": "myapp.example.com",
|
||||
"domainPickerDescription": "Inserisci il dominio completo della risorsa per vedere le opzioni disponibili.",
|
||||
"domainPickerDescriptionSaas": "Inserisci un dominio completo, un sottodominio o semplicemente un nome per vedere le opzioni disponibili",
|
||||
"domainPickerTabAll": "Tutti",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Sottodominio: {subdomain}",
|
||||
"domainPickerNamespace": "Namespace: {namespace}",
|
||||
"domainPickerShowMore": "Mostra Altro",
|
||||
"regionSelectorTitle": "Seleziona regione",
|
||||
"regionSelectorInfo": "Selezionare una regione ci aiuta a fornire migliori performance per la tua posizione. Non devi necessariamente essere nella stessa regione del tuo server.",
|
||||
"regionSelectorPlaceholder": "Scegli una regione",
|
||||
"regionSelectorComingSoon": "Prossimamente",
|
||||
"billingLoadingSubscription": "Caricamento abbonamento...",
|
||||
"billingFreeTier": "Piano Gratuito",
|
||||
"billingWarningOverLimit": "Avviso: Hai superato uno o più limiti di utilizzo. I tuoi siti non si connetteranno finché non modifichi il tuo abbonamento o non adegui il tuo utilizzo.",
|
||||
"billingUsageLimitsOverview": "Panoramica dei Limiti di Utilizzo",
|
||||
"billingMonitorUsage": "Monitora il tuo utilizzo rispetto ai limiti configurati. Se hai bisogno di aumentare i limiti, contattaci all'indirizzo support@pangolin.net.",
|
||||
"billingDataUsage": "Utilizzo dei Dati",
|
||||
"billingOnlineTime": "Tempo Online del Sito",
|
||||
"billingUsers": "Utenti Attivi",
|
||||
"billingDomains": "Domini Attivi",
|
||||
"billingRemoteExitNodes": "Nodi Self-hosted Attivi",
|
||||
"billingNoLimitConfigured": "Nessun limite configurato",
|
||||
"billingEstimatedPeriod": "Periodo di Fatturazione Stimato",
|
||||
"billingIncludedUsage": "Utilizzo Incluso",
|
||||
"billingIncludedUsageDescription": "Utilizzo incluso nel tuo piano di abbonamento corrente",
|
||||
"billingFreeTierIncludedUsage": "Elenchi di utilizzi inclusi nel piano gratuito",
|
||||
"billingIncluded": "incluso",
|
||||
"billingEstimatedTotal": "Totale Stimato:",
|
||||
"billingNotes": "Note",
|
||||
"billingEstimateNote": "Questa è una stima basata sul tuo utilizzo attuale.",
|
||||
"billingActualChargesMayVary": "I costi effettivi possono variare.",
|
||||
"billingBilledAtEnd": "Sarai fatturato alla fine del periodo di fatturazione.",
|
||||
"billingModifySubscription": "Modifica Abbonamento",
|
||||
"billingStartSubscription": "Inizia Abbonamento",
|
||||
"billingRecurringCharge": "Addebito Ricorrente",
|
||||
"billingManageSubscriptionSettings": "Gestisci impostazioni e preferenze dell'abbonamento",
|
||||
"billingNoActiveSubscription": "Non hai un abbonamento attivo. Avvia il tuo abbonamento per aumentare i limiti di utilizzo.",
|
||||
"billingFailedToLoadSubscription": "Caricamento abbonamento fallito",
|
||||
"billingFailedToLoadUsage": "Caricamento utilizzo fallito",
|
||||
"billingFailedToGetCheckoutUrl": "Errore durante l'ottenimento dell'URL di pagamento",
|
||||
"billingPleaseTryAgainLater": "Per favore, riprova più tardi.",
|
||||
"billingCheckoutError": "Errore di Pagamento",
|
||||
"billingFailedToGetPortalUrl": "Errore durante l'ottenimento dell'URL del portale",
|
||||
"billingPortalError": "Errore del Portale",
|
||||
"billingDataUsageInfo": "Hai addebitato tutti i dati trasferiti attraverso i tunnel sicuri quando sei connesso al cloud. Questo include sia il traffico in entrata e in uscita attraverso tutti i siti. Quando si raggiunge il limite, i siti si disconnetteranno fino a quando non si aggiorna il piano o si riduce l'utilizzo. I dati non vengono caricati quando si utilizzano nodi.",
|
||||
"billingOnlineTimeInfo": "Ti viene addebitato in base al tempo in cui i tuoi siti rimangono connessi al cloud. Ad esempio, 44,640 minuti è uguale a un sito in esecuzione 24/7 per un mese intero. Quando raggiungi il tuo limite, i tuoi siti si disconnetteranno fino a quando non aggiorni il tuo piano o riduci l'utilizzo. Il tempo non viene caricato quando si usano i nodi.",
|
||||
"billingUsersInfo": "Sei addebitato per ogni utente nella tua organizzazione. La fatturazione viene calcolata giornalmente in base al numero di account utente attivi nella tua organizzazione.",
|
||||
"billingDomainInfo": "Sei addebitato per ogni dominio nella tua organizzazione. La fatturazione viene calcolata giornalmente in base al numero di account dominio attivi nella tua organizzazione.",
|
||||
"billingRemoteExitNodesInfo": "Sei addebitato per ogni nodo gestito nella tua organizzazione. La fatturazione viene calcolata giornalmente in base al numero di nodi gestiti attivi nella tua organizzazione.",
|
||||
"domainNotFound": "Domini Non Trovati",
|
||||
"domainNotFoundDescription": "Questa risorsa è disabilitata perché il dominio non esiste più nel nostro sistema. Si prega di impostare un nuovo dominio per questa risorsa.",
|
||||
"failed": "Fallito",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Si è verificato un problema con la tua chiave di sicurezza. Riprova.",
|
||||
"twoFactorRequired": "È richiesta l'autenticazione a due fattori per registrare una chiave di sicurezza.",
|
||||
"twoFactor": "Autenticazione a Due Fattori",
|
||||
"twoFactorAuthentication": "Autenticazione A Due Fattori",
|
||||
"twoFactorDescription": "Questa organizzazione richiede l'autenticazione a due fattori.",
|
||||
"enableTwoFactor": "Abilita Autenticazione A Due Fattori",
|
||||
"organizationSecurityPolicy": "Politica Di Sicurezza Dell'Organizzazione",
|
||||
"organizationSecurityPolicyDescription": "Questa organizzazione ha requisiti di sicurezza che devono essere soddisfatti prima di poter accedere",
|
||||
"securityRequirements": "Requisiti Di Sicurezza",
|
||||
"allRequirementsMet": "Tutti i requisiti sono stati soddisfatti",
|
||||
"completeRequirementsToContinue": "Completa i requisiti qui sotto per continuare ad accedere a questa organizzazione",
|
||||
"youCanNowAccessOrganization": "Ora puoi accedere a questa organizzazione",
|
||||
"reauthenticationRequired": "Durata Sessione",
|
||||
"reauthenticationDescription": "Questa organizzazione richiede di accedere ogni {maxDays} giorni.",
|
||||
"reauthenticationDescriptionHours": "Questa organizzazione richiede di accedere ogni {maxHours} ore.",
|
||||
"reauthenticateNow": "Accedi Di Nuovo",
|
||||
"adminEnabled2FaOnYourAccount": "Il tuo amministratore ha abilitato l'autenticazione a due fattori per {email}. Completa il processo di configurazione per continuare.",
|
||||
"continueToApplication": "Continua all'Applicazione",
|
||||
"securityKeyAdd": "Aggiungi Chiave di Sicurezza",
|
||||
"securityKeyRegisterTitle": "Registra Nuova Chiave di Sicurezza",
|
||||
"securityKeyRegisterDescription": "Collega la tua chiave di sicurezza e inserisci un nome per identificarla",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "Le modifiche DNS possono richiedere del tempo per propagarsi in Internet. Questo può richiedere da pochi minuti a 48 ore, a seconda del tuo provider DNS e delle impostazioni TTL.",
|
||||
"resourcePortRequired": "Numero di porta richiesto per risorse non-HTTP",
|
||||
"resourcePortNotAllowed": "Il numero di porta non deve essere impostato per risorse HTTP",
|
||||
"billingPricingCalculatorLink": "Calcolatore di Prezzi",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Accetto i",
|
||||
"termsOfService": "termini di servizio",
|
||||
@@ -1319,7 +1422,7 @@
|
||||
"privacyPolicy": "informativa sulla privacy"
|
||||
},
|
||||
"siteRequired": "Il sito è richiesto.",
|
||||
"olmTunnel": "Olm Tunnel",
|
||||
"olmTunnel": "Tunnel Olm",
|
||||
"olmTunnelDescription": "Usa Olm per la connettività client",
|
||||
"errorCreatingClient": "Errore nella creazione del client",
|
||||
"clientDefaultsNotFound": "Impostazioni predefinite del client non trovate",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Proxy Esterno Abilitato",
|
||||
"addNewTarget": "Aggiungi Nuovo Target",
|
||||
"targetsList": "Elenco dei Target",
|
||||
"advancedMode": "Modalità Avanzata",
|
||||
"targetErrorDuplicateTargetFound": "Target duplicato trovato",
|
||||
"healthCheckHealthy": "Sano",
|
||||
"healthCheckUnhealthy": "Non Sano",
|
||||
"healthCheckUnknown": "Sconosciuto",
|
||||
"healthCheck": "Controllo Salute",
|
||||
"configureHealthCheck": "Configura Controllo Salute",
|
||||
"configureHealthCheckDescription": "Imposta il monitoraggio della salute per {target}",
|
||||
"enableHealthChecks": "Abilita i Controlli di Salute",
|
||||
"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",
|
||||
"healthCheckPath": "Percorso",
|
||||
"healthHostname": "IP / Nome host",
|
||||
"healthPort": "Porta",
|
||||
"healthCheckPathDescription": "Percorso per verificare lo stato di salute.",
|
||||
"healthyIntervalSeconds": "Intervallo Sano",
|
||||
"unhealthyIntervalSeconds": "Intervallo Non Sano",
|
||||
"IntervalSeconds": "Intervallo Sano",
|
||||
"timeoutSeconds": "Timeout",
|
||||
"timeIsInSeconds": "Il tempo è in secondi",
|
||||
"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.",
|
||||
"customHeaders": "Intestazioni Personalizzate",
|
||||
"customHeadersDescription": "Intestazioni nuova riga separate: Intestazione-Nome: valore",
|
||||
"headersValidationError": "Le intestazioni devono essere nel formato: Intestazione-Nome: valore.",
|
||||
"saveHealthCheck": "Salva Controllo Salute",
|
||||
"healthCheckSaved": "Controllo Salute Salvato",
|
||||
"healthCheckSavedDescription": "La configurazione del controllo salute è stata salvata con successo",
|
||||
"healthCheckError": "Errore Controllo Salute",
|
||||
"healthCheckErrorDescription": "Si è verificato un errore durante il salvataggio della configurazione del controllo salute.",
|
||||
"healthCheckPathRequired": "Il percorso del controllo salute è richiesto",
|
||||
"healthCheckMethodRequired": "Metodo HTTP richiesto",
|
||||
"healthCheckIntervalMin": "L'intervallo del controllo deve essere almeno di 5 secondi",
|
||||
"healthCheckTimeoutMin": "Il timeout deve essere di almeno 1 secondo",
|
||||
"healthCheckRetryMin": "I tentativi di riprova devono essere almeno 1",
|
||||
"httpMethod": "Metodo HTTP",
|
||||
"selectHttpMethod": "Seleziona metodo HTTP",
|
||||
"domainPickerSubdomainLabel": "Sottodominio",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Inserisci un sottodominio per cercare e selezionare dai domini gratuiti disponibili.",
|
||||
"domainPickerFreeDomains": "Domini Gratuiti",
|
||||
"domainPickerSearchForAvailableDomains": "Cerca domini disponibili",
|
||||
"domainPickerNotWorkSelfHosted": "Nota: I domini forniti gratuitamente non sono disponibili per le istanze self-hosted al momento.",
|
||||
"resourceDomain": "Dominio",
|
||||
"resourceEditDomain": "Modifica Dominio",
|
||||
"siteName": "Nome del Sito",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protocollo",
|
||||
"editInternalResourceDialogSitePort": "Porta del Sito",
|
||||
"editInternalResourceDialogTargetConfiguration": "Configurazione Target",
|
||||
"editInternalResourceDialogDestinationIP": "IP di Destinazione",
|
||||
"editInternalResourceDialogDestinationPort": "Porta di Destinazione",
|
||||
"editInternalResourceDialogCancel": "Annulla",
|
||||
"editInternalResourceDialogSaveResource": "Salva Risorsa",
|
||||
"editInternalResourceDialogSuccess": "Successo",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Porta del Sito",
|
||||
"createInternalResourceDialogSitePortDescription": "Usa questa porta per accedere alla risorsa nel sito quando sei connesso con un client.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Configurazione Target",
|
||||
"createInternalResourceDialogDestinationIP": "IP di Destinazione",
|
||||
"createInternalResourceDialogDestinationIPDescription": "L'indirizzo IP della risorsa sulla rete del sito.",
|
||||
"createInternalResourceDialogDestinationPort": "Porta di Destinazione",
|
||||
"createInternalResourceDialogDestinationIPDescription": "L'indirizzo IP o hostname della risorsa nella rete del sito.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "La porta sull'IP di destinazione dove la risorsa è accessibile.",
|
||||
"createInternalResourceDialogCancel": "Annulla",
|
||||
"createInternalResourceDialogCreateResource": "Crea Risorsa",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Errore di Accesso Automatico",
|
||||
"autoLoginErrorNoRedirectUrl": "Nessun URL di reindirizzamento ricevuto dal provider di identità.",
|
||||
"autoLoginErrorGeneratingUrl": "Impossibile generare l'URL di autenticazione.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Nodi Remoti",
|
||||
"remoteExitNodeDescription": "Self-host uno o più nodi remoti per estendere la connettività di rete e ridurre la dipendenza dal cloud",
|
||||
"remoteExitNodes": "Nodi",
|
||||
"searchRemoteExitNodes": "Cerca nodi...",
|
||||
"remoteExitNodeAdd": "Aggiungi Nodo",
|
||||
"remoteExitNodeErrorDelete": "Errore nell'eliminare il nodo",
|
||||
"remoteExitNodeQuestionRemove": "Sei sicuro di voler rimuovere il nodo dall'organizzazione?",
|
||||
"remoteExitNodeMessageRemove": "Una volta rimosso, il nodo non sarà più accessibile.",
|
||||
"remoteExitNodeConfirmDelete": "Conferma Eliminazione Nodo",
|
||||
"remoteExitNodeDelete": "Elimina Nodo",
|
||||
"sidebarRemoteExitNodes": "Nodi Remoti",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Crea Nodo",
|
||||
"description": "Crea un nuovo nodo per estendere la connettività di rete",
|
||||
"viewAllButton": "Visualizza Tutti I Nodi",
|
||||
"strategy": {
|
||||
"title": "Strategia di Creazione",
|
||||
"description": "Scegli questa opzione per configurare manualmente il nodo o generare nuove credenziali.",
|
||||
"adopt": {
|
||||
"title": "Adotta Nodo",
|
||||
"description": "Scegli questo se hai già le credenziali per il nodo."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Genera Chiavi",
|
||||
"description": "Scegli questa opzione se vuoi generare nuove chiavi per il nodo"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Adotta Nodo Esistente",
|
||||
"description": "Inserisci le credenziali del nodo esistente che vuoi adottare",
|
||||
"nodeIdLabel": "ID Nodo",
|
||||
"nodeIdDescription": "L'ID del nodo esistente che si desidera adottare",
|
||||
"secretLabel": "Segreto",
|
||||
"secretDescription": "La chiave segreta del nodo esistente",
|
||||
"submitButton": "Adotta Nodo"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Credenziali Generate",
|
||||
"description": "Usa queste credenziali generate per configurare il nodo",
|
||||
"nodeIdTitle": "ID Nodo",
|
||||
"secretTitle": "Segreto",
|
||||
"saveCredentialsTitle": "Aggiungi Credenziali alla Configurazione",
|
||||
"saveCredentialsDescription": "Aggiungi queste credenziali al tuo file di configurazione del nodo self-hosted Pangolin per completare la connessione.",
|
||||
"submitButton": "Crea Nodo"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "L'ID del nodo e il segreto sono necessari quando si adotta un nodo esistente"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Caricamento impostazioni predefinite fallito",
|
||||
"defaultsNotLoaded": "Impostazioni predefinite non caricate",
|
||||
"createFailed": "Impossibile creare il nodo"
|
||||
},
|
||||
"success": {
|
||||
"created": "Nodo creato con successo"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Selezione Nodo",
|
||||
"remoteExitNodeSelectionDescription": "Seleziona un nodo per instradare il traffico per questo sito locale",
|
||||
"remoteExitNodeRequired": "Un nodo deve essere selezionato per i siti locali",
|
||||
"noRemoteExitNodesAvailable": "Nessun Nodo Disponibile",
|
||||
"noRemoteExitNodesAvailableDescription": "Non ci sono nodi disponibili per questa organizzazione. Crea un nodo prima per usare i siti locali.",
|
||||
"exitNode": "Nodo di Uscita",
|
||||
"country": "Paese",
|
||||
"rulesMatchCountry": "Attualmente basato sull'IP di origine",
|
||||
"managedSelfHosted": {
|
||||
"title": "Gestito Auto-Ospitato",
|
||||
"description": "Server Pangolin self-hosted più affidabile e a bassa manutenzione con campanelli e fischietti extra",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Converti questo nodo in auto-ospitato gestito"
|
||||
},
|
||||
"internationaldomaindetected": "Dominio Internazionale Rilevato",
|
||||
"willbestoredas": "Verrà conservato come:"
|
||||
}
|
||||
"willbestoredas": "Verrà conservato come:",
|
||||
"roleMappingDescription": "Determinare come i ruoli sono assegnati agli utenti quando accedono quando è abilitata la fornitura automatica.",
|
||||
"selectRole": "Seleziona un ruolo",
|
||||
"roleMappingExpression": "Espressione",
|
||||
"selectRolePlaceholder": "Scegli un ruolo",
|
||||
"selectRoleDescription": "Seleziona un ruolo da assegnare a tutti gli utenti da questo provider di identità",
|
||||
"roleMappingExpressionDescription": "Inserire un'espressione JMESPath per estrarre le informazioni sul ruolo dal token ID",
|
||||
"idpTenantIdRequired": "L'ID dell'inquilino è obbligatorio",
|
||||
"invalidValue": "Valore non valido",
|
||||
"idpTypeLabel": "Tipo Provider Identità",
|
||||
"roleMappingExpressionPlaceholder": "es. contiene(gruppi, 'admin') && 'Admin' <unk> <unk> 'Membro'",
|
||||
"idpGoogleConfiguration": "Configurazione Google",
|
||||
"idpGoogleConfigurationDescription": "Configura le tue credenziali di Google OAuth2",
|
||||
"idpGoogleClientIdDescription": "Il Tuo Client Id Google OAuth2",
|
||||
"idpGoogleClientSecretDescription": "Il Tuo Client Google OAuth2 Secret",
|
||||
"idpAzureConfiguration": "Configurazione Azure Entra ID",
|
||||
"idpAzureConfigurationDescription": "Configura le credenziali OAuth2 di Azure Entra ID",
|
||||
"idpTenantId": "ID Tenant",
|
||||
"idpTenantIdPlaceholder": "iltuo-inquilino-id",
|
||||
"idpAzureTenantIdDescription": "Il tuo ID del tenant Azure (trovato nella panoramica di Azure Active Directory)",
|
||||
"idpAzureClientIdDescription": "Il Tuo Id Client Registrazione App Azure",
|
||||
"idpAzureClientSecretDescription": "Il Tuo Client Di Registrazione App Azure Secret",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Configurazione Google",
|
||||
"idpAzureConfigurationTitle": "Configurazione Azure Entra ID",
|
||||
"idpTenantIdLabel": "ID Tenant",
|
||||
"idpAzureClientIdDescription2": "Il Tuo Id Client Registrazione App Azure",
|
||||
"idpAzureClientSecretDescription2": "Il Tuo Client Di Registrazione App Azure Secret",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC provider",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Sottorete",
|
||||
"subnetDescription": "La sottorete per la configurazione di rete di questa organizzazione.",
|
||||
"authPage": "Pagina Autenticazione",
|
||||
"authPageDescription": "Configura la pagina di autenticazione per la tua organizzazione",
|
||||
"authPageDomain": "Dominio Pagina Auth",
|
||||
"noDomainSet": "Nessun dominio impostato",
|
||||
"changeDomain": "Cambia Dominio",
|
||||
"selectDomain": "Seleziona Dominio",
|
||||
"restartCertificate": "Riavvia Certificato",
|
||||
"editAuthPageDomain": "Modifica Dominio Pagina Auth",
|
||||
"setAuthPageDomain": "Imposta Dominio Pagina Autenticazione",
|
||||
"failedToFetchCertificate": "Recupero del certificato non riuscito",
|
||||
"failedToRestartCertificate": "Riavvio del certificato non riuscito",
|
||||
"addDomainToEnableCustomAuthPages": "Aggiungi un dominio per abilitare le pagine di autenticazione personalizzate per la tua organizzazione",
|
||||
"selectDomainForOrgAuthPage": "Seleziona un dominio per la pagina di autenticazione dell'organizzazione",
|
||||
"domainPickerProvidedDomain": "Dominio Fornito",
|
||||
"domainPickerFreeProvidedDomain": "Dominio Fornito Gratuito",
|
||||
"domainPickerVerified": "Verificato",
|
||||
"domainPickerUnverified": "Non Verificato",
|
||||
"domainPickerInvalidSubdomainStructure": "Questo sottodominio contiene caratteri o struttura non validi. Sarà sanificato automaticamente quando si salva.",
|
||||
"domainPickerError": "Errore",
|
||||
"domainPickerErrorLoadDomains": "Impossibile caricare i domini dell'organizzazione",
|
||||
"domainPickerErrorCheckAvailability": "Impossibile verificare la disponibilità del dominio",
|
||||
"domainPickerInvalidSubdomain": "Sottodominio non valido",
|
||||
"domainPickerInvalidSubdomainRemoved": "L'input \"{sub}\" è stato rimosso perché non è valido.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" non può essere reso valido per {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Sottodominio igienizzato",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" è stato corretto in \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Accedi alla tua organizzazione",
|
||||
"orgAuthChooseIdpDescription": "Scegli il tuo provider di identità per continuare",
|
||||
"orgAuthNoIdpConfigured": "Questa organizzazione non ha nessun provider di identità configurato. Puoi accedere con la tua identità Pangolin.",
|
||||
"orgAuthSignInWithPangolin": "Accedi con Pangolino",
|
||||
"subscriptionRequiredToUse": "Per utilizzare questa funzionalità è necessario un abbonamento.",
|
||||
"idpDisabled": "I provider di identità sono disabilitati.",
|
||||
"orgAuthPageDisabled": "La pagina di autenticazione dell'organizzazione è disabilitata.",
|
||||
"domainRestartedDescription": "Verifica del dominio riavviata con successo",
|
||||
"resourceAddEntrypointsEditFile": "Modifica file: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Modifica file: docker-compose.yml",
|
||||
"emailVerificationRequired": "Verifica via email. Effettua nuovamente il login via {dashboardUrl}/auth/login completa questo passaggio. Quindi, torna qui.",
|
||||
"twoFactorSetupRequired": "È richiesta la configurazione di autenticazione a due fattori. Effettua nuovamente l'accesso tramite {dashboardUrl}/auth/login completa questo passaggio. Quindi, torna qui.",
|
||||
"additionalSecurityRequired": "Necessaria Sicurezza Aggiuntiva",
|
||||
"organizationRequiresAdditionalSteps": "Questa organizzazione richiede ulteriori passi di sicurezza prima di poter accedere alle risorse.",
|
||||
"completeTheseSteps": "Completa questi passaggi",
|
||||
"enableTwoFactorAuthentication": "Abilita autenticazione a due fattori",
|
||||
"completeSecuritySteps": "Passi Di Sicurezza Completa",
|
||||
"securitySettings": "Impostazioni Di Sicurezza",
|
||||
"securitySettingsDescription": "Configura i criteri di sicurezza per la tua organizzazione",
|
||||
"requireTwoFactorForAllUsers": "Richiede l'autenticazione a due fattori per tutti gli utenti",
|
||||
"requireTwoFactorDescription": "Se abilitata, tutti gli utenti interni di questa organizzazione devono avere un'autenticazione a due fattori abilitata per accedere all'organizzazione.",
|
||||
"requireTwoFactorDisabledDescription": "Questa funzione richiede una licenza valida (Enterprise) o un abbonamento attivo (SaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "Devi abilitare l'autenticazione a due fattori per il tuo account prima di applicarla per tutti gli utenti",
|
||||
"maxSessionLength": "Lunghezza Massima Della Sessione",
|
||||
"maxSessionLengthDescription": "Imposta la durata massima per le sessioni utente. Dopo questo periodo, gli utenti dovranno autenticarsi.",
|
||||
"maxSessionLengthDisabledDescription": "Questa funzione richiede una licenza valida (Enterprise) o un abbonamento attivo (SaaS)",
|
||||
"selectSessionLength": "Seleziona lunghezza sessione",
|
||||
"unenforced": "Non Applicato",
|
||||
"1Hour": "1 ora",
|
||||
"3Hours": "3 ore",
|
||||
"6Hours": "6 ore",
|
||||
"12Hours": "12 ore",
|
||||
"1DaySession": "1 giorno",
|
||||
"3Days": "3 giorni",
|
||||
"7Days": "7 giorni",
|
||||
"14Days": "14 giorni",
|
||||
"30DaysSession": "30 giorni",
|
||||
"90DaysSession": "90 giorni",
|
||||
"180DaysSession": "180 giorni",
|
||||
"passwordExpiryDays": "Scadenza Password",
|
||||
"editPasswordExpiryDescription": "Imposta il numero di giorni prima che gli utenti debbano cambiare la password.",
|
||||
"selectPasswordExpiry": "Seleziona scadenza password",
|
||||
"30Days": "30 giorni",
|
||||
"1Day": "1 giorno",
|
||||
"60Days": "60 giorni",
|
||||
"90Days": "90 giorni",
|
||||
"180Days": "180 giorni",
|
||||
"1Year": "1 anno",
|
||||
"subscriptionBadge": "Abbonamento Richiesto",
|
||||
"securityPolicyChangeWarning": "Avviso Modifica Politica Di Sicurezza",
|
||||
"securityPolicyChangeDescription": "Si sta per modificare le impostazioni dei criteri di sicurezza. Dopo il salvataggio, potrebbe essere necessario autenticarsi nuovamente per conformarsi a questi aggiornamenti dei criteri. Tutti gli utenti che non sono conformi dovranno anche autenticarsi.",
|
||||
"securityPolicyChangeConfirmMessage": "Confermo",
|
||||
"securityPolicyChangeWarningText": "Questo influenzerà tutti gli utenti dell'organizzazione",
|
||||
"authPageErrorUpdateMessage": "Si è verificato un errore durante l'aggiornamento delle impostazioni della pagina di autenticazione",
|
||||
"authPageErrorUpdate": "Impossibile aggiornare la pagina di autenticazione",
|
||||
"authPageUpdated": "Pagina di autenticazione aggiornata con successo",
|
||||
"healthCheckNotAvailable": "Locale",
|
||||
"rewritePath": "Riscrivi percorso",
|
||||
"rewritePathDescription": "Riscrivi eventualmente il percorso prima di inoltrarlo al target.",
|
||||
"continueToApplication": "Continua con l'applicazione",
|
||||
"checkingInvite": "Controllo Invito",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Rimuovi Autenticazione Intestazione",
|
||||
"resourceHeaderAuthRemoveDescription": "Autenticazione intestazione rimossa con successo.",
|
||||
"resourceErrorHeaderAuthRemove": "Impossibile rimuovere l'autenticazione dell'intestazione",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Impossibile rimuovere l'autenticazione dell'intestazione per la risorsa.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Autenticazione Intestazione Abilitata",
|
||||
"resourceHeaderAuthProtectionDisabled": "Autenticazione Intestazione Disabilitata",
|
||||
"headerAuthRemove": "Rimuovi Autenticazione Intestazione",
|
||||
"headerAuthAdd": "Aggiungi Autenticazione Intestazione",
|
||||
"resourceErrorHeaderAuthSetup": "Impossibile impostare l'autenticazione dell'intestazione",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Impossibile impostare l'autenticazione dell'intestazione per la risorsa.",
|
||||
"resourceHeaderAuthSetup": "Autenticazione intestazione impostata con successo",
|
||||
"resourceHeaderAuthSetupDescription": "L'autenticazione dell'intestazione è stata impostata correttamente.",
|
||||
"resourceHeaderAuthSetupTitle": "Imposta Autenticazione Intestazione",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Imposta le credenziali di autenticazione di base (nome utente e password) per proteggere questa risorsa con Autenticazione intestazione HTTP. Accedi usando il formato https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Imposta Autenticazione Intestazione",
|
||||
"actionSetResourceHeaderAuth": "Imposta Autenticazione Intestazione",
|
||||
"enterpriseEdition": "Enterprise Edition",
|
||||
"unlicensed": "Senza Licenza",
|
||||
"beta": "Beta",
|
||||
"manageClients": "Gestisci Clienti",
|
||||
"manageClientsDescription": "I client sono dispositivi che possono connettersi ai tuoi siti",
|
||||
"licenseTableValidUntil": "Valido Fino A",
|
||||
"saasLicenseKeysSettingsTitle": "Licenze Enterprise",
|
||||
"saasLicenseKeysSettingsDescription": "Genera e gestisci le chiavi di licenza Enterprise per le istanze di Pangolin self-hosted",
|
||||
"sidebarEnterpriseLicenses": "Licenze",
|
||||
"generateLicenseKey": "Genera Chiave Di Licenza",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Inserisci un indirizzo email valido",
|
||||
"useCaseTypeRequired": "Si prega di selezionare un tipo di caso di utilizzo",
|
||||
"firstNameRequired": "Il nome è obbligatorio",
|
||||
"lastNameRequired": "Il cognome è obbligatorio",
|
||||
"primaryUseRequired": "Descrivi il tuo uso primario",
|
||||
"jobTitleRequiredBusiness": "Il titolo di lavoro è richiesto per l'uso aziendale",
|
||||
"industryRequiredBusiness": "L'industria è richiesta per l'uso commerciale",
|
||||
"stateProvinceRegionRequired": "Stato/Provincia/Regione è richiesta",
|
||||
"postalZipCodeRequired": "Codice postale/CAP obbligatorio",
|
||||
"companyNameRequiredBusiness": "Il nome dell'azienda è richiesto per l'uso aziendale",
|
||||
"countryOfResidenceRequiredBusiness": "Paese di residenza è richiesto per uso professionale",
|
||||
"countryRequiredPersonal": "Il paese è richiesto per uso personale",
|
||||
"agreeToTermsRequired": "Devi accettare i termini",
|
||||
"complianceConfirmationRequired": "È necessario confermare la conformità alla licenza commerciale Fossorial"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Uso Personale",
|
||||
"description": "Per uso individuale, non commerciale, come l'apprendimento, progetti personali o sperimentazione."
|
||||
},
|
||||
"business": {
|
||||
"title": "Uso Aziendale",
|
||||
"description": "Da utilizzare all'interno di organizzazioni, aziende o attività commerciali o generatrici di entrate."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Email & Tipo Di Licenza",
|
||||
"description": "Inserisci la tua email e scegli il tipo di licenza"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Informazioni Personali",
|
||||
"description": "Raccontaci di te"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Informazioni Di Contatto",
|
||||
"description": "I tuoi dati di contatto"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Termini E Genera",
|
||||
"description": "Controlla e accetta i termini per generare la tua licenza"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Trasparenza Di Utilizzo",
|
||||
"description": "Seleziona il livello di licenza che rispecchia accuratamente il tuo utilizzo previsto. La Licenza Personale consente l'uso gratuito del Software per le attività commerciali individuali, non commerciali o su piccola scala con entrate lorde annue inferiori a $100.000 USD. Qualsiasi uso oltre questi limiti — compreso l'uso all'interno di un'azienda, organizzazione, o altro ambiente generatore di entrate — richiede una licenza Enterprise valida e il pagamento della tassa di licenza applicabile. Tutti gli utenti, siano essi personali o aziendali, devono rispettare i termini di licenza commerciale Fossorial."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Informazioni Periodo Di Prova",
|
||||
"description": "Questa chiave di licenza abilita le funzionalità Enterprise per un periodo di valutazione di 7 giorni. L'accesso continuo alle funzionalità a pagamento oltre il periodo di valutazione richiede l'attivazione con una licenza personale o Enterprise valida. Per la licenza Enterprise contatta sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Stai usando Pangolin per uso personale o di affari?",
|
||||
"firstName": "Nome",
|
||||
"lastName": "Cognome",
|
||||
"jobTitle": "Titolo Del Lavoro",
|
||||
"primaryUseQuestion": "Per che cosa hai in primo luogo intenzione di usare Pangolin?",
|
||||
"industryQuestion": "Qual è la sua industria?",
|
||||
"prospectiveUsersQuestion": "Quanti potenziali utenti si aspettano di avere?",
|
||||
"prospectiveSitesQuestion": "Quanti siti potenziali (gallerie) ci si aspetta di avere?",
|
||||
"companyName": "Nome della società",
|
||||
"countryOfResidence": "Paese di residenza",
|
||||
"stateProvinceRegion": "Stato / Provincia / Regione",
|
||||
"postalZipCode": "Codice Postale / Zip",
|
||||
"companyWebsite": "Sito web dell'azienda",
|
||||
"companyPhoneNumber": "Numero di telefono dell'azienda",
|
||||
"country": "Paese",
|
||||
"phoneNumberOptional": "Numero di telefono (facoltativo)",
|
||||
"complianceConfirmation": "Confermo che le informazioni che ho fornito sono accurate e che sono in conformità con la Fossorial Commercial License. La segnalazione di informazioni inesatte o l'uso errato del prodotto è una violazione della licenza e può portare alla revoca della chiave."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Chiudi",
|
||||
"previous": "Precedente",
|
||||
"next": "Successivo",
|
||||
"generateLicenseKey": "Genera Chiave Di Licenza"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Chiave di licenza generata con successo",
|
||||
"description": "La chiave di licenza è stata generata ed è pronta per l'uso."
|
||||
},
|
||||
"error": {
|
||||
"title": "Impossibile generare la chiave di licenza",
|
||||
"description": "Si è verificato un errore nella generazione della chiave di licenza."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Priorità",
|
||||
"priorityDescription": "I percorsi prioritari più alti sono valutati prima. Priorità = 100 significa ordinamento automatico (decidi di sistema). Usa un altro numero per applicare la priorità manuale.",
|
||||
"instanceName": "Nome Istanza",
|
||||
"pathMatchModalTitle": "Configura Corrispondenza Percorso",
|
||||
"pathMatchModalDescription": "Impostare come le richieste in arrivo devono essere abbinate in base al loro percorso.",
|
||||
"pathMatchType": "Tipo di Corrispondenza",
|
||||
"pathMatchPrefix": "Prefisso",
|
||||
"pathMatchExact": "Esatto",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Valore Percorso",
|
||||
"clear": "Pulisci",
|
||||
"saveChanges": "Salva Modifiche",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/path",
|
||||
"pathMatchPrefixHelp": "Esempio: /api corrisponde /api, /api/users etc.",
|
||||
"pathMatchExactHelp": "Esempio: /api corrisponde solo /api",
|
||||
"pathMatchRegexHelp": "Esempio: ^/api/.* corrisponde /api/anything",
|
||||
"pathRewriteModalTitle": "Configura La Riscrittura Percorso",
|
||||
"pathRewriteModalDescription": "Trasforma il percorso corrispondente prima di inoltrarlo al bersaglio.",
|
||||
"pathRewriteType": "Tipo Di Riscrittura",
|
||||
"pathRewritePrefixOption": "Prefisso - Sostituisci prefisso",
|
||||
"pathRewriteExactOption": "Esatto - Sostituisci l'intero percorso",
|
||||
"pathRewriteRegexOption": "Regex - Sostituzione modello",
|
||||
"pathRewriteStripPrefixOption": "Prefisso striscia - Rimuovi prefisso",
|
||||
"pathRewriteValue": "Riscrittura Valore",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/nuovo-percorso",
|
||||
"pathRewritePrefixHelp": "Sostituisci il prefisso abbinato con questo valore",
|
||||
"pathRewriteExactHelp": "Sostituisci l'intero percorso con questo valore quando il percorso corrisponde esattamente",
|
||||
"pathRewriteRegexHelp": "Usa gruppi di acquisizione come $1, $2 per la sostituzione",
|
||||
"pathRewriteStripPrefixHelp": "Lasciare vuoto per strisciare il prefisso o fornire un nuovo prefisso",
|
||||
"pathRewritePrefix": "Prefisso",
|
||||
"pathRewriteExact": "Esatto",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Striscia",
|
||||
"pathRewriteStripLabel": "striscia",
|
||||
"sidebarEnableEnterpriseLicense": "Abilita Licenza Enterprise",
|
||||
"cannotbeUndone": "Questo non può essere annullato.",
|
||||
"toConfirm": "per confermare",
|
||||
"deleteClientQuestion": "Sei sicuro di voler rimuovere il client dal sito e dall'organizzazione?",
|
||||
"clientMessageRemove": "Una volta rimosso, il client non sarà più in grado di connettersi al sito.",
|
||||
"sidebarLogs": "Registri",
|
||||
"request": "Richiesta",
|
||||
"logs": "Registri",
|
||||
"logsSettingsDescription": "Monitora i registri raccolti da questa orginizzazione",
|
||||
"searchLogs": "Cerca registro...",
|
||||
"action": "Azione",
|
||||
"actor": "Attore",
|
||||
"timestamp": "Timestamp",
|
||||
"accessLogs": "Log Accesso",
|
||||
"exportCsv": "Esporta CSV",
|
||||
"actorId": "Id Attore",
|
||||
"allowedByRule": "Consentito dalla regola",
|
||||
"allowedNoAuth": "Non Consentito Auth",
|
||||
"validAccessToken": "Token Di Accesso Valido",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Password Valida",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Risorsa Bloccata",
|
||||
"droppedByRule": "Eliminato dalla regola",
|
||||
"noSessions": "Nessuna Sessione",
|
||||
"temporaryRequestToken": "Token Di Richiesta Temporaneo",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Motivo",
|
||||
"requestLogs": "Log Richiesta",
|
||||
"host": "Host",
|
||||
"location": "Posizione",
|
||||
"actionLogs": "Log Azioni",
|
||||
"sidebarLogsRequest": "Log Richiesta",
|
||||
"sidebarLogsAccess": "Log Accesso",
|
||||
"sidebarLogsAction": "Log Azioni",
|
||||
"logRetention": "Ritenzione Registro",
|
||||
"logRetentionDescription": "Gestisci per quanto tempo i diversi tipi di log sono mantenuti per questa organizzazione o disabilitali",
|
||||
"requestLogsDescription": "Visualizza i registri di richiesta dettagliati per le risorse in questa organizzazione",
|
||||
"logRetentionRequestLabel": "Richiedi Ritenzione Log",
|
||||
"logRetentionRequestDescription": "Per quanto tempo conservare i log delle richieste",
|
||||
"logRetentionAccessLabel": "Ritenzione Registro Accesso",
|
||||
"logRetentionAccessDescription": "Per quanto tempo conservare i log di accesso",
|
||||
"logRetentionActionLabel": "Ritenzione Registro Azioni",
|
||||
"logRetentionActionDescription": "Per quanto tempo conservare i log delle azioni",
|
||||
"logRetentionDisabled": "Disabilitato",
|
||||
"logRetention3Days": "3 giorni",
|
||||
"logRetention7Days": "7 giorni",
|
||||
"logRetention14Days": "14 giorni",
|
||||
"logRetention30Days": "30 giorni",
|
||||
"logRetention90Days": "90 giorni",
|
||||
"logRetentionForever": "Per Sempre",
|
||||
"actionLogsDescription": "Visualizza una cronologia delle azioni eseguite in questa organizzazione",
|
||||
"accessLogsDescription": "Visualizza le richieste di autenticazione di accesso per le risorse in questa organizzazione",
|
||||
"licenseRequiredToUse": "Per utilizzare questa funzione è necessaria una licenza Enterprise.",
|
||||
"certResolver": "Risolutore Di Certificato",
|
||||
"certResolverDescription": "Selezionare il risolutore di certificati da usare per questa risorsa.",
|
||||
"selectCertResolver": "Seleziona Risolutore Di Certificato",
|
||||
"enterCustomResolver": "Inserisci Risolutore Personalizzato",
|
||||
"preferWildcardCert": "Preferisci Certificato Wildcard",
|
||||
"unverified": "Non Verificato",
|
||||
"domainSetting": "Impostazioni Dominio",
|
||||
"domainSettingDescription": "Configura le impostazioni per il tuo dominio",
|
||||
"preferWildcardCertDescription": "Tentativo di generare un certificato jolly (richiede un risolutore di certificati correttamente configurato).",
|
||||
"recordName": "Nome Record",
|
||||
"auto": "Automatico",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Come aggiungere record",
|
||||
"dnsRecord": "Record DNS",
|
||||
"required": "Richiesto",
|
||||
"domainSettingsUpdated": "Impostazioni dominio aggiornate con successo",
|
||||
"orgOrDomainIdMissing": "Manca l'ID dell'organizzazione o del dominio",
|
||||
"loadingDNSRecords": "Caricamento record DNS...",
|
||||
"olmUpdateAvailableInfo": "È disponibile una versione aggiornata di Olm. Si prega di aggiornare all'ultima versione per la migliore esperienza.",
|
||||
"client": "Client",
|
||||
"proxyProtocol": "Impostazioni Protocollo Proxy",
|
||||
"proxyProtocolDescription": "Configurare il protocollo proxy per preservare gli indirizzi IP client per i servizi TCP/UDP.",
|
||||
"enableProxyProtocol": "Abilita Protocollo Proxy",
|
||||
"proxyProtocolInfo": "Conserva gli indirizzi IP del client per i backend TCP/UDP",
|
||||
"proxyProtocolVersion": "Versione Protocollo Proxy",
|
||||
"version1": " Versione 1 (Consigliato)",
|
||||
"version2": "Versione 2",
|
||||
"versionDescription": "La versione 1 è testuale e ampiamente supportata. La versione 2 è binaria e più efficiente, ma meno compatibile.",
|
||||
"warning": "Attenzione",
|
||||
"proxyProtocolWarning": "La tua applicazione backend deve essere configurata per accettare le connessioni del protocollo proxy. Se il tuo backend non supporta il protocollo proxy, abilitando questa opzione si interromperanno tutte le connessioni. Assicurati di configurare il tuo backend per fidarti delle intestazioni del protocollo proxy da Traefik.",
|
||||
"restarting": "Riavvio...",
|
||||
"manual": "Manuale",
|
||||
"messageSupport": "Supporto Messaggio",
|
||||
"supportNotAvailableTitle": "Supporto Non Disponibile",
|
||||
"supportNotAvailableDescription": "Il supporto non è disponibile in questo momento. Puoi inviare un'email a support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Richiesta Di Supporto Inviata",
|
||||
"supportRequestSentDescription": "Il tuo messaggio è stato inviato con successo.",
|
||||
"supportRequestFailedTitle": "Impossibile inviare la richiesta",
|
||||
"supportRequestFailedDescription": "Si è verificato un errore durante l'invio della richiesta di supporto.",
|
||||
"supportSubjectRequired": "L'oggetto è obbligatorio",
|
||||
"supportSubjectMaxLength": "L'oggetto deve contenere almeno 255 caratteri",
|
||||
"supportMessageRequired": "Il messaggio è obbligatorio",
|
||||
"supportReplyTo": "Rispondi A",
|
||||
"supportSubject": "Oggetto",
|
||||
"supportSubjectPlaceholder": "Inserisci oggetto",
|
||||
"supportMessage": "Messaggio",
|
||||
"supportMessagePlaceholder": "Inserisci il tuo messaggio",
|
||||
"supportSending": "Invio...",
|
||||
"supportSend": "Invia",
|
||||
"supportMessageSent": "Messaggio Inviato!",
|
||||
"supportWillContact": "Saremo in contatto a breve!",
|
||||
"selectLogRetention": "Seleziona ritenzione log",
|
||||
"showColumns": "Mostra Colonne",
|
||||
"hideColumns": "Nascondi Colonne",
|
||||
"columnVisibility": "Visibilità Colonna",
|
||||
"toggleColumn": "Attiva/disattiva colonna {columnName}",
|
||||
"allColumns": "Tutte Le Colonne",
|
||||
"defaultColumns": "Colonne Predefinite",
|
||||
"customizeView": "Personalizza Vista",
|
||||
"viewOptions": "Opzioni Visualizzazione",
|
||||
"selectAll": "Seleziona Tutto",
|
||||
"selectNone": "Seleziona Nessuno",
|
||||
"selectedResources": "Risorse Selezionate",
|
||||
"enableSelected": "Abilita Selezionati",
|
||||
"disableSelected": "Disabilita Selezionati",
|
||||
"checkSelectedStatus": "Controlla lo stato dei selezionati"
|
||||
}
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "편집",
|
||||
"siteConfirmDelete": "사이트 삭제 확인",
|
||||
"siteDelete": "사이트 삭제",
|
||||
"siteMessageRemove": "제거되면 사이트에 더 이상 접근할 수 없습니다. 사이트와 관련된 모든 리소스와 대상도 제거됩니다.",
|
||||
"siteMessageConfirm": "확인을 위해 아래에 사이트 이름을 입력해 주세요.",
|
||||
"siteQuestionRemove": "조직에서 사이트 {selectedSite}를 제거하시겠습니까?",
|
||||
"siteMessageRemove": "삭제되면 사이트에 더 이상 액세스할 수 없습니다. 사이트와 연결된 모든 대상도 삭제됩니다.",
|
||||
"siteQuestionRemove": "조직에서 사이트를 제거하시겠습니까?",
|
||||
"siteManageSites": "사이트 관리",
|
||||
"siteDescription": "안전한 터널을 통해 네트워크에 연결할 수 있도록 허용",
|
||||
"siteCreate": "사이트 생성",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "모든 WireGuard 클라이언트를 사용하여 터널을 설정하세요. 수동 NAT 설정이 필요합니다.",
|
||||
"siteWgDescriptionSaas": "모든 WireGuard 클라이언트를 사용하여 터널을 설정하세요. 수동 NAT 설정이 필요합니다. 자체 호스팅 노드에서만 작동합니다.",
|
||||
"siteLocalDescription": "로컬 리소스만 사용 가능합니다. 터널링이 없습니다.",
|
||||
"siteLocalDescriptionSaas": "로컬 리소스만. 터널링 없음. 자체 호스팅 노드에서만 작동합니다.",
|
||||
"siteLocalDescriptionSaas": "로컬 리소스 전용. 터널링 금지. 원격 노드에서만 사용 가능합니다.",
|
||||
"siteSeeAll": "모든 사이트 보기",
|
||||
"siteTunnelDescription": "사이트에 연결하는 방법을 결정하세요",
|
||||
"siteNewtCredentials": "Newt 자격 증명",
|
||||
@@ -154,8 +153,7 @@
|
||||
"protected": "보호됨",
|
||||
"notProtected": "보호되지 않음",
|
||||
"resourceMessageRemove": "제거되면 리소스에 더 이상 접근할 수 없습니다. 리소스와 연결된 모든 대상도 제거됩니다.",
|
||||
"resourceMessageConfirm": "확인을 위해 아래에 리소스의 이름을 입력하세요.",
|
||||
"resourceQuestionRemove": "조직에서 리소스 {selectedResource}를 제거하시겠습니까?",
|
||||
"resourceQuestionRemove": "조직에서 리소스를 제거하시겠습니까?",
|
||||
"resourceHTTP": "HTTPS 리소스",
|
||||
"resourceHTTPDescription": "서브도메인 또는 기본 도메인을 사용하여 HTTPS를 통해 앱에 대한 요청을 프록시합니다.",
|
||||
"resourceRaw": "원시 TCP/UDP 리소스",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "사이트 선택",
|
||||
"siteSearch": "사이트 검색",
|
||||
"siteNotFound": "사이트를 찾을 수 없습니다.",
|
||||
"selectCountry": "국가 선택하기",
|
||||
"searchCountries": "국가 검색...",
|
||||
"noCountryFound": "국가를 찾을 수 없습니다.",
|
||||
"siteSelectionDescription": "이 사이트는 대상에 대한 연결을 제공합니다.",
|
||||
"resourceType": "리소스 유형",
|
||||
"resourceTypeDescription": "리소스에 접근하는 방법을 결정하세요",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "기본 도메인",
|
||||
"subdomnainDescription": "리소스에 접근할 수 있는 하위 도메인입니다.",
|
||||
"resourceRawSettings": "TCP/UDP 설정",
|
||||
"resourceRawSettingsDescription": "TCP/UDP를 통해 리소스에 접근하는 방법을 구성하세요.",
|
||||
"resourceRawSettingsDescription": "리소스를 TCP/UDP를 통해 액세스하는 방법을 구성합니다. 리소스를 호스트 Pangolin 서버의 포트에 매핑하여 서버-public-ip:매핑된 포트에서 리소스에 액세스할 수 있습니다.",
|
||||
"protocol": "프로토콜",
|
||||
"protocolSelect": "프로토콜 선택",
|
||||
"resourcePortNumber": "포트 번호",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "조직 삭제 확인",
|
||||
"orgMessageRemove": "이 작업은 되돌릴 수 없으며 모든 관련 데이터를 삭제합니다.",
|
||||
"orgMessageConfirm": "확인을 위해 아래에 조직 이름을 입력하십시오.",
|
||||
"orgQuestionRemove": "조직 {selectedOrg}을(를) 제거하시겠습니까?",
|
||||
"orgQuestionRemove": "조직을 삭제하시겠습니까?",
|
||||
"orgUpdated": "조직이 업데이트되었습니다.",
|
||||
"orgUpdatedDescription": "조직이 업데이트되었습니다.",
|
||||
"orgErrorUpdate": "조직 업데이트에 실패했습니다.",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "API 키 생성",
|
||||
"apiKeysErrorDelete": "API 키 삭제 오류",
|
||||
"apiKeysErrorDeleteMessage": "API 키 삭제 오류",
|
||||
"apiKeysQuestionRemove": "조직에서 API 키 {selectedApiKey}를 제거하시겠습니까?",
|
||||
"apiKeysQuestionRemove": "조직에서 API 키를 제거하시겠습니까?",
|
||||
"apiKeysMessageRemove": "삭제되면 API 키를 더 이상 사용할 수 없습니다.",
|
||||
"apiKeysMessageConfirm": "확인을 위해 아래에 API 키의 이름을 입력해 주세요.",
|
||||
"apiKeysDeleteConfirm": "API 키 삭제 확인",
|
||||
"apiKeysDelete": "API 키 삭제",
|
||||
"apiKeysManage": "API 키 관리",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "사용자 삭제 확인",
|
||||
"userDeleteServer": "서버에서 사용자 삭제",
|
||||
"userMessageRemove": "사용자가 모든 조직에서 제거되며 서버에서 완전히 삭제됩니다.",
|
||||
"userMessageConfirm": "확인을 위해 아래에 사용자 이름을 입력하십시오.",
|
||||
"userQuestionRemove": "정말로 {selectedUser}를 서버에서 영구적으로 삭제하시겠습니까?",
|
||||
"userQuestionRemove": "서버에서 사용자를 영구적으로 삭제하시겠습니까?",
|
||||
"licenseKey": "라이센스 키",
|
||||
"valid": "유효",
|
||||
"numberOfSites": "사이트 수",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Fossorial 상업 라이선스 및 구독 약관 보기",
|
||||
"licenseMessageRemove": "이 작업은 라이센스 키와 그에 의해 부여된 모든 관련 권한을 제거합니다.",
|
||||
"licenseMessageConfirm": "확인을 위해 아래에 라이센스 키를 입력하세요.",
|
||||
"licenseQuestionRemove": "라이센스 키 {selectedKey}를 삭제하시겠습니까?",
|
||||
"licenseQuestionRemove": "라이선스 키를 삭제하시겠습니까?",
|
||||
"licenseKeyDelete": "라이센스 키 삭제",
|
||||
"licenseKeyDeleteConfirm": "라이센스 키 삭제 확인",
|
||||
"licenseTitle": "라이선스 상태 관리",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "초대를 제거하는 동안 오류가 발생했습니다.",
|
||||
"inviteRemoved": "초대가 제거되었습니다.",
|
||||
"inviteRemovedDescription": "{email}에 대한 초대가 삭제되었습니다.",
|
||||
"inviteQuestionRemove": "초대 {email}를 제거하시겠습니까?",
|
||||
"inviteQuestionRemove": "초대를 제거하시겠습니까?",
|
||||
"inviteMessageRemove": "한 번 제거되면 이 초대는 더 이상 유효하지 않습니다. 나중에 사용자를 다시 초대할 수 있습니다.",
|
||||
"inviteMessageConfirm": "확인을 위해 아래 초대의 이메일 주소를 입력해 주세요.",
|
||||
"inviteQuestionRegenerate": "{email}에 대한 초대장을 다시 생성하시겠습니까? 이전 초대장은 취소됩니다.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "사용자를 제거하는 동안 오류가 발생했습니다.",
|
||||
"userOrgRemoved": "사용자가 제거되었습니다.",
|
||||
"userOrgRemovedDescription": "사용자 {email}가 조직에서 제거되었습니다.",
|
||||
"userQuestionOrgRemove": "{email}을 조직에서 제거하시겠습니까?",
|
||||
"userQuestionOrgRemove": "조직에서 이 사용자를 제거하시겠습니까?",
|
||||
"userMessageOrgRemove": "이 사용자가 제거되면 더 이상 조직에 접근할 수 없습니다. 나중에 다시 초대할 수 있지만, 초대를 다시 수락해야 합니다.",
|
||||
"userMessageOrgConfirm": "확인을 위해 아래에 사용자 이름을 입력하세요.",
|
||||
"userRemoveOrgConfirm": "사용자 제거 확인",
|
||||
"userRemoveOrg": "조직에서 사용자 제거",
|
||||
"users": "사용자",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "사용자를 역할에 추가하는 동안 오류가 발생했습니다.",
|
||||
"userSaved": "사용자 저장됨",
|
||||
"userSavedDescription": "사용자가 업데이트되었습니다.",
|
||||
"autoProvisioned": "자동 프로비저닝됨",
|
||||
"autoProvisionedDescription": "이 사용자가 ID 공급자에 의해 자동으로 관리될 수 있도록 허용합니다",
|
||||
"accessControlsDescription": "이 사용자가 조직에서 접근하고 수행할 수 있는 작업을 관리하세요",
|
||||
"accessControlsSubmit": "접근 제어 저장",
|
||||
"roles": "역할",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "생성일",
|
||||
"proxyErrorInvalidHeader": "잘못된 사용자 정의 호스트 헤더 값입니다. 도메인 이름 형식을 사용하거나 사용자 정의 호스트 헤더를 해제하려면 비워 두십시오.",
|
||||
"proxyErrorTls": "유효하지 않은 TLS 서버 이름입니다. 도메인 이름 형식을 사용하거나 비워 두어 TLS 서버 이름을 제거하십시오.",
|
||||
"proxyEnableSSL": "SSL 활성화 (https)",
|
||||
"proxyEnableSSL": "SSL 활성화",
|
||||
"proxyEnableSSLDescription": "대상에 대한 안전한 HTTPS 연결을 위해 SSL/TLS 암호화를 활성화하세요.",
|
||||
"target": "대상",
|
||||
"configureTarget": "대상 구성",
|
||||
"targetErrorFetch": "대상 가져오는 데 실패했습니다.",
|
||||
"targetErrorFetchDescription": "대상 가져오는 중 오류가 발생했습니다",
|
||||
"siteErrorFetch": "리소스를 가져오는 데 실패했습니다",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "보안 연결 구성",
|
||||
"targetTlsSettingsDescription": "리소스에 대한 SSL/TLS 설정 구성",
|
||||
"targetTlsSettingsAdvanced": "고급 TLS 설정",
|
||||
"targetTlsSni": "TLS 서버 이름 (SNI)",
|
||||
"targetTlsSni": "TLS 서버 이름",
|
||||
"targetTlsSniDescription": "SNI에 사용할 TLS 서버 이름. 기본값을 사용하려면 비워 두십시오.",
|
||||
"targetTlsSubmit": "설정 저장",
|
||||
"targets": "대상 구성",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "세션 전체 동안 동일한 백엔드 대상을 유지합니다.",
|
||||
"methodSelect": "선택 방법",
|
||||
"targetSubmit": "대상 추가",
|
||||
"targetNoOne": "대상이 없습니다. 양식을 사용하여 대상을 추가하세요.",
|
||||
"targetNoOne": "이 리소스에는 대상이 없습니다. 백엔드로 요청을 보내려면 대상을 추가하세요.",
|
||||
"targetNoOneDescription": "위에 하나 이상의 대상을 추가하면 로드 밸런싱이 활성화됩니다.",
|
||||
"targetsSubmit": "대상 저장",
|
||||
"addTarget": "대상 추가",
|
||||
"targetErrorInvalidIp": "유효하지 않은 IP 주소",
|
||||
"targetErrorInvalidIpDescription": "유효한 IP 주소 또는 호스트 이름을 입력하세요.",
|
||||
"targetErrorInvalidPort": "유효하지 않은 포트",
|
||||
"targetErrorInvalidPortDescription": "유효한 포트 번호를 입력하세요.",
|
||||
"targetErrorNoSite": "선택된 사이트 없음",
|
||||
"targetErrorNoSiteDescription": "대상을 위해 사이트를 선택하세요.",
|
||||
"targetCreated": "대상 생성",
|
||||
"targetCreatedDescription": "대상이 성공적으로 생성되었습니다.",
|
||||
"targetErrorCreate": "대상 생성 실패",
|
||||
"targetErrorCreateDescription": "대상 생성 중 오류가 발생했습니다.",
|
||||
"save": "저장",
|
||||
"proxyAdditional": "추가 프록시 설정",
|
||||
"proxyAdditionalDescription": "리소스가 프록시 설정을 처리하는 방법 구성",
|
||||
"proxyCustomHeader": "사용자 정의 호스트 헤더",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "잘못된 IP 주소 형식",
|
||||
"ipAddressErrorInvalidOctet": "유효하지 않은 IP 주소 옥텟",
|
||||
"path": "경로",
|
||||
"matchPath": "경로 맞춤",
|
||||
"ipAddressRange": "IP 범위",
|
||||
"rulesErrorFetch": "규칙을 가져오는 데 실패했습니다.",
|
||||
"rulesErrorFetchDescription": "규칙을 가져오는 중 오류가 발생했습니다",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "서버 관리자 - 판골린",
|
||||
"licenseTierProfessional": "전문 라이센스",
|
||||
"licenseTierEnterprise": "기업 라이선스",
|
||||
"licenseTierCommercial": "상업용 라이선스",
|
||||
"licenseTierPersonal": "개인 라이선스",
|
||||
"licensed": "라이센스",
|
||||
"yes": "예",
|
||||
"no": "아니요",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "시스템에서 ID 제공자를 보고 관리합니다",
|
||||
"idpDeletedDescription": "신원 공급자가 성공적으로 삭제되었습니다",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "정말로 아이덴티티 공급자 {name}를 영구적으로 삭제하시겠습니까?",
|
||||
"idpQuestionRemove": "아이덴티티 공급자를 영구적으로 삭제하시겠습니까?",
|
||||
"idpMessageRemove": "이 작업은 아이덴티티 공급자와 모든 관련 구성을 제거합니다. 이 공급자를 통해 인증하는 사용자는 더 이상 로그인할 수 없습니다.",
|
||||
"idpMessageConfirm": "확인을 위해 아래에 아이덴티티 제공자의 이름을 입력하세요.",
|
||||
"idpConfirmDelete": "신원 제공자 삭제 확인",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "이 신원 공급자를 위한 표시 이름",
|
||||
"idpAutoProvisionUsers": "사용자 자동 프로비저닝",
|
||||
"idpAutoProvisionUsersDescription": "활성화되면 사용자가 첫 로그인 시 시스템에 자동으로 생성되며, 사용자와 역할 및 조직을 매핑할 수 있습니다.",
|
||||
"licenseBadge": "전문가",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "제공자 유형",
|
||||
"idpTypeDescription": "구성할 ID 공급자의 유형을 선택하십시오.",
|
||||
"idpOidcConfigure": "OAuth2/OIDC 구성",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "재설정 코드를 확인하려면 이메일을 확인하세요.",
|
||||
"passwordNew": "새 비밀번호",
|
||||
"passwordNewConfirm": "새 비밀번호 확인",
|
||||
"changePassword": "비밀번호 변경",
|
||||
"changePasswordDescription": "계정 비밀번호를 업데이트하십시오",
|
||||
"oldPassword": "현재 비밀번호",
|
||||
"newPassword": "새 비밀번호",
|
||||
"confirmNewPassword": "새 비밀번호 확인",
|
||||
"changePasswordError": "비밀번호 변경 실패",
|
||||
"changePasswordErrorDescription": "비밀번호를 변경하는 중 오류가 발생했습니다",
|
||||
"changePasswordSuccess": "비밀번호 변경 완료",
|
||||
"changePasswordSuccessDescription": "비밀번호가 성공적으로 업데이트되었습니다",
|
||||
"passwordExpiryRequired": "비밀번호 만료 필요",
|
||||
"passwordExpiryDescription": "이 조직은 {maxDays}일마다 비밀번호 변경을 요구합니다.",
|
||||
"changePasswordNow": "지금 비밀번호 변경",
|
||||
"pincodeAuth": "인증 코드",
|
||||
"pincodeSubmit2": "코드 제출",
|
||||
"passwordResetSubmit": "재설정 요청",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "전문 에디션이 필요합니다.",
|
||||
"licenseTierProfessionalRequiredDescription": "이 기능은 Professional Edition에서만 사용할 수 있습니다.",
|
||||
"actionGetOrg": "조직 가져오기",
|
||||
"updateOrgUser": "조직 사용자 업데이트",
|
||||
"createOrgUser": "조직 사용자 생성",
|
||||
"actionUpdateOrg": "조직 업데이트",
|
||||
"actionUpdateUser": "사용자 업데이트",
|
||||
"actionGetUser": "사용자 조회",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "사이트 삭제",
|
||||
"actionGetSite": "사이트 가져오기",
|
||||
"actionListSites": "사이트 목록",
|
||||
"actionApplyBlueprint": "청사진 적용",
|
||||
"setupToken": "설정 토큰",
|
||||
"setupTokenDescription": "서버 콘솔에서 설정 토큰 입력.",
|
||||
"setupTokenRequired": "설정 토큰이 필요합니다",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "탐색 메뉴",
|
||||
"navbarDescription": "애플리케이션의 주요 탐색 메뉴",
|
||||
"navbarDocsLink": "문서",
|
||||
"commercialEdition": "상업용 에디션",
|
||||
"otpErrorEnable": "2FA를 활성화할 수 없습니다.",
|
||||
"otpErrorEnableDescription": "2FA를 활성화하는 동안 오류가 발생했습니다",
|
||||
"otpSetupCheckCode": "6자리 코드를 입력하세요",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "모든 사용자",
|
||||
"sidebarIdentityProviders": "신원 공급자",
|
||||
"sidebarLicense": "라이선스",
|
||||
"sidebarClients": "클라이언트 (Beta)",
|
||||
"sidebarClients": "클라이언트",
|
||||
"sidebarDomains": "도메인",
|
||||
"enableDockerSocket": "Docker 소켓 활성화",
|
||||
"enableDockerSocketDescription": "컨테이너 정보를 채우기 위해 Docker 소켓 검색을 활성화합니다. 소켓 경로는 Newt에 제공되어야 합니다.",
|
||||
"sidebarBluePrints": "청사진",
|
||||
"blueprints": "청사진",
|
||||
"blueprintsDescription": "선언적 구성을 적용하고 이전 실행을 봅니다",
|
||||
"blueprintAdd": "청사진 추가",
|
||||
"blueprintGoBack": "모든 청사진 보기",
|
||||
"blueprintCreate": "청사진 생성",
|
||||
"blueprintCreateDescription2": "새 청사진을 생성하고 적용하려면 아래 단계를 따르십시오",
|
||||
"blueprintDetails": "청사진 세부사항",
|
||||
"blueprintDetailsDescription": "적용된 청사진의 결과와 발생한 오류를 확인합니다",
|
||||
"blueprintInfo": "청사진 정보",
|
||||
"message": "메시지",
|
||||
"blueprintContentsDescription": "인프라를 설명하는 YAML 콘텐츠를 정의하십시오",
|
||||
"blueprintErrorCreateDescription": "청사진을 적용하는 중 오류가 발생했습니다",
|
||||
"blueprintErrorCreate": "청사진 생성 오류",
|
||||
"searchBlueprintProgress": "청사진 검색...",
|
||||
"appliedAt": "적용 시점",
|
||||
"source": "출처",
|
||||
"contents": "콘텐츠",
|
||||
"parsedContents": "구문 분석된 콘텐츠 (읽기 전용)",
|
||||
"enableDockerSocket": "Docker 청사진 활성화",
|
||||
"enableDockerSocketDescription": "블루프린트 레이블을 위한 Docker 소켓 레이블 수집을 활성화합니다. 소켓 경로는 Newt에 제공되어야 합니다.",
|
||||
"enableDockerSocketLink": "자세히 알아보기",
|
||||
"viewDockerContainers": "도커 컨테이너 보기",
|
||||
"containersIn": "{siteName}의 컨테이너",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "도메인 생성",
|
||||
"domainCreatedDescription": "도메인이 성공적으로 생성되었습니다",
|
||||
"domainDeletedDescription": "도메인이 성공적으로 삭제되었습니다",
|
||||
"domainQuestionRemove": "도메인 {domain}을(를) 계정에서 제거하시겠습니까?",
|
||||
"domainQuestionRemove": "계정에서 도메인을 제거하시겠습니까?",
|
||||
"domainMessageRemove": "제거되면 도메인이 더 이상 계정과 연관되지 않습니다.",
|
||||
"domainMessageConfirm": "확인하려면 아래에 도메인명을 입력하세요.",
|
||||
"domainConfirmDelete": "도메인 삭제 확인",
|
||||
"domainDelete": "도메인 삭제",
|
||||
"domain": "도메인",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "업데이트 가능",
|
||||
"newtUpdateAvailableInfo": "뉴트의 새 버전이 출시되었습니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.",
|
||||
"domainPickerEnterDomain": "도메인",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com, 또는 그냥 myapp",
|
||||
"domainPickerPlaceholder": "myapp.example.com",
|
||||
"domainPickerDescription": "리소스의 전체 도메인을 입력하여 사용 가능한 옵션을 확인하십시오.",
|
||||
"domainPickerDescriptionSaas": "전체 도메인, 서브도메인 또는 이름을 입력하여 사용 가능한 옵션을 확인하십시오.",
|
||||
"domainPickerTabAll": "모두",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "서브도메인: {subdomain}",
|
||||
"domainPickerNamespace": "이름 공간: {namespace}",
|
||||
"domainPickerShowMore": "더보기",
|
||||
"regionSelectorTitle": "지역 선택",
|
||||
"regionSelectorInfo": "지역을 선택하면 위치에 따라 더 나은 성능이 제공됩니다. 서버와 같은 지역에 있을 필요는 없습니다.",
|
||||
"regionSelectorPlaceholder": "지역 선택",
|
||||
"regionSelectorComingSoon": "곧 출시 예정",
|
||||
"billingLoadingSubscription": "구독 불러오는 중...",
|
||||
"billingFreeTier": "무료 티어",
|
||||
"billingWarningOverLimit": "경고: 하나 이상의 사용 한도를 초과했습니다. 구독을 수정하거나 사용량을 조정하기 전까지 사이트는 연결되지 않습니다.",
|
||||
"billingUsageLimitsOverview": "사용 한도 개요",
|
||||
"billingMonitorUsage": "설정된 한도에 대한 사용량을 모니터링합니다. 한도를 늘려야 하는 경우 support@pangolin.net로 연락하십시오.",
|
||||
"billingDataUsage": "데이터 사용량",
|
||||
"billingOnlineTime": "사이트 온라인 시간",
|
||||
"billingUsers": "활성 사용자",
|
||||
"billingDomains": "활성 도메인",
|
||||
"billingRemoteExitNodes": "활성 자체 호스팅 노드",
|
||||
"billingNoLimitConfigured": "구성된 한도가 없습니다.",
|
||||
"billingEstimatedPeriod": "예상 청구 기간",
|
||||
"billingIncludedUsage": "포함 사용량",
|
||||
"billingIncludedUsageDescription": "현재 구독 계획에 포함된 사용량",
|
||||
"billingFreeTierIncludedUsage": "무료 티어 사용 허용량",
|
||||
"billingIncluded": "포함됨",
|
||||
"billingEstimatedTotal": "예상 총액:",
|
||||
"billingNotes": "노트",
|
||||
"billingEstimateNote": "현재 사용량을 기반으로 한 추정치입니다.",
|
||||
"billingActualChargesMayVary": "실제 청구 금액은 다를 수 있습니다.",
|
||||
"billingBilledAtEnd": "청구 기간이 끝난 후 청구됩니다.",
|
||||
"billingModifySubscription": "구독 수정",
|
||||
"billingStartSubscription": "구독 시작",
|
||||
"billingRecurringCharge": "반복 요금",
|
||||
"billingManageSubscriptionSettings": "구독 설정 및 기본 설정을 관리합니다",
|
||||
"billingNoActiveSubscription": "활성 구독이 없습니다. 사용 한도를 늘리려면 구독을 시작하십시오.",
|
||||
"billingFailedToLoadSubscription": "구독을 불러오는 데 실패했습니다.",
|
||||
"billingFailedToLoadUsage": "사용량을 불러오는 데 실패했습니다.",
|
||||
"billingFailedToGetCheckoutUrl": "체크아웃 URL을 가져오는 데 실패했습니다.",
|
||||
"billingPleaseTryAgainLater": "나중에 다시 시도하십시오.",
|
||||
"billingCheckoutError": "체크아웃 오류",
|
||||
"billingFailedToGetPortalUrl": "포털 URL을 가져오는 데 실패했습니다.",
|
||||
"billingPortalError": "포털 오류",
|
||||
"billingDataUsageInfo": "클라우드에 연결할 때 보안 터널을 통해 전송된 모든 데이터에 대해 비용이 청구됩니다. 여기에는 모든 사이트의 들어오고 나가는 트래픽이 포함됩니다. 사용량 한도에 도달하면 플랜을 업그레이드하거나 사용량을 줄일 때까지 사이트가 연결 해제됩니다. 노드를 사용하는 경우 데이터는 요금이 청구되지 않습니다.",
|
||||
"billingOnlineTimeInfo": "사이트가 클라우드에 연결된 시간에 따라 요금이 청구됩니다. 예를 들어, 44,640분은 사이트가 한 달 내내 24시간 작동하는 것과 같습니다. 사용량 한도에 도달하면 플랜을 업그레이드하거나 사용량을 줄일 때까지 사이트가 연결 해제됩니다. 노드를 사용할 때 시간은 요금이 청구되지 않습니다.",
|
||||
"billingUsersInfo": "조직의 사용자마다 요금이 청구됩니다. 청구는 조직의 활성 사용자 계정 수에 따라 매일 계산됩니다.",
|
||||
"billingDomainInfo": "조직의 도메인마다 요금이 청구됩니다. 청구는 조직의 활성 도메인 계정 수에 따라 매일 계산됩니다.",
|
||||
"billingRemoteExitNodesInfo": "조직의 관리 노드마다 요금이 청구됩니다. 청구는 조직의 활성 관리 노드 수에 따라 매일 계산됩니다.",
|
||||
"domainNotFound": "도메인을 찾을 수 없습니다",
|
||||
"domainNotFoundDescription": "이 리소스는 도메인이 더 이상 시스템에 존재하지 않아 비활성화되었습니다. 이 리소스에 대한 새 도메인을 설정하세요.",
|
||||
"failed": "실패",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "보안 키를 사용하는 데 문제가 발생했습니다. 다시 시도하세요.",
|
||||
"twoFactorRequired": "보안 키를 등록하려면 이중 인증이 필요합니다.",
|
||||
"twoFactor": "이중 인증",
|
||||
"twoFactorAuthentication": "이중 인증",
|
||||
"twoFactorDescription": "이 조직은 이중 인증을 요구합니다.",
|
||||
"enableTwoFactor": "이중 인증 활성화",
|
||||
"organizationSecurityPolicy": "조직 보안 정책",
|
||||
"organizationSecurityPolicyDescription": "이 조직에는 접근하기 전에 준수해야 하는 보안 요구 사항이 있습니다",
|
||||
"securityRequirements": "보안 요구 사항",
|
||||
"allRequirementsMet": "모든 요구 사항이 충족되었습니다",
|
||||
"completeRequirementsToContinue": "이 조직에 계속 접근하려면 아래 요구 사항을 완료하십시오",
|
||||
"youCanNowAccessOrganization": "이제 이 조직에 접근할 수 있습니다",
|
||||
"reauthenticationRequired": "세션 길이",
|
||||
"reauthenticationDescription": "이 조직은 {maxDays}일마다 로그인하는 것을 요구합니다.",
|
||||
"reauthenticationDescriptionHours": "이 조직은 {maxHours}시간마다 로그인하는 것을 요구합니다.",
|
||||
"reauthenticateNow": "다시 로그인",
|
||||
"adminEnabled2FaOnYourAccount": "관리자가 {email}에 대한 이중 인증을 활성화했습니다. 계속하려면 설정을 완료하세요.",
|
||||
"continueToApplication": "응용 프로그램으로 계속",
|
||||
"securityKeyAdd": "보안 키 추가",
|
||||
"securityKeyRegisterTitle": "새 보안 키 등록",
|
||||
"securityKeyRegisterDescription": "보안 키를 연결하고 식별할 이름을 입력하세요.",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "DNS 변경 사항은 인터넷 전체에 전파되는 데 시간이 걸립니다. DNS 제공자와 TTL 설정에 따라 몇 분에서 48시간까지 걸릴 수 있습니다.",
|
||||
"resourcePortRequired": "HTTP 리소스가 아닌 경우 포트 번호가 필요합니다",
|
||||
"resourcePortNotAllowed": "HTTP 리소스에 대해 포트 번호를 설정하지 마세요",
|
||||
"billingPricingCalculatorLink": "가격 계산기",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "동의합니다",
|
||||
"termsOfService": "서비스 약관",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "외부 프록시 활성화됨",
|
||||
"addNewTarget": "새 대상 추가",
|
||||
"targetsList": "대상 목록",
|
||||
"advancedMode": "고급 모드",
|
||||
"targetErrorDuplicateTargetFound": "중복 대상 발견",
|
||||
"healthCheckHealthy": "정상",
|
||||
"healthCheckUnhealthy": "비정상",
|
||||
"healthCheckUnknown": "알 수 없음",
|
||||
"healthCheck": "상태 확인",
|
||||
"configureHealthCheck": "상태 확인 설정",
|
||||
"configureHealthCheckDescription": "{target}에 대한 상태 모니터링 설정",
|
||||
"enableHealthChecks": "상태 확인 활성화",
|
||||
"enableHealthChecksDescription": "이 대상을 모니터링하여 건강 상태를 확인하세요. 필요에 따라 대상과 다른 엔드포인트를 모니터링할 수 있습니다.",
|
||||
"healthScheme": "방법",
|
||||
"healthSelectScheme": "방법 선택",
|
||||
"healthCheckPath": "경로",
|
||||
"healthHostname": "IP / 호스트",
|
||||
"healthPort": "포트",
|
||||
"healthCheckPathDescription": "상태 확인을 위한 경로입니다.",
|
||||
"healthyIntervalSeconds": "정상 간격",
|
||||
"unhealthyIntervalSeconds": "비정상 간격",
|
||||
"IntervalSeconds": "정상 간격",
|
||||
"timeoutSeconds": "시간 초과",
|
||||
"timeIsInSeconds": "시간은 초 단위입니다",
|
||||
"retryAttempts": "재시도 횟수",
|
||||
"expectedResponseCodes": "예상 응답 코드",
|
||||
"expectedResponseCodesDescription": "정상 상태를 나타내는 HTTP 상태 코드입니다. 비워 두면 200-300이 정상으로 간주됩니다.",
|
||||
"customHeaders": "사용자 정의 헤더",
|
||||
"customHeadersDescription": "헤더는 새 줄로 구분됨: Header-Name: value",
|
||||
"headersValidationError": "헤더는 형식이어야 합니다: 헤더명: 값.",
|
||||
"saveHealthCheck": "상태 확인 저장",
|
||||
"healthCheckSaved": "상태 확인이 저장되었습니다.",
|
||||
"healthCheckSavedDescription": "상태 확인 구성이 성공적으로 저장되었습니다",
|
||||
"healthCheckError": "상태 확인 오류",
|
||||
"healthCheckErrorDescription": "상태 확인 구성을 저장하는 동안 오류가 발생했습니다",
|
||||
"healthCheckPathRequired": "상태 확인 경로는 필수입니다.",
|
||||
"healthCheckMethodRequired": "HTTP 방법은 필수입니다.",
|
||||
"healthCheckIntervalMin": "확인 간격은 최소 5초여야 합니다.",
|
||||
"healthCheckTimeoutMin": "시간 초과는 최소 1초여야 합니다.",
|
||||
"healthCheckRetryMin": "재시도 횟수는 최소 1회여야 합니다.",
|
||||
"httpMethod": "HTTP 메소드",
|
||||
"selectHttpMethod": "HTTP 메소드 선택",
|
||||
"domainPickerSubdomainLabel": "서브도메인",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "사용 가능한 무료 도메인에서 검색 및 선택할 서브도메인 입력.",
|
||||
"domainPickerFreeDomains": "무료 도메인",
|
||||
"domainPickerSearchForAvailableDomains": "사용 가능한 도메인 검색",
|
||||
"domainPickerNotWorkSelfHosted": "참고: 무료 제공 도메인은 현재 자체 호스팅 인스턴스에 사용할 수 없습니다.",
|
||||
"resourceDomain": "도메인",
|
||||
"resourceEditDomain": "도메인 수정",
|
||||
"siteName": "사이트 이름",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "프로토콜",
|
||||
"editInternalResourceDialogSitePort": "사이트 포트",
|
||||
"editInternalResourceDialogTargetConfiguration": "대상 구성",
|
||||
"editInternalResourceDialogDestinationIP": "대상 IP",
|
||||
"editInternalResourceDialogDestinationPort": "대상 IP의 포트",
|
||||
"editInternalResourceDialogCancel": "취소",
|
||||
"editInternalResourceDialogSaveResource": "리소스 저장",
|
||||
"editInternalResourceDialogSuccess": "성공",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "사이트 포트",
|
||||
"createInternalResourceDialogSitePortDescription": "사이트에 연결되었을 때 리소스에 접근하기 위해 이 포트를 사용합니다.",
|
||||
"createInternalResourceDialogTargetConfiguration": "대상 설정",
|
||||
"createInternalResourceDialogDestinationIP": "대상 IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "사이트 네트워크의 자원 IP 주소입니다.",
|
||||
"createInternalResourceDialogDestinationPort": "대상 포트",
|
||||
"createInternalResourceDialogDestinationIPDescription": "사이트 네트워크의 자원 IP 또는 호스트 네임 주소입니다.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "대상 IP에서 리소스에 접근할 수 있는 포트입니다.",
|
||||
"createInternalResourceDialogCancel": "취소",
|
||||
"createInternalResourceDialogCreateResource": "리소스 생성",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "자동 로그인 오류",
|
||||
"autoLoginErrorNoRedirectUrl": "ID 공급자로부터 리디렉션 URL을 받지 못했습니다.",
|
||||
"autoLoginErrorGeneratingUrl": "인증 URL 생성 실패.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "원격 노드",
|
||||
"remoteExitNodeDescription": "네트워크 연결성을 확장하고 클라우드 의존도를 줄이기 위해 하나 이상의 원격 노드를 자체 호스트하십시오.",
|
||||
"remoteExitNodes": "노드",
|
||||
"searchRemoteExitNodes": "노드 검색...",
|
||||
"remoteExitNodeAdd": "노드 추가",
|
||||
"remoteExitNodeErrorDelete": "노드 삭제 오류",
|
||||
"remoteExitNodeQuestionRemove": "조직에서 노드를 제거하시겠습니까?",
|
||||
"remoteExitNodeMessageRemove": "한 번 제거되면 더 이상 노드에 접근할 수 없습니다.",
|
||||
"remoteExitNodeConfirmDelete": "노드 삭제 확인",
|
||||
"remoteExitNodeDelete": "노드 삭제",
|
||||
"sidebarRemoteExitNodes": "원격 노드",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "노드 생성",
|
||||
"description": "네트워크 연결성을 확장하기 위해 새 노드를 생성하세요",
|
||||
"viewAllButton": "모든 노드 보기",
|
||||
"strategy": {
|
||||
"title": "생성 전략",
|
||||
"description": "노드를 직접 구성하거나 새 자격 증명을 생성하려면 이것을 선택하세요.",
|
||||
"adopt": {
|
||||
"title": "노드 채택",
|
||||
"description": "이미 노드의 자격 증명이 있는 경우 이것을 선택하세요."
|
||||
},
|
||||
"generate": {
|
||||
"title": "키 생성",
|
||||
"description": "노드에 대한 새 키를 생성하려면 이것을 선택하세요"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "기존 노드 채택",
|
||||
"description": "채택하려는 기존 노드의 자격 증명을 입력하세요",
|
||||
"nodeIdLabel": "노드 ID",
|
||||
"nodeIdDescription": "채택하려는 기존 노드의 ID",
|
||||
"secretLabel": "비밀",
|
||||
"secretDescription": "기존 노드의 비밀 키",
|
||||
"submitButton": "노드 채택"
|
||||
},
|
||||
"generate": {
|
||||
"title": "생성된 자격 증명",
|
||||
"description": "생성된 자격 증명을 사용하여 노드를 구성하세요",
|
||||
"nodeIdTitle": "노드 ID",
|
||||
"secretTitle": "비밀",
|
||||
"saveCredentialsTitle": "구성에 자격 증명 추가",
|
||||
"saveCredentialsDescription": "연결을 완료하려면 이러한 자격 증명을 자체 호스팅 Pangolin 노드 구성 파일에 추가하십시오.",
|
||||
"submitButton": "노드 생성"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "기존 노드를 채택하려면 노드 ID와 비밀 키가 필요합니다"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "기본값 로드 실패",
|
||||
"defaultsNotLoaded": "기본값 로드되지 않음",
|
||||
"createFailed": "노드 생성 실패"
|
||||
},
|
||||
"success": {
|
||||
"created": "노드가 성공적으로 생성되었습니다"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "노드 선택",
|
||||
"remoteExitNodeSelectionDescription": "이 로컬 사이트에서 트래픽을 라우팅할 노드를 선택하세요",
|
||||
"remoteExitNodeRequired": "로컬 사이트에 노드를 선택해야 합니다",
|
||||
"noRemoteExitNodesAvailable": "사용 가능한 노드가 없습니다",
|
||||
"noRemoteExitNodesAvailableDescription": "이 조직에 사용 가능한 노드가 없습니다. 로컬 사이트를 사용하려면 먼저 노드를 생성하세요.",
|
||||
"exitNode": "종단 노드",
|
||||
"country": "국가",
|
||||
"rulesMatchCountry": "현재 소스 IP를 기반으로 합니다",
|
||||
"managedSelfHosted": {
|
||||
"title": "관리 자체 호스팅",
|
||||
"description": "더 신뢰할 수 있고 낮은 유지보수의 자체 호스팅 팡골린 서버, 추가 기능 포함",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "이 노드를 관리 자체 호스팅으로 변환"
|
||||
},
|
||||
"internationaldomaindetected": "국제 도메인 감지됨",
|
||||
"willbestoredas": "다음으로 저장됩니다:"
|
||||
}
|
||||
"willbestoredas": "다음으로 저장됩니다:",
|
||||
"roleMappingDescription": "자동 프로비저닝이 활성화되면 사용자가 로그인할 때 역할이 할당되는 방법을 결정합니다.",
|
||||
"selectRole": "역할 선택",
|
||||
"roleMappingExpression": "표현식",
|
||||
"selectRolePlaceholder": "역할 선택",
|
||||
"selectRoleDescription": "이 신원 공급자로부터 모든 사용자에게 할당할 역할을 선택하십시오.",
|
||||
"roleMappingExpressionDescription": "ID 토큰에서 역할 정보를 추출하기 위한 JMESPath 표현식을 입력하세요.",
|
||||
"idpTenantIdRequired": "테넌트 ID가 필요합니다",
|
||||
"invalidValue": "잘못된 값",
|
||||
"idpTypeLabel": "신원 공급자 유형",
|
||||
"roleMappingExpressionPlaceholder": "예: contains(groups, 'admin') && 'Admin' || 'Member'",
|
||||
"idpGoogleConfiguration": "Google 구성",
|
||||
"idpGoogleConfigurationDescription": "Google OAuth2 자격 증명을 구성합니다.",
|
||||
"idpGoogleClientIdDescription": "Google OAuth2 클라이언트 ID",
|
||||
"idpGoogleClientSecretDescription": "Google OAuth2 클라이언트 비밀",
|
||||
"idpAzureConfiguration": "Azure Entra ID 구성",
|
||||
"idpAzureConfigurationDescription": "Azure Entra ID OAuth2 자격 증명을 구성합니다.",
|
||||
"idpTenantId": "테넌트 ID",
|
||||
"idpTenantIdPlaceholder": "your-tenant-id",
|
||||
"idpAzureTenantIdDescription": "Azure 액티브 디렉터리 개요에서 찾은 Azure 테넌트 ID",
|
||||
"idpAzureClientIdDescription": "Azure 앱 등록 클라이언트 ID",
|
||||
"idpAzureClientSecretDescription": "Azure 앱 등록 클라이언트 비밀",
|
||||
"idpGoogleTitle": "구글",
|
||||
"idpGoogleAlt": "구글",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "애저",
|
||||
"idpGoogleConfigurationTitle": "Google 구성",
|
||||
"idpAzureConfigurationTitle": "Azure Entra ID 구성",
|
||||
"idpTenantIdLabel": "테넌트 ID",
|
||||
"idpAzureClientIdDescription2": "Azure 앱 등록 클라이언트 ID",
|
||||
"idpAzureClientSecretDescription2": "Azure 앱 등록 클라이언트 비밀",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC 공급자",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC 공급자",
|
||||
"subnet": "서브넷",
|
||||
"subnetDescription": "이 조직의 네트워크 구성에 대한 서브넷입니다.",
|
||||
"authPage": "인증 페이지",
|
||||
"authPageDescription": "조직에 대한 인증 페이지를 구성합니다.",
|
||||
"authPageDomain": "인증 페이지 도메인",
|
||||
"noDomainSet": "도메인 설정 없음",
|
||||
"changeDomain": "도메인 변경",
|
||||
"selectDomain": "도메인 선택",
|
||||
"restartCertificate": "인증서 재시작",
|
||||
"editAuthPageDomain": "인증 페이지 도메인 편집",
|
||||
"setAuthPageDomain": "인증 페이지 도메인 설정",
|
||||
"failedToFetchCertificate": "인증서 가져오기 실패",
|
||||
"failedToRestartCertificate": "인증서 재시작 실패",
|
||||
"addDomainToEnableCustomAuthPages": "조직의 맞춤 인증 페이지를 활성화하려면 도메인을 추가하세요.",
|
||||
"selectDomainForOrgAuthPage": "조직 인증 페이지에 대한 도메인을 선택하세요.",
|
||||
"domainPickerProvidedDomain": "제공된 도메인",
|
||||
"domainPickerFreeProvidedDomain": "무료 제공된 도메인",
|
||||
"domainPickerVerified": "검증됨",
|
||||
"domainPickerUnverified": "검증되지 않음",
|
||||
"domainPickerInvalidSubdomainStructure": "이 하위 도메인은 잘못된 문자 또는 구조를 포함하고 있습니다. 저장 시 자동으로 정리됩니다.",
|
||||
"domainPickerError": "오류",
|
||||
"domainPickerErrorLoadDomains": "조직 도메인 로드 실패",
|
||||
"domainPickerErrorCheckAvailability": "도메인 가용성 확인 실패",
|
||||
"domainPickerInvalidSubdomain": "잘못된 하위 도메인",
|
||||
"domainPickerInvalidSubdomainRemoved": "입력 \"{sub}\"이(가) 유효하지 않으므로 제거되었습니다.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\"을(를) {domain}에 대해 유효하게 만들 수 없습니다.",
|
||||
"domainPickerSubdomainSanitized": "하위 도메인 정리됨",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\"이(가) \"{sanitized}\"로 수정되었습니다",
|
||||
"orgAuthSignInTitle": "조직에 로그인",
|
||||
"orgAuthChooseIdpDescription": "계속하려면 신원 공급자를 선택하세요.",
|
||||
"orgAuthNoIdpConfigured": "이 조직은 구성된 신원 공급자가 없습니다. 대신 Pangolin 아이덴티티로 로그인할 수 있습니다.",
|
||||
"orgAuthSignInWithPangolin": "Pangolin으로 로그인",
|
||||
"subscriptionRequiredToUse": "이 기능을 사용하려면 구독이 필요합니다.",
|
||||
"idpDisabled": "신원 공급자가 비활성화되었습니다.",
|
||||
"orgAuthPageDisabled": "조직 인증 페이지가 비활성화되었습니다.",
|
||||
"domainRestartedDescription": "도메인 인증이 성공적으로 재시작되었습니다.",
|
||||
"resourceAddEntrypointsEditFile": "파일 편집: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "파일 편집: docker-compose.yml",
|
||||
"emailVerificationRequired": "이메일 인증이 필요합니다. 이 단계를 완료하려면 {dashboardUrl}/auth/login 통해 다시 로그인하십시오. 그런 다음 여기로 돌아오세요.",
|
||||
"twoFactorSetupRequired": "이중 인증 설정이 필요합니다. 이 단계를 완료하려면 {dashboardUrl}/auth/login 통해 다시 로그인하십시오. 그런 다음 여기로 돌아오세요.",
|
||||
"additionalSecurityRequired": "추가 보안 필요",
|
||||
"organizationRequiresAdditionalSteps": "이 조직은 자원에 접근하기 전에 추가 보안 단계를 요구합니다.",
|
||||
"completeTheseSteps": "이 단계를 완료하십시오",
|
||||
"enableTwoFactorAuthentication": "이중 인증 활성화",
|
||||
"completeSecuritySteps": "보안 단계 완료",
|
||||
"securitySettings": "보안 설정",
|
||||
"securitySettingsDescription": "조직에 대한 보안 정책을 구성합니다",
|
||||
"requireTwoFactorForAllUsers": "모든 사용자에 대해 이중 인증 요구",
|
||||
"requireTwoFactorDescription": "활성화되면, 이 조직의 모든 내부 사용자는 조직에 접근하기 위해 이중 인증을 활성화해야 합니다.",
|
||||
"requireTwoFactorDisabledDescription": "이 기능을 사용하려면 유효한 라이선스(Enterprise) 또는 활성 구독(SaaS)가 필요합니다.",
|
||||
"requireTwoFactorCannotEnableDescription": "모든 사용자에게 강제하기 전에 계정에 대해 이중 인증을 활성화해야 합니다",
|
||||
"maxSessionLength": "최대 세션 길이",
|
||||
"maxSessionLengthDescription": "사용자 세션의 최대 지속 시간을 설정합니다. 이 시간이 지나면 사용자는 다시 인증해야 합니다.",
|
||||
"maxSessionLengthDisabledDescription": "이 기능을 사용하려면 유효한 라이선스(Enterprise) 또는 활성 구독(SaaS)가 필요합니다.",
|
||||
"selectSessionLength": "세션 길이 선택",
|
||||
"unenforced": "강제되지 않음",
|
||||
"1Hour": "1 시간",
|
||||
"3Hours": "3 시간",
|
||||
"6Hours": "6 시간",
|
||||
"12Hours": "12 시간",
|
||||
"1DaySession": "1 일",
|
||||
"3Days": "3 일",
|
||||
"7Days": "7 일",
|
||||
"14Days": "14 일",
|
||||
"30DaysSession": "30 일",
|
||||
"90DaysSession": "90 일",
|
||||
"180DaysSession": "180 일",
|
||||
"passwordExpiryDays": "비밀번호 만료",
|
||||
"editPasswordExpiryDescription": "사용자가 비밀번호를 변경해야 하는 날 수를 설정합니다.",
|
||||
"selectPasswordExpiry": "비밀번호 만료 선택",
|
||||
"30Days": "30 일",
|
||||
"1Day": "1 일",
|
||||
"60Days": "60 일",
|
||||
"90Days": "90 일",
|
||||
"180Days": "180 일",
|
||||
"1Year": "1 년",
|
||||
"subscriptionBadge": "구독 필요",
|
||||
"securityPolicyChangeWarning": "보안 정책 변경 경고",
|
||||
"securityPolicyChangeDescription": "보안 정책 설정을 변경하려고 합니다. 저장 후, 정책 업데이트를 준수하기 위해 다시 인증해야 할 수도 있습니다. 규정을 준수하지 않는 모든 사용자도 다시 인증해야 합니다.",
|
||||
"securityPolicyChangeConfirmMessage": "확인합니다",
|
||||
"securityPolicyChangeWarningText": "이 작업은 조직의 모든 사용자에게 영향을 미칩니다",
|
||||
"authPageErrorUpdateMessage": "인증 페이지 설정을 업데이트하는 동안 오류가 발생했습니다",
|
||||
"authPageErrorUpdate": "인증 페이지를 업데이트할 수 없습니다",
|
||||
"authPageUpdated": "인증 페이지가 성공적으로 업데이트되었습니다",
|
||||
"healthCheckNotAvailable": "로컬",
|
||||
"rewritePath": "경로 재작성",
|
||||
"rewritePathDescription": "대상으로 전달하기 전에 경로를 선택적으로 재작성합니다.",
|
||||
"continueToApplication": "응용 프로그램으로 계속",
|
||||
"checkingInvite": "초대 확인 중",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "헤더 인증 제거",
|
||||
"resourceHeaderAuthRemoveDescription": "헤더 인증이 성공적으로 제거되었습니다.",
|
||||
"resourceErrorHeaderAuthRemove": "헤더 인증 제거 실패",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "리소스의 헤더 인증을 제거할 수 없습니다.",
|
||||
"resourceHeaderAuthProtectionEnabled": "헤더 인증 활성화됨",
|
||||
"resourceHeaderAuthProtectionDisabled": "헤더 인증 비활성화됨",
|
||||
"headerAuthRemove": "헤더 인증 삭제",
|
||||
"headerAuthAdd": "헤더 인증 추가",
|
||||
"resourceErrorHeaderAuthSetup": "헤더 인증 설정 실패",
|
||||
"resourceErrorHeaderAuthSetupDescription": "리소스의 헤더 인증을 설정할 수 없습니다.",
|
||||
"resourceHeaderAuthSetup": "헤더 인증이 성공적으로 설정되었습니다.",
|
||||
"resourceHeaderAuthSetupDescription": "헤더 인증이 성공적으로 설정되었습니다.",
|
||||
"resourceHeaderAuthSetupTitle": "헤더 인증 설정",
|
||||
"resourceHeaderAuthSetupTitleDescription": "이 리소스를 HTTP 헤더 인증으로 보호하기 위해 기본 인증 자격 증명(사용자이름 및 비밀번호)을 설정합니다. 다음과 같은 형식으로 액세스하세요 https://사용자이름:비밀번호@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "헤더 인증 설정",
|
||||
"actionSetResourceHeaderAuth": "헤더 인증 설정",
|
||||
"enterpriseEdition": "엔터프라이즈 에디션",
|
||||
"unlicensed": "라이선스 없음",
|
||||
"beta": "베타",
|
||||
"manageClients": "클라이언트 관리",
|
||||
"manageClientsDescription": "클라이언트는 당신의 사이트에 연결할 수 있는 디바이스입니다.",
|
||||
"licenseTableValidUntil": "유효 기한",
|
||||
"saasLicenseKeysSettingsTitle": "엔터프라이즈 라이선스",
|
||||
"saasLicenseKeysSettingsDescription": "자체 호스팅된 Pangolin 인스턴스를 위한 엔터프라이즈 라이선스 키를 생성하고 관리합니다.",
|
||||
"sidebarEnterpriseLicenses": "라이선스",
|
||||
"generateLicenseKey": "라이선스 키 생성",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "유효한 이메일 주소를 입력하세요",
|
||||
"useCaseTypeRequired": "사용 사례 유형을 선택하세요",
|
||||
"firstNameRequired": "이름은 필수입니다.",
|
||||
"lastNameRequired": "성은 필수입니다.",
|
||||
"primaryUseRequired": "주요 용도를 설명하세요",
|
||||
"jobTitleRequiredBusiness": "사업용 직책은 필수입니다.",
|
||||
"industryRequiredBusiness": "사업용 산업은 필수입니다.",
|
||||
"stateProvinceRegionRequired": "주/도/지역이 필수입니다.",
|
||||
"postalZipCodeRequired": "우편번호/ZIP 코드가 필수입니다.",
|
||||
"companyNameRequiredBusiness": "사업용 회사 이름은 필수입니다.",
|
||||
"countryOfResidenceRequiredBusiness": "사업용 거주 국가는 필수입니다.",
|
||||
"countryRequiredPersonal": "개인용 국가가 필수입니다.",
|
||||
"agreeToTermsRequired": "약관에 동의해야 합니다.",
|
||||
"complianceConfirmationRequired": "Fossorial 상용 라이선스를 준수함을 확인해야 합니다."
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "개인 용도",
|
||||
"description": "학습, 개인 프로젝트 또는 실험과 같은 개인, 비상업적 용도로 사용합니다."
|
||||
},
|
||||
"business": {
|
||||
"title": "사업 용도",
|
||||
"description": "조직, 회사 또는 수익 창출 활동 내에서 사용됩니다."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "이메일 및 라이선스 유형",
|
||||
"description": "이메일을 입력하고 라이선스 유형을 선택하세요"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "개인 정보",
|
||||
"description": "자기소개를 해주세요"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "연락처 정보",
|
||||
"description": "당신의 연락처 정보"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "약관 및 생성",
|
||||
"description": "라이선스를 생성하기 위해 약관을 검토하고 수락하세요"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "사용 공개",
|
||||
"description": "당신의 의도된 사용에 정확히 맞는 라이선스 등급을 선택하세요. 개인 라이선스는 연간 총 수익 100,000 USD 이하의 개인, 비상업적 또는 소규모 상업 활동을 위한 소프트웨어의 무료 사용을 허용합니다. 이러한 제한을 넘는 모든 사용 — 비즈니스, 조직 또는 기타 수익 창출 환경 내에서의 사용 — 은 유효한 엔터프라이즈 라이선스 및 해당 라이선스 수수료의 지불이 필요합니다. 개인 또는 기업 사용자는 모두 Fossorial 상용 라이선스 조건을 준수해야 합니다."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "시험 기간 정보",
|
||||
"description": "이 라이선스 키는 엔터프라이즈 기능을 평가판 기간 동안 7일 동안 활성화합니다. 평가 기간 이후 유료 기능에 대한 계속된 액세스는 유효한 개인 또는 엔터프라이즈 라이선스 하에서 활성화가 필요합니다. 엔터프라이즈 라이선스에 대한 정보는 sales@pangolin.net에 문의하세요."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "개인 또는 사업용으로 Pangolin을 사용하시나요?",
|
||||
"firstName": "이름",
|
||||
"lastName": "성",
|
||||
"jobTitle": "직책",
|
||||
"primaryUseQuestion": "Pangolin을 주로 무엇에 사용하려고 계획하시나요?",
|
||||
"industryQuestion": "당신의 산업은 무엇입니까?",
|
||||
"prospectiveUsersQuestion": "예상하는 잠재적 사용자는 몇 명입니까?",
|
||||
"prospectiveSitesQuestion": "예상하는 잠재적 사이트(터널)는 몇 개입니까?",
|
||||
"companyName": "회사 이름",
|
||||
"countryOfResidence": "거주 국가",
|
||||
"stateProvinceRegion": "주 / 도 / 지역",
|
||||
"postalZipCode": "우편번호 / ZIP 코드",
|
||||
"companyWebsite": "회사 웹사이트",
|
||||
"companyPhoneNumber": "회사 전화번호",
|
||||
"country": "국가",
|
||||
"phoneNumberOptional": "전화번호 (선택 항목)",
|
||||
"complianceConfirmation": "제가 제공한 정보가 정확하고 Fossorial 상용 라이선스를 준수하는지 확인합니다. 부정확한 정보를 보고하거나 제품 사용을 실수로 식별하는 것은 라이선스 위반이며, 키가 취소될 수 있습니다."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "닫기",
|
||||
"previous": "이전",
|
||||
"next": "다음",
|
||||
"generateLicenseKey": "라이선스 키 생성"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "라이선스 키가 성공적으로 생성되었습니다",
|
||||
"description": "당신의 라이선스 키가 생성되었으며 사용 준비가 되었습니다."
|
||||
},
|
||||
"error": {
|
||||
"title": "라이선스 키 생성에 실패했습니다",
|
||||
"description": "라이선스 키를 생성하는 동안 오류가 발생했습니다."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "우선순위",
|
||||
"priorityDescription": "우선 순위가 높은 경로가 먼저 평가됩니다. 우선 순위 = 100은 자동 정렬(시스템 결정)이 의미합니다. 수동 우선 순위를 적용하려면 다른 숫자를 사용하세요.",
|
||||
"instanceName": "인스턴스 이름",
|
||||
"pathMatchModalTitle": "경로 매칭 설정",
|
||||
"pathMatchModalDescription": "경로별로 들어오는 요청을 어떻게 매칭할지 설정합니다.",
|
||||
"pathMatchType": "일치 유형",
|
||||
"pathMatchPrefix": "접두사",
|
||||
"pathMatchExact": "정확하게",
|
||||
"pathMatchRegex": "정규 표현식",
|
||||
"pathMatchValue": "경로 값",
|
||||
"clear": "지우기",
|
||||
"saveChanges": "변경 사항 저장",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/경로",
|
||||
"pathMatchPrefixHelp": "예: /api 는 /api, /api/users 등을 매칭합니다.",
|
||||
"pathMatchExactHelp": "예: /api 는 /api 만 매칭합니다.",
|
||||
"pathMatchRegexHelp": "예: ^/api/.* 는 /api/anything를 매칭합니다",
|
||||
"pathRewriteModalTitle": "경로 재작성 설정",
|
||||
"pathRewriteModalDescription": "대상으로 전달하기 전에 매칭된 경로를 변환합니다.",
|
||||
"pathRewriteType": "재작성 유형",
|
||||
"pathRewritePrefixOption": "접두사 - 접두사 대체",
|
||||
"pathRewriteExactOption": "정확 - 전체 경로 대체",
|
||||
"pathRewriteRegexOption": "정규 표현식 - 패턴 대체",
|
||||
"pathRewriteStripPrefixOption": "접두사 제거 - 접두사 삭제",
|
||||
"pathRewriteValue": "재작성 값",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/새-경로",
|
||||
"pathRewritePrefixHelp": "일치하는 접두사를 이 값으로 대체합니다",
|
||||
"pathRewriteExactHelp": "경로가 정확히 일치할 때 전체 경로를 이 값으로 대체합니다",
|
||||
"pathRewriteRegexHelp": "$1, $2와 같은 캡처 그룹을 사용하여 대체",
|
||||
"pathRewriteStripPrefixHelp": "접두사를 제거하거나 새 접두사를 제공하려면 비워 둡니다",
|
||||
"pathRewritePrefix": "접두사",
|
||||
"pathRewriteExact": "정확하게",
|
||||
"pathRewriteRegex": "정규 표현식",
|
||||
"pathRewriteStrip": "제거",
|
||||
"pathRewriteStripLabel": "제거",
|
||||
"sidebarEnableEnterpriseLicense": "엔터프라이즈 라이선스 활성화",
|
||||
"cannotbeUndone": "이 작업은 되돌릴 수 없습니다.",
|
||||
"toConfirm": "확인하려면",
|
||||
"deleteClientQuestion": "고객을 사이트와 조직에서 제거하시겠습니까?",
|
||||
"clientMessageRemove": "제거되면 클라이언트는 사이트에 더 이상 연결할 수 없습니다.",
|
||||
"sidebarLogs": "로그",
|
||||
"request": "요청",
|
||||
"logs": "로그",
|
||||
"logsSettingsDescription": "이 조직에서 수집된 로그를 모니터링합니다",
|
||||
"searchLogs": "로그 검색...",
|
||||
"action": "작업",
|
||||
"actor": "행위자",
|
||||
"timestamp": "타임스탬프",
|
||||
"accessLogs": "접근 로그",
|
||||
"exportCsv": "CSV 내보내기",
|
||||
"actorId": "행위자 ID",
|
||||
"allowedByRule": "룰에 의해 허용됨",
|
||||
"allowedNoAuth": "인증 없음 허용됨",
|
||||
"validAccessToken": "유효한 접근 토큰",
|
||||
"validHeaderAuth": "유효한 헤더 인증",
|
||||
"validPincode": "유효한 핀코드",
|
||||
"validPassword": "유효한 비밀번호",
|
||||
"validEmail": "유효한 이메일",
|
||||
"validSSO": "유효한 SSO",
|
||||
"resourceBlocked": "리소스 차단됨",
|
||||
"droppedByRule": "룰에 의해 드롭됨",
|
||||
"noSessions": "세션 없음",
|
||||
"temporaryRequestToken": "임시 요청 토큰",
|
||||
"noMoreAuthMethods": "유효한 인증 없음",
|
||||
"ip": "IP",
|
||||
"reason": "이유",
|
||||
"requestLogs": "요청 로그",
|
||||
"host": "호스트",
|
||||
"location": "위치",
|
||||
"actionLogs": "작업 로그",
|
||||
"sidebarLogsRequest": "요청 로그",
|
||||
"sidebarLogsAccess": "접근 로그",
|
||||
"sidebarLogsAction": "작업 로그",
|
||||
"logRetention": "로그 보관",
|
||||
"logRetentionDescription": "다양한 유형의 로그를 이 조직에 대해 얼마나 오래 보관할지 관리하거나 비활성화합니다",
|
||||
"requestLogsDescription": "이 조직의 자원에 대한 상세한 요청 로그를 봅니다",
|
||||
"logRetentionRequestLabel": "요청 로그 보관",
|
||||
"logRetentionRequestDescription": "요청 로그를 얼마나 오래 보관할지",
|
||||
"logRetentionAccessLabel": "접근 로그 보관",
|
||||
"logRetentionAccessDescription": "접근 로그를 얼마나 오래 보관할지",
|
||||
"logRetentionActionLabel": "작업 로그 보관",
|
||||
"logRetentionActionDescription": "작업 로그를 얼마나 오래 보관할지",
|
||||
"logRetentionDisabled": "비활성화됨",
|
||||
"logRetention3Days": "3 일",
|
||||
"logRetention7Days": "7 일",
|
||||
"logRetention14Days": "14 일",
|
||||
"logRetention30Days": "30 일",
|
||||
"logRetention90Days": "90 일",
|
||||
"logRetentionForever": "영구",
|
||||
"actionLogsDescription": "이 조직에서 수행된 작업의 기록을 봅니다",
|
||||
"accessLogsDescription": "이 조직의 자원에 대한 접근 인증 요청을 확인합니다",
|
||||
"licenseRequiredToUse": "이 기능을 사용하려면 Enterprise 라이선스가 필요합니다.",
|
||||
"certResolver": "인증서 해결사",
|
||||
"certResolverDescription": "이 리소스에 사용할 인증서 해결사를 선택하세요.",
|
||||
"selectCertResolver": "인증서 해결사 선택",
|
||||
"enterCustomResolver": "사용자 정의 해결사 입력",
|
||||
"preferWildcardCert": "와일드카드 인증서 선호",
|
||||
"unverified": "검증되지 않음",
|
||||
"domainSetting": "도메인 설정",
|
||||
"domainSettingDescription": "도메인에 대한 설정을 구성하세요.",
|
||||
"preferWildcardCertDescription": "와일드카드 인증서를 생성하려고 시도합니다 (올바르게 구성된 인증서 해결사가 필요합니다).",
|
||||
"recordName": "레코드 이름",
|
||||
"auto": "자동",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "레코드 추가 방법",
|
||||
"dnsRecord": "DNS 레코드",
|
||||
"required": "필수",
|
||||
"domainSettingsUpdated": "도메인 설정이 성공적으로 업데이트되었습니다",
|
||||
"orgOrDomainIdMissing": "조직 ID 또는 도메인 ID가 누락되었습니다",
|
||||
"loadingDNSRecords": "DNS 레코드를 로드하는 중...",
|
||||
"olmUpdateAvailableInfo": "올름의 새 버전이 이용 가능합니다. 최상의 경험을 위해 최신 버전으로 업데이트하세요.",
|
||||
"client": "클라이언트",
|
||||
"proxyProtocol": "프록시 프로토콜 설정",
|
||||
"proxyProtocolDescription": "프록시 프로토콜을 구성하여 TCP/UDP 서비스에 대한 클라이언트 IP 주소를 보존하십시오.",
|
||||
"enableProxyProtocol": "프록시 프로토콜 활성화",
|
||||
"proxyProtocolInfo": "TCP/UDP 백엔드의 클라이언트 IP 주소를 보존합니다",
|
||||
"proxyProtocolVersion": "프록시 프로토콜 버전",
|
||||
"version1": " 버전 1 (추천)",
|
||||
"version2": "버전 2",
|
||||
"versionDescription": "버전 1은 텍스트 기반으로 널리 지원됩니다. 버전 2는 이진 기반으로 더 효율적이지만 호환성이 낮습니다.",
|
||||
"warning": "경고",
|
||||
"proxyProtocolWarning": "백엔드 애플리케이션이 프록시 프로토콜 연결을 허용하도록 구성되어야 합니다. 백엔드가 프록시 프로토콜을 지원하지 않으면, 이를 활성화하면 모든 연결이 끊어집니다. 트래픽에서 온 프록시 프로토콜 헤더를 백엔드가 신뢰하도록 구성하십시오.",
|
||||
"restarting": "재시작 중...",
|
||||
"manual": "수동",
|
||||
"messageSupport": "지원 메시지",
|
||||
"supportNotAvailableTitle": "지원 불가",
|
||||
"supportNotAvailableDescription": "현재 지원을 받을 수 없습니다. support@pangolin.net으로 이메일을 보낼 수 있습니다.",
|
||||
"supportRequestSentTitle": "지원 요청 전송 완료",
|
||||
"supportRequestSentDescription": "메시지가 성공적으로 전송되었습니다.",
|
||||
"supportRequestFailedTitle": "요청 전송 실패",
|
||||
"supportRequestFailedDescription": "지원 요청을 보내는 중 오류가 발생했습니다.",
|
||||
"supportSubjectRequired": "제목은 필수입니다",
|
||||
"supportSubjectMaxLength": "제목은 255자 이내여야 합니다",
|
||||
"supportMessageRequired": "메시지는 필수입니다",
|
||||
"supportReplyTo": "회신",
|
||||
"supportSubject": "제목",
|
||||
"supportSubjectPlaceholder": "제목 입력",
|
||||
"supportMessage": "메시지",
|
||||
"supportMessagePlaceholder": "메시지를 입력하십시오",
|
||||
"supportSending": "발송 중...",
|
||||
"supportSend": "보내기",
|
||||
"supportMessageSent": "메시지 전송 완료!",
|
||||
"supportWillContact": "곧 연락드리겠습니다!",
|
||||
"selectLogRetention": "로그 보존 선택",
|
||||
"showColumns": "열 표시",
|
||||
"hideColumns": "열 숨기기",
|
||||
"columnVisibility": "열 가시성",
|
||||
"toggleColumn": "{columnName} 열 토글",
|
||||
"allColumns": "모든 열",
|
||||
"defaultColumns": "기본 열",
|
||||
"customizeView": "보기 사용자 지정",
|
||||
"viewOptions": "보기 옵션",
|
||||
"selectAll": "모두 선택",
|
||||
"selectNone": "선택하지 않음",
|
||||
"selectedResources": "선택된 리소스",
|
||||
"enableSelected": "선택된 항목 활성화",
|
||||
"disableSelected": "선택된 항목 비활성화",
|
||||
"checkSelectedStatus": "선택된 항목 상태 확인"
|
||||
}
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "Rediger",
|
||||
"siteConfirmDelete": "Bekreft Sletting av Område",
|
||||
"siteDelete": "Slett Område",
|
||||
"siteMessageRemove": "Når området slettes, vil det ikke lenger være tilgjengelig. Alle ressurser og mål assosiert med området vil også bli slettet.",
|
||||
"siteMessageConfirm": "For å bekrefte, vennligst skriv inn navnet i området nedenfor.",
|
||||
"siteQuestionRemove": "Er du sikker på at du vil slette området {selectedSite} fra organisasjonen?",
|
||||
"siteMessageRemove": "Når nettstedet er fjernet, vil det ikke lenger være tilgjengelig. Alle målene for nettstedet vil også bli fjernet.",
|
||||
"siteQuestionRemove": "Er du sikker på at du vil fjerne nettstedet fra organisasjonen?",
|
||||
"siteManageSites": "Administrer Områder",
|
||||
"siteDescription": "Tillat tilkobling til nettverket ditt gjennom sikre tunneler",
|
||||
"siteCreate": "Opprett område",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Bruk hvilken som helst WireGuard-klient for å etablere en tunnel. Manuell NAT-oppsett kreves.",
|
||||
"siteWgDescriptionSaas": "Bruk hvilken som helst WireGuard-klient for å etablere en tunnel. Manuell NAT-oppsett er nødvendig. FUNGERER KUN PÅ SELVHOSTEDE NODER",
|
||||
"siteLocalDescription": "Kun lokale ressurser. Ingen tunnelering.",
|
||||
"siteLocalDescriptionSaas": "Kun lokale ressurser. Ingen tunneling. FUNGERER KUN PÅ SELVHOSTEDE NODER",
|
||||
"siteLocalDescriptionSaas": "Lokale ressurser. Ingen tunnelering. Bare tilgjengelig på eksterne noder.",
|
||||
"siteSeeAll": "Se alle områder",
|
||||
"siteTunnelDescription": "Bestem hvordan du vil koble deg til ditt område",
|
||||
"siteNewtCredentials": "Newt påloggingsinformasjon",
|
||||
@@ -118,7 +117,7 @@
|
||||
"usageExamples": "Brukseksempler",
|
||||
"tokenId": "Token-ID",
|
||||
"requestHeades": "Request Headers",
|
||||
"queryParameter": "Query Parameter",
|
||||
"queryParameter": "Forespørsel Params",
|
||||
"importantNote": "Viktig merknad",
|
||||
"shareImportantDescription": "Av sikkerhetsgrunner anbefales det å bruke headere fremfor query parametere der det er mulig, da query parametere kan logges i serverlogger eller nettleserhistorikk.",
|
||||
"token": "Token",
|
||||
@@ -132,7 +131,7 @@
|
||||
"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.",
|
||||
"shareSeeOnce": "Du får bare se denne lenken én gang. Pass på å kopiere den.",
|
||||
"shareSeeOnce": "Du vil bare kunne se denne linken én gang. Pass på å kopiere den.",
|
||||
"shareAccessHint": "Alle med denne lenken kan få tilgang til ressursen. Del forsiktig.",
|
||||
"shareTokenUsage": "Se tilgangstokenbruk",
|
||||
"createLink": "Opprett lenke",
|
||||
@@ -154,8 +153,7 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "For å bekrefte, skriv inn navnet på ressursen nedenfor.",
|
||||
"resourceQuestionRemove": "Er du sikker på at du vil fjerne ressursen {selectedResource} fra organisasjonen?",
|
||||
"resourceQuestionRemove": "Er du sikker på at du vil fjerne ressursen fra organisasjonen?",
|
||||
"resourceHTTP": "HTTPS-ressurs",
|
||||
"resourceHTTPDescription": "Proxy-forespørsler til appen din over HTTPS ved bruk av et underdomene eller grunndomene.",
|
||||
"resourceRaw": "Rå TCP/UDP-ressurs",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Velg område",
|
||||
"siteSearch": "Søk i område",
|
||||
"siteNotFound": "Ingen område funnet.",
|
||||
"selectCountry": "Velg land",
|
||||
"searchCountries": "Søk land...",
|
||||
"noCountryFound": "Ingen land funnet.",
|
||||
"siteSelectionDescription": "Dette området vil gi tilkobling til mål.",
|
||||
"resourceType": "Ressurstype",
|
||||
"resourceTypeDescription": "Bestem hvordan du vil få tilgang til ressursen din",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Grunndomene",
|
||||
"subdomnainDescription": "Underdomenet der ressursen din vil være tilgjengelig.",
|
||||
"resourceRawSettings": "TCP/UDP-innstillinger",
|
||||
"resourceRawSettingsDescription": "Konfigurer tilgang til ressursen din over TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Konfigurer hvordan din ressurs vil bli tilgjengelig over TCP/UDP. Du kartlegger ressursen til en port på vertsserveren Pangolin slik at du får tilgang til ressursene fra server-ip:mappet port.",
|
||||
"protocol": "Protokoll",
|
||||
"protocolSelect": "Velg en protokoll",
|
||||
"resourcePortNumber": "Portnummer",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Bekreft Sletting av Organisasjon",
|
||||
"orgMessageRemove": "Denne handlingen er irreversibel og vil slette alle tilknyttede data.",
|
||||
"orgMessageConfirm": "For å bekrefte, vennligst skriv inn navnet på organisasjonen nedenfor.",
|
||||
"orgQuestionRemove": "Er du sikker på at du vil fjerne organisasjonen {selectedOrg}?",
|
||||
"orgQuestionRemove": "Er du sikker på at du vil fjerne organisasjonen?",
|
||||
"orgUpdated": "Organisasjon oppdatert",
|
||||
"orgUpdatedDescription": "Organisasjonen har blitt oppdatert.",
|
||||
"orgErrorUpdate": "Kunne ikke oppdatere organisasjonen",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Generer API-nøkkel",
|
||||
"apiKeysErrorDelete": "Feil under sletting av API-nøkkel",
|
||||
"apiKeysErrorDeleteMessage": "Feil ved sletting av API-nøkkel",
|
||||
"apiKeysQuestionRemove": "Er du sikker på at du vil fjerne API-nøkkelen {selectedApiKey} fra organisasjonen?",
|
||||
"apiKeysQuestionRemove": "Er du sikker på at du vil fjerne API-nøkkelen fra organisasjonen?",
|
||||
"apiKeysMessageRemove": "Når den er fjernet, vil API-nøkkelen ikke lenger kunne brukes.",
|
||||
"apiKeysMessageConfirm": "For å bekrefte, vennligst skriv inn navnet på API-nøkkelen nedenfor.",
|
||||
"apiKeysDeleteConfirm": "Bekreft sletting av API-nøkkel",
|
||||
"apiKeysDelete": "Slett API-nøkkel",
|
||||
"apiKeysManage": "Administrer API-nøkler",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Bekreft sletting av bruker",
|
||||
"userDeleteServer": "Slett bruker fra server",
|
||||
"userMessageRemove": "Brukeren vil bli fjernet fra alle organisasjoner og vil bli fullstendig fjernet fra serveren.",
|
||||
"userMessageConfirm": "For å bekrefte, vennligst skriv inn navnet på brukeren nedenfor.",
|
||||
"userQuestionRemove": "Er du sikker på at du vil slette {selectedUser} permanent fra serveren?",
|
||||
"userQuestionRemove": "Er du sikker på at du vil slette brukeren permanent fra serveren?",
|
||||
"licenseKey": "Lisensnøkkel",
|
||||
"valid": "Gyldig",
|
||||
"numberOfSites": "Antall områder",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Vis Fossorial kommersiell lisens og abonnementsvilkår",
|
||||
"licenseMessageRemove": "Dette vil fjerne lisensnøkkelen og alle tilknyttede tillatelser gitt av den.",
|
||||
"licenseMessageConfirm": "For å bekrefte, vennligst skriv inn lisensnøkkelen nedenfor.",
|
||||
"licenseQuestionRemove": "Er du sikker på at du vil slette lisensnøkkelen {selectedKey} ?",
|
||||
"licenseQuestionRemove": "Er du sikker på at du vil slette lisensnøkkelen?",
|
||||
"licenseKeyDelete": "Slett Lisensnøkkel",
|
||||
"licenseKeyDeleteConfirm": "Bekreft sletting av lisensnøkkel",
|
||||
"licenseTitle": "Behandle lisensstatus",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Det oppstod en feil under fjerning av invitasjonen.",
|
||||
"inviteRemoved": "Invitasjon fjernet",
|
||||
"inviteRemovedDescription": "Invitasjonen for {email} er fjernet.",
|
||||
"inviteQuestionRemove": "Er du sikker på at du vil fjerne invitasjonen {email}?",
|
||||
"inviteQuestionRemove": "Er du sikker på at du vil fjerne invitasjonen?",
|
||||
"inviteMessageRemove": "Når fjernet, vil denne invitasjonen ikke lenger være gyldig. Du kan alltid invitere brukeren på nytt senere.",
|
||||
"inviteMessageConfirm": "For å bekrefte, vennligst tast inn invitasjonens e-postadresse nedenfor.",
|
||||
"inviteQuestionRegenerate": "Er du sikker på at du vil generere invitasjonen på nytt for {email}? Dette vil ugyldiggjøre den forrige invitasjonen.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Det oppstod en feil under fjerning av brukeren.",
|
||||
"userOrgRemoved": "Bruker fjernet",
|
||||
"userOrgRemovedDescription": "Brukeren {email} er fjernet fra organisasjonen.",
|
||||
"userQuestionOrgRemove": "Er du sikker på at du vil fjerne {email} fra organisasjonen?",
|
||||
"userQuestionOrgRemove": "Er du sikker på at du vil fjerne denne brukeren fra organisasjonen?",
|
||||
"userMessageOrgRemove": "Når denne brukeren er fjernet, vil de ikke lenger ha tilgang til organisasjonen. Du kan alltid invitere dem på nytt senere, men de vil måtte godta invitasjonen på nytt.",
|
||||
"userMessageOrgConfirm": "For å bekrefte, vennligst skriv inn navnet på brukeren nedenfor.",
|
||||
"userRemoveOrgConfirm": "Bekreft fjerning av bruker",
|
||||
"userRemoveOrg": "Fjern bruker fra organisasjon",
|
||||
"users": "Brukere",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Det oppstod en feil under tilordning av brukeren til rollen.",
|
||||
"userSaved": "Bruker lagret",
|
||||
"userSavedDescription": "Brukeren har blitt oppdatert.",
|
||||
"autoProvisioned": "Auto avlyst",
|
||||
"autoProvisionedDescription": "Tillat denne brukeren å bli automatisk administrert av en identitetsleverandør",
|
||||
"accessControlsDescription": "Administrer hva denne brukeren kan få tilgang til og gjøre i organisasjonen",
|
||||
"accessControlsSubmit": "Lagre tilgangskontroller",
|
||||
"roles": "Roller",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Opprettet",
|
||||
"proxyErrorInvalidHeader": "Ugyldig verdi for egendefinert vertsoverskrift. Bruk domenenavnformat, eller lagre tomt for å fjerne den egendefinerte vertsoverskriften.",
|
||||
"proxyErrorTls": "Ugyldig TLS-servernavn. Bruk domenenavnformat, eller la stå tomt for å fjerne TLS-servernavnet.",
|
||||
"proxyEnableSSL": "Aktiver SSL (https)",
|
||||
"proxyEnableSSL": "Aktiver SSL",
|
||||
"proxyEnableSSLDescription": "Aktiver SSL/TLS-kryptering for sikre HTTPS-tilkoblinger til dine mål.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Konfigurer mål",
|
||||
"targetErrorFetch": "Kunne ikke hente mål",
|
||||
"targetErrorFetchDescription": "Det oppsto en feil under henting av mål",
|
||||
"siteErrorFetch": "Klarte ikke å hente ressurs",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Sikker tilkoblings-konfigurasjon",
|
||||
"targetTlsSettingsDescription": "Konfigurer SSL/TLS-innstillinger for ressursen din",
|
||||
"targetTlsSettingsAdvanced": "Avanserte TLS-innstillinger",
|
||||
"targetTlsSni": "TLS Servernavn (SNI)",
|
||||
"targetTlsSni": "TLS servernavn",
|
||||
"targetTlsSniDescription": "TLS-servernavnet som skal brukes for SNI. La stå tomt for å bruke standardverdien.",
|
||||
"targetTlsSubmit": "Lagre innstillinger",
|
||||
"targets": "Målkonfigurasjon",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Behold tilkoblinger på samme bakend-mål gjennom hele sesjonen.",
|
||||
"methodSelect": "Velg metode",
|
||||
"targetSubmit": "Legg til mål",
|
||||
"targetNoOne": "Ingen mål. Legg til et mål ved hjelp av skjemaet.",
|
||||
"targetNoOne": "Denne ressursen har ikke noen mål. Legg til et mål for å konfigurere hvor du vil sende forespørsler til din backend.",
|
||||
"targetNoOneDescription": "Å legge til mer enn ett mål ovenfor vil aktivere lastbalansering.",
|
||||
"targetsSubmit": "Lagre mål",
|
||||
"addTarget": "Legg til mål",
|
||||
"targetErrorInvalidIp": "Ugyldig IP-adresse",
|
||||
"targetErrorInvalidIpDescription": "Skriv inn en gyldig IP-adresse eller vertsnavn",
|
||||
"targetErrorInvalidPort": "Ugyldig port",
|
||||
"targetErrorInvalidPortDescription": "Vennligst skriv inn et gyldig portnummer",
|
||||
"targetErrorNoSite": "Ingen nettsted valgt",
|
||||
"targetErrorNoSiteDescription": "Velg et nettsted for målet",
|
||||
"targetCreated": "Mål opprettet",
|
||||
"targetCreatedDescription": "Målet har blitt opprettet",
|
||||
"targetErrorCreate": "Kunne ikke opprette målet",
|
||||
"targetErrorCreateDescription": "Det oppstod en feil under oppretting av målet",
|
||||
"save": "Lagre",
|
||||
"proxyAdditional": "Ytterligere Proxy-innstillinger",
|
||||
"proxyAdditionalDescription": "Konfigurer hvordan ressursen din håndterer proxy-innstillinger",
|
||||
"proxyCustomHeader": "Tilpasset verts-header",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Ugyldig IP-adresseformat",
|
||||
"ipAddressErrorInvalidOctet": "Ugyldig IP-adresse-oktet",
|
||||
"path": "Sti",
|
||||
"matchPath": "Match sti",
|
||||
"ipAddressRange": "IP-område",
|
||||
"rulesErrorFetch": "Klarte ikke å hente regler",
|
||||
"rulesErrorFetchDescription": "Det oppsto en feil under henting av regler",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Server Admin - Pangolin",
|
||||
"licenseTierProfessional": "Profesjonell lisens",
|
||||
"licenseTierEnterprise": "Bedriftslisens",
|
||||
"licenseTierCommercial": "Kommersiell lisens",
|
||||
"licenseTierPersonal": "Personlig lisens",
|
||||
"licensed": "Lisensiert",
|
||||
"yes": "Ja",
|
||||
"no": "Nei",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Vis og administrer identitetsleverandører i systemet",
|
||||
"idpDeletedDescription": "Identitetsleverandør slettet vellykket",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Er du sikker på at du vil slette identitetsleverandøren {name} permanent?",
|
||||
"idpQuestionRemove": "Er du sikker på at du vil slette identitetsleverandøren permanent?",
|
||||
"idpMessageRemove": "Dette vil fjerne identitetsleverandøren og alle tilhørende konfigurasjoner. Brukere som autentiserer seg via denne leverandøren vil ikke lenger kunne logge inn.",
|
||||
"idpMessageConfirm": "For å bekrefte, vennligst skriv inn navnet på identitetsleverandøren nedenfor.",
|
||||
"idpConfirmDelete": "Bekreft Sletting av Identitetsleverandør",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Et visningsnavn for denne identitetsleverandøren",
|
||||
"idpAutoProvisionUsers": "Automatisk brukerklargjøring",
|
||||
"idpAutoProvisionUsersDescription": "Når aktivert, opprettes brukere automatisk i systemet ved første innlogging, med mulighet til å tilordne brukere til roller og organisasjoner.",
|
||||
"licenseBadge": "Profesjonell",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Leverandørtype",
|
||||
"idpTypeDescription": "Velg typen identitetsleverandør du ønsker å konfigurere",
|
||||
"idpOidcConfigure": "OAuth2/OIDC-konfigurasjon",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Sjekk e-posten din for tilbakestillingskoden.",
|
||||
"passwordNew": "Nytt passord",
|
||||
"passwordNewConfirm": "Bekreft nytt passord",
|
||||
"changePassword": "Endre passord",
|
||||
"changePasswordDescription": "Oppdater passordet for din konto",
|
||||
"oldPassword": "Nåværende passord",
|
||||
"newPassword": "Nytt passord",
|
||||
"confirmNewPassword": "Bekreft nytt passord",
|
||||
"changePasswordError": "Kunne ikke endre passord",
|
||||
"changePasswordErrorDescription": "Det oppstod en feil under endring av passordet",
|
||||
"changePasswordSuccess": "Passordet er endret",
|
||||
"changePasswordSuccessDescription": "Ditt passord ble oppdatert",
|
||||
"passwordExpiryRequired": "Passordutløp kreves",
|
||||
"passwordExpiryDescription": "Denne organisasjonen krever at du bytter passord hver {maxDays} dag.",
|
||||
"changePasswordNow": "Bytt passord nå",
|
||||
"pincodeAuth": "Autentiseringskode",
|
||||
"pincodeSubmit2": "Send inn kode",
|
||||
"passwordResetSubmit": "Be om tilbakestilling",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Profesjonell utgave påkrevd",
|
||||
"licenseTierProfessionalRequiredDescription": "Denne funksjonen er kun tilgjengelig i den profesjonelle utgaven.",
|
||||
"actionGetOrg": "Hent organisasjon",
|
||||
"updateOrgUser": "Oppdater org.bruker",
|
||||
"createOrgUser": "Opprett Org bruker",
|
||||
"actionUpdateOrg": "Oppdater organisasjon",
|
||||
"actionUpdateUser": "Oppdater bruker",
|
||||
"actionGetUser": "Hent bruker",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Slett område",
|
||||
"actionGetSite": "Hent område",
|
||||
"actionListSites": "List opp områder",
|
||||
"actionApplyBlueprint": "Bruk blåkopi",
|
||||
"setupToken": "Oppsetttoken",
|
||||
"setupTokenDescription": "Skriv inn oppsetttoken fra serverkonsollen.",
|
||||
"setupTokenRequired": "Oppsetttoken er nødvendig",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Navigasjonsmeny",
|
||||
"navbarDescription": "Hovednavigasjonsmeny for applikasjonen",
|
||||
"navbarDocsLink": "Dokumentasjon",
|
||||
"commercialEdition": "Kommersiell utgave",
|
||||
"otpErrorEnable": "Kunne ikke aktivere 2FA",
|
||||
"otpErrorEnableDescription": "En feil oppstod under aktivering av 2FA",
|
||||
"otpSetupCheckCode": "Vennligst skriv inn en 6-sifret kode",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Alle brukere",
|
||||
"sidebarIdentityProviders": "Identitetsleverandører",
|
||||
"sidebarLicense": "Lisens",
|
||||
"sidebarClients": "Klienter (Beta)",
|
||||
"sidebarClients": "Klienter",
|
||||
"sidebarDomains": "Domener",
|
||||
"enableDockerSocket": "Aktiver Docker Socket",
|
||||
"enableDockerSocketDescription": "Aktiver Docker Socket-oppdagelse for å fylle ut containerinformasjon. Socket-stien må oppgis til Newt.",
|
||||
"sidebarBluePrints": "Tegninger",
|
||||
"blueprints": "Tegninger",
|
||||
"blueprintsDescription": "Bruk deklarative konfigurasjoner og vis tidligere kjøringer",
|
||||
"blueprintAdd": "Legg til blåkopi",
|
||||
"blueprintGoBack": "Se alle blåkopier",
|
||||
"blueprintCreate": "Opprette mal",
|
||||
"blueprintCreateDescription2": "Følg trinnene nedenfor for å opprette og bruke en ny plantegning",
|
||||
"blueprintDetails": "Blåkopi detaljer",
|
||||
"blueprintDetailsDescription": "Se resultatet av den påførte blåkopien og alle feil som oppstod",
|
||||
"blueprintInfo": "Blåkopi informasjon",
|
||||
"message": "Melding",
|
||||
"blueprintContentsDescription": "Definer innhold av YAML som beskriver din infrastruktur",
|
||||
"blueprintErrorCreateDescription": "Det oppstod en feil da plantegningen ble lagt til",
|
||||
"blueprintErrorCreate": "Feil ved opprettelse av plantegning",
|
||||
"searchBlueprintProgress": "Søk etter plantegninger...",
|
||||
"appliedAt": "Anvendt på",
|
||||
"source": "Kilde",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Lær mer",
|
||||
"viewDockerContainers": "Vis Docker-containere",
|
||||
"containersIn": "Containere i {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Opprett domene",
|
||||
"domainCreatedDescription": "Domene ble opprettet",
|
||||
"domainDeletedDescription": "Domene ble slettet",
|
||||
"domainQuestionRemove": "Er du sikker på at du vil fjerne domenet {domain} fra kontoen din?",
|
||||
"domainQuestionRemove": "Er du sikker på at du vil fjerne domenet fra kontoen din?",
|
||||
"domainMessageRemove": "Når domenet er fjernet, vil det ikke lenger være knyttet til kontoen din.",
|
||||
"domainMessageConfirm": "For å bekrefte, vennligst skriv inn domenenavnet nedenfor.",
|
||||
"domainConfirmDelete": "Bekreft sletting av domene",
|
||||
"domainDelete": "Slett domene",
|
||||
"domain": "Domene",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Oppdatering tilgjengelig",
|
||||
"newtUpdateAvailableInfo": "En ny versjon av Newt er tilgjengelig. Vennligst oppdater til den nyeste versjonen for den beste opplevelsen.",
|
||||
"domainPickerEnterDomain": "Domene",
|
||||
"domainPickerPlaceholder": "minapp.eksempel.com, api.v1.mittdomene.com, eller bare minapp",
|
||||
"domainPickerPlaceholder": "minapp.eksempel.no",
|
||||
"domainPickerDescription": "Skriv inn hele domenet til ressursen for å se tilgjengelige alternativer.",
|
||||
"domainPickerDescriptionSaas": "Skriv inn et fullt domene, underdomene eller bare et navn for å se tilgjengelige alternativer",
|
||||
"domainPickerTabAll": "Alle",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Underdomene: {subdomain}",
|
||||
"domainPickerNamespace": "Navnerom: {namespace}",
|
||||
"domainPickerShowMore": "Vis mer",
|
||||
"regionSelectorTitle": "Velg Region",
|
||||
"regionSelectorInfo": "Å velge en region hjelper oss med å gi bedre ytelse for din lokasjon. Du trenger ikke være i samme region som serveren.",
|
||||
"regionSelectorPlaceholder": "Velg en region",
|
||||
"regionSelectorComingSoon": "Kommer snart",
|
||||
"billingLoadingSubscription": "Laster abonnement...",
|
||||
"billingFreeTier": "Gratis nivå",
|
||||
"billingWarningOverLimit": "Advarsel: Du har overskredet en eller flere bruksgrenser. Nettstedene dine vil ikke koble til før du endrer abonnementet ditt eller justerer bruken.",
|
||||
"billingUsageLimitsOverview": "Oversikt over bruksgrenser",
|
||||
"billingMonitorUsage": "Overvåk bruken din i forhold til konfigurerte grenser. Hvis du trenger økte grenser, vennligst kontakt support@pangolin.net.",
|
||||
"billingDataUsage": "Databruk",
|
||||
"billingOnlineTime": "Online tid for nettsteder",
|
||||
"billingUsers": "Aktive brukere",
|
||||
"billingDomains": "Aktive domener",
|
||||
"billingRemoteExitNodes": "Aktive selvstyrte noder",
|
||||
"billingNoLimitConfigured": "Ingen grense konfigurert",
|
||||
"billingEstimatedPeriod": "Estimert faktureringsperiode",
|
||||
"billingIncludedUsage": "Inkludert Bruk",
|
||||
"billingIncludedUsageDescription": "Bruk inkludert i din nåværende abonnementsplan",
|
||||
"billingFreeTierIncludedUsage": "Gratis nivå bruksgrenser",
|
||||
"billingIncluded": "inkludert",
|
||||
"billingEstimatedTotal": "Estimert Totalt:",
|
||||
"billingNotes": "Notater",
|
||||
"billingEstimateNote": "Dette er et estimat basert på din nåværende bruk.",
|
||||
"billingActualChargesMayVary": "Faktiske kostnader kan variere.",
|
||||
"billingBilledAtEnd": "Du vil bli fakturert ved slutten av faktureringsperioden.",
|
||||
"billingModifySubscription": "Endre abonnement",
|
||||
"billingStartSubscription": "Start abonnement",
|
||||
"billingRecurringCharge": "Innkommende Avgift",
|
||||
"billingManageSubscriptionSettings": "Administrer abonnementsinnstillinger og preferanser",
|
||||
"billingNoActiveSubscription": "Du har ikke et aktivt abonnement. Start abonnementet ditt for å øke bruksgrensene.",
|
||||
"billingFailedToLoadSubscription": "Klarte ikke å laste abonnement",
|
||||
"billingFailedToLoadUsage": "Klarte ikke å laste bruksdata",
|
||||
"billingFailedToGetCheckoutUrl": "Mislyktes å få betalingslenke",
|
||||
"billingPleaseTryAgainLater": "Vennligst prøv igjen senere.",
|
||||
"billingCheckoutError": "Kasserror",
|
||||
"billingFailedToGetPortalUrl": "Mislyktes å hente portal URL",
|
||||
"billingPortalError": "Portalfeil",
|
||||
"billingDataUsageInfo": "Du er ladet for all data som overføres gjennom dine sikre tunneler når du er koblet til skyen. Dette inkluderer både innkommende og utgående trafikk på alle dine nettsteder. Når du når grensen din, vil sidene koble fra til du oppgraderer planen eller reduserer bruken. Data belastes ikke ved bruk av EK-grupper.",
|
||||
"billingOnlineTimeInfo": "Du er ladet på hvor lenge sidene dine forblir koblet til skyen. For eksempel tilsvarer 44,640 minutter ett nettsted som går 24/7 i en hel måned. Når du når grensen din, vil sidene koble fra til du oppgraderer planen eller reduserer bruken. Tid belastes ikke når du bruker noder.",
|
||||
"billingUsersInfo": "Du belastes for hver bruker i organisasjonen din. Faktureringen beregnes daglig basert på antall aktive brukerkontoer i organisasjonen din.",
|
||||
"billingDomainInfo": "Du belastes for hvert domene i organisasjonen din. Faktureringen beregnes daglig basert på antall aktive domenekontoer i organisasjonen din.",
|
||||
"billingRemoteExitNodesInfo": "Du belastes for hver styrt node i organisasjonen din. Faktureringen beregnes daglig basert på antall aktive styrte noder i organisasjonen din.",
|
||||
"domainNotFound": "Domene ikke funnet",
|
||||
"domainNotFoundDescription": "Denne ressursen er deaktivert fordi domenet ikke lenger eksisterer i systemet vårt. Vennligst angi et nytt domene for denne ressursen.",
|
||||
"failed": "Mislyktes",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Det oppstod et problem med å bruke sikkerhetsnøkkelen din. Vennligst prøv igjen.",
|
||||
"twoFactorRequired": "Tofaktorautentisering er påkrevd for å registrere en sikkerhetsnøkkel.",
|
||||
"twoFactor": "Tofaktorautentisering",
|
||||
"twoFactorAuthentication": "To-faktor autentisering",
|
||||
"twoFactorDescription": "Denne organisasjonen krever to-faktor-autentisering.",
|
||||
"enableTwoFactor": "Aktiver to-faktor autentisering",
|
||||
"organizationSecurityPolicy": "Retningslinjer for organisasjons sikkerhet",
|
||||
"organizationSecurityPolicyDescription": "Denne organisasjonen har sikkerhetskrav som må oppfylles før du får tilgang til den",
|
||||
"securityRequirements": "Krav Til Sikkerhet",
|
||||
"allRequirementsMet": "Alle krav er oppfylt",
|
||||
"completeRequirementsToContinue": "Fullfør kravene nedenfor for å fortsette tilgangen til denne organisasjonen",
|
||||
"youCanNowAccessOrganization": "Du har nå tilgang til denne organisasjonen",
|
||||
"reauthenticationRequired": "Økt lengde",
|
||||
"reauthenticationDescription": "Denne organisasjonen krever at du logger på alle {maxDays} dager.",
|
||||
"reauthenticationDescriptionHours": "Denne organisasjonen krever at du logger inn hver {maxHours} time.",
|
||||
"reauthenticateNow": "Logg inn igjen",
|
||||
"adminEnabled2FaOnYourAccount": "Din administrator har aktivert tofaktorautentisering for {email}. Vennligst fullfør oppsettsprosessen for å fortsette.",
|
||||
"continueToApplication": "Fortsett til applikasjonen",
|
||||
"securityKeyAdd": "Legg til sikkerhetsnøkkel",
|
||||
"securityKeyRegisterTitle": "Registrer ny sikkerhetsnøkkel",
|
||||
"securityKeyRegisterDescription": "Koble til sikkerhetsnøkkelen og skriv inn et navn for å identifisere den",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "DNS-endringer kan ta litt tid å propagere over internett. Dette kan ta fra noen få minutter til 48 timer, avhengig av din DNS-leverandør og TTL-innstillinger.",
|
||||
"resourcePortRequired": "Portnummer er påkrevd for ikke-HTTP-ressurser",
|
||||
"resourcePortNotAllowed": "Portnummer skal ikke angis for HTTP-ressurser",
|
||||
"billingPricingCalculatorLink": "Pris Kalkulator",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Jeg godtar",
|
||||
"termsOfService": "brukervilkårene",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Ekstern proxy aktivert",
|
||||
"addNewTarget": "Legg til nytt mål",
|
||||
"targetsList": "Liste over mål",
|
||||
"advancedMode": "Avansert modus",
|
||||
"targetErrorDuplicateTargetFound": "Duplikat av mål funnet",
|
||||
"healthCheckHealthy": "Sunn",
|
||||
"healthCheckUnhealthy": "Usunn",
|
||||
"healthCheckUnknown": "Ukjent",
|
||||
"healthCheck": "Helsekontroll",
|
||||
"configureHealthCheck": "Konfigurer Helsekontroll",
|
||||
"configureHealthCheckDescription": "Sett opp helsekontroll for {target}",
|
||||
"enableHealthChecks": "Aktiver Helsekontroller",
|
||||
"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",
|
||||
"healthCheckPath": "Sti",
|
||||
"healthHostname": "IP / Vert",
|
||||
"healthPort": "Port",
|
||||
"healthCheckPathDescription": "Stien for å sjekke helsestatus.",
|
||||
"healthyIntervalSeconds": "Sunt intervall",
|
||||
"unhealthyIntervalSeconds": "Usunt intervall",
|
||||
"IntervalSeconds": "Sunt intervall",
|
||||
"timeoutSeconds": "Tidsavbrudd",
|
||||
"timeIsInSeconds": "Tid er i sekunder",
|
||||
"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.",
|
||||
"customHeaders": "Egendefinerte topptekster",
|
||||
"customHeadersDescription": "Overskrifter som er adskilt med linje: Overskriftsnavn: verdi",
|
||||
"headersValidationError": "Topptekst må være i formatet: header-navn: verdi.",
|
||||
"saveHealthCheck": "Lagre Helsekontroll",
|
||||
"healthCheckSaved": "Helsekontroll Lagret",
|
||||
"healthCheckSavedDescription": "Helsekontrollkonfigurasjonen ble lagret",
|
||||
"healthCheckError": "Helsekontrollfeil",
|
||||
"healthCheckErrorDescription": "Det oppstod en feil under lagring av helsekontrollkonfigurasjonen",
|
||||
"healthCheckPathRequired": "Helsekontrollsti er påkrevd",
|
||||
"healthCheckMethodRequired": "HTTP-metode er påkrevd",
|
||||
"healthCheckIntervalMin": "Sjekkeintervallet må være minst 5 sekunder",
|
||||
"healthCheckTimeoutMin": "Timeout må være minst 1 sekund",
|
||||
"healthCheckRetryMin": "Forsøk på nytt må være minst 1",
|
||||
"httpMethod": "HTTP-metode",
|
||||
"selectHttpMethod": "Velg HTTP-metode",
|
||||
"domainPickerSubdomainLabel": "Underdomene",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Skriv inn et underdomene for å søke og velge blant tilgjengelige gratis domener.",
|
||||
"domainPickerFreeDomains": "Gratis domener",
|
||||
"domainPickerSearchForAvailableDomains": "Søk etter tilgjengelige domener",
|
||||
"domainPickerNotWorkSelfHosted": "Merk: Gratis tilbudte domener er ikke tilgjengelig for selv-hostede instanser akkurat nå.",
|
||||
"resourceDomain": "Domene",
|
||||
"resourceEditDomain": "Rediger domene",
|
||||
"siteName": "Områdenavn",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protokoll",
|
||||
"editInternalResourceDialogSitePort": "Områdeport",
|
||||
"editInternalResourceDialogTargetConfiguration": "Målkonfigurasjon",
|
||||
"editInternalResourceDialogDestinationIP": "Destinasjons-IP",
|
||||
"editInternalResourceDialogDestinationPort": "Destinasjonsport",
|
||||
"editInternalResourceDialogCancel": "Avbryt",
|
||||
"editInternalResourceDialogSaveResource": "Lagre ressurs",
|
||||
"editInternalResourceDialogSuccess": "Suksess",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Områdeport",
|
||||
"createInternalResourceDialogSitePortDescription": "Bruk denne porten for å få tilgang til ressursen på området når du er tilkoblet med en klient.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Målkonfigurasjon",
|
||||
"createInternalResourceDialogDestinationIP": "Destinasjons-IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "IP-adressen til ressursen på områdets nettverk.",
|
||||
"createInternalResourceDialogDestinationPort": "Destinasjonsport",
|
||||
"createInternalResourceDialogDestinationIPDescription": "IP eller vertsnavn til ressursen på nettstedets nettverk.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "Porten på destinasjons-IP-en der ressursen kan nås.",
|
||||
"createInternalResourceDialogCancel": "Avbryt",
|
||||
"createInternalResourceDialogCreateResource": "Opprett ressurs",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Feil ved automatisk innlogging",
|
||||
"autoLoginErrorNoRedirectUrl": "Ingen omdirigerings-URL mottatt fra identitetsleverandøren.",
|
||||
"autoLoginErrorGeneratingUrl": "Kunne ikke generere autentiserings-URL.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Eksterne Noder",
|
||||
"remoteExitNodeDescription": "Selvbetjent én eller flere eksterne noder for å utvide nettverkstilkoblingen din og redusere avhengighet på skyen",
|
||||
"remoteExitNodes": "Noder",
|
||||
"searchRemoteExitNodes": "Søk noder...",
|
||||
"remoteExitNodeAdd": "Legg til Node",
|
||||
"remoteExitNodeErrorDelete": "Feil ved sletting av node",
|
||||
"remoteExitNodeQuestionRemove": "Er du sikker på at du vil fjerne noden fra organisasjonen?",
|
||||
"remoteExitNodeMessageRemove": "Når noden er fjernet, vil ikke lenger være tilgjengelig.",
|
||||
"remoteExitNodeConfirmDelete": "Bekreft sletting av Node",
|
||||
"remoteExitNodeDelete": "Slett Node",
|
||||
"sidebarRemoteExitNodes": "Eksterne Noder",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Opprett node",
|
||||
"description": "Opprett en ny node for å utvide nettverkstilkoblingen din",
|
||||
"viewAllButton": "Vis alle koder",
|
||||
"strategy": {
|
||||
"title": "Opprettelsesstrategi",
|
||||
"description": "Velg denne for manuelt å konfigurere noden eller generere nye legitimasjoner.",
|
||||
"adopt": {
|
||||
"title": "Adopter Node",
|
||||
"description": "Velg dette hvis du allerede har legitimasjon til noden."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Generer Nøkler",
|
||||
"description": "Velg denne hvis du vil generere nye nøkler for noden"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Adopter Eksisterende Node",
|
||||
"description": "Skriv inn opplysningene til den eksisterende noden du vil adoptere",
|
||||
"nodeIdLabel": "Node-ID",
|
||||
"nodeIdDescription": "ID-en til den eksisterende noden du vil adoptere",
|
||||
"secretLabel": "Sikkerhetsnøkkel",
|
||||
"secretDescription": "Den hemmelige nøkkelen til en eksisterende node",
|
||||
"submitButton": "Adopter Node"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Genererte Legitimasjoner",
|
||||
"description": "Bruk disse genererte opplysningene for å konfigurere noden din",
|
||||
"nodeIdTitle": "Node-ID",
|
||||
"secretTitle": "Sikkerhet",
|
||||
"saveCredentialsTitle": "Legg til Legitimasjoner til Config",
|
||||
"saveCredentialsDescription": "Legg til disse legitimasjonene i din selv-hostede Pangolin node-konfigurasjonsfil for å fullføre koblingen.",
|
||||
"submitButton": "Opprett node"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "Node ID og Secret er påkrevd når du adopterer en eksisterende node"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Feil ved lasting av standarder",
|
||||
"defaultsNotLoaded": "Standarder ikke lastet",
|
||||
"createFailed": "Kan ikke opprette node"
|
||||
},
|
||||
"success": {
|
||||
"created": "Node opprettet"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Noden utvalg",
|
||||
"remoteExitNodeSelectionDescription": "Velg en node for å sende trafikk gjennom for dette lokale nettstedet",
|
||||
"remoteExitNodeRequired": "En node må velges for lokale nettsteder",
|
||||
"noRemoteExitNodesAvailable": "Ingen noder tilgjengelig",
|
||||
"noRemoteExitNodesAvailableDescription": "Ingen noder er tilgjengelige for denne organisasjonen. Opprett en node først for å bruke lokale nettsteder.",
|
||||
"exitNode": "Utgangsnode",
|
||||
"country": "Land",
|
||||
"rulesMatchCountry": "For tiden basert på kilde IP",
|
||||
"managedSelfHosted": {
|
||||
"title": "Administrert selv-hostet",
|
||||
"description": "Sikre og lavvedlikeholdsservere, selvbetjente Pangolin med ekstra klokker, og understell",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Konverter denne noden til manuelt bruk"
|
||||
},
|
||||
"internationaldomaindetected": "Internasjonalt domene oppdaget",
|
||||
"willbestoredas": "Vil bli lagret som:"
|
||||
}
|
||||
"willbestoredas": "Vil bli lagret som:",
|
||||
"roleMappingDescription": "Bestem hvordan roller tilordnes brukere når innloggingen er aktivert når autog-rapportering er aktivert.",
|
||||
"selectRole": "Velg en rolle",
|
||||
"roleMappingExpression": "Uttrykk",
|
||||
"selectRolePlaceholder": "Velg en rolle",
|
||||
"selectRoleDescription": "Velg en rolle å tilordne alle brukere fra denne identitet leverandøren",
|
||||
"roleMappingExpressionDescription": "Skriv inn et JMESPath uttrykk for å hente rolleinformasjon fra ID-nøkkelen",
|
||||
"idpTenantIdRequired": "Bedriftens ID kreves",
|
||||
"invalidValue": "Ugyldig verdi",
|
||||
"idpTypeLabel": "Identitet leverandør type",
|
||||
"roleMappingExpressionPlaceholder": "F.eks. inneholder(grupper, 'admin') && 'Admin' ⋅'Medlem'",
|
||||
"idpGoogleConfiguration": "Google Konfigurasjon",
|
||||
"idpGoogleConfigurationDescription": "Konfigurer din Google OAuth2 legitimasjon",
|
||||
"idpGoogleClientIdDescription": "Din Google OAuth2-klient-ID",
|
||||
"idpGoogleClientSecretDescription": "Google OAuth2-klienten din hemmelig",
|
||||
"idpAzureConfiguration": "Azure Entra ID konfigurasjon",
|
||||
"idpAzureConfigurationDescription": "Konfigurere din Azure Entra ID OAuth2 legitimasjon",
|
||||
"idpTenantId": "Leietaker-ID",
|
||||
"idpTenantIdPlaceholder": "din-tenant-id",
|
||||
"idpAzureTenantIdDescription": "Din Azure leie-ID (funnet i Azure Active Directory-oversikten)",
|
||||
"idpAzureClientIdDescription": "Din Azure App registrerings klient-ID",
|
||||
"idpAzureClientSecretDescription": "Din Azure App registrerings klient hemmelig",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Google Konfigurasjon",
|
||||
"idpAzureConfigurationTitle": "Azure Entra ID konfigurasjon",
|
||||
"idpTenantIdLabel": "Leietaker-ID",
|
||||
"idpAzureClientIdDescription2": "Din Azure App registrerings klient-ID",
|
||||
"idpAzureClientSecretDescription2": "Din Azure App registrerings klient hemmelig",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC leverandør",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Subnett",
|
||||
"subnetDescription": "Undernettverket for denne organisasjonens nettverkskonfigurasjon.",
|
||||
"authPage": "Autentiseringsside",
|
||||
"authPageDescription": "Konfigurer autoriseringssiden for din organisasjon",
|
||||
"authPageDomain": "Autentiseringsside domene",
|
||||
"noDomainSet": "Ingen domene valgt",
|
||||
"changeDomain": "Endre domene",
|
||||
"selectDomain": "Velg domene",
|
||||
"restartCertificate": "Omstart sertifikat",
|
||||
"editAuthPageDomain": "Rediger auth sidedomene",
|
||||
"setAuthPageDomain": "Angi autoriseringsside domene",
|
||||
"failedToFetchCertificate": "Kunne ikke hente sertifikat",
|
||||
"failedToRestartCertificate": "Kan ikke starte sertifikat",
|
||||
"addDomainToEnableCustomAuthPages": "Legg til et domene for å aktivere egendefinerte autentiseringssider for organisasjonen din",
|
||||
"selectDomainForOrgAuthPage": "Velg et domene for organisasjonens autentiseringsside",
|
||||
"domainPickerProvidedDomain": "Gitt domene",
|
||||
"domainPickerFreeProvidedDomain": "Gratis oppgitt domene",
|
||||
"domainPickerVerified": "Bekreftet",
|
||||
"domainPickerUnverified": "Uverifisert",
|
||||
"domainPickerInvalidSubdomainStructure": "Dette underdomenet inneholder ugyldige tegn eller struktur. Det vil automatisk bli utsatt når du lagrer.",
|
||||
"domainPickerError": "Feil",
|
||||
"domainPickerErrorLoadDomains": "Kan ikke laste organisasjonens domener",
|
||||
"domainPickerErrorCheckAvailability": "Kunne ikke kontrollere domenetilgjengelighet",
|
||||
"domainPickerInvalidSubdomain": "Ugyldig underdomene",
|
||||
"domainPickerInvalidSubdomainRemoved": "Inndata \"{sub}\" ble fjernet fordi det ikke er gyldig.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" kunne ikke gjøres gyldig for {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Underdomenet som ble sanivert",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" var korrigert til \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Logg inn på din organisasjon",
|
||||
"orgAuthChooseIdpDescription": "Velg din identitet leverandør for å fortsette",
|
||||
"orgAuthNoIdpConfigured": "Denne organisasjonen har ikke noen identitetstjeneste konfigurert. Du kan i stedet logge inn med Pangolin identiteten din.",
|
||||
"orgAuthSignInWithPangolin": "Logg inn med Pangolin",
|
||||
"subscriptionRequiredToUse": "Et abonnement er påkrevd for å bruke denne funksjonen.",
|
||||
"idpDisabled": "Identitetsleverandører er deaktivert.",
|
||||
"orgAuthPageDisabled": "Informasjons-siden for organisasjon er deaktivert.",
|
||||
"domainRestartedDescription": "Domene-verifiseringen ble startet på nytt",
|
||||
"resourceAddEntrypointsEditFile": "Rediger fil: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Rediger fil: docker-compose.yml",
|
||||
"emailVerificationRequired": "E-postbekreftelse er nødvendig. Logg inn på nytt via {dashboardUrl}/auth/login og fullfør dette trinnet. Kom deretter tilbake her.",
|
||||
"twoFactorSetupRequired": "To-faktor autentiseringsoppsett er nødvendig. Vennligst logg inn igjen via {dashboardUrl}/auth/login og fullfør dette steget. Kom deretter tilbake her.",
|
||||
"additionalSecurityRequired": "Ekstra sikkerhet kreves",
|
||||
"organizationRequiresAdditionalSteps": "Denne organisasjonen krever ytterligere sikkerhetstrinn før du får tilgang til ressurser.",
|
||||
"completeTheseSteps": "Fullfør disse trinnene",
|
||||
"enableTwoFactorAuthentication": "Aktiver to-faktor autentisering",
|
||||
"completeSecuritySteps": "Fullfør sikkerhetstrinnene",
|
||||
"securitySettings": "Sikkerhet innstillinger",
|
||||
"securitySettingsDescription": "Konfigurere sikkerhetspolicyer for din organisasjon",
|
||||
"requireTwoFactorForAllUsers": "Krev to-faktor autentisering for alle brukere",
|
||||
"requireTwoFactorDescription": "Når aktivert må alle interne brukere i denne organisasjonen ha to-faktorautentisering aktivert for å få tilgang til organisasjonen.",
|
||||
"requireTwoFactorDisabledDescription": "Denne funksjonen krever en gyldig lisens (Enterprise) eller aktivt abonnement (SaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "Du må aktivere to-faktor-autentisering for din konto før det håndheves for alle brukere",
|
||||
"maxSessionLength": "Maksimal øktlengde",
|
||||
"maxSessionLengthDescription": "Angi maksimal varighet for brukerøkter. Etter denne gangen må brukerne logge inn på nytt.",
|
||||
"maxSessionLengthDisabledDescription": "Denne funksjonen krever en gyldig lisens (Enterprise) eller aktivt abonnement (SaaS)",
|
||||
"selectSessionLength": "Velg øktlengde",
|
||||
"unenforced": "Tvungen",
|
||||
"1Hour": "1 time",
|
||||
"3Hours": "3 timer",
|
||||
"6Hours": "6 timer",
|
||||
"12Hours": "12 timer",
|
||||
"1DaySession": "1 dag",
|
||||
"3Days": "3 dager",
|
||||
"7Days": "7 dager",
|
||||
"14Days": "14 dager",
|
||||
"30DaysSession": "30 dager",
|
||||
"90DaysSession": "90 dager",
|
||||
"180DaysSession": "180 dager",
|
||||
"passwordExpiryDays": "Passord utløper",
|
||||
"editPasswordExpiryDescription": "Angi antall dager før brukere må endre passordet sitt.",
|
||||
"selectPasswordExpiry": "Velg passordutløp",
|
||||
"30Days": "30 dager",
|
||||
"1Day": "1 dag",
|
||||
"60Days": "60 dager",
|
||||
"90Days": "90 dager",
|
||||
"180Days": "180 dager",
|
||||
"1Year": "1 år",
|
||||
"subscriptionBadge": "Abonnement kreves",
|
||||
"securityPolicyChangeWarning": "Sikkerhetsregler forandring advarsel",
|
||||
"securityPolicyChangeDescription": "Du er i ferd med å endre innstillingene for sikkerhetspolicy. Etter å ha spart må du kanskje gjenopplogge deg på for å oppfylle disse policyoppdateringene. Alle brukere som ikke samsvarer vil også måtte autentisere.",
|
||||
"securityPolicyChangeConfirmMessage": "Jeg bekrefter",
|
||||
"securityPolicyChangeWarningText": "Dette vil påvirke alle brukere i organisasjonen",
|
||||
"authPageErrorUpdateMessage": "Det oppstod en feil under oppdatering av innstillingene for godkjenningssiden",
|
||||
"authPageErrorUpdate": "Kunne ikke oppdatere autoriseringssiden",
|
||||
"authPageUpdated": "Godkjenningsside oppdatert",
|
||||
"healthCheckNotAvailable": "Lokal",
|
||||
"rewritePath": "Omskriv sti",
|
||||
"rewritePathDescription": "Valgfritt omskrive stien før videresending til målet.",
|
||||
"continueToApplication": "Fortsett til applikasjonen",
|
||||
"checkingInvite": "Sjekker invitasjon",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Fjern topptekst Auth",
|
||||
"resourceHeaderAuthRemoveDescription": "Topplinje autentisering fjernet.",
|
||||
"resourceErrorHeaderAuthRemove": "Kunne ikke fjerne topptekst autentisering",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Kunne ikke fjerne topptekst autentisering for ressursen.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Topplinje autentisering aktivert",
|
||||
"resourceHeaderAuthProtectionDisabled": "Topplinje autentisering deaktivert",
|
||||
"headerAuthRemove": "Fjern topptekst Auth",
|
||||
"headerAuthAdd": "Legg til topptekst godkjenning",
|
||||
"resourceErrorHeaderAuthSetup": "Kunne ikke sette topptekst autentisering",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Kunne ikke sette topplinje autentisering for ressursen.",
|
||||
"resourceHeaderAuthSetup": "Header godkjenningssett var vellykket",
|
||||
"resourceHeaderAuthSetupDescription": "Topplinje autentisering har blitt lagret.",
|
||||
"resourceHeaderAuthSetupTitle": "Angi topptekst godkjenning",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Angi grunnleggende auth legitimasjon (brukernavn og passord) for å beskytte denne ressursen med HTTP Header autentisering. Tilgang til det ved hjelp av formatet https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Angi topptekst godkjenning",
|
||||
"actionSetResourceHeaderAuth": "Angi topptekst godkjenning",
|
||||
"enterpriseEdition": "Enterprise Edition",
|
||||
"unlicensed": "Ikke lisensiert",
|
||||
"beta": "beta",
|
||||
"manageClients": "Administrer klienter",
|
||||
"manageClientsDescription": "Klienter er enheter som kan koble seg til nettstedet ditt",
|
||||
"licenseTableValidUntil": "Gyldig til",
|
||||
"saasLicenseKeysSettingsTitle": "Bedriftstillatelse Lisenser",
|
||||
"saasLicenseKeysSettingsDescription": "Generer og administrer Enterprise lisensnøkler for selvbetjente Pangolin forekomster",
|
||||
"sidebarEnterpriseLicenses": "Lisenser",
|
||||
"generateLicenseKey": "Generer lisensnøkkel",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Vennligst skriv inn en gyldig e-postadresse",
|
||||
"useCaseTypeRequired": "Vennligst velg en bruk sakstype",
|
||||
"firstNameRequired": "Fornavn er påkrevd",
|
||||
"lastNameRequired": "Etternavn er påkrevd",
|
||||
"primaryUseRequired": "Beskriv din primære bruk",
|
||||
"jobTitleRequiredBusiness": "Jobbtittel er påkrevd for forretningsbruk",
|
||||
"industryRequiredBusiness": "Næringslivet må til forretningsbruk",
|
||||
"stateProvinceRegionRequired": "Stat/provins/region kreves",
|
||||
"postalZipCodeRequired": "Postnummer er påkrevd",
|
||||
"companyNameRequiredBusiness": "Firmanavn er påkrevd for bedriftens bruk",
|
||||
"countryOfResidenceRequiredBusiness": "Land som skal oppholde seg er nødvendig for bruk til forretningsdrift",
|
||||
"countryRequiredPersonal": "Land er påkrevd for personlig bruk",
|
||||
"agreeToTermsRequired": "Du må godta vilkårene",
|
||||
"complianceConfirmationRequired": "Du må bekrefte at du overholder Fossorial Kommersiell lisens"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Personlig bruk",
|
||||
"description": "For enkeltpersoner, ikke-kommersiell bruk som læring, personlige prosjekter eller eksperimentering."
|
||||
},
|
||||
"business": {
|
||||
"title": "Forretningsmessig bruk",
|
||||
"description": "Til bruk innenfor organisasjoner eller virksomheter eller forretningsmessige inntekter eller aktiviteter."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "E-post & lisenstype",
|
||||
"description": "Skriv inn e-postadressen din og velg lisenstypen din"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Personlig Informasjon",
|
||||
"description": "Fortell oss om deg selv"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Kontakt Informasjon",
|
||||
"description": "Dine kontaktopplysninger"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Vilkår og generere",
|
||||
"description": "Se gjennom og godta vilkårene for å generere lisensen"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Bruk utlevering",
|
||||
"description": "Velg lisensnivået som reflekterer nøyaktig din tiltenkte bruk. Personlige lisenser tillater fri bruk av programvare for enkelte, ikke-kommersielle eller småskala kommersielle aktiviteter, med en årlig brutto inntekt på under 100 000 amerikanske dollar. All bruk ut over disse grensene – inkludert bruk innenfor en virksomhet, organisasjon eller andre inntekter miljø - krever en gyldig Enterprise lisens og betaling av gjeldende lisensavgift. Alle brukere, enten personlig eller Enterprise, må overholde de kommersielle tillatelsene på Fossorial."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Informasjon om prøveperiode",
|
||||
"description": "Denne lisensnøkkelen tillater funksjoner i Enterprise for en 7-dagers evalueringsperiode. Fortsatt tilgang til betalt funksjoner utenfor evalueringsperioden krever aktivering under en gyldig Personlig eller Enterprise License. For Enterprise licensing, kontakt sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Bruker du Pangolin for personlig eller forretningsbruk?",
|
||||
"firstName": "Fornavn",
|
||||
"lastName": "Etternavn (Automatic Translation)",
|
||||
"jobTitle": "Jobb tittel",
|
||||
"primaryUseQuestion": "Hva planlegger du først og fremst å bruke Pangolin for?",
|
||||
"industryQuestion": "Hva er din industri?",
|
||||
"prospectiveUsersQuestion": "Hvor mange prospektive brukere forventer du å ha?",
|
||||
"prospectiveSitesQuestion": "Hvor mange prospektive nettsteder (tunnels) forventer du å ha?",
|
||||
"companyName": "Navn på bedrift",
|
||||
"countryOfResidence": "Oppholdsland",
|
||||
"stateProvinceRegion": "Fylke / Region",
|
||||
"postalZipCode": "Postnummer / postnummer",
|
||||
"companyWebsite": "Firmaets hjemmeside",
|
||||
"companyPhoneNumber": "Firmaets telefonnummer",
|
||||
"country": "Land",
|
||||
"phoneNumberOptional": "Telefonnummer (valgfritt)",
|
||||
"complianceConfirmation": "Jeg bekrefter at opplysningene jeg oppga er korrekte og at jeg er i samsvar med Fossorial Kommersiell Lisens. Rapportering av unøyaktig informasjon eller feilidentifisering av bruk av produktet bryter lisensen, og kan føre til at nøkkelen din blir opphevet."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Lukk",
|
||||
"previous": "Forrige",
|
||||
"next": "Neste",
|
||||
"generateLicenseKey": "Generer lisensnøkkel"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Lisensnøkkel ble generert",
|
||||
"description": "Din lisensnøkkel har blitt generert og er klar til bruk."
|
||||
},
|
||||
"error": {
|
||||
"title": "Kan ikke generere lisensnøkkel",
|
||||
"description": "Det oppstod en feil ved generering av lisensnøkkelen."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Prioritet",
|
||||
"priorityDescription": "Høyere prioriterte ruter evalueres først. Prioritet = 100 betyr automatisk bestilling (systembeslutninger). Bruk et annet nummer til å håndheve manuell prioritet.",
|
||||
"instanceName": "Forekomst navn",
|
||||
"pathMatchModalTitle": "Konfigurere matching av sti",
|
||||
"pathMatchModalDescription": "Sett opp hvordan innkommende forespørsler skal matches basert på deres bane.",
|
||||
"pathMatchType": "Trefftype",
|
||||
"pathMatchPrefix": "Prefiks",
|
||||
"pathMatchExact": "Nøyaktig",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Verdi for sti",
|
||||
"clear": "Tøm",
|
||||
"saveChanges": "Lagre endringer",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/sti",
|
||||
"pathMatchPrefixHelp": "Eksempel: /api matcher /api, /api/users, etc.",
|
||||
"pathMatchExactHelp": "Eksempel: /api passer bare /api",
|
||||
"pathMatchRegexHelp": "Eksempel: ^/api/.* matcher /api/alt",
|
||||
"pathRewriteModalTitle": "Konfigurer ferdigskriving av sti",
|
||||
"pathRewriteModalDescription": "Overfør banen som passet før den videresendes til målet.",
|
||||
"pathRewriteType": "Omskriv type",
|
||||
"pathRewritePrefixOption": "Prefiks - erstatt prefiks",
|
||||
"pathRewriteExactOption": "Eksakt - Erstatt hele banen",
|
||||
"pathRewriteRegexOption": "Regex - Ekkobilde",
|
||||
"pathRewriteStripPrefixOption": "Ta bort prefiks - fjern prefiks",
|
||||
"pathRewriteValue": "Omskriv verdi",
|
||||
"pathRewriteRegexPlaceholder": "/ny/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/ny sti",
|
||||
"pathRewritePrefixHelp": "Erstatt det samsvarende prefikset med denne verdien",
|
||||
"pathRewriteExactHelp": "Erstatt hele banen med denne verdien når stien samsvarer nøyaktig",
|
||||
"pathRewriteRegexHelp": "Bruk opptaksgrupper som $1, $2 for erstatning",
|
||||
"pathRewriteStripPrefixHelp": "La stå tomt for å ta opp prefiks eller legge til nytt prefiks",
|
||||
"pathRewritePrefix": "Prefiks",
|
||||
"pathRewriteExact": "Nøyaktig",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Stripe",
|
||||
"pathRewriteStripLabel": "stripe",
|
||||
"sidebarEnableEnterpriseLicense": "Aktiver Enterprise lisens",
|
||||
"cannotbeUndone": "Dette kan ikke angres.",
|
||||
"toConfirm": "å bekrefte",
|
||||
"deleteClientQuestion": "Er du sikker på at du vil fjerne klienten fra nettstedet og organisasjonen?",
|
||||
"clientMessageRemove": "Når klienten er fjernet, kan den ikke lenger koble seg til nettstedet.",
|
||||
"sidebarLogs": "Logger",
|
||||
"request": "Forespørsel",
|
||||
"logs": "Logger",
|
||||
"logsSettingsDescription": "Overvåk logger samlet fra denne orginiasjonen",
|
||||
"searchLogs": "Søk i logger...",
|
||||
"action": "Handling",
|
||||
"actor": "Aktør",
|
||||
"timestamp": "Tidsstempel",
|
||||
"accessLogs": "Tilgangslogger (Automatic Translation)",
|
||||
"exportCsv": "Eksportere CSV",
|
||||
"actorId": "Skuespiller ID",
|
||||
"allowedByRule": "Tillatt etter regel",
|
||||
"allowedNoAuth": "Tillatt Ingen Auth",
|
||||
"validAccessToken": "Gyldig tilgangsnøkkel",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Gyldig passord",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Ressurs blokkert",
|
||||
"droppedByRule": "Legg i regelen",
|
||||
"noSessions": "Ingen økter",
|
||||
"temporaryRequestToken": "Midlertidig forespørsel Token",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Grunn",
|
||||
"requestLogs": "Forespørselslogger (Automatic Translation)",
|
||||
"host": "Vert",
|
||||
"location": "Sted",
|
||||
"actionLogs": "Handlingslogger",
|
||||
"sidebarLogsRequest": "Forespørselslogger (Automatic Translation)",
|
||||
"sidebarLogsAccess": "Tilgangslogger (Automatic Translation)",
|
||||
"sidebarLogsAction": "Handlingslogger",
|
||||
"logRetention": "Logg tilbaketrekning",
|
||||
"logRetentionDescription": "Håndter hvor lenge ulike typer logger beholdes for denne organisasjonen, eller deaktiver dem",
|
||||
"requestLogsDescription": "Se detaljerte forespørselslogger for ressurser i denne organisasjonen",
|
||||
"logRetentionRequestLabel": "Be om loggoverføring",
|
||||
"logRetentionRequestDescription": "Hvor lenge du vil beholde forespørselslogger",
|
||||
"logRetentionAccessLabel": "Få tilgang til loggoverføring",
|
||||
"logRetentionAccessDescription": "Hvor lenge du vil beholde adgangslogger",
|
||||
"logRetentionActionLabel": "Handlings logg nytt",
|
||||
"logRetentionActionDescription": "Hvor lenge handlingen skal lagres",
|
||||
"logRetentionDisabled": "Deaktivert",
|
||||
"logRetention3Days": "3 dager",
|
||||
"logRetention7Days": "7 dager",
|
||||
"logRetention14Days": "14 dager",
|
||||
"logRetention30Days": "30 dager",
|
||||
"logRetention90Days": "90 dager",
|
||||
"logRetentionForever": "Alltid",
|
||||
"actionLogsDescription": "Vis historikk for handlinger som er utført i denne organisasjonen",
|
||||
"accessLogsDescription": "Vis autoriseringsforespørsler for ressurser i denne organisasjonen",
|
||||
"licenseRequiredToUse": "En Enterprise lisens er påkrevd for å bruke denne funksjonen.",
|
||||
"certResolver": "Sertifikat løser",
|
||||
"certResolverDescription": "Velg sertifikatløser som skal brukes for denne ressursen.",
|
||||
"selectCertResolver": "Velg sertifikatløser",
|
||||
"enterCustomResolver": "Legg inn egendefinert løser",
|
||||
"preferWildcardCert": "Foretrekk Wildcard sertifikat",
|
||||
"unverified": "Uverifisert",
|
||||
"domainSetting": "Domene innstillinger",
|
||||
"domainSettingDescription": "Konfigurer innstillinger for ditt domene",
|
||||
"preferWildcardCertDescription": "Forsøk på å generere et jokertegn (krever en riktig konfigurert sertifikatløsning).",
|
||||
"recordName": "Lagre navn",
|
||||
"auto": "Automatisk",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Hvordan legge til poster",
|
||||
"dnsRecord": "DNS registre",
|
||||
"required": "Påkrevd",
|
||||
"domainSettingsUpdated": "Domene innstillinger ble oppdatert",
|
||||
"orgOrDomainIdMissing": "ID for organisasjon eller domene mangler",
|
||||
"loadingDNSRecords": "Laster DNS-poster...",
|
||||
"olmUpdateAvailableInfo": "En oppdatert versjon av Olm er tilgjengelig. Oppdater til den nyeste versjonen for å få den beste opplevelsen.",
|
||||
"client": "Klient",
|
||||
"proxyProtocol": "Protokoll innstillinger for Protokoll",
|
||||
"proxyProtocolDescription": "Konfigurer Proxy-protokoll for å bevare klientens IP-adresser til TCP/UDP tjenester.",
|
||||
"enableProxyProtocol": "Aktiver Proxy-protokoll",
|
||||
"proxyProtocolInfo": "Bevar klientens IP-adresser for TCP/UDP bakover",
|
||||
"proxyProtocolVersion": "Proxy protokoll versjon",
|
||||
"version1": " Versjon 1 (Anbefalt)",
|
||||
"version2": "Versjon 2",
|
||||
"versionDescription": "Versjon 1 er tekstbasert og støttet. Versjon 2 er binært og mer effektivt, men mindre kompatibel.",
|
||||
"warning": "Advarsel",
|
||||
"proxyProtocolWarning": "Din backend applikasjon må være konfigurert for å godta Proxy Protokoller. Hvis din backend ikke støtter Proxy Protocol, vil aktivering av dette bryte alle tilkoblinger. Sørg for å konfigurere backend til å stole på Proxy Protokoll overskrifter fra Traefik.",
|
||||
"restarting": "Restarter...",
|
||||
"manual": "Manuell",
|
||||
"messageSupport": "Støtte for melding",
|
||||
"supportNotAvailableTitle": "Støtte ikke tilgjengelig",
|
||||
"supportNotAvailableDescription": "Støtte er ikke tilgjengelig akkurat nå. Du kan sende en e-post til support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Supportforespørsel sendt",
|
||||
"supportRequestSentDescription": "Din melding er sendt.",
|
||||
"supportRequestFailedTitle": "Kunne ikke sende forespørsel",
|
||||
"supportRequestFailedDescription": "En feil oppstod under sending av din forespørsel om støtte.",
|
||||
"supportSubjectRequired": "Emne er påkrevd",
|
||||
"supportSubjectMaxLength": "Emne må være 255 tegn eller mindre",
|
||||
"supportMessageRequired": "Melding er påkrevd",
|
||||
"supportReplyTo": "Svar til",
|
||||
"supportSubject": "Emne",
|
||||
"supportSubjectPlaceholder": "Angi emne",
|
||||
"supportMessage": "Melding",
|
||||
"supportMessagePlaceholder": "Skriv din melding",
|
||||
"supportSending": "Sender...",
|
||||
"supportSend": "Sende",
|
||||
"supportMessageSent": "Melding sendt!",
|
||||
"supportWillContact": "Vi kommer raskt til å ta kontakt!",
|
||||
"selectLogRetention": "Velg oppbevaring av logg",
|
||||
"showColumns": "Vis kolonner",
|
||||
"hideColumns": "Skjul kolonner",
|
||||
"columnVisibility": "Kolonne Synlighet",
|
||||
"toggleColumn": "Veksle {columnName} kolonne",
|
||||
"allColumns": "Alle kolonner",
|
||||
"defaultColumns": "Standard kolonner",
|
||||
"customizeView": "Tilpass visning",
|
||||
"viewOptions": "Vis alternativer",
|
||||
"selectAll": "Velg alle",
|
||||
"selectNone": "Velg ingen",
|
||||
"selectedResources": "Valgte ressurser",
|
||||
"enableSelected": "Aktiver valgte",
|
||||
"disableSelected": "Deaktiver valgte",
|
||||
"checkSelectedStatus": "Kontroller status for valgte"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,9 +47,8 @@
|
||||
"edit": "Edytuj",
|
||||
"siteConfirmDelete": "Potwierdź usunięcie witryny",
|
||||
"siteDelete": "Usuń witrynę",
|
||||
"siteMessageRemove": "Po usunięciu, witryna nie będzie już dostępna. Wszystkie zasoby i cele związane z witryną zostaną również usunięte.",
|
||||
"siteMessageConfirm": "Aby potwierdzić, wpisz nazwę witryny poniżej.",
|
||||
"siteQuestionRemove": "Czy na pewno chcesz usunąć stronę {selectedSite} z organizacji?",
|
||||
"siteMessageRemove": "Po usunięciu witryna nie będzie już dostępna. Wszystkie cele związane z witryną zostaną również usunięte.",
|
||||
"siteQuestionRemove": "Czy na pewno chcesz usunąć witrynę z organizacji?",
|
||||
"siteManageSites": "Zarządzaj stronami",
|
||||
"siteDescription": "Zezwalaj na połączenie z siecią przez bezpieczne tunele",
|
||||
"siteCreate": "Utwórz witrynę",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Użyj dowolnego klienta WireGuard do utworzenia tunelu. Wymagana jest ręczna konfiguracja NAT.",
|
||||
"siteWgDescriptionSaas": "Użyj dowolnego klienta WireGuard do utworzenia tunelu. Wymagana ręczna konfiguracja NAT. DZIAŁA TYLKO NA SAMODZIELNIE HOSTOWANYCH WĘZŁACH",
|
||||
"siteLocalDescription": "Tylko lokalne zasoby. Brak tunelu.",
|
||||
"siteLocalDescriptionSaas": "Tylko zasoby lokalne. Brak tunelowania. DZIAŁA TYLKO NA SAMODZIELNIE HOSTOWANYCH WĘZŁACH",
|
||||
"siteLocalDescriptionSaas": "Tylko zasoby lokalne. Brak tunelu. Dostępne tylko w węzłach zdalnych.",
|
||||
"siteSeeAll": "Zobacz wszystkie witryny",
|
||||
"siteTunnelDescription": "Określ jak chcesz połączyć się ze swoją stroną",
|
||||
"siteNewtCredentials": "Aktualne dane logowania",
|
||||
@@ -132,7 +131,7 @@
|
||||
"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.",
|
||||
"shareSeeOnce": "Możesz zobaczyć tylko ten link. Upewnij się, że go skopiowało.",
|
||||
"shareSeeOnce": "Możesz zobaczyć ten link tylko raz. Pamiętaj, aby go skopiować.",
|
||||
"shareAccessHint": "Każdy z tym linkiem może uzyskać dostęp do zasobu. Podziel się nim ostrożnie.",
|
||||
"shareTokenUsage": "Zobacz użycie tokenu dostępu",
|
||||
"createLink": "Utwórz link",
|
||||
@@ -154,8 +153,7 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "Aby potwierdzić, wpisz nazwę zasobu poniżej.",
|
||||
"resourceQuestionRemove": "Czy na pewno chcesz usunąć zasób {selectedResource} z organizacji?",
|
||||
"resourceQuestionRemove": "Czy na pewno chcesz usunąć zasób z organizacji?",
|
||||
"resourceHTTP": "Zasób HTTPS",
|
||||
"resourceHTTPDescription": "Proxy do Twojej aplikacji przez HTTPS, przy użyciu poddomeny lub domeny bazowej.",
|
||||
"resourceRaw": "Surowy zasób TCP/UDP",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Wybierz witrynę",
|
||||
"siteSearch": "Szukaj witryny",
|
||||
"siteNotFound": "Nie znaleziono witryny.",
|
||||
"selectCountry": "Wybierz kraj",
|
||||
"searchCountries": "Szukaj krajów...",
|
||||
"noCountryFound": "Nie znaleziono kraju.",
|
||||
"siteSelectionDescription": "Ta strona zapewni połączenie z celem.",
|
||||
"resourceType": "Typ zasobu",
|
||||
"resourceTypeDescription": "Określ jak chcesz uzyskać dostęp do swojego zasobu",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Bazowa domena",
|
||||
"subdomnainDescription": "Poddomena, w której twój zasób będzie dostępny.",
|
||||
"resourceRawSettings": "Ustawienia TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Skonfiguruj jak twój zasób będzie dostępny przez TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Skonfiguruj jak twój zasób będzie dostępny przez TCP/UDP. Zmapujesz zasób do portu na serwerze hosta Pangolin, dzięki czemu możesz uzyskać dostęp do zasobu z serwera-public ip:mapped-port.",
|
||||
"protocol": "Protokół",
|
||||
"protocolSelect": "Wybierz protokół",
|
||||
"resourcePortNumber": "Numer portu",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Potwierdź usunięcie organizacji",
|
||||
"orgMessageRemove": "Ta akcja jest nieodwracalna i usunie wszystkie powiązane dane.",
|
||||
"orgMessageConfirm": "Aby potwierdzić, wpisz nazwę organizacji poniżej.",
|
||||
"orgQuestionRemove": "Czy na pewno chcesz usunąć organizację {selectedOrg}?",
|
||||
"orgQuestionRemove": "Czy na pewno chcesz usunąć organizację?",
|
||||
"orgUpdated": "Organizacja zaktualizowana",
|
||||
"orgUpdatedDescription": "Organizacja została zaktualizowana.",
|
||||
"orgErrorUpdate": "Nie udało się zaktualizować organizacji",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Generuj klucz API",
|
||||
"apiKeysErrorDelete": "Błąd podczas usuwania klucza API",
|
||||
"apiKeysErrorDeleteMessage": "Błąd podczas usuwania klucza API",
|
||||
"apiKeysQuestionRemove": "Czy na pewno chcesz usunąć klucz API {selectedApiKey} z organizacji?",
|
||||
"apiKeysQuestionRemove": "Czy na pewno chcesz usunąć klucz API z organizacji?",
|
||||
"apiKeysMessageRemove": "Po usunięciu klucz API nie będzie już mógł być używany.",
|
||||
"apiKeysMessageConfirm": "Aby potwierdzić, wpisz nazwę klucza API poniżej.",
|
||||
"apiKeysDeleteConfirm": "Potwierdź usunięcie klucza API",
|
||||
"apiKeysDelete": "Usuń klucz API",
|
||||
"apiKeysManage": "Zarządzaj kluczami API",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Potwierdź usunięcie użytkownika",
|
||||
"userDeleteServer": "Usuń użytkownika z serwera",
|
||||
"userMessageRemove": "Użytkownik zostanie usunięty ze wszystkich organizacji i całkowicie usunięty z serwera.",
|
||||
"userMessageConfirm": "Aby potwierdzić, wpisz nazwę użytkownika poniżej.",
|
||||
"userQuestionRemove": "Czy na pewno chcesz trwale usunąć {selectedUser} z serwera?",
|
||||
"userQuestionRemove": "Czy na pewno chcesz trwale usunąć użytkownika z serwera?",
|
||||
"licenseKey": "Klucz licencyjny",
|
||||
"valid": "Prawidłowy",
|
||||
"numberOfSites": "Liczba witryn",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Zobacz Fossorial Commercial License & Subskrypcja",
|
||||
"licenseMessageRemove": "Spowoduje to usunięcie klucza licencyjnego i wszystkich przypisanych przez niego uprawnień.",
|
||||
"licenseMessageConfirm": "Aby potwierdzić, wpisz klucz licencyjny poniżej.",
|
||||
"licenseQuestionRemove": "Czy na pewno chcesz usunąć klucz licencyjny {selectedKey}?",
|
||||
"licenseQuestionRemove": "Czy na pewno chcesz usunąć klucz licencyjny?",
|
||||
"licenseKeyDelete": "Usuń klucz licencyjny",
|
||||
"licenseKeyDeleteConfirm": "Potwierdź usunięcie klucza licencyjnego",
|
||||
"licenseTitle": "Zarządzaj statusem licencji",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Wystąpił błąd podczas usuwania zaproszenia.",
|
||||
"inviteRemoved": "Zaproszenie usunięte",
|
||||
"inviteRemovedDescription": "Zaproszenie dla {email} zostało usunięte.",
|
||||
"inviteQuestionRemove": "Czy na pewno chcesz usunąć zaproszenie {email}?",
|
||||
"inviteQuestionRemove": "Czy na pewno chcesz usunąć zaproszenie?",
|
||||
"inviteMessageRemove": "Po usunięciu to zaproszenie nie będzie już ważne. Zawsze możesz ponownie zaprosić użytkownika później.",
|
||||
"inviteMessageConfirm": "Aby potwierdzić, wpisz poniżej adres email zaproszenia.",
|
||||
"inviteQuestionRegenerate": "Czy na pewno chcesz ponownie wygenerować zaproszenie {email}? Spowoduje to unieważnienie poprzedniego zaproszenia.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Wystąpił błąd podczas usuwania użytkownika.",
|
||||
"userOrgRemoved": "Użytkownik usunięty",
|
||||
"userOrgRemovedDescription": "Użytkownik {email} został usunięty z organizacji.",
|
||||
"userQuestionOrgRemove": "Czy na pewno chcesz usunąć {email} z organizacji?",
|
||||
"userQuestionOrgRemove": "Czy na pewno chcesz usunąć tego użytkownika z organizacji?",
|
||||
"userMessageOrgRemove": "Po usunięciu ten użytkownik nie będzie miał już dostępu do organizacji. Zawsze możesz ponownie go zaprosić później, ale będzie musiał ponownie zaakceptować zaproszenie.",
|
||||
"userMessageOrgConfirm": "Aby potwierdzić, wpisz nazwę użytkownika poniżej.",
|
||||
"userRemoveOrgConfirm": "Potwierdź usunięcie użytkownika",
|
||||
"userRemoveOrg": "Usuń użytkownika z organizacji",
|
||||
"users": "Użytkownicy",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Wystąpił błąd podczas dodawania użytkownika do roli.",
|
||||
"userSaved": "Użytkownik zapisany",
|
||||
"userSavedDescription": "Użytkownik został zaktualizowany.",
|
||||
"autoProvisioned": "Przesłane automatycznie",
|
||||
"autoProvisionedDescription": "Pozwól temu użytkownikowi na automatyczne zarządzanie przez dostawcę tożsamości",
|
||||
"accessControlsDescription": "Zarządzaj tym, do czego użytkownik ma dostęp i co może robić w organizacji",
|
||||
"accessControlsSubmit": "Zapisz kontrole dostępu",
|
||||
"roles": "Role",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Utworzono",
|
||||
"proxyErrorInvalidHeader": "Nieprawidłowa wartość niestandardowego nagłówka hosta. Użyj formatu nazwy domeny lub zapisz pusty, aby usunąć niestandardowy nagłówek hosta.",
|
||||
"proxyErrorTls": "Nieprawidłowa nazwa serwera TLS. Użyj formatu nazwy domeny lub zapisz pusty, aby usunąć nazwę serwera TLS.",
|
||||
"proxyEnableSSL": "Włącz SSL (https)",
|
||||
"proxyEnableSSL": "Włącz SSL",
|
||||
"proxyEnableSSLDescription": "Włącz szyfrowanie SSL/TLS dla bezpiecznych połączeń HTTPS z Twoimi celami.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Konfiguruj Targety",
|
||||
"targetErrorFetch": "Nie udało się pobrać celów",
|
||||
"targetErrorFetchDescription": "Wystąpił błąd podczas pobierania celów",
|
||||
"siteErrorFetch": "Nie udało się pobrać zasobu",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Konfiguracja bezpiecznego połączenia",
|
||||
"targetTlsSettingsDescription": "Skonfiguruj ustawienia SSL/TLS dla twojego zasobu",
|
||||
"targetTlsSettingsAdvanced": "Zaawansowane ustawienia TLS",
|
||||
"targetTlsSni": "Nazwa serwera TLS (SNI)",
|
||||
"targetTlsSni": "Nazwa serwera TLS",
|
||||
"targetTlsSniDescription": "Nazwa serwera TLS do użycia dla SNI. Pozostaw puste, aby użyć domyślnej.",
|
||||
"targetTlsSubmit": "Zapisz ustawienia",
|
||||
"targets": "Konfiguracja celów",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Utrzymuj połączenia na tym samym celu backendowym przez całą sesję.",
|
||||
"methodSelect": "Wybierz metodę",
|
||||
"targetSubmit": "Dodaj cel",
|
||||
"targetNoOne": "Brak celów. Dodaj cel używając formularza.",
|
||||
"targetNoOne": "Ten zasób nie ma żadnych celów. Dodaj cel, aby skonfigurować miejsce wysyłania żądań do twojego backendu.",
|
||||
"targetNoOneDescription": "Dodanie więcej niż jednego celu powyżej włączy równoważenie obciążenia.",
|
||||
"targetsSubmit": "Zapisz cele",
|
||||
"addTarget": "Dodaj cel",
|
||||
"targetErrorInvalidIp": "Nieprawidłowy adres IP",
|
||||
"targetErrorInvalidIpDescription": "Wprowadź prawidłowy adres IP lub nazwę hosta",
|
||||
"targetErrorInvalidPort": "Nieprawidłowy port",
|
||||
"targetErrorInvalidPortDescription": "Wprowadź prawidłowy numer portu",
|
||||
"targetErrorNoSite": "Nie wybrano witryny",
|
||||
"targetErrorNoSiteDescription": "Wybierz witrynę docelową",
|
||||
"targetCreated": "Cel utworzony",
|
||||
"targetCreatedDescription": "Cel został utworzony pomyślnie",
|
||||
"targetErrorCreate": "Nie udało się utworzyć celu",
|
||||
"targetErrorCreateDescription": "Wystąpił błąd podczas tworzenia celu",
|
||||
"save": "Zapisz",
|
||||
"proxyAdditional": "Dodatkowe ustawienia proxy",
|
||||
"proxyAdditionalDescription": "Skonfiguruj jak twój zasób obsługuje ustawienia proxy",
|
||||
"proxyCustomHeader": "Niestandardowy nagłówek hosta",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Nieprawidłowy format adresu IP",
|
||||
"ipAddressErrorInvalidOctet": "Nieprawidłowy oktet adresu IP",
|
||||
"path": "Ścieżka",
|
||||
"matchPath": "Ścieżka dopasowania",
|
||||
"ipAddressRange": "Zakres IP",
|
||||
"rulesErrorFetch": "Nie udało się pobrać reguł",
|
||||
"rulesErrorFetchDescription": "Wystąpił błąd podczas pobierania reguł",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Administrator serwera - Pangolin",
|
||||
"licenseTierProfessional": "Licencja Professional",
|
||||
"licenseTierEnterprise": "Licencja Enterprise",
|
||||
"licenseTierCommercial": "Licencja handlowa",
|
||||
"licenseTierPersonal": "Licencja osobista",
|
||||
"licensed": "Licencjonowany",
|
||||
"yes": "Tak",
|
||||
"no": "Nie",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Wyświetl i zarządzaj dostawcami tożsamości w systemie",
|
||||
"idpDeletedDescription": "Dostawca tożsamości został pomyślnie usunięty",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Czy na pewno chcesz trwale usunąć dostawcę tożsamości {name}?",
|
||||
"idpQuestionRemove": "Czy na pewno chcesz trwale usunąć dostawcę tożsamości?",
|
||||
"idpMessageRemove": "Spowoduje to usunięcie dostawcy tożsamości i wszystkich powiązanych konfiguracji. Użytkownicy uwierzytelniający się przez tego dostawcę nie będą mogli się już zalogować.",
|
||||
"idpMessageConfirm": "Aby potwierdzić, wpisz nazwę dostawcy tożsamości poniżej.",
|
||||
"idpConfirmDelete": "Potwierdź usunięcie dostawcy tożsamości",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Nazwa wyświetlana dla tego dostawcy tożsamości",
|
||||
"idpAutoProvisionUsers": "Automatyczne tworzenie użytkowników",
|
||||
"idpAutoProvisionUsersDescription": "Gdy włączone, użytkownicy będą automatycznie tworzeni w systemie przy pierwszym logowaniu z możliwością mapowania użytkowników do ról i organizacji.",
|
||||
"licenseBadge": "Profesjonalny",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Typ dostawcy",
|
||||
"idpTypeDescription": "Wybierz typ dostawcy tożsamości, który chcesz skonfigurować",
|
||||
"idpOidcConfigure": "Konfiguracja OAuth2/OIDC",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Sprawdź swój e-mail, aby znaleźć kod resetowania.",
|
||||
"passwordNew": "Nowe hasło",
|
||||
"passwordNewConfirm": "Potwierdź nowe hasło",
|
||||
"changePassword": "Zmień hasło",
|
||||
"changePasswordDescription": "Zaktualizuj hasło do konta",
|
||||
"oldPassword": "Bieżące hasło",
|
||||
"newPassword": "Nowe hasło",
|
||||
"confirmNewPassword": "Potwierdź nowe hasło",
|
||||
"changePasswordError": "Nie udało się zmienić hasła",
|
||||
"changePasswordErrorDescription": "Wystąpił błąd podczas zmiany hasła",
|
||||
"changePasswordSuccess": "Hasło zostało pomyślnie zmienione",
|
||||
"changePasswordSuccessDescription": "Twoje hasło zostało pomyślnie zaktualizowane",
|
||||
"passwordExpiryRequired": "Wymagane hasło wygasające",
|
||||
"passwordExpiryDescription": "Organizacja wymaga zmiany hasła co {maxDays} dni.",
|
||||
"changePasswordNow": "Zmień hasło teraz",
|
||||
"pincodeAuth": "Kod uwierzytelniający",
|
||||
"pincodeSubmit2": "Wyślij kod",
|
||||
"passwordResetSubmit": "Zażądaj resetowania",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Wymagana edycja Professional",
|
||||
"licenseTierProfessionalRequiredDescription": "Ta funkcja jest dostępna tylko w edycji Professional.",
|
||||
"actionGetOrg": "Pobierz organizację",
|
||||
"updateOrgUser": "Aktualizuj użytkownika Org",
|
||||
"createOrgUser": "Utwórz użytkownika Org",
|
||||
"actionUpdateOrg": "Aktualizuj organizację",
|
||||
"actionUpdateUser": "Zaktualizuj użytkownika",
|
||||
"actionGetUser": "Pobierz użytkownika",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Usuń witrynę",
|
||||
"actionGetSite": "Pobierz witrynę",
|
||||
"actionListSites": "Lista witryn",
|
||||
"actionApplyBlueprint": "Zastosuj schemat",
|
||||
"setupToken": "Skonfiguruj token",
|
||||
"setupTokenDescription": "Wprowadź token konfiguracji z konsoli serwera.",
|
||||
"setupTokenRequired": "Wymagany jest token konfiguracji",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Menu nawigacyjne",
|
||||
"navbarDescription": "Główne menu nawigacyjne aplikacji",
|
||||
"navbarDocsLink": "Dokumentacja",
|
||||
"commercialEdition": "Edycja komercyjna",
|
||||
"otpErrorEnable": "Nie można włączyć 2FA",
|
||||
"otpErrorEnableDescription": "Wystąpił błąd podczas włączania 2FA",
|
||||
"otpSetupCheckCode": "Wprowadź 6-cyfrowy kod",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Wszyscy użytkownicy",
|
||||
"sidebarIdentityProviders": "Dostawcy tożsamości",
|
||||
"sidebarLicense": "Licencja",
|
||||
"sidebarClients": "Klienci (Beta)",
|
||||
"sidebarClients": "Klientami",
|
||||
"sidebarDomains": "Domeny",
|
||||
"enableDockerSocket": "Włącz gniazdo dokera",
|
||||
"enableDockerSocketDescription": "Włącz wykrywanie Docker Socket w celu wypełnienia informacji o kontenerach. Ścieżka gniazda musi być dostarczona do Newt.",
|
||||
"sidebarBluePrints": "Schematy",
|
||||
"blueprints": "Schematy",
|
||||
"blueprintsDescription": "Zastosuj konfiguracje deklaracyjne i wyświetl poprzednie operacje",
|
||||
"blueprintAdd": "Dodaj schemat",
|
||||
"blueprintGoBack": "Zobacz wszystkie schematy",
|
||||
"blueprintCreate": "Utwórz schemat",
|
||||
"blueprintCreateDescription2": "Wykonaj poniższe kroki, aby utworzyć i zastosować nowy schemat",
|
||||
"blueprintDetails": "Szczegóły Projektu",
|
||||
"blueprintDetailsDescription": "Zobacz wynik zastosowanego schematu i wszelkie błędy, które wystąpiły",
|
||||
"blueprintInfo": "Informacje o projekcie",
|
||||
"message": "Wiadomość",
|
||||
"blueprintContentsDescription": "Zdefiniuj zawartość YAML opisującą Twoją infrastrukturę",
|
||||
"blueprintErrorCreateDescription": "Wystąpił błąd podczas stosowania schematu",
|
||||
"blueprintErrorCreate": "Błąd podczas tworzenia schematu",
|
||||
"searchBlueprintProgress": "Szukaj schematów...",
|
||||
"appliedAt": "Zastosowano",
|
||||
"source": "Źródło",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Dowiedz się więcej",
|
||||
"viewDockerContainers": "Zobacz kontenery dokujące",
|
||||
"containersIn": "Pojemniki w {siteName}",
|
||||
@@ -1147,7 +1196,7 @@
|
||||
"containerLabels": "Etykiety",
|
||||
"containerLabelsCount": "{count, plural, one {# etykieta} few {# etykiety} many {# etykiet} other {# etykiet}}",
|
||||
"containerLabelsTitle": "Etykiety kontenera",
|
||||
"containerLabelEmpty": "<empty>",
|
||||
"containerLabelEmpty": "<pusty>",
|
||||
"containerPorts": "Porty",
|
||||
"containerPortsMore": "+{count} więcej",
|
||||
"containerActions": "Akcje",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Utwórz domenę",
|
||||
"domainCreatedDescription": "Domena utworzona pomyślnie",
|
||||
"domainDeletedDescription": "Domena usunięta pomyślnie",
|
||||
"domainQuestionRemove": "Czy na pewno chcesz usunąć domenę {domain} ze swojego konta?",
|
||||
"domainQuestionRemove": "Czy na pewno chcesz usunąć domenę ze swojego konta?",
|
||||
"domainMessageRemove": "Po usunięciu domena nie będzie już powiązana z twoim kontem.",
|
||||
"domainMessageConfirm": "Aby potwierdzić, wpisz nazwę domeny poniżej.",
|
||||
"domainConfirmDelete": "Potwierdź usunięcie domeny",
|
||||
"domainDelete": "Usuń domenę",
|
||||
"domain": "Domena",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Dostępna aktualizacja",
|
||||
"newtUpdateAvailableInfo": "Nowa wersja Newt jest dostępna. Prosimy o aktualizację do najnowszej wersji dla najlepszej pracy.",
|
||||
"domainPickerEnterDomain": "Domena",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com lub po prostu myapp",
|
||||
"domainPickerPlaceholder": "mojapp.example.com",
|
||||
"domainPickerDescription": "Wpisz pełną domenę zasobu, aby zobaczyć dostępne opcje.",
|
||||
"domainPickerDescriptionSaas": "Wprowadź pełną domenę, subdomenę lub po prostu nazwę, aby zobaczyć dostępne opcje",
|
||||
"domainPickerTabAll": "Wszystko",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Subdomena: {subdomain}",
|
||||
"domainPickerNamespace": "Przestrzeń nazw: {namespace}",
|
||||
"domainPickerShowMore": "Pokaż więcej",
|
||||
"regionSelectorTitle": "Wybierz region",
|
||||
"regionSelectorInfo": "Wybór regionu pomaga nam zapewnić lepszą wydajność dla Twojej lokalizacji. Nie musisz być w tym samym regionie co Twój serwer.",
|
||||
"regionSelectorPlaceholder": "Wybierz region",
|
||||
"regionSelectorComingSoon": "Wkrótce dostępne",
|
||||
"billingLoadingSubscription": "Ładowanie subskrypcji...",
|
||||
"billingFreeTier": "Darmowy pakiet",
|
||||
"billingWarningOverLimit": "Ostrzeżenie: Przekroczyłeś jeden lub więcej limitów użytkowania. Twoje witryny nie połączą się, dopóki nie zmienisz subskrypcji lub nie dostosujesz użytkowania.",
|
||||
"billingUsageLimitsOverview": "Przegląd Limitów Użytkowania",
|
||||
"billingMonitorUsage": "Monitoruj swoje wykorzystanie w porównaniu do skonfigurowanych limitów. Jeśli potrzebujesz zwiększenia limitów, skontaktuj się z nami pod adresem support@pangolin.net.",
|
||||
"billingDataUsage": "Użycie danych",
|
||||
"billingOnlineTime": "Czas Online Strony",
|
||||
"billingUsers": "Aktywni użytkownicy",
|
||||
"billingDomains": "Aktywne domeny",
|
||||
"billingRemoteExitNodes": "Aktywne samodzielnie-hostowane węzły",
|
||||
"billingNoLimitConfigured": "Nie skonfigurowano limitu",
|
||||
"billingEstimatedPeriod": "Szacowany Okres Rozliczeniowy",
|
||||
"billingIncludedUsage": "Zawarte użycie",
|
||||
"billingIncludedUsageDescription": "Użycie zawarte w obecnym planie subskrypcji",
|
||||
"billingFreeTierIncludedUsage": "Limity użycia dla darmowego pakietu",
|
||||
"billingIncluded": "zawarte",
|
||||
"billingEstimatedTotal": "Szacowana Całkowita:",
|
||||
"billingNotes": "Notatki",
|
||||
"billingEstimateNote": "To jest szacunkowe, oparte na Twoim obecnym użyciu.",
|
||||
"billingActualChargesMayVary": "Rzeczywiste opłaty mogą się różnić.",
|
||||
"billingBilledAtEnd": "Zostaniesz obciążony na koniec okresu rozliczeniowego.",
|
||||
"billingModifySubscription": "Modyfikuj Subskrypcję",
|
||||
"billingStartSubscription": "Rozpocznij Subskrypcję",
|
||||
"billingRecurringCharge": "Opłata Cyklowa",
|
||||
"billingManageSubscriptionSettings": "Zarządzaj ustawieniami i preferencjami subskrypcji",
|
||||
"billingNoActiveSubscription": "Nie masz aktywnej subskrypcji. Rozpocznij subskrypcję, aby zwiększyć limity użytkowania.",
|
||||
"billingFailedToLoadSubscription": "Nie udało się załadować subskrypcji",
|
||||
"billingFailedToLoadUsage": "Nie udało się załadować użycia",
|
||||
"billingFailedToGetCheckoutUrl": "Nie udało się uzyskać adresu URL zakupu",
|
||||
"billingPleaseTryAgainLater": "Spróbuj ponownie później.",
|
||||
"billingCheckoutError": "Błąd przy kasie",
|
||||
"billingFailedToGetPortalUrl": "Nie udało się uzyskać adresu URL portalu",
|
||||
"billingPortalError": "Błąd Portalu",
|
||||
"billingDataUsageInfo": "Jesteś obciążony za wszystkie dane przesyłane przez bezpieczne tunele, gdy jesteś podłączony do chmury. Obejmuje to zarówno ruch przychodzący, jak i wychodzący we wszystkich Twoich witrynach. Gdy osiągniesz swój limit, twoje strony zostaną rozłączone, dopóki nie zaktualizujesz planu lub nie ograniczysz użycia. Dane nie będą naliczane przy użyciu węzłów.",
|
||||
"billingOnlineTimeInfo": "Opłata zależy od tego, jak długo twoje strony pozostają połączone z chmurą. Na przykład 44,640 minut oznacza jedną stronę działającą 24/7 przez cały miesiąc. Kiedy osiągniesz swój limit, twoje strony zostaną rozłączone, dopóki nie zaktualizujesz planu lub nie zmniejsz jego wykorzystania. Czas nie będzie naliczany przy użyciu węzłów.",
|
||||
"billingUsersInfo": "Jesteś obciążany za każdego użytkownika w twojej organizacji. Rozliczenia są obliczane codziennie na podstawie liczby aktywnych kont użytkowników w twojej organizacji.",
|
||||
"billingDomainInfo": "Jesteś obciążany za każdą domenę w twojej organizacji. Rozliczenia są obliczane codziennie na podstawie liczby aktywnych kont domen w twojej organizacji.",
|
||||
"billingRemoteExitNodesInfo": "Jesteś obciążany za każdy zarządzany węzeł w twojej organizacji. Rozliczenia są obliczane codziennie na podstawie liczby aktywnych zarządzanych węzłów w twojej organizacji.",
|
||||
"domainNotFound": "Nie znaleziono domeny",
|
||||
"domainNotFoundDescription": "Zasób jest wyłączony, ponieważ domena nie istnieje już w naszym systemie. Proszę ustawić nową domenę dla tego zasobu.",
|
||||
"failed": "Niepowodzenie",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Wystąpił problem z używaniem klucza bezpieczeństwa. Proszę spróbować ponownie.",
|
||||
"twoFactorRequired": "Uwierzytelnianie dwuskładnikowe jest wymagane do zarejestrowania klucza bezpieczeństwa.",
|
||||
"twoFactor": "Uwierzytelnianie dwuskładnikowe",
|
||||
"twoFactorAuthentication": "Uwierzytelnianie dwuetapowe",
|
||||
"twoFactorDescription": "Ta organizacja wymaga uwierzytelniania dwuskładnikowego.",
|
||||
"enableTwoFactor": "Włącz uwierzytelnianie dwuetapowe",
|
||||
"organizationSecurityPolicy": "Polityka bezpieczeństwa organizacji",
|
||||
"organizationSecurityPolicyDescription": "Ta organizacja ma wymagania bezpieczeństwa, które muszą być spełnione, zanim będziesz mógł uzyskać dostęp do niej",
|
||||
"securityRequirements": "Wymogi bezpieczeństwa",
|
||||
"allRequirementsMet": "Wszystkie wymagania zostały spełnione",
|
||||
"completeRequirementsToContinue": "Wypełnij poniższe wymagania, aby kontynuować dostęp do tej organizacji",
|
||||
"youCanNowAccessOrganization": "Teraz możesz uzyskać dostęp do tej organizacji",
|
||||
"reauthenticationRequired": "Długość sesji",
|
||||
"reauthenticationDescription": "Organizacja wymaga logowania co {maxDays} dni.",
|
||||
"reauthenticationDescriptionHours": "Organizacja wymaga logowania co {maxHours} godzin.",
|
||||
"reauthenticateNow": "Zaloguj się ponownie",
|
||||
"adminEnabled2FaOnYourAccount": "Twój administrator włączył uwierzytelnianie dwuskładnikowe dla {email}. Proszę ukończyć proces konfiguracji, aby kontynuować.",
|
||||
"continueToApplication": "Kontynuuj do aplikacji",
|
||||
"securityKeyAdd": "Dodaj klucz bezpieczeństwa",
|
||||
"securityKeyRegisterTitle": "Zarejestruj nowy klucz bezpieczeństwa",
|
||||
"securityKeyRegisterDescription": "Podłącz swój klucz bezpieczeństwa i wprowadź nazwę, aby go zidentyfikować",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "Zmiany DNS mogą zająć trochę czasu na rozpropagowanie się w Internecie. Może to potrwać od kilku minut do 48 godzin, w zależności od dostawcy DNS i ustawień TTL.",
|
||||
"resourcePortRequired": "Numer portu jest wymagany dla zasobów non-HTTP",
|
||||
"resourcePortNotAllowed": "Numer portu nie powinien być ustawiony dla zasobów HTTP",
|
||||
"billingPricingCalculatorLink": "Kalkulator Cen",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Zgadzam się z",
|
||||
"termsOfService": "warunkami usługi",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Zewnętrzny Proxy Włączony",
|
||||
"addNewTarget": "Dodaj nowy cel",
|
||||
"targetsList": "Lista celów",
|
||||
"advancedMode": "Tryb zaawansowany",
|
||||
"targetErrorDuplicateTargetFound": "Znaleziono duplikat celu",
|
||||
"healthCheckHealthy": "Zdrowy",
|
||||
"healthCheckUnhealthy": "Niezdrowy",
|
||||
"healthCheckUnknown": "Nieznany",
|
||||
"healthCheck": "Kontrola Zdrowia",
|
||||
"configureHealthCheck": "Skonfiguruj Kontrolę Zdrowia",
|
||||
"configureHealthCheckDescription": "Skonfiguruj monitorowanie zdrowia dla {target}",
|
||||
"enableHealthChecks": "Włącz Kontrole Zdrowia",
|
||||
"enableHealthChecksDescription": "Monitoruj zdrowie tego celu. Możesz monitorować inny punkt końcowy niż docelowy w razie potrzeby.",
|
||||
"healthScheme": "Metoda",
|
||||
"healthSelectScheme": "Wybierz metodę",
|
||||
"healthCheckPath": "Ścieżka",
|
||||
"healthHostname": "IP / Nazwa hosta",
|
||||
"healthPort": "Port",
|
||||
"healthCheckPathDescription": "Ścieżka do sprawdzania stanu zdrowia.",
|
||||
"healthyIntervalSeconds": "Interwał Zdrowy",
|
||||
"unhealthyIntervalSeconds": "Interwał Niezdrowy",
|
||||
"IntervalSeconds": "Interwał Zdrowy",
|
||||
"timeoutSeconds": "Limit Czasu",
|
||||
"timeIsInSeconds": "Czas w sekundach",
|
||||
"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.",
|
||||
"customHeaders": "Niestandardowe nagłówki",
|
||||
"customHeadersDescription": "Nagłówki oddzielone: Nazwa nagłówka: wartość",
|
||||
"headersValidationError": "Nagłówki muszą być w formacie: Nazwa nagłówka: wartość.",
|
||||
"saveHealthCheck": "Zapisz Kontrolę Zdrowia",
|
||||
"healthCheckSaved": "Kontrola Zdrowia Zapisana",
|
||||
"healthCheckSavedDescription": "Konfiguracja kontroli zdrowia została zapisana pomyślnie",
|
||||
"healthCheckError": "Błąd Kontroli Zdrowia",
|
||||
"healthCheckErrorDescription": "Wystąpił błąd podczas zapisywania konfiguracji kontroli zdrowia",
|
||||
"healthCheckPathRequired": "Ścieżka kontroli zdrowia jest wymagana",
|
||||
"healthCheckMethodRequired": "Metoda HTTP jest wymagana",
|
||||
"healthCheckIntervalMin": "Interwał sprawdzania musi wynosić co najmniej 5 sekund",
|
||||
"healthCheckTimeoutMin": "Limit czasu musi wynosić co najmniej 1 sekundę",
|
||||
"healthCheckRetryMin": "Liczba prób ponowienia musi wynosić co najmniej 1",
|
||||
"httpMethod": "Metoda HTTP",
|
||||
"selectHttpMethod": "Wybierz metodę HTTP",
|
||||
"domainPickerSubdomainLabel": "Poddomena",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Wprowadź poddomenę, aby wyszukać i wybrać z dostępnych darmowych domen.",
|
||||
"domainPickerFreeDomains": "Darmowe domeny",
|
||||
"domainPickerSearchForAvailableDomains": "Szukaj dostępnych domen",
|
||||
"domainPickerNotWorkSelfHosted": "Uwaga: Darmowe domeny nie są obecnie dostępne dla instancji samodzielnie-hostowanych.",
|
||||
"resourceDomain": "Domena",
|
||||
"resourceEditDomain": "Edytuj domenę",
|
||||
"siteName": "Nazwa strony",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protokół",
|
||||
"editInternalResourceDialogSitePort": "Port witryny",
|
||||
"editInternalResourceDialogTargetConfiguration": "Konfiguracja celu",
|
||||
"editInternalResourceDialogDestinationIP": "IP docelowe",
|
||||
"editInternalResourceDialogDestinationPort": "Port docelowy",
|
||||
"editInternalResourceDialogCancel": "Anuluj",
|
||||
"editInternalResourceDialogSaveResource": "Zapisz zasób",
|
||||
"editInternalResourceDialogSuccess": "Sukces",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Port witryny",
|
||||
"createInternalResourceDialogSitePortDescription": "Użyj tego portu, aby uzyskać dostęp do zasobu na stronie, gdy połączony z klientem.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Konfiguracja celu",
|
||||
"createInternalResourceDialogDestinationIP": "IP docelowe",
|
||||
"createInternalResourceDialogDestinationIPDescription": "Adres IP zasobu w sieci strony.",
|
||||
"createInternalResourceDialogDestinationPort": "Port docelowy",
|
||||
"createInternalResourceDialogDestinationIPDescription": "Adres IP lub nazwa hosta zasobu w sieci witryny.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "Port na docelowym IP, gdzie zasób jest dostępny.",
|
||||
"createInternalResourceDialogCancel": "Anuluj",
|
||||
"createInternalResourceDialogCreateResource": "Utwórz zasób",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Błąd automatycznego logowania",
|
||||
"autoLoginErrorNoRedirectUrl": "Nie otrzymano URL przekierowania od dostawcy tożsamości.",
|
||||
"autoLoginErrorGeneratingUrl": "Nie udało się wygenerować URL uwierzytelniania.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Zdalne węzły",
|
||||
"remoteExitNodeDescription": "Samodzielny host jeden lub więcej węzłów zdalnych, aby rozszerzyć łączność z siecią i zmniejszyć zależność od chmury",
|
||||
"remoteExitNodes": "Węzły",
|
||||
"searchRemoteExitNodes": "Szukaj węzłów...",
|
||||
"remoteExitNodeAdd": "Dodaj węzeł",
|
||||
"remoteExitNodeErrorDelete": "Błąd podczas usuwania węzła",
|
||||
"remoteExitNodeQuestionRemove": "Czy na pewno chcesz usunąć węzeł z organizacji?",
|
||||
"remoteExitNodeMessageRemove": "Po usunięciu, węzeł nie będzie już dostępny.",
|
||||
"remoteExitNodeConfirmDelete": "Potwierdź usunięcie węzła",
|
||||
"remoteExitNodeDelete": "Usuń węzeł",
|
||||
"sidebarRemoteExitNodes": "Zdalne węzły",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Utwórz węzeł",
|
||||
"description": "Utwórz nowy węzeł, aby rozszerzyć połączenie z siecią",
|
||||
"viewAllButton": "Zobacz wszystkie węzły",
|
||||
"strategy": {
|
||||
"title": "Strategia Tworzenia",
|
||||
"description": "Wybierz to, aby ręcznie skonfigurować węzeł lub wygenerować nowe poświadczenia.",
|
||||
"adopt": {
|
||||
"title": "Zaadoptuj Węzeł",
|
||||
"description": "Wybierz to, jeśli masz już dane logowania dla węzła."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Generuj Klucze",
|
||||
"description": "Wybierz to, jeśli chcesz wygenerować nowe klucze dla węzła"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Zaadoptuj Istniejący Węzeł",
|
||||
"description": "Wprowadź dane logowania istniejącego węzła, który chcesz przyjąć",
|
||||
"nodeIdLabel": "ID węzła",
|
||||
"nodeIdDescription": "ID istniejącego węzła, który chcesz przyjąć",
|
||||
"secretLabel": "Sekret",
|
||||
"secretDescription": "Sekretny klucz istniejącego węzła",
|
||||
"submitButton": "Przyjmij węzeł"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Wygenerowane Poświadczenia",
|
||||
"description": "Użyj tych danych logowania, aby skonfigurować węzeł",
|
||||
"nodeIdTitle": "ID węzła",
|
||||
"secretTitle": "Sekret",
|
||||
"saveCredentialsTitle": "Dodaj Poświadczenia do Konfiguracji",
|
||||
"saveCredentialsDescription": "Dodaj te poświadczenia do pliku konfiguracyjnego swojego samodzielnie-hostowanego węzła Pangolin, aby zakończyć połączenie.",
|
||||
"submitButton": "Utwórz węzeł"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "Identyfikator węzła i sekret są wymagane podczas przyjmowania istniejącego węzła"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Nie udało się załadować domyślnych ustawień",
|
||||
"defaultsNotLoaded": "Domyślne ustawienia nie zostały załadowane",
|
||||
"createFailed": "Nie udało się utworzyć węzła"
|
||||
},
|
||||
"success": {
|
||||
"created": "Węzeł utworzony pomyślnie"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Wybór węzła",
|
||||
"remoteExitNodeSelectionDescription": "Wybierz węzeł do przekierowania ruchu dla tej lokalnej witryny",
|
||||
"remoteExitNodeRequired": "Węzeł musi być wybrany dla lokalnych witryn",
|
||||
"noRemoteExitNodesAvailable": "Brak dostępnych węzłów",
|
||||
"noRemoteExitNodesAvailableDescription": "Węzły nie są dostępne dla tej organizacji. Utwórz węzeł, aby używać lokalnych witryn.",
|
||||
"exitNode": "Węzeł Wyjściowy",
|
||||
"country": "Kraj",
|
||||
"rulesMatchCountry": "Obecnie bazuje na adresie IP źródła",
|
||||
"managedSelfHosted": {
|
||||
"title": "Zarządzane Samodzielnie-Hostingowane",
|
||||
"description": "Większa niezawodność i niska konserwacja serwera Pangolin z dodatkowymi dzwonkami i sygnałami",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Konwertuj ten węzeł do zarządzanego samodzielnie"
|
||||
},
|
||||
"internationaldomaindetected": "Wykryto międzynarodową domenę",
|
||||
"willbestoredas": "Będą przechowywane jako:"
|
||||
}
|
||||
"willbestoredas": "Będą przechowywane jako:",
|
||||
"roleMappingDescription": "Określ jak role są przypisywane do użytkowników podczas logowania się, gdy automatyczne świadczenie jest włączone.",
|
||||
"selectRole": "Wybierz rolę",
|
||||
"roleMappingExpression": "Wyrażenie",
|
||||
"selectRolePlaceholder": "Wybierz rolę",
|
||||
"selectRoleDescription": "Wybierz rolę do przypisania wszystkim użytkownikom od tego dostawcy tożsamości",
|
||||
"roleMappingExpressionDescription": "Wprowadź wyrażenie JMESŚcieżki, aby wyodrębnić informacje o roli z tokenu ID",
|
||||
"idpTenantIdRequired": "ID lokatora jest wymagane",
|
||||
"invalidValue": "Nieprawidłowa wartość",
|
||||
"idpTypeLabel": "Typ dostawcy tożsamości",
|
||||
"roleMappingExpressionPlaceholder": "np. zawiera(grupy, 'admin') && 'Admin' || 'Członek'",
|
||||
"idpGoogleConfiguration": "Konfiguracja Google",
|
||||
"idpGoogleConfigurationDescription": "Skonfiguruj swoje poświadczenia Google OAuth2",
|
||||
"idpGoogleClientIdDescription": "Twój identyfikator klienta Google OAuth2",
|
||||
"idpGoogleClientSecretDescription": "Twój klucz klienta Google OAuth2",
|
||||
"idpAzureConfiguration": "Konfiguracja Azure Entra ID",
|
||||
"idpAzureConfigurationDescription": "Skonfiguruj swoje dane logowania OAuth2 Azure Entra",
|
||||
"idpTenantId": "ID Najemcy",
|
||||
"idpTenantIdPlaceholder": "twoj-lokator",
|
||||
"idpAzureTenantIdDescription": "Twój identyfikator dzierżawcy Azure (znaleziony w Podglądzie Azure Active Directory",
|
||||
"idpAzureClientIdDescription": "Twój identyfikator klienta rejestracji aplikacji Azure",
|
||||
"idpAzureClientSecretDescription": "Klucz tajny Twojego klienta rejestracji aplikacji Azure",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Konfiguracja Google",
|
||||
"idpAzureConfigurationTitle": "Konfiguracja Azure Entra ID",
|
||||
"idpTenantIdLabel": "ID Najemcy",
|
||||
"idpAzureClientIdDescription2": "Twój identyfikator klienta rejestracji aplikacji Azure",
|
||||
"idpAzureClientSecretDescription2": "Klucz tajny Twojego klienta rejestracji aplikacji Azure",
|
||||
"idpGoogleDescription": "Dostawca Google OAuth2/OIDC",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Podsieć",
|
||||
"subnetDescription": "Podsieć dla konfiguracji sieci tej organizacji.",
|
||||
"authPage": "Strona uwierzytelniania",
|
||||
"authPageDescription": "Skonfiguruj stronę uwierzytelniania dla swojej organizacji",
|
||||
"authPageDomain": "Domena strony uwierzytelniania",
|
||||
"noDomainSet": "Nie ustawiono domeny",
|
||||
"changeDomain": "Zmień domenę",
|
||||
"selectDomain": "Wybierz domenę",
|
||||
"restartCertificate": "Uruchom ponownie certyfikat",
|
||||
"editAuthPageDomain": "Edytuj domenę strony uwierzytelniania",
|
||||
"setAuthPageDomain": "Ustaw domenę strony uwierzytelniania",
|
||||
"failedToFetchCertificate": "Nie udało się pobrać certyfikatu",
|
||||
"failedToRestartCertificate": "Nie udało się ponownie uruchomić certyfikatu",
|
||||
"addDomainToEnableCustomAuthPages": "Dodaj domenę, aby włączyć niestandardowe strony uwierzytelniania dla Twojej organizacji",
|
||||
"selectDomainForOrgAuthPage": "Wybierz domenę dla strony uwierzytelniania organizacji",
|
||||
"domainPickerProvidedDomain": "Dostarczona domena",
|
||||
"domainPickerFreeProvidedDomain": "Darmowa oferowana domena",
|
||||
"domainPickerVerified": "Zweryfikowano",
|
||||
"domainPickerUnverified": "Niezweryfikowane",
|
||||
"domainPickerInvalidSubdomainStructure": "Ta subdomena zawiera nieprawidłowe znaki lub strukturę. Zostanie ona automatycznie oczyszczona po zapisaniu.",
|
||||
"domainPickerError": "Błąd",
|
||||
"domainPickerErrorLoadDomains": "Nie udało się załadować domen organizacji",
|
||||
"domainPickerErrorCheckAvailability": "Nie udało się sprawdzić dostępności domeny",
|
||||
"domainPickerInvalidSubdomain": "Nieprawidłowa subdomena",
|
||||
"domainPickerInvalidSubdomainRemoved": "Wejście \"{sub}\" zostało usunięte, ponieważ jest nieprawidłowe.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" nie może być poprawne dla {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Poddomena oczyszczona",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" został skorygowany do \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Zaloguj się do swojej organizacji",
|
||||
"orgAuthChooseIdpDescription": "Wybierz swojego dostawcę tożsamości, aby kontynuować",
|
||||
"orgAuthNoIdpConfigured": "Ta organizacja nie ma skonfigurowanych żadnych dostawców tożsamości. Zamiast tego możesz zalogować się za pomocą swojej tożsamości Pangolin.",
|
||||
"orgAuthSignInWithPangolin": "Zaloguj się używając Pangolin",
|
||||
"subscriptionRequiredToUse": "Do korzystania z tej funkcji wymagana jest subskrypcja.",
|
||||
"idpDisabled": "Dostawcy tożsamości są wyłączeni",
|
||||
"orgAuthPageDisabled": "Strona autoryzacji organizacji jest wyłączona.",
|
||||
"domainRestartedDescription": "Weryfikacja domeny zrestartowana pomyślnie",
|
||||
"resourceAddEntrypointsEditFile": "Edytuj plik: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Edytuj plik: docker-compose.yml",
|
||||
"emailVerificationRequired": "Weryfikacja adresu e-mail jest wymagana. Zaloguj się ponownie przez {dashboardUrl}/auth/login zakończył ten krok. Następnie wróć tutaj.",
|
||||
"twoFactorSetupRequired": "Konfiguracja uwierzytelniania dwuskładnikowego jest wymagana. Zaloguj się ponownie przez {dashboardUrl}/auth/login dokończ ten krok. Następnie wróć tutaj.",
|
||||
"additionalSecurityRequired": "Wymagane dodatkowe zabezpieczenie",
|
||||
"organizationRequiresAdditionalSteps": "Ta organizacja wymaga dodatkowych kroków bezpieczeństwa, zanim będziesz mógł uzyskać dostęp do zasobów.",
|
||||
"completeTheseSteps": "Wykonaj te kroki",
|
||||
"enableTwoFactorAuthentication": "Włącz uwierzytelnianie dwuskładnikowe",
|
||||
"completeSecuritySteps": "Zakończ kroki bezpieczeństwa",
|
||||
"securitySettings": "Ustawienia zabezpieczeń",
|
||||
"securitySettingsDescription": "Skonfiguruj politykę bezpieczeństwa dla Twojej organizacji",
|
||||
"requireTwoFactorForAllUsers": "Wymagaj uwierzytelniania dwuetapowego dla wszystkich użytkowników",
|
||||
"requireTwoFactorDescription": "Po włączeniu wszyscy użytkownicy wewnętrzni w tej organizacji muszą mieć włączone uwierzytelnianie dwuskładnikowe, aby uzyskać dostęp do organizacji.",
|
||||
"requireTwoFactorDisabledDescription": "Ta funkcja wymaga poprawnej licencji (Enterprise) lub aktywnej subskrypcji (SaaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "Musisz włączyć uwierzytelnianie dwuskładnikowe dla swojego konta przed wymuszaniem go dla wszystkich użytkowników",
|
||||
"maxSessionLength": "Maksymalna długość sesji",
|
||||
"maxSessionLengthDescription": "Ustaw maksymalny czas trwania sesji użytkownika. Po tym czasie użytkownicy będą musieli ponownie uwierzytelniać.",
|
||||
"maxSessionLengthDisabledDescription": "Ta funkcja wymaga poprawnej licencji (Enterprise) lub aktywnej subskrypcji (SaaaS)",
|
||||
"selectSessionLength": "Wybierz długość sesji",
|
||||
"unenforced": "Niewymuszony",
|
||||
"1Hour": "1 godzina",
|
||||
"3Hours": "3 godziny",
|
||||
"6Hours": "6 godzin",
|
||||
"12Hours": "12 godzin",
|
||||
"1DaySession": "1 dzień",
|
||||
"3Days": "3 dni",
|
||||
"7Days": "7 dni",
|
||||
"14Days": "14 dni",
|
||||
"30DaysSession": "30 dni",
|
||||
"90DaysSession": "90 dni",
|
||||
"180DaysSession": "180 dni",
|
||||
"passwordExpiryDays": "Hasło wygasa",
|
||||
"editPasswordExpiryDescription": "Ustaw liczbę dni zanim użytkownicy będą musieli zmienić swoje hasło.",
|
||||
"selectPasswordExpiry": "Wybierz wygasanie hasła",
|
||||
"30Days": "30 dni",
|
||||
"1Day": "1 dzień",
|
||||
"60Days": "60 dni",
|
||||
"90Days": "90 dni",
|
||||
"180Days": "180 dni",
|
||||
"1Year": "1 rok",
|
||||
"subscriptionBadge": "Wymagana subskrypcja",
|
||||
"securityPolicyChangeWarning": "Ostrzeżenie o zmianach w polityce bezpieczeństwa",
|
||||
"securityPolicyChangeDescription": "Zamierzasz zmienić ustawienia polityki bezpieczeństwa. Po zapisaniu konieczne może być ponowne uwierzytelnienie w celu zapewnienia zgodności z tymi aktualizacjami polityki. Wszyscy użytkownicy, którzy nie są zgodni, będą również musieli ponownie uwierzytelniać.",
|
||||
"securityPolicyChangeConfirmMessage": "Potwierdzam",
|
||||
"securityPolicyChangeWarningText": "To wpłynie na wszystkich użytkowników w organizacji",
|
||||
"authPageErrorUpdateMessage": "Wystąpił błąd podczas aktualizacji ustawień strony uwierzytelniania",
|
||||
"authPageErrorUpdate": "Nie można zaktualizować strony uwierzytelniania",
|
||||
"authPageUpdated": "Strona uwierzytelniania została pomyślnie zaktualizowana",
|
||||
"healthCheckNotAvailable": "Lokalny",
|
||||
"rewritePath": "Przepis Ścieżki",
|
||||
"rewritePathDescription": "Opcjonalnie przepisz ścieżkę przed przesłaniem do celu.",
|
||||
"continueToApplication": "Kontynuuj do aplikacji",
|
||||
"checkingInvite": "Sprawdzanie zaproszenia",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Usuń autoryzację nagłówka",
|
||||
"resourceHeaderAuthRemoveDescription": "Uwierzytelnianie nagłówka zostało pomyślnie usunięte.",
|
||||
"resourceErrorHeaderAuthRemove": "Nie udało się usunąć uwierzytelniania nagłówka",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Nie można usunąć uwierzytelniania nagłówka zasobu.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Uwierzytelnianie nagłówka włączone",
|
||||
"resourceHeaderAuthProtectionDisabled": "Uwierzytelnianie nagłówka wyłączone",
|
||||
"headerAuthRemove": "Usuń autoryzację nagłówka",
|
||||
"headerAuthAdd": "Dodaj Autoryzacja nagłówka",
|
||||
"resourceErrorHeaderAuthSetup": "Nie udało się ustawić uwierzytelniania nagłówka",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Nie można ustawić uwierzytelniania nagłówka dla zasobu.",
|
||||
"resourceHeaderAuthSetup": "Uwierzytelnianie nagłówka ustawione pomyślnie",
|
||||
"resourceHeaderAuthSetupDescription": "Uwierzytelnianie nagłówka zostało ustawione.",
|
||||
"resourceHeaderAuthSetupTitle": "Ustaw uwierzytelnianie nagłówka",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Ustaw podstawowe dane uwierzytelniające (nazwa użytkownika i hasło), aby chronić ten zasób za pomocą uwierzytelniania nagłówka HTTP. Uzyskaj dostęp za pomocą formatu https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Ustaw uwierzytelnianie nagłówka",
|
||||
"actionSetResourceHeaderAuth": "Ustaw uwierzytelnianie nagłówka",
|
||||
"enterpriseEdition": "Edycja Enterprise",
|
||||
"unlicensed": "Nielicencjonowane",
|
||||
"beta": "Beta",
|
||||
"manageClients": "Zarządzaj klientami",
|
||||
"manageClientsDescription": "Klienci to urządzenia, które mogą łączyć się z Twoimi witrynami",
|
||||
"licenseTableValidUntil": "Ważny do",
|
||||
"saasLicenseKeysSettingsTitle": "Licencje przedsiębiorstwa",
|
||||
"saasLicenseKeysSettingsDescription": "Generuj i zarządzaj kluczami licencyjnymi Enterprise dla samodzielnych instancji Pangolin",
|
||||
"sidebarEnterpriseLicenses": "Licencje",
|
||||
"generateLicenseKey": "Generuj klucz licencyjny",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Wprowadź poprawny adres e-mail",
|
||||
"useCaseTypeRequired": "Proszę wybrać typ litery",
|
||||
"firstNameRequired": "Imię jest wymagane",
|
||||
"lastNameRequired": "Nazwisko jest wymagane",
|
||||
"primaryUseRequired": "Opisz swoje podstawowe użycie",
|
||||
"jobTitleRequiredBusiness": "Tytuł pracy jest wymagany do użytku służbowego",
|
||||
"industryRequiredBusiness": "Przemysł jest wymagany do celów biznesowych.",
|
||||
"stateProvinceRegionRequired": "Wymagany jest stan/województwo/region",
|
||||
"postalZipCodeRequired": "Kod pocztowy jest wymagany",
|
||||
"companyNameRequiredBusiness": "Nazwa firmy jest wymagana do użytku służbowego",
|
||||
"countryOfResidenceRequiredBusiness": "Kraj zamieszkania jest wymagany do celów służbowych",
|
||||
"countryRequiredPersonal": "Kraj jest wymagany do użytku osobistego",
|
||||
"agreeToTermsRequired": "Musisz zaakceptować regulamin",
|
||||
"complianceConfirmationRequired": "Musisz potwierdzić zgodność z Fossorial Commercial License"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Użytkowanie osobiste",
|
||||
"description": "Dla celów indywidualnych, niekomercyjnych, takich jak nauka, projekty osobiste lub eksperymenty."
|
||||
},
|
||||
"business": {
|
||||
"title": "Wykorzystanie służbowe",
|
||||
"description": "Do użytku w ramach organizacji, przedsiębiorstw lub działalności komercyjnej lub generującej dochody."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Typ adresu e-mail i licencji",
|
||||
"description": "Wprowadź swój adres e-mail i wybierz rodzaj licencji"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Informacje osobiste",
|
||||
"description": "Powiedz nam o sobie"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Informacje kontaktowe",
|
||||
"description": "Twoje dane kontaktowe"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Reguły i generuj",
|
||||
"description": "Przejrzyj i zaakceptuj warunki generowania licencji"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Ujawnienie użycia",
|
||||
"description": "Wybierz poziom licencji, który dokładnie odzwierciedla zamierzone użycie. Licencja osobista pozwala na bezpłatne wykorzystanie oprogramowania do działalności komercyjnej, o charakterze indywidualnym, niekomercyjnym lub na małą skalę, o rocznym dochodzie brutto poniżej 100 000 USD. Wszelkie zastosowania wykraczające poza te ograniczenia – w tym wykorzystanie w przedsiębiorstwie, organizacja, lub inne środowisko generujące dochód – wymaga ważnej licencji przedsiębiorstwa i uiszczenia stosownej opłaty licencyjnej. Wszyscy użytkownicy, niezależnie od tego, czy są prywatni czy przedsiębiorcy, muszą przestrzegać warunków licencji Fossorial Commercial License."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Informacje o okresie próbnym",
|
||||
"description": "Ten klucz licencyjny umożliwia przedsiębiorstwom funkcje na 7-dniowy okres oceny. Ciągły dostęp do płatnych funkcji po zakończeniu okresu oceny wymaga aktywacji na podstawie ważnej licencji osobistej lub prywatnej. W celu uzyskania licencji przedsiębiorstwa skontaktuj się z sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Używasz Pangolin do użytku osobistego lub biznesowego?",
|
||||
"firstName": "Imię",
|
||||
"lastName": "Nazwisko",
|
||||
"jobTitle": "Tytuł zadania",
|
||||
"primaryUseQuestion": "Na co planujesz przede wszystkim stosować lek Pangolin?",
|
||||
"industryQuestion": "Jaki jest twój przemysł?",
|
||||
"prospectiveUsersQuestion": "Ilu potencjalnych użytkowników oczekujesz?",
|
||||
"prospectiveSitesQuestion": "Ile potencjalnych stron (tuneli) oczekujesz?",
|
||||
"companyName": "Nazwa firmy",
|
||||
"countryOfResidence": "Kraj zamieszkania",
|
||||
"stateProvinceRegion": "Województwo / Region",
|
||||
"postalZipCode": "Kod pocztowy",
|
||||
"companyWebsite": "Strona internetowa firmy",
|
||||
"companyPhoneNumber": "Numer telefonu firmy",
|
||||
"country": "Kraj",
|
||||
"phoneNumberOptional": "Numer telefonu (opcjonalnie)",
|
||||
"complianceConfirmation": "Potwierdzam, że podane przeze mnie informacje są dokładne i że jestem zgodny z Fossorial Commercial License. Zgłaszanie nieprawidłowych informacji lub błędne oznaczanie użycia produktu jest naruszeniem licencji i może skutkować cofnięciem klucza."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Zamknij",
|
||||
"previous": "Poprzedni",
|
||||
"next": "Następny",
|
||||
"generateLicenseKey": "Generuj klucz licencyjny"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Klucz licencyjny wygenerowany pomyślnie",
|
||||
"description": "Twój klucz licencyjny został wygenerowany i jest gotowy do użycia."
|
||||
},
|
||||
"error": {
|
||||
"title": "Nie udało się wygenerować klucza licencyjnego",
|
||||
"description": "Wystąpił błąd podczas generowania klucza licencji."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Priorytet",
|
||||
"priorityDescription": "Najpierw oceniane są trasy priorytetowe. Priorytet = 100 oznacza automatyczne zamawianie (decyzje systemowe). Użyj innego numeru, aby wyegzekwować ręczny priorytet.",
|
||||
"instanceName": "Nazwa instancji",
|
||||
"pathMatchModalTitle": "Skonfiguruj dopasowanie ścieżki",
|
||||
"pathMatchModalDescription": "Skonfiguruj sposób dopasowania przychodzących żądań na podstawie ich ścieżki.",
|
||||
"pathMatchType": "Typ dopasowania",
|
||||
"pathMatchPrefix": "Prefiks",
|
||||
"pathMatchExact": "Dokładny",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Wartość ścieżki",
|
||||
"clear": "Wyczyść",
|
||||
"saveChanges": "Zapisz zmiany",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/ścieżka",
|
||||
"pathMatchPrefixHelp": "Przykład: /api pasuje do /api, /api/users itp.",
|
||||
"pathMatchExactHelp": "Przykład: /api pasuje tylko /api",
|
||||
"pathMatchRegexHelp": "Przykład: ^/api/.* pasuje do /api/cokolwiek",
|
||||
"pathRewriteModalTitle": "Konfiguruj Przepisywanie Ścieżki",
|
||||
"pathRewriteModalDescription": "Przekształć dopasowaną ścieżkę przed przekierowaniem do celu.",
|
||||
"pathRewriteType": "Typ przekierowania",
|
||||
"pathRewritePrefixOption": "Prefiks - Zamień prefiks",
|
||||
"pathRewriteExactOption": "Dokładny - Zamień całą ścieżkę",
|
||||
"pathRewriteRegexOption": "Regex - zamiennik wzoru",
|
||||
"pathRewriteStripPrefixOption": "Prefiks paska - Usuń prefiks",
|
||||
"pathRewriteValue": "Przepisz wartość",
|
||||
"pathRewriteRegexPlaceholder": "/nowy/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "Zastąp dopasowany prefiks tą wartością",
|
||||
"pathRewriteExactHelp": "Zastąp całą ścieżkę tą wartością, gdy ścieżka dokładnie pasuje do siebie",
|
||||
"pathRewriteRegexHelp": "Użyj grup przechwytywania takich jak $1, $2 do zamiany",
|
||||
"pathRewriteStripPrefixHelp": "Pozostaw puste, aby usunąć prefiks lub podać nowy prefiks",
|
||||
"pathRewritePrefix": "Prefiks",
|
||||
"pathRewriteExact": "Dokładny",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Pasek",
|
||||
"pathRewriteStripLabel": "pasek",
|
||||
"sidebarEnableEnterpriseLicense": "Włącz licencję przedsiębiorstwa",
|
||||
"cannotbeUndone": "Tej operacji nie można cofnąć.",
|
||||
"toConfirm": "potwierdzić",
|
||||
"deleteClientQuestion": "Czy na pewno chcesz usunąć klienta z witryny i organizacji?",
|
||||
"clientMessageRemove": "Po usunięciu, klient nie będzie już mógł połączyć się z witryną.",
|
||||
"sidebarLogs": "Logi",
|
||||
"request": "Żądanie",
|
||||
"logs": "Logi",
|
||||
"logsSettingsDescription": "Monitoruj logi zebrane z tej orginizacji",
|
||||
"searchLogs": "Szukaj dzienników...",
|
||||
"action": "Akcja",
|
||||
"actor": "Aktor",
|
||||
"timestamp": "Znacznik czasu",
|
||||
"accessLogs": "Logi dostępu",
|
||||
"exportCsv": "Eksportuj CSV",
|
||||
"actorId": "Identyfikator podmiotu",
|
||||
"allowedByRule": "Dozwolone przez regułę",
|
||||
"allowedNoAuth": "Dozwolone Brak Auth",
|
||||
"validAccessToken": "Ważny token dostępu",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Prawidłowe hasło",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Zasób zablokowany",
|
||||
"droppedByRule": "Upuszczone przez regułę",
|
||||
"noSessions": "Brak sesji",
|
||||
"temporaryRequestToken": "Tymczasowy token żądania",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Powód",
|
||||
"requestLogs": "Dzienniki żądań",
|
||||
"host": "Host",
|
||||
"location": "Lokalizacja",
|
||||
"actionLogs": "Dzienniki działań",
|
||||
"sidebarLogsRequest": "Dzienniki żądań",
|
||||
"sidebarLogsAccess": "Logi dostępu",
|
||||
"sidebarLogsAction": "Dzienniki działań",
|
||||
"logRetention": "Zachowanie dziennika",
|
||||
"logRetentionDescription": "Zarządzaj jak długo różne typy logów są zachowane dla tej organizacji lub wyłącz je",
|
||||
"requestLogsDescription": "Zobacz szczegółowe dzienniki żądań zasobów w tej organizacji",
|
||||
"logRetentionRequestLabel": "Zachowanie dziennika żądań",
|
||||
"logRetentionRequestDescription": "Jak długo zachować dzienniki żądań",
|
||||
"logRetentionAccessLabel": "Zachowanie dziennika dostępu",
|
||||
"logRetentionAccessDescription": "Jak długo zachować dzienniki dostępu",
|
||||
"logRetentionActionLabel": "Zachowanie dziennika akcji",
|
||||
"logRetentionActionDescription": "Jak długo zachować dzienniki akcji",
|
||||
"logRetentionDisabled": "Wyłączone",
|
||||
"logRetention3Days": "3 dni",
|
||||
"logRetention7Days": "7 dni",
|
||||
"logRetention14Days": "14 dni",
|
||||
"logRetention30Days": "30 dni",
|
||||
"logRetention90Days": "90 dni",
|
||||
"logRetentionForever": "Na zawsze",
|
||||
"actionLogsDescription": "Zobacz historię działań wykonywanych w tej organizacji",
|
||||
"accessLogsDescription": "Wyświetl prośby o autoryzację dostępu do zasobów w tej organizacji",
|
||||
"licenseRequiredToUse": "Licencja Enterprise jest wymagana do korzystania z tej funkcji.",
|
||||
"certResolver": "Rozwiązywanie certyfikatów",
|
||||
"certResolverDescription": "Wybierz resolver certyfikatów do użycia dla tego zasobu.",
|
||||
"selectCertResolver": "Wybierz Resolver certyfikatów",
|
||||
"enterCustomResolver": "Wprowadź niestandardowy Resolver",
|
||||
"preferWildcardCert": "Preferuj Certyfikat Wildcard",
|
||||
"unverified": "Niezweryfikowane",
|
||||
"domainSetting": "Ustawienia domeny",
|
||||
"domainSettingDescription": "Skonfiguruj ustawienia domeny",
|
||||
"preferWildcardCertDescription": "Próba wygenerowania certyfikatu wieloznacznego (wymaga poprawnie skonfigurowanego resolwera certyfikatów).",
|
||||
"recordName": "Nazwa rekordu",
|
||||
"auto": "Auto",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Jak dodać rekordy",
|
||||
"dnsRecord": "Wpisy DNS",
|
||||
"required": "Wymagane",
|
||||
"domainSettingsUpdated": "Ustawienia domeny zaktualizowane pomyślnie",
|
||||
"orgOrDomainIdMissing": "Brakuje identyfikatora organizacji lub domeny",
|
||||
"loadingDNSRecords": "Ładowanie rekordów DNS...",
|
||||
"olmUpdateAvailableInfo": "Dostępna jest zaktualizowana wersja Olm. Zaktualizuj do najnowszej wersji, aby uzyskać najlepsze doświadczenia.",
|
||||
"client": "Klient",
|
||||
"proxyProtocol": "Ustawienia protokołu proxy",
|
||||
"proxyProtocolDescription": "Skonfiguruj protokół Proxy aby zachować adresy IP klienta dla usług TCP/UDP.",
|
||||
"enableProxyProtocol": "Włącz protokół proxy",
|
||||
"proxyProtocolInfo": "Zachowaj adresy IP klienta dla backendów TCP/UDP",
|
||||
"proxyProtocolVersion": "Wersja protokołu proxy",
|
||||
"version1": " Wersja 1 (zalecane)",
|
||||
"version2": "Wersja 2",
|
||||
"versionDescription": "Wersja 1 jest oparta na tekście i szeroko wspierana. Wersja 2 jest binarna i bardziej efektywna, ale mniej kompatybilna.",
|
||||
"warning": "Ostrzeżenie",
|
||||
"proxyProtocolWarning": "Twoja aplikacja backend musi być skonfigurowana tak, aby przyjmować połączenia z protokołem proxy. Jeśli Twój backend nie obsługuje protokołu proxy, włączenie to spowoduje przerwanie wszystkich połączeń. Upewnij się, że konfiguracja twojego backendu do zaufanych nagłówków protokołu proxy z Traefik.",
|
||||
"restarting": "Restartowanie...",
|
||||
"manual": "Ręcznie",
|
||||
"messageSupport": "Obsługa wiadomości",
|
||||
"supportNotAvailableTitle": "Wsparcie niedostępne",
|
||||
"supportNotAvailableDescription": "Wsparcie nie jest teraz dostępne. Możesz wysłać e-mail na adres support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Prośba o wsparcie wysłana",
|
||||
"supportRequestSentDescription": "Wiadomość została wysłana pomyślnie.",
|
||||
"supportRequestFailedTitle": "Nie udało się wysłać żądania",
|
||||
"supportRequestFailedDescription": "Wystąpił błąd podczas wysyłania prośby o wsparcie.",
|
||||
"supportSubjectRequired": "Temat jest wymagany",
|
||||
"supportSubjectMaxLength": "Temat musi mieć 255 znaków lub mniej",
|
||||
"supportMessageRequired": "Wiadomość jest wymagana",
|
||||
"supportReplyTo": "Odpowiedź do",
|
||||
"supportSubject": "Temat",
|
||||
"supportSubjectPlaceholder": "Wprowadź temat",
|
||||
"supportMessage": "Wiadomość",
|
||||
"supportMessagePlaceholder": "Wprowadź swoją wiadomość",
|
||||
"supportSending": "Wysyłanie...",
|
||||
"supportSend": "Wyślij",
|
||||
"supportMessageSent": "Wiadomość wysłana!",
|
||||
"supportWillContact": "Wkrótce będziemy w kontakcie!",
|
||||
"selectLogRetention": "Wybierz zatrzymanie dziennika",
|
||||
"showColumns": "Pokaż kolumny",
|
||||
"hideColumns": "Ukryj kolumny",
|
||||
"columnVisibility": "Widoczność kolumn",
|
||||
"toggleColumn": "Przełącz kolumnę {columnName}",
|
||||
"allColumns": "Wszystkie kolumny",
|
||||
"defaultColumns": "Kolumny domyślne",
|
||||
"customizeView": "Dostosuj widok",
|
||||
"viewOptions": "Opcje widoku",
|
||||
"selectAll": "Zaznacz wszystko",
|
||||
"selectNone": "Nie wybierz żadnego",
|
||||
"selectedResources": "Wybrane Zasoby",
|
||||
"enableSelected": "Włącz zaznaczone",
|
||||
"disableSelected": "Wyłącz zaznaczone",
|
||||
"checkSelectedStatus": "Sprawdź status zaznaczonych"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,9 +47,8 @@
|
||||
"edit": "Редактировать",
|
||||
"siteConfirmDelete": "Подтвердить удаление сайта",
|
||||
"siteDelete": "Удалить сайт",
|
||||
"siteMessageRemove": "После удаления сайт больше не будет доступен. Все ресурсы и целевые узлы, связанные с сайтом, также будут удалены.",
|
||||
"siteMessageConfirm": "Для подтверждения введите название сайта ниже.",
|
||||
"siteQuestionRemove": "Вы уверены, что хотите удалить сайт {selectedSite} из организации?",
|
||||
"siteMessageRemove": "После удаления сайт больше не будет доступен. Все цели, связанные с сайтом, также будут удалены.",
|
||||
"siteQuestionRemove": "Вы уверены, что хотите удалить сайт из организации?",
|
||||
"siteManageSites": "Управление сайтами",
|
||||
"siteDescription": "Обеспечьте подключение к вашей сети через защищённые туннели",
|
||||
"siteCreate": "Создать сайт",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Используйте любой клиент WireGuard для открытия туннеля. Требуется ручная настройка NAT.",
|
||||
"siteWgDescriptionSaas": "Используйте любой клиент WireGuard для создания туннеля. Требуется ручная настройка NAT. РАБОТАЕТ ТОЛЬКО НА САМОСТОЯТЕЛЬНО РАЗМЕЩЕННЫХ УЗЛАХ",
|
||||
"siteLocalDescription": "Только локальные ресурсы. Без туннелирования.",
|
||||
"siteLocalDescriptionSaas": "Только локальные ресурсы. Без туннелирования. РАБОТАЕТ ТОЛЬКО НА САМОСТОЯТЕЛЬНО РАЗМЕЩЕННЫХ УЗЛАХ",
|
||||
"siteLocalDescriptionSaas": "Только локальные ресурсы. Нет туннелей. Только для удаленных узлов.",
|
||||
"siteSeeAll": "Просмотреть все сайты",
|
||||
"siteTunnelDescription": "Выберите способ подключения к вашему сайту",
|
||||
"siteNewtCredentials": "Учётные данные Newt",
|
||||
@@ -132,7 +131,7 @@
|
||||
"expireIn": "Срок действия",
|
||||
"neverExpire": "Бессрочный доступ",
|
||||
"shareExpireDescription": "Срок действия - это период, в течение которого ссылка будет работать и предоставлять доступ к ресурсу. После этого времени ссылка перестанет работать, и пользователи, использовавшие эту ссылку, потеряют доступ к ресурсу.",
|
||||
"shareSeeOnce": "Вы сможете увидеть эту ссылку только один раз. Обязательно скопируйте её.",
|
||||
"shareSeeOnce": "Вы сможете увидеть эту ссылку только один раз. Обязательно скопируйте ее.",
|
||||
"shareAccessHint": "Любой, у кого есть эта ссылка, может получить доступ к ресурсу. Делитесь ею с осторожностью.",
|
||||
"shareTokenUsage": "Посмотреть использование токена доступа",
|
||||
"createLink": "Создать ссылку",
|
||||
@@ -154,8 +153,7 @@
|
||||
"protected": "Защищён",
|
||||
"notProtected": "Не защищён",
|
||||
"resourceMessageRemove": "После удаления ресурс больше не будет доступен. Все целевые узлы, связанные с ресурсом, также будут удалены.",
|
||||
"resourceMessageConfirm": "Для подтверждения введите название ресурса ниже.",
|
||||
"resourceQuestionRemove": "Вы действительно хотите удалить ресурс {selectedResource} из организации?",
|
||||
"resourceQuestionRemove": "Вы уверены, что хотите удалить ресурс из организации?",
|
||||
"resourceHTTP": "HTTPS-ресурс",
|
||||
"resourceHTTPDescription": "Проксирование запросов к вашему приложению через HTTPS с использованием поддомена или базового домена.",
|
||||
"resourceRaw": "Сырой TCP/UDP-ресурс",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Выберите сайт",
|
||||
"siteSearch": "Поиск сайта",
|
||||
"siteNotFound": "Сайт не найден.",
|
||||
"selectCountry": "Выберите страну",
|
||||
"searchCountries": "Поиск стран...",
|
||||
"noCountryFound": "Страна не найдена.",
|
||||
"siteSelectionDescription": "Этот сайт предоставит подключение к цели.",
|
||||
"resourceType": "Тип ресурса",
|
||||
"resourceTypeDescription": "Определите, как вы хотите получать доступ к вашему ресурсу",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Базовый домен",
|
||||
"subdomnainDescription": "Поддомен, на котором будет доступен ресурс.",
|
||||
"resourceRawSettings": "Настройки TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Настройте, как будет осуществляться доступ к вашему ресурсу через TCP/UDP",
|
||||
"resourceRawSettingsDescription": "Настройте доступ к вашему ресурсу по TCP/UDP. Вы соотносите ресурс с портом на сервере хоста Pangolin, так что вы можете получить доступ к ресурсу с сервера server-public-ip:mapped-порта.",
|
||||
"protocol": "Протокол",
|
||||
"protocolSelect": "Выберите протокол",
|
||||
"resourcePortNumber": "Номер порта",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Подтвердить удаление",
|
||||
"orgMessageRemove": "Это действие необратимо и удалит все связанные данные.",
|
||||
"orgMessageConfirm": "Для подтверждения введите название организации ниже.",
|
||||
"orgQuestionRemove": "Вы действительно хотите удалить организацию {selectedOrg}?",
|
||||
"orgQuestionRemove": "Вы уверены, что хотите удалить организацию?",
|
||||
"orgUpdated": "Организация обновлена",
|
||||
"orgUpdatedDescription": "Организация была успешно обновлена.",
|
||||
"orgErrorUpdate": "Не удалось обновить организацию",
|
||||
@@ -236,7 +237,7 @@
|
||||
"accessUserCreate": "Создать пользователя",
|
||||
"accessUserRemove": "Удалить пользователя",
|
||||
"username": "Имя пользователя",
|
||||
"identityProvider": "Identity Provider",
|
||||
"identityProvider": "Поставщик удостоверений",
|
||||
"role": "Роль",
|
||||
"nameRequired": "Имя обязательно",
|
||||
"accessRolesManage": "Управление ролями",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "Сгенерировать ключ API",
|
||||
"apiKeysErrorDelete": "Ошибка при удалении ключа API",
|
||||
"apiKeysErrorDeleteMessage": "Не удалось удалить ключ API",
|
||||
"apiKeysQuestionRemove": "Вы действительно хотите удалить ключ API {selectedApiKey} из организации?",
|
||||
"apiKeysQuestionRemove": "Вы уверены, что хотите удалить API ключ из организации?",
|
||||
"apiKeysMessageRemove": "После удаления ключ API больше сможет быть использован.",
|
||||
"apiKeysMessageConfirm": "Для подтверждения введите название ключа API ниже.",
|
||||
"apiKeysDeleteConfirm": "Подтвердить удаление",
|
||||
"apiKeysDelete": "Удаление ключа API",
|
||||
"apiKeysManage": "Управление ключами API",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Подтвердить удаление",
|
||||
"userDeleteServer": "Удаление пользователя с сервера",
|
||||
"userMessageRemove": "Пользователь будет удалён из всех организаций и полностью удалён с сервера.",
|
||||
"userMessageConfirm": "Для подтверждения введите имя пользователя ниже.",
|
||||
"userQuestionRemove": "Вы действительно хотите навсегда удалить {selectedUser} с сервера?",
|
||||
"userQuestionRemove": "Вы уверены, что хотите навсегда удалить пользователя с сервера?",
|
||||
"licenseKey": "Лицензионный ключ",
|
||||
"valid": "Действителен",
|
||||
"numberOfSites": "Количество сайтов",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Просмотреть коммерческую лицензию Fossorial и условия подписки",
|
||||
"licenseMessageRemove": "Это удалит лицензионный ключ и все связанные с ним разрешения.",
|
||||
"licenseMessageConfirm": "Для подтверждения введите лицензионный ключ ниже.",
|
||||
"licenseQuestionRemove": "Вы уверены, что хотите удалить лицензионный ключ {selectedKey}?",
|
||||
"licenseQuestionRemove": "Вы уверены, что хотите удалить лицензионный ключ?",
|
||||
"licenseKeyDelete": "Удалить лицензионный ключ",
|
||||
"licenseKeyDeleteConfirm": "Подтвердить удаление лицензионного ключа",
|
||||
"licenseTitle": "Управление статусом лицензии",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Произошла ошибка при удалении приглашения.",
|
||||
"inviteRemoved": "Приглашение удалено",
|
||||
"inviteRemovedDescription": "Приглашение для {email} было удалено.",
|
||||
"inviteQuestionRemove": "Вы уверены, что хотите удалить приглашение {email}?",
|
||||
"inviteQuestionRemove": "Вы уверены, что хотите удалить приглашение?",
|
||||
"inviteMessageRemove": "После удаления это приглашение больше не будет действительным. Вы всегда можете пригласить пользователя заново.",
|
||||
"inviteMessageConfirm": "Для подтверждения введите email адрес приглашения ниже.",
|
||||
"inviteQuestionRegenerate": "Вы уверены, что хотите пересоздать приглашение для {email}? Это отзовёт предыдущее приглашение.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Произошла ошибка при удалении пользователя.",
|
||||
"userOrgRemoved": "Пользователь удалён",
|
||||
"userOrgRemovedDescription": "Пользователь {email} был удалён из организации.",
|
||||
"userQuestionOrgRemove": "Вы уверены, что хотите удалить {email} из организации?",
|
||||
"userQuestionOrgRemove": "Вы уверены, что хотите удалить этого пользователя из организации?",
|
||||
"userMessageOrgRemove": "После удаления этот пользователь больше не будет иметь доступ к организации. Вы всегда можете пригласить его заново, но ему нужно будет снова принять приглашение.",
|
||||
"userMessageOrgConfirm": "Для подтверждения введите имя пользователя ниже.",
|
||||
"userRemoveOrgConfirm": "Подтвердить удаление пользователя",
|
||||
"userRemoveOrg": "Удалить пользователя из организации",
|
||||
"users": "Пользователи",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Произошла ошибка при добавлении пользователя в роль.",
|
||||
"userSaved": "Пользователь сохранён",
|
||||
"userSavedDescription": "Пользователь был обновлён.",
|
||||
"autoProvisioned": "Автоподбор",
|
||||
"autoProvisionedDescription": "Разрешить автоматическое управление этим пользователем",
|
||||
"accessControlsDescription": "Управляйте тем, к чему этот пользователь может получить доступ и что делать в организации",
|
||||
"accessControlsSubmit": "Сохранить контроль доступа",
|
||||
"roles": "Роли",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "Создано в",
|
||||
"proxyErrorInvalidHeader": "Неверное значение пользовательского заголовка Host. Используйте формат доменного имени или оставьте пустым для сброса пользовательского заголовка Host.",
|
||||
"proxyErrorTls": "Неверное имя TLS сервера. Используйте формат доменного имени или оставьте пустым для удаления имени TLS сервера.",
|
||||
"proxyEnableSSL": "Включить SSL (https)",
|
||||
"proxyEnableSSL": "Включить SSL",
|
||||
"proxyEnableSSLDescription": "Включить шифрование SSL/TLS для безопасных HTTPS подключений к вашим целям.",
|
||||
"target": "Target",
|
||||
"configureTarget": "Настроить адресаты",
|
||||
"targetErrorFetch": "Не удалось получить цели",
|
||||
"targetErrorFetchDescription": "Произошла ошибка при получении целей",
|
||||
"siteErrorFetch": "Не удалось получить ресурс",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "Конфигурация безопасного соединения",
|
||||
"targetTlsSettingsDescription": "Настройте параметры SSL/TLS для вашего ресурса",
|
||||
"targetTlsSettingsAdvanced": "Расширенные настройки TLS",
|
||||
"targetTlsSni": "Имя TLS сервера (SNI)",
|
||||
"targetTlsSni": "Имя TLS сервера",
|
||||
"targetTlsSniDescription": "Имя TLS сервера для использования в SNI. Оставьте пустым для использования по умолчанию.",
|
||||
"targetTlsSubmit": "Сохранить настройки",
|
||||
"targets": "Конфигурация целей",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Сохранять соединения на одной и той же целевой точке в течение всей сессии.",
|
||||
"methodSelect": "Выберите метод",
|
||||
"targetSubmit": "Добавить цель",
|
||||
"targetNoOne": "Нет целей. Добавьте цель с помощью формы.",
|
||||
"targetNoOne": "Этот ресурс не имеет никаких целей. Добавьте цель для настройки, где отправлять запросы к вашему бэкэнду.",
|
||||
"targetNoOneDescription": "Добавление более одной цели выше включит балансировку нагрузки.",
|
||||
"targetsSubmit": "Сохранить цели",
|
||||
"addTarget": "Добавить цель",
|
||||
"targetErrorInvalidIp": "Неверный IP-адрес",
|
||||
"targetErrorInvalidIpDescription": "Пожалуйста, введите действительный IP адрес или имя хоста",
|
||||
"targetErrorInvalidPort": "Неверный порт",
|
||||
"targetErrorInvalidPortDescription": "Пожалуйста, введите правильный номер порта",
|
||||
"targetErrorNoSite": "Сайт не выбран",
|
||||
"targetErrorNoSiteDescription": "Пожалуйста, выберите сайт для цели",
|
||||
"targetCreated": "Цель создана",
|
||||
"targetCreatedDescription": "Цель была успешно создана",
|
||||
"targetErrorCreate": "Не удалось создать цель",
|
||||
"targetErrorCreateDescription": "Произошла ошибка при создании цели",
|
||||
"save": "Сохранить",
|
||||
"proxyAdditional": "Дополнительные настройки прокси",
|
||||
"proxyAdditionalDescription": "Настройте, как ваш ресурс обрабатывает настройки прокси",
|
||||
"proxyCustomHeader": "Пользовательский заголовок Host",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Неверный формат IP адреса",
|
||||
"ipAddressErrorInvalidOctet": "Неверный октет IP адреса",
|
||||
"path": "Путь",
|
||||
"matchPath": "Путь матча",
|
||||
"ipAddressRange": "Диапазон IP",
|
||||
"rulesErrorFetch": "Не удалось получить правила",
|
||||
"rulesErrorFetchDescription": "Произошла ошибка при получении правил",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Администратор сервера - Pangolin",
|
||||
"licenseTierProfessional": "Профессиональная лицензия",
|
||||
"licenseTierEnterprise": "Корпоративная лицензия",
|
||||
"licenseTierCommercial": "Коммерческая лицензия",
|
||||
"licenseTierPersonal": "Личная лицензия",
|
||||
"licensed": "Лицензировано",
|
||||
"yes": "Да",
|
||||
"no": "Нет",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Просмотр и управление поставщиками удостоверений в системе",
|
||||
"idpDeletedDescription": "Поставщик удостоверений успешно удалён",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Вы уверены, что хотите навсегда удалить поставщика удостоверений {name}?",
|
||||
"idpQuestionRemove": "Вы уверены, что хотите навсегда удалить поставщика удостоверений?",
|
||||
"idpMessageRemove": "Это удалит поставщика удостоверений и все связанные конфигурации. Пользователи, которые аутентифицируются через этого поставщика, больше не смогут войти.",
|
||||
"idpMessageConfirm": "Для подтверждения введите имя поставщика удостоверений ниже.",
|
||||
"idpConfirmDelete": "Подтвердить удаление поставщика удостоверений",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Отображаемое имя для этого поставщика удостоверений",
|
||||
"idpAutoProvisionUsers": "Автоматическое создание пользователей",
|
||||
"idpAutoProvisionUsersDescription": "При включении пользователи будут автоматически создаваться в системе при первом входе с возможностью сопоставления пользователей с ролями и организациями.",
|
||||
"licenseBadge": "Профессиональная",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "Тип поставщика",
|
||||
"idpTypeDescription": "Выберите тип поставщика удостоверений, который вы хотите настроить",
|
||||
"idpOidcConfigure": "Конфигурация OAuth2/OIDC",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "Проверьте вашу почту для получения кода сброса пароля.",
|
||||
"passwordNew": "Новый пароль",
|
||||
"passwordNewConfirm": "Подтвердите новый пароль",
|
||||
"changePassword": "Изменить пароль",
|
||||
"changePasswordDescription": "Обновить пароль учетной записи",
|
||||
"oldPassword": "Текущий пароль",
|
||||
"newPassword": "Новый пароль",
|
||||
"confirmNewPassword": "Подтвердите новый пароль",
|
||||
"changePasswordError": "Не удалось сменить пароль",
|
||||
"changePasswordErrorDescription": "Произошла ошибка при смене пароля",
|
||||
"changePasswordSuccess": "Пароль успешно изменен",
|
||||
"changePasswordSuccessDescription": "Ваш пароль был успешно обновлен",
|
||||
"passwordExpiryRequired": "Требуется срок действия пароля",
|
||||
"passwordExpiryDescription": "Эта организация требует смены пароля каждые {maxDays} дней.",
|
||||
"changePasswordNow": "Изменить пароль сейчас",
|
||||
"pincodeAuth": "Код аутентификатора",
|
||||
"pincodeSubmit2": "Отправить код",
|
||||
"passwordResetSubmit": "Запросить сброс",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Требуется профессиональная версия",
|
||||
"licenseTierProfessionalRequiredDescription": "Эта функция доступна только в профессиональной версии.",
|
||||
"actionGetOrg": "Получить организацию",
|
||||
"updateOrgUser": "Обновить пользователя Org",
|
||||
"createOrgUser": "Создать пользователя Org",
|
||||
"actionUpdateOrg": "Обновить организацию",
|
||||
"actionUpdateUser": "Обновить пользователя",
|
||||
"actionGetUser": "Получить пользователя",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Удалить сайт",
|
||||
"actionGetSite": "Получить сайт",
|
||||
"actionListSites": "Список сайтов",
|
||||
"actionApplyBlueprint": "Применить чертёж",
|
||||
"setupToken": "Код настройки",
|
||||
"setupTokenDescription": "Введите токен настройки из консоли сервера.",
|
||||
"setupTokenRequired": "Токен настройки обязателен",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Навигационное меню",
|
||||
"navbarDescription": "Главное навигационное меню приложения",
|
||||
"navbarDocsLink": "Документация",
|
||||
"commercialEdition": "Коммерческая версия",
|
||||
"otpErrorEnable": "Невозможно включить 2FA",
|
||||
"otpErrorEnableDescription": "Произошла ошибка при включении 2FA",
|
||||
"otpSetupCheckCode": "Пожалуйста, введите 6-значный код",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Все пользователи",
|
||||
"sidebarIdentityProviders": "Поставщики удостоверений",
|
||||
"sidebarLicense": "Лицензия",
|
||||
"sidebarClients": "Клиенты (бета)",
|
||||
"sidebarClients": "Клиенты",
|
||||
"sidebarDomains": "Домены",
|
||||
"enableDockerSocket": "Включить Docker Socket",
|
||||
"enableDockerSocketDescription": "Включить обнаружение Docker Socket для заполнения информации о контейнерах. Путь к сокету должен быть предоставлен Newt.",
|
||||
"sidebarBluePrints": "Чертежи",
|
||||
"blueprints": "Чертежи",
|
||||
"blueprintsDescription": "Применить декларирующие конфигурации и просмотреть предыдущие запуски",
|
||||
"blueprintAdd": "Добавить чертёж",
|
||||
"blueprintGoBack": "Посмотреть все чертежи",
|
||||
"blueprintCreate": "Создать чертёж",
|
||||
"blueprintCreateDescription2": "Для создания и применения нового чертежа выполните следующие шаги",
|
||||
"blueprintDetails": "Детали чертежа",
|
||||
"blueprintDetailsDescription": "Посмотреть результат примененного чертежа и все возникшие ошибки",
|
||||
"blueprintInfo": "Информация о чертеже",
|
||||
"message": "Сообщение",
|
||||
"blueprintContentsDescription": "Определите содержимое YAML, описывающее вашу инфраструктуру",
|
||||
"blueprintErrorCreateDescription": "Произошла ошибка при применении чертежа",
|
||||
"blueprintErrorCreate": "Ошибка при создании чертежа",
|
||||
"searchBlueprintProgress": "Поиск чертежей...",
|
||||
"appliedAt": "Заявка на",
|
||||
"source": "Источник",
|
||||
"contents": "Содержание",
|
||||
"parsedContents": "Переработанное содержимое (только для чтения)",
|
||||
"enableDockerSocket": "Включить чертёж Docker",
|
||||
"enableDockerSocketDescription": "Включить scraping ярлыка Docker Socket для ярлыков чертежей. Путь к сокету должен быть предоставлен в Newt.",
|
||||
"enableDockerSocketLink": "Узнать больше",
|
||||
"viewDockerContainers": "Просмотр контейнеров Docker",
|
||||
"containersIn": "Контейнеры в {siteName}",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Создать Домен",
|
||||
"domainCreatedDescription": "Домен успешно создан",
|
||||
"domainDeletedDescription": "Домен успешно удален",
|
||||
"domainQuestionRemove": "Вы уверены, что хотите удалить домен {domain} из вашего аккаунта?",
|
||||
"domainQuestionRemove": "Вы уверены, что хотите удалить домен из вашей учетной записи?",
|
||||
"domainMessageRemove": "После удаления домен больше не будет связан с вашей учетной записью.",
|
||||
"domainMessageConfirm": "Для подтверждения введите ниже имя домена.",
|
||||
"domainConfirmDelete": "Подтвердить удаление домена",
|
||||
"domainDelete": "Удалить Домен",
|
||||
"domain": "Домен",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "Доступно обновление",
|
||||
"newtUpdateAvailableInfo": "Доступна новая версия Newt. Пожалуйста, обновитесь до последней версии для лучшего опыта.",
|
||||
"domainPickerEnterDomain": "Домен",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com, или просто myapp",
|
||||
"domainPickerPlaceholder": "myapp.example.com",
|
||||
"domainPickerDescription": "Введите полный домен ресурса, чтобы увидеть доступные опции.",
|
||||
"domainPickerDescriptionSaas": "Введите полный домен, поддомен или просто имя, чтобы увидеть доступные опции",
|
||||
"domainPickerTabAll": "Все",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Поддомен: {subdomain}",
|
||||
"domainPickerNamespace": "Пространство имен: {namespace}",
|
||||
"domainPickerShowMore": "Показать еще",
|
||||
"regionSelectorTitle": "Выберите регион",
|
||||
"regionSelectorInfo": "Выбор региона помогает нам обеспечить лучшее качество обслуживания для вашего расположения. Вам необязательно находиться в том же регионе, что и ваш сервер.",
|
||||
"regionSelectorPlaceholder": "Выбор региона",
|
||||
"regionSelectorComingSoon": "Скоро будет",
|
||||
"billingLoadingSubscription": "Загрузка подписки...",
|
||||
"billingFreeTier": "Бесплатный уровень",
|
||||
"billingWarningOverLimit": "Предупреждение: Вы превысили одну или несколько границ использования. Ваши сайты не подключатся, пока вы не измените подписку или не скорректируете использование.",
|
||||
"billingUsageLimitsOverview": "Обзор лимитов использования",
|
||||
"billingMonitorUsage": "Контролируйте использование в соответствии с установленными лимитами. Если вам требуется увеличение лимитов, пожалуйста, свяжитесь с нами support@pangolin.net.",
|
||||
"billingDataUsage": "Использование данных",
|
||||
"billingOnlineTime": "Время работы сайта",
|
||||
"billingUsers": "Активные пользователи",
|
||||
"billingDomains": "Активные домены",
|
||||
"billingRemoteExitNodes": "Активные самоуправляемые узлы",
|
||||
"billingNoLimitConfigured": "Лимит не установлен",
|
||||
"billingEstimatedPeriod": "Предполагаемый период выставления счетов",
|
||||
"billingIncludedUsage": "Включенное использование",
|
||||
"billingIncludedUsageDescription": "Использование, включенное в ваш текущий план подписки",
|
||||
"billingFreeTierIncludedUsage": "Бесплатное использование ограничений",
|
||||
"billingIncluded": "включено",
|
||||
"billingEstimatedTotal": "Предполагаемая сумма:",
|
||||
"billingNotes": "Заметки",
|
||||
"billingEstimateNote": "Это приблизительная оценка на основании вашего текущего использования.",
|
||||
"billingActualChargesMayVary": "Фактические начисления могут отличаться.",
|
||||
"billingBilledAtEnd": "С вас будет выставлен счет в конце периода выставления счетов.",
|
||||
"billingModifySubscription": "Изменить подписку",
|
||||
"billingStartSubscription": "Начать подписку",
|
||||
"billingRecurringCharge": "Периодический взнос",
|
||||
"billingManageSubscriptionSettings": "Управляйте настройками и предпочтениями вашей подписки",
|
||||
"billingNoActiveSubscription": "У вас нет активной подписки. Начните подписку, чтобы увеличить лимиты использования.",
|
||||
"billingFailedToLoadSubscription": "Не удалось загрузить подписку",
|
||||
"billingFailedToLoadUsage": "Не удалось загрузить использование",
|
||||
"billingFailedToGetCheckoutUrl": "Не удалось получить URL-адрес для оплаты",
|
||||
"billingPleaseTryAgainLater": "Пожалуйста, повторите попытку позже.",
|
||||
"billingCheckoutError": "Ошибка при оформлении заказа",
|
||||
"billingFailedToGetPortalUrl": "Не удалось получить URL-адрес портала",
|
||||
"billingPortalError": "Ошибка портала",
|
||||
"billingDataUsageInfo": "Вы несете ответственность за все данные, переданные через безопасные туннели при подключении к облаку. Это включает как входящий, так и исходящий трафик на всех ваших сайтах. При достижении лимита ваши сайты будут отключаться до тех пор, пока вы не обновите план или не уменьшите его использование. При использовании узлов не взимается плата.",
|
||||
"billingOnlineTimeInfo": "Вы тарифицируете на то, как долго ваши сайты будут подключены к облаку. Например, 44 640 минут равны одному сайту, работающему круглосуточно за весь месяц. Когда вы достигните лимита, ваши сайты будут отключаться до тех пор, пока вы не обновите тарифный план или не сократите нагрузку. При использовании узлов не тарифицируется.",
|
||||
"billingUsersInfo": "С вас взимается плата за каждого пользователя в вашей организации. Оплата рассчитывается ежедневно исходя из количества активных учетных записей пользователей в вашей организации.",
|
||||
"billingDomainInfo": "С вас взимается плата за каждый домен в вашей организации. Оплата рассчитывается ежедневно исходя из количества активных учетных записей доменов в вашей организации.",
|
||||
"billingRemoteExitNodesInfo": "С вас взимается плата за каждый управляемый узел в вашей организации. Оплата рассчитывается ежедневно исходя из количества активных управляемых узлов в вашей организации.",
|
||||
"domainNotFound": "Домен не найден",
|
||||
"domainNotFoundDescription": "Этот ресурс отключен, так как домен больше не существует в нашей системе. Пожалуйста, установите новый домен для этого ресурса.",
|
||||
"failed": "Ошибка",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Произошла проблема при использовании вашего ключа безопасности. Пожалуйста, попробуйте еще раз.",
|
||||
"twoFactorRequired": "Для регистрации ключа безопасности требуется двухфакторная аутентификация.",
|
||||
"twoFactor": "Двухфакторная аутентификация",
|
||||
"twoFactorAuthentication": "Двухфакторная аутентификация",
|
||||
"twoFactorDescription": "Эта организация требует двухфакторной аутентификации.",
|
||||
"enableTwoFactor": "Включить двухфакторную аутентификацию",
|
||||
"organizationSecurityPolicy": "Политика безопасности Организации",
|
||||
"organizationSecurityPolicyDescription": "У этой организации есть требования безопасности, которые должны быть выполнены, прежде чем вы сможете получить доступ к ней",
|
||||
"securityRequirements": "Требования безопасности",
|
||||
"allRequirementsMet": "Все требования выполнены",
|
||||
"completeRequirementsToContinue": "Выполните следующие требования, чтобы продолжить доступ к этой организации",
|
||||
"youCanNowAccessOrganization": "Теперь вы можете получить доступ к этой организации",
|
||||
"reauthenticationRequired": "Длина сессии",
|
||||
"reauthenticationDescription": "Эта организация требует входа каждый {maxDays} дней.",
|
||||
"reauthenticationDescriptionHours": "Эта организация требует входа в систему каждый {maxHours} часов.",
|
||||
"reauthenticateNow": "Войти снова",
|
||||
"adminEnabled2FaOnYourAccount": "Ваш администратор включил двухфакторную аутентификацию для {email}. Пожалуйста, завершите процесс настройки, чтобы продолжить.",
|
||||
"continueToApplication": "Перейти к приложению",
|
||||
"securityKeyAdd": "Добавить ключ безопасности",
|
||||
"securityKeyRegisterTitle": "Регистрация нового ключа безопасности",
|
||||
"securityKeyRegisterDescription": "Подключите свой ключ безопасности и введите имя для его идентификации",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "Изменения DNS могут занять некоторое время для распространения через интернет. Это может занять от нескольких минут до 48 часов в зависимости от вашего DNS провайдера и настроек TTL.",
|
||||
"resourcePortRequired": "Номер порта необходим для не-HTTP ресурсов",
|
||||
"resourcePortNotAllowed": "Номер порта не должен быть установлен для HTTP ресурсов",
|
||||
"billingPricingCalculatorLink": "Калькулятор расценок",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Я согласен с",
|
||||
"termsOfService": "условия использования",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Внешний прокси включен",
|
||||
"addNewTarget": "Добавить новую цель",
|
||||
"targetsList": "Список целей",
|
||||
"advancedMode": "Расширенный режим",
|
||||
"targetErrorDuplicateTargetFound": "Обнаружена дублирующаяся цель",
|
||||
"healthCheckHealthy": "Здоровый",
|
||||
"healthCheckUnhealthy": "Нездоровый",
|
||||
"healthCheckUnknown": "Неизвестно",
|
||||
"healthCheck": "Проверка здоровья",
|
||||
"configureHealthCheck": "Настроить проверку здоровья",
|
||||
"configureHealthCheckDescription": "Настройте мониторинг состояния для {target}",
|
||||
"enableHealthChecks": "Включить проверки здоровья",
|
||||
"enableHealthChecksDescription": "Мониторинг здоровья этой цели. При необходимости можно контролировать другую конечную точку.",
|
||||
"healthScheme": "Метод",
|
||||
"healthSelectScheme": "Выберите метод",
|
||||
"healthCheckPath": "Путь",
|
||||
"healthHostname": "IP / хост",
|
||||
"healthPort": "Порт",
|
||||
"healthCheckPathDescription": "Путь к проверке состояния здоровья.",
|
||||
"healthyIntervalSeconds": "Интервал здоровых состояний",
|
||||
"unhealthyIntervalSeconds": "Интервал нездоровых состояний",
|
||||
"IntervalSeconds": "Интервал здоровых состояний",
|
||||
"timeoutSeconds": "Тайм-аут",
|
||||
"timeIsInSeconds": "Время указано в секундах",
|
||||
"retryAttempts": "Количество попыток повторного запроса",
|
||||
"expectedResponseCodes": "Ожидаемые коды ответов",
|
||||
"expectedResponseCodesDescription": "HTTP-код состояния, указывающий на здоровое состояние. Если оставить пустым, 200-300 считается здоровым.",
|
||||
"customHeaders": "Пользовательские заголовки",
|
||||
"customHeadersDescription": "Заголовки новой строки, разделённые: название заголовка: значение",
|
||||
"headersValidationError": "Заголовки должны быть в формате: Название заголовка: значение.",
|
||||
"saveHealthCheck": "Сохранить проверку здоровья",
|
||||
"healthCheckSaved": "Проверка здоровья сохранена",
|
||||
"healthCheckSavedDescription": "Конфигурация проверки состояния успешно сохранена",
|
||||
"healthCheckError": "Ошибка проверки состояния",
|
||||
"healthCheckErrorDescription": "Произошла ошибка при сохранении конфигурации проверки состояния",
|
||||
"healthCheckPathRequired": "Требуется путь проверки состояния",
|
||||
"healthCheckMethodRequired": "Требуется метод HTTP",
|
||||
"healthCheckIntervalMin": "Интервал проверки должен составлять не менее 5 секунд",
|
||||
"healthCheckTimeoutMin": "Тайм-аут должен составлять не менее 1 секунды",
|
||||
"healthCheckRetryMin": "Количество попыток должно быть не менее 1",
|
||||
"httpMethod": "HTTP метод",
|
||||
"selectHttpMethod": "Выберите HTTP метод",
|
||||
"domainPickerSubdomainLabel": "Поддомен",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Введите поддомен для поиска и выбора из доступных свободных доменов.",
|
||||
"domainPickerFreeDomains": "Свободные домены",
|
||||
"domainPickerSearchForAvailableDomains": "Поиск доступных доменов",
|
||||
"domainPickerNotWorkSelfHosted": "Примечание: бесплатные предоставляемые домены в данный момент недоступны для самоуправляемых экземпляров.",
|
||||
"resourceDomain": "Домен",
|
||||
"resourceEditDomain": "Редактировать домен",
|
||||
"siteName": "Имя сайта",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Протокол",
|
||||
"editInternalResourceDialogSitePort": "Порт сайта",
|
||||
"editInternalResourceDialogTargetConfiguration": "Настройка цели",
|
||||
"editInternalResourceDialogDestinationIP": "Целевая IP",
|
||||
"editInternalResourceDialogDestinationPort": "Целевой порт",
|
||||
"editInternalResourceDialogCancel": "Отмена",
|
||||
"editInternalResourceDialogSaveResource": "Сохранить ресурс",
|
||||
"editInternalResourceDialogSuccess": "Успешно",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Порт сайта",
|
||||
"createInternalResourceDialogSitePortDescription": "Используйте этот порт для доступа к ресурсу на сайте при подключении с клиентом.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Настройка цели",
|
||||
"createInternalResourceDialogDestinationIP": "Целевая IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "IP-адрес ресурса в сети сайта.",
|
||||
"createInternalResourceDialogDestinationPort": "Целевой порт",
|
||||
"createInternalResourceDialogDestinationIPDescription": "IP или адрес хоста ресурса в сети сайта.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "Порт на IP-адресе назначения, где доступен ресурс.",
|
||||
"createInternalResourceDialogCancel": "Отмена",
|
||||
"createInternalResourceDialogCreateResource": "Создать ресурс",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Ошибка автоматического входа",
|
||||
"autoLoginErrorNoRedirectUrl": "URL-адрес перенаправления не получен от провайдера удостоверения.",
|
||||
"autoLoginErrorGeneratingUrl": "Не удалось сгенерировать URL-адрес аутентификации.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Удаленные узлы",
|
||||
"remoteExitNodeDescription": "Самохост-один или несколько удаленных узлов для расширения сетевого подключения и уменьшения зависимости от облака",
|
||||
"remoteExitNodes": "Узлы",
|
||||
"searchRemoteExitNodes": "Поиск узлов...",
|
||||
"remoteExitNodeAdd": "Добавить узел",
|
||||
"remoteExitNodeErrorDelete": "Ошибка удаления узла",
|
||||
"remoteExitNodeQuestionRemove": "Вы уверены, что хотите удалить узел из организации?",
|
||||
"remoteExitNodeMessageRemove": "После удаления узел больше не будет доступен.",
|
||||
"remoteExitNodeConfirmDelete": "Подтвердите удаление узла",
|
||||
"remoteExitNodeDelete": "Удалить узел",
|
||||
"sidebarRemoteExitNodes": "Удаленные узлы",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Создать узел",
|
||||
"description": "Создайте новый узел, чтобы расширить сетевое подключение",
|
||||
"viewAllButton": "Все узлы",
|
||||
"strategy": {
|
||||
"title": "Стратегия создания",
|
||||
"description": "Выберите эту опцию для настройки вашего узла или создания новых учетных данных.",
|
||||
"adopt": {
|
||||
"title": "Принять узел",
|
||||
"description": "Выберите это, если у вас уже есть учетные данные для узла."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Сгенерировать ключи",
|
||||
"description": "Выберите это, если вы хотите создать новые ключи для узла"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Принять существующий узел",
|
||||
"description": "Введите учетные данные существующего узла, который вы хотите принять",
|
||||
"nodeIdLabel": "ID узла",
|
||||
"nodeIdDescription": "ID существующего узла, который вы хотите принять",
|
||||
"secretLabel": "Секретный ключ",
|
||||
"secretDescription": "Секретный ключ существующего узла",
|
||||
"submitButton": "Принять узел"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Сгенерированные учетные данные",
|
||||
"description": "Используйте эти учётные данные для настройки вашего узла",
|
||||
"nodeIdTitle": "ID узла",
|
||||
"secretTitle": "Секретный ключ",
|
||||
"saveCredentialsTitle": "Добавить учетные данные в конфигурацию",
|
||||
"saveCredentialsDescription": "Добавьте эти учетные данные в файл конфигурации вашего самоуправляемого узла Pangolin, чтобы завершить подключение.",
|
||||
"submitButton": "Создать узел"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "ID узла и секрет требуются при установке существующего узла"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Не удалось загрузить параметры по умолчанию",
|
||||
"defaultsNotLoaded": "Параметры по умолчанию не загружены",
|
||||
"createFailed": "Не удалось создать узел"
|
||||
},
|
||||
"success": {
|
||||
"created": "Узел успешно создан"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Выбор узла",
|
||||
"remoteExitNodeSelectionDescription": "Выберите узел для маршрутизации трафика для этого локального сайта",
|
||||
"remoteExitNodeRequired": "Узел должен быть выбран для локальных сайтов",
|
||||
"noRemoteExitNodesAvailable": "Нет доступных узлов",
|
||||
"noRemoteExitNodesAvailableDescription": "Для этой организации узлы не доступны. Сначала создайте узел, чтобы использовать локальные сайты.",
|
||||
"exitNode": "Узел выхода",
|
||||
"country": "Страна",
|
||||
"rulesMatchCountry": "В настоящее время основано на исходном IP",
|
||||
"managedSelfHosted": {
|
||||
"title": "Управляемый с самовывоза",
|
||||
"description": "Более надежный и низко обслуживаемый сервер Pangolin с дополнительными колокольнями и свистками",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Конвертировать этот узел в управляемый себе-хост"
|
||||
},
|
||||
"internationaldomaindetected": "Обнаружен международный домен",
|
||||
"willbestoredas": "Будет храниться как:"
|
||||
}
|
||||
"willbestoredas": "Будет храниться как:",
|
||||
"roleMappingDescription": "Определите, как роли, назначаемые пользователям, когда они войдут в систему автоматического профиля.",
|
||||
"selectRole": "Выберите роль",
|
||||
"roleMappingExpression": "Выражение",
|
||||
"selectRolePlaceholder": "Выберите роль",
|
||||
"selectRoleDescription": "Выберите роль, чтобы назначить всем пользователям этого поставщика идентификации",
|
||||
"roleMappingExpressionDescription": "Введите выражение JMESPath, чтобы извлечь информацию о роли из ID токена",
|
||||
"idpTenantIdRequired": "Требуется ID владельца",
|
||||
"invalidValue": "Неверное значение",
|
||||
"idpTypeLabel": "Тип поставщика удостоверений",
|
||||
"roleMappingExpressionPlaceholder": "например, contains(groups, 'admin') && 'Admin' || 'Member'",
|
||||
"idpGoogleConfiguration": "Конфигурация Google",
|
||||
"idpGoogleConfigurationDescription": "Настройка учетных данных Google OAuth2",
|
||||
"idpGoogleClientIdDescription": "Ваш Google OAuth2 ID клиента",
|
||||
"idpGoogleClientSecretDescription": "Ваш Google OAuth2 Секрет",
|
||||
"idpAzureConfiguration": "Конфигурация Azure Entra ID",
|
||||
"idpAzureConfigurationDescription": "Настройте учетные данные Azure Entra ID OAuth2",
|
||||
"idpTenantId": "Идентификатор арендатора",
|
||||
"idpTenantIdPlaceholder": "ваш тенант-id",
|
||||
"idpAzureTenantIdDescription": "Идентификатор арендатора Azure (найден в обзоре Active Directory Azure)",
|
||||
"idpAzureClientIdDescription": "Ваш идентификатор клиента Azure App",
|
||||
"idpAzureClientSecretDescription": "Секрет регистрации клиента Azure App",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Конфигурация Google",
|
||||
"idpAzureConfigurationTitle": "Конфигурация Azure Entra ID",
|
||||
"idpTenantIdLabel": "Идентификатор арендатора",
|
||||
"idpAzureClientIdDescription2": "Ваш идентификатор клиента Azure App",
|
||||
"idpAzureClientSecretDescription2": "Секрет регистрации клиента Azure App",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC провайдер",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "Подсеть",
|
||||
"subnetDescription": "Подсеть для конфигурации сети этой организации.",
|
||||
"authPage": "Страница авторизации",
|
||||
"authPageDescription": "Настройка страницы авторизации для вашей организации",
|
||||
"authPageDomain": "Домен страницы авторизации",
|
||||
"noDomainSet": "Домен не установлен",
|
||||
"changeDomain": "Изменить домен",
|
||||
"selectDomain": "Выберите домен",
|
||||
"restartCertificate": "Перезапустить сертификат",
|
||||
"editAuthPageDomain": "Редактировать домен страницы авторизации",
|
||||
"setAuthPageDomain": "Установить домен страницы авторизации",
|
||||
"failedToFetchCertificate": "Не удалось получить сертификат",
|
||||
"failedToRestartCertificate": "Не удалось перезапустить сертификат",
|
||||
"addDomainToEnableCustomAuthPages": "Добавьте домен для включения пользовательских страниц аутентификации для вашей организации",
|
||||
"selectDomainForOrgAuthPage": "Выберите домен для страницы аутентификации организации",
|
||||
"domainPickerProvidedDomain": "Домен предоставлен",
|
||||
"domainPickerFreeProvidedDomain": "Бесплатный домен",
|
||||
"domainPickerVerified": "Подтверждено",
|
||||
"domainPickerUnverified": "Не подтверждено",
|
||||
"domainPickerInvalidSubdomainStructure": "Этот поддомен содержит недопустимые символы или структуру. Он будет очищен автоматически при сохранении.",
|
||||
"domainPickerError": "Ошибка",
|
||||
"domainPickerErrorLoadDomains": "Не удалось загрузить домены организации",
|
||||
"domainPickerErrorCheckAvailability": "Не удалось проверить доступность домена",
|
||||
"domainPickerInvalidSubdomain": "Неверный поддомен",
|
||||
"domainPickerInvalidSubdomainRemoved": "Ввод \"{sub}\" был удален, потому что он недействителен.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" не может быть действительным для {domain}.",
|
||||
"domainPickerSubdomainSanitized": "Субдомен очищен",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" был исправлен на \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "Войдите в свою организацию",
|
||||
"orgAuthChooseIdpDescription": "Выберите своего поставщика удостоверений личности для продолжения",
|
||||
"orgAuthNoIdpConfigured": "Эта организация не имеет настроенных поставщиков идентификационных данных. Вместо этого вы можете войти в свой Pangolin.",
|
||||
"orgAuthSignInWithPangolin": "Войти через Pangolin",
|
||||
"subscriptionRequiredToUse": "Для использования этой функции требуется подписка.",
|
||||
"idpDisabled": "Провайдеры идентификации отключены.",
|
||||
"orgAuthPageDisabled": "Страница авторизации организации отключена.",
|
||||
"domainRestartedDescription": "Проверка домена успешно перезапущена",
|
||||
"resourceAddEntrypointsEditFile": "Редактировать файл: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Редактировать файл: docker-compose.yml",
|
||||
"emailVerificationRequired": "Требуется подтверждение адреса электронной почты. Пожалуйста, войдите снова через {dashboardUrl}/auth/login завершить этот шаг. Затем вернитесь сюда.",
|
||||
"twoFactorSetupRequired": "Требуется настройка двухфакторной аутентификации. Пожалуйста, войдите снова через {dashboardUrl}/auth/login завершить этот шаг. Затем вернитесь сюда.",
|
||||
"additionalSecurityRequired": "Требуется дополнительная безопасность",
|
||||
"organizationRequiresAdditionalSteps": "Эта организация требует дополнительных шагов безопасности, прежде чем вы сможете получить доступ к ресурсам.",
|
||||
"completeTheseSteps": "Выполните эти шаги",
|
||||
"enableTwoFactorAuthentication": "Включить двухфакторную аутентификацию",
|
||||
"completeSecuritySteps": "Пройти шаги безопасности",
|
||||
"securitySettings": "Настройки безопасности",
|
||||
"securitySettingsDescription": "Настройка политик безопасности для вашей организации",
|
||||
"requireTwoFactorForAllUsers": "Требовать двухфакторную аутентификацию для всех пользователей",
|
||||
"requireTwoFactorDescription": "Когда включено, все внутренние пользователи в этой организации должны иметь двухфакторную аутентификацию для доступа к организации.",
|
||||
"requireTwoFactorDisabledDescription": "Эта функция требует действительной лицензии (Enterprise) или активной подписки (SaaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "Вы должны включить двухфакторную аутентификацию для вашей учетной записи, прежде чем принудительно ее применять для всех пользователей",
|
||||
"maxSessionLength": "Максимальная длина сессии",
|
||||
"maxSessionLengthDescription": "Установите максимальную длительность сессий пользователя. После этого времени, пользователям нужно будет пройти повторную аутентификацию.",
|
||||
"maxSessionLengthDisabledDescription": "Эта функция требует действительной лицензии (Enterprise) или активной подписки (SaaS)",
|
||||
"selectSessionLength": "Выберите длину сеанса",
|
||||
"unenforced": "Не применено",
|
||||
"1Hour": "1 час",
|
||||
"3Hours": "3 часа",
|
||||
"6Hours": "6 часов",
|
||||
"12Hours": "12 часов",
|
||||
"1DaySession": "1 день",
|
||||
"3Days": "3 дня",
|
||||
"7Days": "7 дней",
|
||||
"14Days": "14 дней",
|
||||
"30DaysSession": "30 дней",
|
||||
"90DaysSession": "90 дней",
|
||||
"180DaysSession": "180 дней",
|
||||
"passwordExpiryDays": "Срок действия пароля",
|
||||
"editPasswordExpiryDescription": "Установите количество дней, прежде чем пользователи должны изменить свой пароль.",
|
||||
"selectPasswordExpiry": "Выберите срок действия пароля",
|
||||
"30Days": "30 дней",
|
||||
"1Day": "1 день",
|
||||
"60Days": "60 дней",
|
||||
"90Days": "90 дней",
|
||||
"180Days": "180 дней",
|
||||
"1Year": "1 год",
|
||||
"subscriptionBadge": "Требуется подписка",
|
||||
"securityPolicyChangeWarning": "Предупреждение об изменении политики безопасности",
|
||||
"securityPolicyChangeDescription": "Вы собираетесь изменить настройки политики безопасности. После сохранения вам может потребоваться повторная аутентификация, чтобы соответствовать этим обновлениям. Все пользователи, которые не соответствуют установленным правилам, также должны пройти процедуру повторной аутентификации.",
|
||||
"securityPolicyChangeConfirmMessage": "Подтверждаю",
|
||||
"securityPolicyChangeWarningText": "Это повлияет на всех пользователей организации",
|
||||
"authPageErrorUpdateMessage": "Произошла ошибка при обновлении настроек страницы авторизации",
|
||||
"authPageErrorUpdate": "Не удалось обновить страницу авторизации",
|
||||
"authPageUpdated": "Страница авторизации успешно обновлена",
|
||||
"healthCheckNotAvailable": "Локальный",
|
||||
"rewritePath": "Переписать путь",
|
||||
"rewritePathDescription": "При необходимости, измените путь перед пересылкой к целевому адресу.",
|
||||
"continueToApplication": "Перейти к приложению",
|
||||
"checkingInvite": "Проверка приглашения",
|
||||
"setResourceHeaderAuth": "установить заголовок ресурса",
|
||||
"resourceHeaderAuthRemove": "Удалить проверку подлинности заголовка",
|
||||
"resourceHeaderAuthRemoveDescription": "Проверка подлинности заголовка успешно удалена.",
|
||||
"resourceErrorHeaderAuthRemove": "Не удалось удалить аутентификацию заголовка",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Не удалось удалить проверку подлинности заголовка ресурса.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Заголовок аутентификации включен",
|
||||
"resourceHeaderAuthProtectionDisabled": "Проверка подлинности заголовка отключена",
|
||||
"headerAuthRemove": "Удалить проверку подлинности заголовка",
|
||||
"headerAuthAdd": "Добавить заголовок аутентификации",
|
||||
"resourceErrorHeaderAuthSetup": "Не удалось установить аутентификацию заголовка",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Не удалось установить проверку подлинности заголовка ресурса.",
|
||||
"resourceHeaderAuthSetup": "Проверка подлинности заголовка успешно установлена",
|
||||
"resourceHeaderAuthSetupDescription": "Проверка подлинности заголовка успешно установлена.",
|
||||
"resourceHeaderAuthSetupTitle": "Установить проверку подлинности заголовка",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Установите основные учетные данные авторизации (имя пользователя и пароль), чтобы защитить этот ресурс с помощью заголовка HTTP. Получите доступ к нему с помощью формата https://username:password@resource.example.com",
|
||||
"resourceHeaderAuthSubmit": "Установить проверку подлинности заголовка",
|
||||
"actionSetResourceHeaderAuth": "Установить проверку подлинности заголовка",
|
||||
"enterpriseEdition": "Корпоративная версия",
|
||||
"unlicensed": "Нелицензированный",
|
||||
"beta": "Бета",
|
||||
"manageClients": "Управление клиентами",
|
||||
"manageClientsDescription": "Клиенты - это устройства, которые могут подключаться к вашим сайтам",
|
||||
"licenseTableValidUntil": "Действителен до",
|
||||
"saasLicenseKeysSettingsTitle": "Корпоративные лицензии",
|
||||
"saasLicenseKeysSettingsDescription": "Генерировать и управлять лицензионными ключами Enterprise для копий Pangolin",
|
||||
"sidebarEnterpriseLicenses": "Лицензии",
|
||||
"generateLicenseKey": "Сгенерировать лицензионный ключ",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Пожалуйста, введите действительный адрес электронной почты",
|
||||
"useCaseTypeRequired": "Пожалуйста, выберите тип варианта использования",
|
||||
"firstNameRequired": "Требуется имя",
|
||||
"lastNameRequired": "Требуется фамилия",
|
||||
"primaryUseRequired": "Пожалуйста, опишите ваше основное использование",
|
||||
"jobTitleRequiredBusiness": "Должность требуется для коммерческого использования",
|
||||
"industryRequiredBusiness": "Промышленность необходима для коммерческого использования",
|
||||
"stateProvinceRegionRequired": "Регион/Область обязательно",
|
||||
"postalZipCodeRequired": "Почтовый индекс требуется",
|
||||
"companyNameRequiredBusiness": "Название компании обязательно для бизнес-использования",
|
||||
"countryOfResidenceRequiredBusiness": "Страна проживания необходима для коммерческого использования",
|
||||
"countryRequiredPersonal": "Страна необходима для личного использования",
|
||||
"agreeToTermsRequired": "Вы должны принять условия",
|
||||
"complianceConfirmationRequired": "Вы должны подтвердить соответствие с Fossorial Commercial License"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Личное использование",
|
||||
"description": "Для индивидуального, некоммерческого использования, например, обучения, личных проектов или экспериментов."
|
||||
},
|
||||
"business": {
|
||||
"title": "Бизнес-использование",
|
||||
"description": "Для использования в организациях, компаниях или коммерческих или приносящих доход видах деятельности."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "Email и тип лицензии",
|
||||
"description": "Введите адрес электронной почты и выберите тип лицензии"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Личная информация",
|
||||
"description": "Расскажите нам о себе"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "Контактная информация",
|
||||
"description": "Ваши контактные данные"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Условия и Сгенерировать",
|
||||
"description": "Просмотрите и примите условия для создания вашей лицензии"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Раскрытие",
|
||||
"description": "Выберите уровень лицензии, который точно отражает ваше предполагаемое использование. Личная Лицензия разрешает свободное использование Программного Обеспечения для частной, некоммерческой или малой коммерческой деятельности с годовым валовым доходом до $100 000 USD. Любое использование сверх этих пределов — включая использование в бизнесе, организацию, или другой приносящей доход среде — требует действительной лицензии предприятия и уплаты соответствующей лицензионной платы. Все пользователи, будь то Личные или Предприятия, обязаны соблюдать условия коммерческой лицензии Fossoral."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Информация о пробном периоде",
|
||||
"description": "Этот лицензионный ключ позволяет корпоративным функциям на 7-дневный период оценки. Для продолжения доступа к платным функциям за пределами ознакомительного периода требуется активация в рамках действующей лицензии Личного или Предприятия. Для получения лицензии свяжитесь с sales@pangolin.net."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Вы используете Pangolin для личного или делового использования?",
|
||||
"firstName": "First Name",
|
||||
"lastName": "Фамилия",
|
||||
"jobTitle": "Заголовок",
|
||||
"primaryUseQuestion": "Что вы планируете использовать Панголин в первую очередь?",
|
||||
"industryQuestion": "Какая у вас отрасль?",
|
||||
"prospectiveUsersQuestion": "Сколько у вас потенциальных пользователей?",
|
||||
"prospectiveSitesQuestion": "Сколько потенциальных сайтов (туннелей) вы ожидаете?",
|
||||
"companyName": "Название компании",
|
||||
"countryOfResidence": "Страна проживания",
|
||||
"stateProvinceRegion": "Область / регион",
|
||||
"postalZipCode": "Почтовый индекс",
|
||||
"companyWebsite": "Веб-сайт компании",
|
||||
"companyPhoneNumber": "Телефон компании",
|
||||
"country": "Страна",
|
||||
"phoneNumberOptional": "Номер телефона (необязательно)",
|
||||
"complianceConfirmation": "Я подтверждаю, что информация, которую я предоставляю, является точной и что я в соответствии с коммерческой лицензии Fossorial. Сообщение о неточной информации или неправильно идентифицирующем использовании продукта является нарушением лицензии и может привести к аннулированию вашего ключа."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Закрыть",
|
||||
"previous": "Предыдущий",
|
||||
"next": "Следующий",
|
||||
"generateLicenseKey": "Сгенерировать лицензионный ключ"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Лицензионный ключ успешно создан",
|
||||
"description": "Ваш лицензионный ключ сгенерирован и готов к использованию."
|
||||
},
|
||||
"error": {
|
||||
"title": "Не удалось сгенерировать лицензионный ключ",
|
||||
"description": "Произошла ошибка при генерации лицензионного ключа."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Приоритет",
|
||||
"priorityDescription": "Маршруты с более высоким приоритетом оцениваются первым. Приоритет = 100 означает автоматическое упорядочение (решение системы). Используйте другой номер для обеспечения ручного приоритета.",
|
||||
"instanceName": "Имя экземпляра",
|
||||
"pathMatchModalTitle": "Настроить соответствие пути",
|
||||
"pathMatchModalDescription": "Настройка соответствия входящих запросов на основе их пути.",
|
||||
"pathMatchType": "Тип совпадения",
|
||||
"pathMatchPrefix": "Префикс",
|
||||
"pathMatchExact": "Точно",
|
||||
"pathMatchRegex": "Регенерация",
|
||||
"pathMatchValue": "Значение пути",
|
||||
"clear": "Очистить",
|
||||
"saveChanges": "Сохранить изменения",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/путь",
|
||||
"pathMatchPrefixHelp": "Пример: /api matches /api, /api/users, etc.",
|
||||
"pathMatchExactHelp": "Пример: /api соответствует только /api",
|
||||
"pathMatchRegexHelp": "Пример: ^/api/.* совпадает с /api/anything",
|
||||
"pathRewriteModalTitle": "Настроить перезапись пути",
|
||||
"pathRewriteModalDescription": "Преобразовать соответствующий путь перед пересылкой к цели.",
|
||||
"pathRewriteType": "Тип перезаписи",
|
||||
"pathRewritePrefixOption": "Префикс - Замена префикса",
|
||||
"pathRewriteExactOption": "Точно - Заменить весь путь",
|
||||
"pathRewriteRegexOption": "Regex - замена шаблона",
|
||||
"pathRewriteStripPrefixOption": "Префикс вырезать - Удалить префикс",
|
||||
"pathRewriteValue": "Перезаписать значение",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "Заменить соответствующий префикс этим значением",
|
||||
"pathRewriteExactHelp": "Замените весь путь этим значением, когда путь точно соответствует",
|
||||
"pathRewriteRegexHelp": "Использовать группы захвата типа $1, $2 для замены",
|
||||
"pathRewriteStripPrefixHelp": "Оставьте пустым для префикса полосы или укажите новый префикс",
|
||||
"pathRewritePrefix": "Префикс",
|
||||
"pathRewriteExact": "Точно",
|
||||
"pathRewriteRegex": "Регенерация",
|
||||
"pathRewriteStrip": "Вырезать",
|
||||
"pathRewriteStripLabel": "полоса",
|
||||
"sidebarEnableEnterpriseLicense": "Включить корпоративную лицензию",
|
||||
"cannotbeUndone": "Это действие не может быть отменено.",
|
||||
"toConfirm": "для подтверждения",
|
||||
"deleteClientQuestion": "Вы уверены, что хотите удалить клиента из сайта и организации?",
|
||||
"clientMessageRemove": "После удаления клиент больше не сможет подключиться к сайту.",
|
||||
"sidebarLogs": "Логи",
|
||||
"request": "Запросить",
|
||||
"logs": "Логи",
|
||||
"logsSettingsDescription": "Отслеживать журналы, собранные в этой организации",
|
||||
"searchLogs": "Поиск журналов...",
|
||||
"action": "Действие",
|
||||
"actor": "Актер",
|
||||
"timestamp": "Отметка времени",
|
||||
"accessLogs": "Журналы доступа",
|
||||
"exportCsv": "Экспорт CSV",
|
||||
"actorId": "ID актера",
|
||||
"allowedByRule": "Разрешено правилом",
|
||||
"allowedNoAuth": "Разрешено без авторизации",
|
||||
"validAccessToken": "Действительный маркер доступа",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "Допустимый пароль",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "Ресурс заблокирован",
|
||||
"droppedByRule": "Отброшено по правилам",
|
||||
"noSessions": "Нет сессий",
|
||||
"temporaryRequestToken": "Временный токен запроса",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "Причина",
|
||||
"requestLogs": "Запросить журналы",
|
||||
"host": "Хост",
|
||||
"location": "Местоположение",
|
||||
"actionLogs": "Журнал действий",
|
||||
"sidebarLogsRequest": "Запросить журналы",
|
||||
"sidebarLogsAccess": "Журналы доступа",
|
||||
"sidebarLogsAction": "Журнал действий",
|
||||
"logRetention": "Сохранение журнала",
|
||||
"logRetentionDescription": "Управление сохранением различных типов журналов для этой организации или отключение их",
|
||||
"requestLogsDescription": "Просмотреть подробные журналы запроса ресурсов в этой организации",
|
||||
"logRetentionRequestLabel": "Запросить сохранение журнала",
|
||||
"logRetentionRequestDescription": "Как долго сохранять журналы запросов",
|
||||
"logRetentionAccessLabel": "Хранение журнала доступа",
|
||||
"logRetentionAccessDescription": "Как долго сохранять журналы доступа",
|
||||
"logRetentionActionLabel": "Сохранение журнала действий",
|
||||
"logRetentionActionDescription": "Как долго хранить журналы действий",
|
||||
"logRetentionDisabled": "Отключено",
|
||||
"logRetention3Days": "3 дня",
|
||||
"logRetention7Days": "7 дней",
|
||||
"logRetention14Days": "14 дней",
|
||||
"logRetention30Days": "30 дней",
|
||||
"logRetention90Days": "90 дней",
|
||||
"logRetentionForever": "Всегда",
|
||||
"actionLogsDescription": "Просмотр истории действий, выполненных в этой организации",
|
||||
"accessLogsDescription": "Просмотр запросов авторизации доступа к ресурсам этой организации",
|
||||
"licenseRequiredToUse": "Для использования этой функции требуется лицензия предприятия.",
|
||||
"certResolver": "Резольвер сертификата",
|
||||
"certResolverDescription": "Выберите резолвер сертификата, который будет использоваться для этого ресурса.",
|
||||
"selectCertResolver": "Выберите резолвер сертификата",
|
||||
"enterCustomResolver": "Введите пользовательский резолвер",
|
||||
"preferWildcardCert": "Предпочитать сертификат Wildcard",
|
||||
"unverified": "Не подтверждено",
|
||||
"domainSetting": "Настройки домена",
|
||||
"domainSettingDescription": "Настройка параметров для вашего домена",
|
||||
"preferWildcardCertDescription": "Попытка создания шаблона сертификата (требуется должным образом сконфигурированный резолвер сертификата).",
|
||||
"recordName": "Имя записи",
|
||||
"auto": "Авто",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Как добавить записи",
|
||||
"dnsRecord": "DNS записи",
|
||||
"required": "Требуется",
|
||||
"domainSettingsUpdated": "Настройки домена успешно обновлены",
|
||||
"orgOrDomainIdMissing": "Отсутствует организация или ID домена",
|
||||
"loadingDNSRecords": "Загрузка записей DNS...",
|
||||
"olmUpdateAvailableInfo": "Доступна обновленная версия Олма. Пожалуйста, обновитесь до последней версии.",
|
||||
"client": "Клиент",
|
||||
"proxyProtocol": "Настройки протокола прокси",
|
||||
"proxyProtocolDescription": "Настроить Прокси-протокол для сохранения IP-адресов клиента для служб TCP/UDP.",
|
||||
"enableProxyProtocol": "Включить Прокси Протокол",
|
||||
"proxyProtocolInfo": "Сохранять IP-адреса клиента для кэша TCP/UDP",
|
||||
"proxyProtocolVersion": "Версия протокола прокси",
|
||||
"version1": " Версия 1 (рекомендуется)",
|
||||
"version2": "Версия 2",
|
||||
"versionDescription": "Версия 1 основана на тексте и широко поддерживается. Версия 2 является бинарной и более эффективной, но менее совместимой.",
|
||||
"warning": "Предупреждение",
|
||||
"proxyProtocolWarning": "Бэкэнд приложение должно быть сконфигурировано для принятия прокси-соединений. Если ваш бэкэнд не поддерживает Прокси-протокол, это нарушит все соединения. Обязательно настройте вашего бэкэнда на доверие заголовкам Proxy Protocol от Traefik.",
|
||||
"restarting": "Перезапуск...",
|
||||
"manual": "Ручной",
|
||||
"messageSupport": "Поддержка сообщений",
|
||||
"supportNotAvailableTitle": "Поддержка недоступна",
|
||||
"supportNotAvailableDescription": "Поддержка сейчас недоступна. Вы можете отправить письмо по адресу support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Запрос на поддержку отправлен",
|
||||
"supportRequestSentDescription": "Ваше сообщение успешно отправлено.",
|
||||
"supportRequestFailedTitle": "Не удалось отправить запрос",
|
||||
"supportRequestFailedDescription": "Произошла ошибка при отправке запроса поддержки.",
|
||||
"supportSubjectRequired": "Необходимо ввести тему",
|
||||
"supportSubjectMaxLength": "Тема должна быть 255 символов или меньше",
|
||||
"supportMessageRequired": "Требуется сообщение",
|
||||
"supportReplyTo": "Ответить",
|
||||
"supportSubject": "Тема",
|
||||
"supportSubjectPlaceholder": "Введите тему",
|
||||
"supportMessage": "Сообщение",
|
||||
"supportMessagePlaceholder": "Введите ваше сообщение",
|
||||
"supportSending": "Отправка...",
|
||||
"supportSend": "Отправить",
|
||||
"supportMessageSent": "Сообщение отправлено!",
|
||||
"supportWillContact": "Мы скоро свяжемся с Вами!",
|
||||
"selectLogRetention": "Выберите удержание журнала",
|
||||
"showColumns": "Показать колонки",
|
||||
"hideColumns": "Скрыть столбцы",
|
||||
"columnVisibility": "Видимость столбцов",
|
||||
"toggleColumn": "Столбец {columnName}",
|
||||
"allColumns": "Все колонки",
|
||||
"defaultColumns": "Столбцы по умолчанию",
|
||||
"customizeView": "Настроить вид",
|
||||
"viewOptions": "Параметры просмотра",
|
||||
"selectAll": "Выделить все",
|
||||
"selectNone": "Не выбирать",
|
||||
"selectedResources": "Выбранные ресурсы",
|
||||
"enableSelected": "Включить выбранные",
|
||||
"disableSelected": "Отключить выбранные",
|
||||
"checkSelectedStatus": "Проверить статус выбранных"
|
||||
}
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "Düzenle",
|
||||
"siteConfirmDelete": "Site Silmeyi Onayla",
|
||||
"siteDelete": "Siteyi Sil",
|
||||
"siteMessageRemove": "Kaldırıldıktan sonra site artık erişilebilir olmayacak. Siteyle ilişkili tüm kaynaklar ve hedefler de kaldırılacaktır.",
|
||||
"siteMessageConfirm": "Onaylamak için lütfen aşağıya sitenin adını yazın.",
|
||||
"siteQuestionRemove": "{selectedSite} sitesini organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"siteMessageRemove": "Kaldırıldıktan sonra site artık erişilebilir olmayacaktır. Siteyle ilişkilendirilmiş tüm hedefler de kaldırılacaktır.",
|
||||
"siteQuestionRemove": "Siteyi organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"siteManageSites": "Siteleri Yönet",
|
||||
"siteDescription": "Ağınıza güvenli tüneller üzerinden bağlantı izni verin",
|
||||
"siteCreate": "Site Oluştur",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "Bir tünel oluşturmak için herhangi bir WireGuard istemcisi kullanın. Manuel NAT kurulumu gereklidir.",
|
||||
"siteWgDescriptionSaas": "Bir tünel oluşturmak için herhangi bir WireGuard istemcisi kullanın. Manuel NAT kurulumu gereklidir. YALNIZCA SELF HOSTED DÜĞÜMLERDE ÇALIŞIR",
|
||||
"siteLocalDescription": "Yalnızca yerel kaynaklar. Tünelleme yok.",
|
||||
"siteLocalDescriptionSaas": "Yalnızca yerel kaynaklar. Tünel yok. YALNIZCA SELF HOSTED DÜĞÜMLERDE ÇALIŞIR",
|
||||
"siteLocalDescriptionSaas": "Yerel kaynaklar yalnızca. Tünel oluşturma yok. Yalnızca uzak düğümlerde mevcuttur.",
|
||||
"siteSeeAll": "Tüm Siteleri Gör",
|
||||
"siteTunnelDescription": "Sitenize nasıl bağlanmak istediğinizi belirleyin",
|
||||
"siteNewtCredentials": "Newt Kimlik Bilgileri",
|
||||
@@ -154,8 +153,7 @@
|
||||
"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.",
|
||||
"resourceMessageConfirm": "Onaylamak için lütfen aşağıya kaynağın adını yazın.",
|
||||
"resourceQuestionRemove": "{selectedResource} kaynağını organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"resourceQuestionRemove": "Kaynağı organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"resourceHTTP": "HTTPS Kaynağı",
|
||||
"resourceHTTPDescription": "Bir alt alan adı veya temel alan adı kullanarak uygulamanıza HTTPS üzerinden vekil istek gönderin.",
|
||||
"resourceRaw": "Ham TCP/UDP Kaynağı",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "Site seç",
|
||||
"siteSearch": "Site ara",
|
||||
"siteNotFound": "Herhangi bir site bulunamadı.",
|
||||
"selectCountry": "Ülke Seç",
|
||||
"searchCountries": "Ülkeleri ara...",
|
||||
"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",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "Temel Alan Adı",
|
||||
"subdomnainDescription": "Kaynağınızın erişilebileceği alt alan adı.",
|
||||
"resourceRawSettings": "TCP/UDP Ayarları",
|
||||
"resourceRawSettingsDescription": "Kaynağınıza TCP/UDP üzerinden erişimin nasıl sağlanacağını yapılandırın",
|
||||
"resourceRawSettingsDescription": "Kaynağınızın TCP/UDP üzerinden nasıl erişileceğini yapılandırın. Kaynağı, sunucudan erişebilmeniz için bir ana bilgisayar Pangolin sunucusundaki bir bağlantı noktasına eşlersiniz: sunucu genel-IP: eşlenen-bağlantı-noktası.",
|
||||
"protocol": "Protokol",
|
||||
"protocolSelect": "Bir protokol seçin",
|
||||
"resourcePortNumber": "Port Numarası",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "Organizasyon Silmeyi Onayla",
|
||||
"orgMessageRemove": "Bu işlem geri alınamaz ve tüm ilişkili verileri silecektir.",
|
||||
"orgMessageConfirm": "Onaylamak için lütfen aşağıya organizasyonun adını yazın.",
|
||||
"orgQuestionRemove": "{selectedOrg} organizasyonunu kaldırmak istediğinizden emin misiniz?",
|
||||
"orgQuestionRemove": "Organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"orgUpdated": "Organizasyon güncellendi",
|
||||
"orgUpdatedDescription": "Organizasyon güncellendi.",
|
||||
"orgErrorUpdate": "Organizasyon güncellenemedi",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "API Anahtarı Oluştur",
|
||||
"apiKeysErrorDelete": "API anahtarı silinirken bir hata oluştu",
|
||||
"apiKeysErrorDeleteMessage": "API anahtarı silinirken bir hata oluştu",
|
||||
"apiKeysQuestionRemove": "{selectedApiKey} API anahtarını organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"apiKeysQuestionRemove": "API anahtarını organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"apiKeysMessageRemove": "Kaldırıldığında, API anahtarı artık kullanılamayacaktır.",
|
||||
"apiKeysMessageConfirm": "Onaylamak için lütfen aşağıya API anahtarının adını yazın.",
|
||||
"apiKeysDeleteConfirm": "API Anahtarının Silinmesini Onaylayın",
|
||||
"apiKeysDelete": "API Anahtarını Sil",
|
||||
"apiKeysManage": "API Anahtarlarını Yönet",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "Kullanıcı Silinmesini Onayla",
|
||||
"userDeleteServer": "Kullanıcıyı Sunucudan Sil",
|
||||
"userMessageRemove": "Kullanıcı tüm organizasyonlardan çıkarılacak ve tamamen sunucudan kaldırılacaktır.",
|
||||
"userMessageConfirm": "Onaylamak için lütfen aşağıya kullanıcının adını yazın.",
|
||||
"userQuestionRemove": "{selectedUser} kullanıcısını sunucudan kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"userQuestionRemove": "Kullanıcıyı sunucudan kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"licenseKey": "Lisans Anahtarı",
|
||||
"valid": "Geçerli",
|
||||
"numberOfSites": "Site Sayısı",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "Fossorial Ticari Lisans ve Abonelik Koşullarını Gör",
|
||||
"licenseMessageRemove": "Bu, lisans anahtarını ve onun tarafından verilen tüm izinleri kaldıracaktır.",
|
||||
"licenseMessageConfirm": "Onaylamak için lütfen aşağıya lisans anahtarını yazın.",
|
||||
"licenseQuestionRemove": "{selectedKey} lisans anahtarını silmek istediğinizden emin misiniz?",
|
||||
"licenseQuestionRemove": "Lisans anahtarını silmek istediğinizden emin misiniz?",
|
||||
"licenseKeyDelete": "Lisans Anahtarını Sil",
|
||||
"licenseKeyDeleteConfirm": "Lisans Anahtarının Silinmesini Onaylayın",
|
||||
"licenseTitle": "Lisans Durumunu Yönet",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "Daveti kaldırırken bir hata oluştu.",
|
||||
"inviteRemoved": "Davetiye kaldırıldı",
|
||||
"inviteRemovedDescription": "{email} için olan davetiye kaldırıldı.",
|
||||
"inviteQuestionRemove": "{email} davetini kaldırmak istediğinizden emin misiniz?",
|
||||
"inviteQuestionRemove": "Davetiyeyi kaldırmak istediğinizden emin misiniz?",
|
||||
"inviteMessageRemove": "Kaldırıldıktan sonra bu davetiye artık geçerli olmayacak. Kullanıcı tekrar davet edilebilir.",
|
||||
"inviteMessageConfirm": "Onaylamak için lütfen aşağıya davetiyenin e-posta adresini yazın.",
|
||||
"inviteQuestionRegenerate": "Are you sure you want to regenerate the invitation for{email, plural, ='' {}, other { for #}}? This will revoke the previous invitation.",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "Kullanıcı kaldırılırken bir hata oluştu.",
|
||||
"userOrgRemoved": "Kullanıcı kaldırıldı",
|
||||
"userOrgRemovedDescription": "{email} kullanıcı organizasyondan kaldırılmıştır.",
|
||||
"userQuestionOrgRemove": "{email} adresini organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"userQuestionOrgRemove": "Kullanıcıyı organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"userMessageOrgRemove": "Kaldırıldığında, bu kullanıcı organizasyona artık erişim sağlayamayacak. Kullanıcı tekrar davet edilebilir, ancak daveti kabul etmesi gerekecek.",
|
||||
"userMessageOrgConfirm": "Onaylamak için lütfen aşağıya kullanıcının adını yazın.",
|
||||
"userRemoveOrgConfirm": "Kullanıcıyı Kaldırmayı Onayla",
|
||||
"userRemoveOrg": "Kullanıcıyı Organizasyondan Kaldır",
|
||||
"users": "Kullanıcılar",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "Kullanıcı role eklenirken bir hata oluştu.",
|
||||
"userSaved": "Kullanıcı kaydedildi",
|
||||
"userSavedDescription": "Kullanıcı güncellenmiştir.",
|
||||
"autoProvisioned": "Otomatik Sağlandı",
|
||||
"autoProvisionedDescription": "Bu kullanıcının kimlik sağlayıcısı tarafından otomatik olarak yönetilmesine izin ver",
|
||||
"accessControlsDescription": "Bu kullanıcının organizasyonda neleri erişebileceğini ve yapabileceğini yönetin",
|
||||
"accessControlsSubmit": "Erişim Kontrollerini Kaydet",
|
||||
"roles": "Roller",
|
||||
@@ -463,7 +463,10 @@
|
||||
"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": "SSL'yi Etkinleştir (https)",
|
||||
"proxyEnableSSL": "SSL Etkinleştir",
|
||||
"proxyEnableSSLDescription": "Hedeflerinize güvenli HTTPS bağlantıları için SSL/TLS şifrelemesi etkinleştirin.",
|
||||
"target": "Hedef",
|
||||
"configureTarget": "Hedefleri Yapılandır",
|
||||
"targetErrorFetch": "Hedefleri alamadı",
|
||||
"targetErrorFetchDescription": "Hedefler alınırken bir hata oluştu",
|
||||
"siteErrorFetch": "kaynağa ulaşılamadı",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "HTTPS & TLS Settings",
|
||||
"targetTlsSettingsDescription": "Configure TLS settings for your resource",
|
||||
"targetTlsSettingsAdvanced": "Gelişmiş TLS Ayarları",
|
||||
"targetTlsSni": "TLS Sunucu Adı (SNI)",
|
||||
"targetTlsSni": "TLS Sunucu Adı",
|
||||
"targetTlsSniDescription": "SNI için kullanılacak TLS Sunucu Adı'",
|
||||
"targetTlsSubmit": "Ayarları Kaydet",
|
||||
"targets": "Hedefler Konfigürasyonu",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "Bağlantıları oturum süresince aynı arka uç hedef üzerinde tutun.",
|
||||
"methodSelect": "Yöntemi Seç",
|
||||
"targetSubmit": "Hedef Ekle",
|
||||
"targetNoOne": "Hiçbir hedef yok. Formu kullanarak bir hedef ekleyin.",
|
||||
"targetNoOne": "Bu kaynağın hedefi yok. Arka planınıza istek göndereceğiniz bir hedef yapılandırmak için hedef ekleyin.",
|
||||
"targetNoOneDescription": "Yukarıdaki birden fazla hedef ekleyerek yük dengeleme etkinleştirilecektir.",
|
||||
"targetsSubmit": "Hedefleri Kaydet",
|
||||
"addTarget": "Hedef Ekle",
|
||||
"targetErrorInvalidIp": "Geçersiz IP adresi",
|
||||
"targetErrorInvalidIpDescription": "Lütfen geçerli bir IP adresi veya host adı girin",
|
||||
"targetErrorInvalidPort": "Geçersiz port",
|
||||
"targetErrorInvalidPortDescription": "Lütfen geçerli bir port numarası girin",
|
||||
"targetErrorNoSite": "Hiçbir site seçili değil",
|
||||
"targetErrorNoSiteDescription": "Lütfen hedef için bir site seçin",
|
||||
"targetCreated": "Hedef oluşturuldu",
|
||||
"targetCreatedDescription": "Hedef başarıyla oluşturuldu",
|
||||
"targetErrorCreate": "Hedef oluşturma başarısız oldu",
|
||||
"targetErrorCreateDescription": "Hedef oluşturulurken bir hata oluştu",
|
||||
"save": "Kaydet",
|
||||
"proxyAdditional": "Ek Proxy Ayarları",
|
||||
"proxyAdditionalDescription": "Kaynağınızın proxy ayarlarını nasıl yöneteceğini yapılandırın",
|
||||
"proxyCustomHeader": "Özel Ana Bilgisayar Başlığı",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "Geçersiz IP adresi formatı",
|
||||
"ipAddressErrorInvalidOctet": "Geçersiz IP adresi okteti",
|
||||
"path": "Yol",
|
||||
"matchPath": "Yol Eşleştir",
|
||||
"ipAddressRange": "IP Aralığı",
|
||||
"rulesErrorFetch": "Kurallar alınamadı",
|
||||
"rulesErrorFetchDescription": "Kurallar alınırken bir hata oluştu",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "Sunucu Yöneticisi - Pangolin",
|
||||
"licenseTierProfessional": "Profesyonel Lisans",
|
||||
"licenseTierEnterprise": "Kurumsal Lisans",
|
||||
"licenseTierCommercial": "Ticari Lisans",
|
||||
"licenseTierPersonal": "Kişisel Lisans",
|
||||
"licensed": "Lisanslı",
|
||||
"yes": "Evet",
|
||||
"no": "Hayır",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "Sistem içindeki kimlik sağlayıcıları görün ve yönetin",
|
||||
"idpDeletedDescription": "Kimlik sağlayıcı başarıyla silindi",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "Kimlik sağlayıcıyı kalıcı olarak silmek istediğinizden emin misiniz? {name}",
|
||||
"idpQuestionRemove": "Kimlik sağlayıcısını kalıcı olarak silmek istediğinizden emin misiniz?",
|
||||
"idpMessageRemove": "Bu, kimlik sağlayıcıyı ve tüm ilişkili yapılandırmaları kaldıracaktır. Bu sağlayıcıdan kimlik doğrulayan kullanıcılar artık giriş yapamayacaktır.",
|
||||
"idpMessageConfirm": "Onaylamak için lütfen aşağıya kimlik sağlayıcının adını yazın.",
|
||||
"idpConfirmDelete": "Kimlik Sağlayıcıyı Silme Onayı",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "Bu kimlik sağlayıcı için bir görüntü adı",
|
||||
"idpAutoProvisionUsers": "Kullanıcıları Otomatik Sağla",
|
||||
"idpAutoProvisionUsersDescription": "Etkinleştirildiğinde, kullanıcılar rol ve organizasyonlara eşleme yeteneğiyle birlikte sistemde otomatik olarak oluşturulacak.",
|
||||
"licenseBadge": "Profesyonel",
|
||||
"licenseBadge": " ",
|
||||
"idpType": "Sağlayıcı Türü",
|
||||
"idpTypeDescription": "Yapılandırmak istediğiniz kimlik sağlayıcısı türünü seçin",
|
||||
"idpOidcConfigure": "OAuth2/OIDC Yapılandırması",
|
||||
@@ -811,7 +827,7 @@
|
||||
"redirectUrl": "Yönlendirme URL'si",
|
||||
"redirectUrlAbout": "Yönlendirme URL'si Hakkında",
|
||||
"redirectUrlAboutDescription": "Bu, kimlik doğrulamasından sonra kullanıcıların yönlendirileceği URL'dir. Bu URL'yi kimlik sağlayıcınızın ayarlarında yapılandırmanız gerekir.",
|
||||
"pangolinAuth": "Auth - Pangolin",
|
||||
"pangolinAuth": "Yetkilendirme - Pangolin",
|
||||
"verificationCodeLengthRequirements": "Doğrulama kodunuz 8 karakter olmalıdır.",
|
||||
"errorOccurred": "Bir hata oluştu",
|
||||
"emailErrorVerify": "E-posta doğrulanamadı: ",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "E-posta gelen kutunuzda sıfırlama kodunu kontrol edin.",
|
||||
"passwordNew": "Yeni Şifre",
|
||||
"passwordNewConfirm": "Yeni Şifreyi Onayla",
|
||||
"changePassword": "Parola Değiştir",
|
||||
"changePasswordDescription": "Hesap şifrenizi güncelleyin",
|
||||
"oldPassword": "Mevcut Şifre",
|
||||
"newPassword": "Yeni Şifre",
|
||||
"confirmNewPassword": "Yeni Şifreyi Onayla",
|
||||
"changePasswordError": "Parola değiştirme başarısız oldu",
|
||||
"changePasswordErrorDescription": "Parolanız değiştiriliyor.",
|
||||
"changePasswordSuccess": "Şifre Başarıyla Değiştirildi",
|
||||
"changePasswordSuccessDescription": "Parolanız başarıyla güncellendi",
|
||||
"passwordExpiryRequired": "Şifre Süresi Gereklidir",
|
||||
"passwordExpiryDescription": "Bu kuruluş, parolanızı {maxDays} günde bir değiştirmenizi gerektirir.",
|
||||
"changePasswordNow": "Şifrenizi Şimdi Değiştirin",
|
||||
"pincodeAuth": "Kimlik Doğrulama Kodu",
|
||||
"pincodeSubmit2": "Kodu Gönder",
|
||||
"passwordResetSubmit": "Sıfırlama İsteği",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "Profesyonel Sürüme Gereklidir",
|
||||
"licenseTierProfessionalRequiredDescription": "Bu özellik yalnızca Professional Edition'da kullanılabilir.",
|
||||
"actionGetOrg": "Kuruluşu Al",
|
||||
"updateOrgUser": "Organizasyon Kullanıcısını Güncelle",
|
||||
"createOrgUser": "Organizasyon Kullanıcısı Oluştur",
|
||||
"actionUpdateOrg": "Kuruluşu Güncelle",
|
||||
"actionUpdateUser": "Kullanıcıyı Güncelle",
|
||||
"actionGetUser": "Kullanıcıyı Getir",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "Siteyi Sil",
|
||||
"actionGetSite": "Siteyi Al",
|
||||
"actionListSites": "Siteleri Listele",
|
||||
"actionApplyBlueprint": "Planı Uygula",
|
||||
"setupToken": "Kurulum Simgesi",
|
||||
"setupTokenDescription": "Sunucu konsolundan kurulum simgesini girin.",
|
||||
"setupTokenRequired": "Kurulum simgesi gerekli",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "Navigasyon Menüsü",
|
||||
"navbarDescription": "Uygulamanın ana navigasyon menüsü",
|
||||
"navbarDocsLink": "Dokümantasyon",
|
||||
"commercialEdition": "Ticari Sürüm",
|
||||
"otpErrorEnable": "2FA etkinleştirilemedi",
|
||||
"otpErrorEnableDescription": "2FA etkinleştirilirken bir hata oluştu",
|
||||
"otpSetupCheckCode": "6 haneli bir kod girin",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "Tüm Kullanıcılar",
|
||||
"sidebarIdentityProviders": "Kimlik Sağlayıcılar",
|
||||
"sidebarLicense": "Lisans",
|
||||
"sidebarClients": "Müşteriler (Beta)",
|
||||
"sidebarClients": "İstemciler",
|
||||
"sidebarDomains": "Alan Adları",
|
||||
"enableDockerSocket": "Docker Soketi Etkinleştir",
|
||||
"enableDockerSocketDescription": "Konteyner bilgilerini doldurmak için Docker Socket keşfini etkinleştirin. Socket yolu Newt'e sağlanmalıdır.",
|
||||
"sidebarBluePrints": "Planlar",
|
||||
"blueprints": "Planlar",
|
||||
"blueprintsDescription": "Deklaratif yapılandırmaları uygulayın ve önceki çalışmaları görüntüleyin",
|
||||
"blueprintAdd": "Plan Ekle",
|
||||
"blueprintGoBack": "Tüm Planları Gör",
|
||||
"blueprintCreate": "Plan Oluştur",
|
||||
"blueprintCreateDescription2": "Yeni bir plan oluşturup uygulamak için aşağıdaki adımları izleyin",
|
||||
"blueprintDetails": "Mavi Yazılım Detayları",
|
||||
"blueprintDetailsDescription": "Uygulanan mavi yazılımın sonucunu ve oluşan hataları görün",
|
||||
"blueprintInfo": "Plan Bilgileri",
|
||||
"message": "Mesaj",
|
||||
"blueprintContentsDescription": "Altyapınızı tanımlayan YAML içeriğini tanımlayın",
|
||||
"blueprintErrorCreateDescription": "Plan uygulanırken bir hata oluştu",
|
||||
"blueprintErrorCreate": "Plan oluşturulurken hata oluştu",
|
||||
"searchBlueprintProgress": "Planlarda ara...",
|
||||
"appliedAt": "Uygulama Zamanı",
|
||||
"source": "Kaynak",
|
||||
"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.",
|
||||
"enableDockerSocketLink": "Daha fazla bilgi",
|
||||
"viewDockerContainers": "Docker Konteynerlerini Görüntüle",
|
||||
"containersIn": "{siteName} içindeki konteynerler",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "Alan Adı Oluştur",
|
||||
"domainCreatedDescription": "Alan adı başarıyla oluşturuldu",
|
||||
"domainDeletedDescription": "Alan adı başarıyla silindi",
|
||||
"domainQuestionRemove": "{domain} alan adını hesabınızdan kaldırmak istediğinizden emin misiniz?",
|
||||
"domainQuestionRemove": "Alan adını hesabınızdan kaldırmak istediğinizden emin misiniz?",
|
||||
"domainMessageRemove": "Kaldırıldığında, alan adı hesabınızla ilişkilendirilmeyecek.",
|
||||
"domainMessageConfirm": "Onaylamak için lütfen aşağıya alan adını yazın.",
|
||||
"domainConfirmDelete": "Alan Adı Silinmesini Onayla",
|
||||
"domainDelete": "Alan Adını Sil",
|
||||
"domain": "Alan Adı",
|
||||
@@ -1233,8 +1281,8 @@
|
||||
"sidebarExpand": "Genişlet",
|
||||
"newtUpdateAvailable": "Güncelleme Mevcut",
|
||||
"newtUpdateAvailableInfo": "Newt'in yeni bir versiyonu mevcut. En iyi deneyim için lütfen en son sürüme güncelleyin.",
|
||||
"domainPickerEnterDomain": "Domain",
|
||||
"domainPickerPlaceholder": "myapp.example.com, api.v1.mydomain.com veya sadece myapp",
|
||||
"domainPickerEnterDomain": "Alan Adı",
|
||||
"domainPickerPlaceholder": "myapp.example.com",
|
||||
"domainPickerDescription": "Mevcut seçenekleri görmek için kaynağın tam etki alanını girin.",
|
||||
"domainPickerDescriptionSaas": "Mevcut seçenekleri görmek için tam etki alanı, alt etki alanı veya sadece bir isim girin",
|
||||
"domainPickerTabAll": "Tümü",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "Alt Alan: {subdomain}",
|
||||
"domainPickerNamespace": "Ad Alanı: {namespace}",
|
||||
"domainPickerShowMore": "Daha Fazla Göster",
|
||||
"regionSelectorTitle": "Bölge Seç",
|
||||
"regionSelectorInfo": "Bir bölge seçmek, konumunuz için daha iyi performans sağlamamıza yardımcı olur. Sunucunuzla aynı bölgede olmanıza gerek yoktur.",
|
||||
"regionSelectorPlaceholder": "Bölge Seçin",
|
||||
"regionSelectorComingSoon": "Yakında Geliyor",
|
||||
"billingLoadingSubscription": "Abonelik yükleniyor...",
|
||||
"billingFreeTier": "Ücretsiz Dilim",
|
||||
"billingWarningOverLimit": "Uyarı: Bir veya daha fazla kullanım limitini aştınız. Aboneliğinizi değiştirmediğiniz veya kullanımı ayarlamadığınız sürece siteleriniz bağlanmayacaktır.",
|
||||
"billingUsageLimitsOverview": "Kullanım Limitleri Genel Görünümü",
|
||||
"billingMonitorUsage": "Kullanımınızı yapılandırılmış limitlerle karşılaştırın. Limitlerin artırılmasına ihtiyacınız varsa, lütfen support@pangolin.net adresinden bizimle iletişime geçin.",
|
||||
"billingDataUsage": "Veri Kullanımı",
|
||||
"billingOnlineTime": "Site Çevrimiçi Süresi",
|
||||
"billingUsers": "Aktif Kullanıcılar",
|
||||
"billingDomains": "Aktif Alanlar",
|
||||
"billingRemoteExitNodes": "Aktif Öz-Host Düğümleri",
|
||||
"billingNoLimitConfigured": "Hiçbir limit yapılandırılmadı",
|
||||
"billingEstimatedPeriod": "Tahmini Fatura Dönemi",
|
||||
"billingIncludedUsage": "Dahil Kullanım",
|
||||
"billingIncludedUsageDescription": "Mevcut abonelik planınıza bağlı kullanım",
|
||||
"billingFreeTierIncludedUsage": "Ücretsiz dilim kullanım hakları",
|
||||
"billingIncluded": "dahil",
|
||||
"billingEstimatedTotal": "Tahmini Toplam:",
|
||||
"billingNotes": "Notlar",
|
||||
"billingEstimateNote": "Bu, mevcut kullanımınıza dayalı bir tahmindir.",
|
||||
"billingActualChargesMayVary": "Asıl ücretler farklılık gösterebilir.",
|
||||
"billingBilledAtEnd": "Fatura döneminin sonunda fatura düzenlenecektir.",
|
||||
"billingModifySubscription": "Aboneliği Düzenle",
|
||||
"billingStartSubscription": "Aboneliği Başlat",
|
||||
"billingRecurringCharge": "Yinelenen Ücret",
|
||||
"billingManageSubscriptionSettings": "Abonelik ayarlarınızı ve tercihlerinizi yönetin",
|
||||
"billingNoActiveSubscription": "Aktif bir aboneliğiniz yok. Kullanım limitlerini artırmak için aboneliğinizi başlatın.",
|
||||
"billingFailedToLoadSubscription": "Abonelik yüklenemedi",
|
||||
"billingFailedToLoadUsage": "Kullanım yüklenemedi",
|
||||
"billingFailedToGetCheckoutUrl": "Ödeme URL'si alınamadı",
|
||||
"billingPleaseTryAgainLater": "Lütfen daha sonra tekrar deneyin.",
|
||||
"billingCheckoutError": "Ödeme Hatası",
|
||||
"billingFailedToGetPortalUrl": "Portal URL'si alınamadı",
|
||||
"billingPortalError": "Portal Hatası",
|
||||
"billingDataUsageInfo": "Buluta bağlandığınızda, güvenli tünellerinizden aktarılan tüm verilerden ücret alınırsınız. Bu, tüm sitelerinizdeki gelen ve giden trafiği içerir. Limitinize ulaştığınızda, planınızı yükseltmeli veya kullanımı azaltmalısınız, aksi takdirde siteleriniz bağlantıyı keser. Düğümler kullanırken verilerden ücret alınmaz.",
|
||||
"billingOnlineTimeInfo": "Sitelerinizin buluta ne kadar süre bağlı kaldığına göre ücretlendirilirsiniz. Örneğin, 44,640 dakika, bir sitenin 24/7 boyunca tam bir ay boyunca çalışması anlamına gelir. Limitinize ulaştığınızda, planınızı yükseltmeyip kullanımı azaltmazsanız siteleriniz bağlantıyı keser. Düğümler kullanırken zamandan ücret alınmaz.",
|
||||
"billingUsersInfo": "Kuruluşunuzdaki her kullanıcı için ücretlendirilirsiniz. Faturalandırma, hesabınızdaki aktif kullanıcı hesaplarının sayısına göre günlük olarak hesaplanır.",
|
||||
"billingDomainInfo": "Kuruluşunuzdaki her alan adı için ücretlendirilirsiniz. Faturalandırma, hesabınızdaki aktif alan adları hesaplarının sayısına göre günlük olarak hesaplanır.",
|
||||
"billingRemoteExitNodesInfo": "Kuruluşunuzdaki her yönetilen Düğüm için ücretlendirilirsiniz. Faturalandırma, hesabınızdaki aktif yönetilen Düğümler sayısına göre günlük olarak hesaplanır.",
|
||||
"domainNotFound": "Alan Adı Bulunamadı",
|
||||
"domainNotFoundDescription": "Bu kaynak devre dışıdır çünkü alan adı sistemimizde artık mevcut değil. Bu kaynak için yeni bir alan adı belirleyin.",
|
||||
"failed": "Başarısız",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "Güvenlik anahtarınızı kullanırken bir sorun oluştu. Lütfen tekrar deneyin.",
|
||||
"twoFactorRequired": "Güvenlik anahtarını kaydetmek için iki faktörlü kimlik doğrulama gereklidir.",
|
||||
"twoFactor": "İki Faktörlü Kimlik Doğrulama",
|
||||
"twoFactorAuthentication": "İki Faktörlü Kimlik Doğrulama",
|
||||
"twoFactorDescription": "Bu kuruluş iki faktörlü kimlik doğrulama gerektirir.",
|
||||
"enableTwoFactor": "İki Faktörlü Kimlik Doğrulamayı Etkinleştir",
|
||||
"organizationSecurityPolicy": "Kuruluş Güvenlik Politikası",
|
||||
"organizationSecurityPolicyDescription": "Bu kuruluşun güvenlik gereksinimlerine erişmeden önce karşılanması gereken güvenlik gereksinimleri vardır.",
|
||||
"securityRequirements": "Güvenlik Gereksinimleri",
|
||||
"allRequirementsMet": "Tüm gereksinimler karşılandı",
|
||||
"completeRequirementsToContinue": "Bu kuruluşa erişmeye devam etmek için aşağıdaki gereksinimleri tamamlayın",
|
||||
"youCanNowAccessOrganization": "Artık bu kuruluşa erişebilirsiniz",
|
||||
"reauthenticationRequired": "Oturum Süresi",
|
||||
"reauthenticationDescription": "Bu kuruluş, {maxDays} günde bir oturum açmanızı gerektirir.",
|
||||
"reauthenticationDescriptionHours": "Bu kuruluş, {maxHours} saatte bir oturum açmanızı gerektirir.",
|
||||
"reauthenticateNow": "Tekrar Giriş Yap",
|
||||
"adminEnabled2FaOnYourAccount": "Yöneticiniz {email} için iki faktörlü kimlik doğrulamayı etkinleştirdi. Devam etmek için kurulum işlemini tamamlayın.",
|
||||
"continueToApplication": "Uygulamaya Devam Et",
|
||||
"securityKeyAdd": "Güvenlik Anahtarı Ekle",
|
||||
"securityKeyRegisterTitle": "Yeni Güvenlik Anahtarı Kaydet",
|
||||
"securityKeyRegisterDescription": "Güvenlik anahtarınızı bağlayın ve tanımlamak için bir ad girin",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "DNS değişikliklerinin internet genelinde yayılması zaman alabilir. DNS sağlayıcınız ve TTL ayarlarına bağlı olarak bu birkaç dakika ile 48 saat arasında değişebilir.",
|
||||
"resourcePortRequired": "HTTP dışı kaynaklar için bağlantı noktası numarası gereklidir",
|
||||
"resourcePortNotAllowed": "HTTP kaynakları için bağlantı noktası numarası ayarlanmamalı",
|
||||
"billingPricingCalculatorLink": "Fiyat Hesaplayıcı",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "Kabul ediyorum",
|
||||
"termsOfService": "hizmet şartları",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "Dış Proxy Etkinleştirildi",
|
||||
"addNewTarget": "Yeni Hedef Ekle",
|
||||
"targetsList": "Hedefler Listesi",
|
||||
"advancedMode": "Gelişmiş Mod",
|
||||
"targetErrorDuplicateTargetFound": "Yinelenen hedef bulundu",
|
||||
"healthCheckHealthy": "Sağlıklı",
|
||||
"healthCheckUnhealthy": "Sağlıksız",
|
||||
"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",
|
||||
"enableHealthChecks": "Sağlık Kontrollerini Etkinleştir",
|
||||
"enableHealthChecksDescription": "Bu hedefin sağlığını izleyin. Gerekirse hedef dışındaki bir son noktayı izleyebilirsiniz.",
|
||||
"healthScheme": "Yöntem",
|
||||
"healthSelectScheme": "Yöntem Seç",
|
||||
"healthCheckPath": "Yol",
|
||||
"healthHostname": "IP / Hostname",
|
||||
"healthPort": "Bağlantı Noktası",
|
||||
"healthCheckPathDescription": "Sağlık durumunu kontrol etmek için yol.",
|
||||
"healthyIntervalSeconds": "Sağlıklı Aralık",
|
||||
"unhealthyIntervalSeconds": "Sağlıksız Aralık",
|
||||
"IntervalSeconds": "Sağlıklı Aralık",
|
||||
"timeoutSeconds": "Zaman Aşımı",
|
||||
"timeIsInSeconds": "Zaman saniye cinsindendir",
|
||||
"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.",
|
||||
"customHeaders": "Özel Başlıklar",
|
||||
"customHeadersDescription": "Başlıklar yeni satırla ayrılmış: Başlık-Adı: değer",
|
||||
"headersValidationError": "Başlıklar şu formatta olmalıdır: Başlık-Adı: değer.",
|
||||
"saveHealthCheck": "Sağlık Kontrolünü Kaydet",
|
||||
"healthCheckSaved": "Sağlık Kontrolü Kaydedildi",
|
||||
"healthCheckSavedDescription": "Sağlık kontrol yapılandırması başarıyla kaydedildi",
|
||||
"healthCheckError": "Sağlık Kontrol Hatası",
|
||||
"healthCheckErrorDescription": "Sağlık kontrol yapılandırması kaydedilirken bir hata oluştu",
|
||||
"healthCheckPathRequired": "Sağlık kontrol yolu gereklidir",
|
||||
"healthCheckMethodRequired": "HTTP yöntemi gereklidir",
|
||||
"healthCheckIntervalMin": "Kontrol aralığı en az 5 saniye olmalıdır",
|
||||
"healthCheckTimeoutMin": "Zaman aşımı en az 1 saniye olmalıdır",
|
||||
"healthCheckRetryMin": "Tekrar deneme girişimleri en az 1 olmalıdır",
|
||||
"httpMethod": "HTTP Yöntemi",
|
||||
"selectHttpMethod": "HTTP yöntemini seçin",
|
||||
"domainPickerSubdomainLabel": "Alt Alan Adı",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "Mevcut ücretsiz alan adları arasından aramak ve seçmek için bir alt alan adı girin.",
|
||||
"domainPickerFreeDomains": "Ücretsiz Alan Adları",
|
||||
"domainPickerSearchForAvailableDomains": "Mevcut alan adlarını ara",
|
||||
"domainPickerNotWorkSelfHosted": "Not: Ücretsiz sağlanan alan adları şu anda öz-host edilmiş örnekler için kullanılabilir değildir.",
|
||||
"resourceDomain": "Alan Adı",
|
||||
"resourceEditDomain": "Alan Adını Düzenle",
|
||||
"siteName": "Site Adı",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "Protokol",
|
||||
"editInternalResourceDialogSitePort": "Site Bağlantı Noktası",
|
||||
"editInternalResourceDialogTargetConfiguration": "Hedef Yapılandırma",
|
||||
"editInternalResourceDialogDestinationIP": "Hedef IP",
|
||||
"editInternalResourceDialogDestinationPort": "Hedef Bağlantı Noktası",
|
||||
"editInternalResourceDialogCancel": "İptal",
|
||||
"editInternalResourceDialogSaveResource": "Kaynağı Kaydet",
|
||||
"editInternalResourceDialogSuccess": "Başarı",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "Site Bağlantı Noktası",
|
||||
"createInternalResourceDialogSitePortDescription": "İstemci ile bağlanıldığında site üzerindeki kaynağa erişmek için bu bağlantı noktasını kullanın.",
|
||||
"createInternalResourceDialogTargetConfiguration": "Hedef Yapılandırma",
|
||||
"createInternalResourceDialogDestinationIP": "Hedef IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "Site ağındaki kaynağın IP adresi.",
|
||||
"createInternalResourceDialogDestinationPort": "Hedef Bağlantı Noktası",
|
||||
"createInternalResourceDialogDestinationIPDescription": "Kaynağın site ağındaki IP veya ana bilgisayar adresi.",
|
||||
"createInternalResourceDialogDestinationPortDescription": "Kaynağa erişilebilecek hedef IP üzerindeki bağlantı noktası.",
|
||||
"createInternalResourceDialogCancel": "İptal",
|
||||
"createInternalResourceDialogCreateResource": "Kaynak Oluştur",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "Otomatik Giriş Hatası",
|
||||
"autoLoginErrorNoRedirectUrl": "Kimlik sağlayıcıdan yönlendirme URL'si alınamadı.",
|
||||
"autoLoginErrorGeneratingUrl": "Kimlik doğrulama URL'si oluşturulamadı.",
|
||||
"remoteExitNodeManageRemoteExitNodes": "Uzak Düğümler",
|
||||
"remoteExitNodeDescription": "Kendi konum ağlarınızdan bir veya daha fazlasını barındırarak, bağlantı kurulumları için buluta bağımlılığı azaltın.",
|
||||
"remoteExitNodes": "Düğümler",
|
||||
"searchRemoteExitNodes": "Düğüm ara...",
|
||||
"remoteExitNodeAdd": "Düğüm Ekle",
|
||||
"remoteExitNodeErrorDelete": "Düğüm silinirken hata oluştu",
|
||||
"remoteExitNodeQuestionRemove": "Düğümü organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"remoteExitNodeMessageRemove": "Kaldırıldığında, düğüm artık erişilebilir olmayacaktır.",
|
||||
"remoteExitNodeConfirmDelete": "Düğüm Silmeyi Onayla",
|
||||
"remoteExitNodeDelete": "Düğümü Sil",
|
||||
"sidebarRemoteExitNodes": "Uzak Düğümler",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "Düğüm Oluştur",
|
||||
"description": "Ağ bağlantınızı genişletmek için yeni bir düğüm oluşturun",
|
||||
"viewAllButton": "Tüm Düğümleri Gör",
|
||||
"strategy": {
|
||||
"title": "Oluşturma Stratejisi",
|
||||
"description": "Düğümünüzü manuel olarak yapılandırmak veya yeni kimlik bilgileri oluşturmak için bunu seçin.",
|
||||
"adopt": {
|
||||
"title": "Düğüm Benimse",
|
||||
"description": "Zaten düğüm için kimlik bilgilerine sahipseniz bunu seçin."
|
||||
},
|
||||
"generate": {
|
||||
"title": "Anahtarları Oluştur",
|
||||
"description": "Düğüm için yeni anahtarlar oluşturmak istiyorsanız bunu seçin"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "Mevcut Düğümü Benimse",
|
||||
"description": "Adayacağınız mevcut düğümün kimlik bilgilerini girin",
|
||||
"nodeIdLabel": "Düğüm ID",
|
||||
"nodeIdDescription": "Adayacağınız mevcut düğümün ID'si",
|
||||
"secretLabel": "Gizli",
|
||||
"secretDescription": "Mevcut düğümün gizli anahtarı",
|
||||
"submitButton": "Düğümü Benimse"
|
||||
},
|
||||
"generate": {
|
||||
"title": "Oluşturulan Kimlik Bilgileri",
|
||||
"description": "Düğümünüzü yapılandırmak için oluşturulan bu kimlik bilgilerini kullanın",
|
||||
"nodeIdTitle": "Düğüm ID",
|
||||
"secretTitle": "Gizli",
|
||||
"saveCredentialsTitle": "Kimlik Bilgilerini Yapılandırmaya Ekle",
|
||||
"saveCredentialsDescription": "Bağlantıyı tamamlamak için bu kimlik bilgilerini öz-host Pangolin düğüm yapılandırma dosyanıza ekleyin.",
|
||||
"submitButton": "Düğüm Oluştur"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "Mevcut bir düğümü benimserken Düğüm ID ve Gizli anahtar gereklidir"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "Varsayılanlar yüklenemedi",
|
||||
"defaultsNotLoaded": "Varsayılanlar yüklenmedi",
|
||||
"createFailed": "Düğüm oluşturulamadı"
|
||||
},
|
||||
"success": {
|
||||
"created": "Düğüm başarıyla oluşturuldu"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "Düğüm Seçimi",
|
||||
"remoteExitNodeSelectionDescription": "Yerel site için trafiği yönlendirecek düğümü seçin",
|
||||
"remoteExitNodeRequired": "Yerel siteler için bir düğüm seçilmelidir",
|
||||
"noRemoteExitNodesAvailable": "Düğüm Bulunamadı",
|
||||
"noRemoteExitNodesAvailableDescription": "Bu organizasyon için düğüm mevcut değil. Yerel siteleri kullanmak için önce bir düğüm oluşturun.",
|
||||
"exitNode": "Çıkış Düğümü",
|
||||
"country": "Ülke",
|
||||
"rulesMatchCountry": "Şu anda kaynak IP'ye dayanarak",
|
||||
"managedSelfHosted": {
|
||||
"title": "Yönetilen Self-Hosted",
|
||||
"description": "Daha güvenilir ve düşük bakım gerektiren, ekstra özelliklere sahip kendi kendine barındırabileceğiniz Pangolin sunucusu",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "Bu Düğümü Yönetilen Kendi Kendine Barındırma Dönüştürün"
|
||||
},
|
||||
"internationaldomaindetected": "Uluslararası Alan Adı Tespit Edildi",
|
||||
"willbestoredas": "Şu şekilde depolanacak:"
|
||||
}
|
||||
"willbestoredas": "Şu şekilde depolanacak:",
|
||||
"roleMappingDescription": "Otomatik Sağlama etkinleştirildiğinde kullanıcıların oturum açarken rollerin nasıl atandığını belirleyin.",
|
||||
"selectRole": "Bir Rol Seçin",
|
||||
"roleMappingExpression": "İfade",
|
||||
"selectRolePlaceholder": "Bir rol seçin",
|
||||
"selectRoleDescription": "Bu kimlik sağlayıcısından tüm kullanıcılara atanacak bir rol seçin",
|
||||
"roleMappingExpressionDescription": "Rol bilgilerini ID tokeninden çıkarmak için bir JMESPath ifadesi girin",
|
||||
"idpTenantIdRequired": "Kiracı Kimliği gereklidir",
|
||||
"invalidValue": "Geçersiz değer",
|
||||
"idpTypeLabel": "Kimlik Sağlayıcı Türü",
|
||||
"roleMappingExpressionPlaceholder": "örn., contains(gruplar, 'yönetici') && 'Yönetici' || 'Üye'",
|
||||
"idpGoogleConfiguration": "Google Yapılandırması",
|
||||
"idpGoogleConfigurationDescription": "Google OAuth2 kimlik bilgilerinizi yapılandırın",
|
||||
"idpGoogleClientIdDescription": "Google OAuth2 İstemci Kimliğiniz",
|
||||
"idpGoogleClientSecretDescription": "Google OAuth2 İstemci Sırrınız",
|
||||
"idpAzureConfiguration": "Azure Entra ID Yapılandırması",
|
||||
"idpAzureConfigurationDescription": "Azure Entra ID OAuth2 kimlik bilgilerinizi yapılandırın",
|
||||
"idpTenantId": "Kiracı Kimliği",
|
||||
"idpTenantIdPlaceholder": "kiraci-kimliginiz",
|
||||
"idpAzureTenantIdDescription": "Azure kiracı kimliğiniz (Azure Active Directory genel bakışında bulunur)",
|
||||
"idpAzureClientIdDescription": "Azure Uygulama Kaydı İstemci Kimliğiniz",
|
||||
"idpAzureClientSecretDescription": "Azure Uygulama Kaydı İstemci Sırrınız",
|
||||
"idpGoogleTitle": "Google",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Google Yapılandırması",
|
||||
"idpAzureConfigurationTitle": "Azure Entra ID Yapılandırması",
|
||||
"idpTenantIdLabel": "Kiracı Kimliği",
|
||||
"idpAzureClientIdDescription2": "Azure Uygulama Kaydı İstemci Kimliğiniz",
|
||||
"idpAzureClientSecretDescription2": "Azure Uygulama Kaydı İstemci Sırrınız",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC sağlayıcısı",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC sağlayıcısı",
|
||||
"subnet": "Alt ağ",
|
||||
"subnetDescription": "Bu organizasyonun ağ yapılandırması için alt ağ.",
|
||||
"authPage": "Yetkilendirme Sayfası",
|
||||
"authPageDescription": "Kuruluşunuz için yetkilendirme sayfasını yapılandırın",
|
||||
"authPageDomain": "Yetkilendirme Sayfası Alanı",
|
||||
"noDomainSet": "Alan belirlenmedi",
|
||||
"changeDomain": "Alanı Değiştir",
|
||||
"selectDomain": "Alan Seçin",
|
||||
"restartCertificate": "Sertifikayı Yenile",
|
||||
"editAuthPageDomain": "Yetkilendirme Sayfası Alanını Düzenle",
|
||||
"setAuthPageDomain": "Yetkilendirme Sayfası Alanını Ayarla",
|
||||
"failedToFetchCertificate": "Sertifika getirilemedi",
|
||||
"failedToRestartCertificate": "Sertifika yeniden başlatılamadı",
|
||||
"addDomainToEnableCustomAuthPages": "Kuruluşunuz için özel kimlik doğrulama sayfalarını etkinleştirmek için bir alan ekleyin",
|
||||
"selectDomainForOrgAuthPage": "Kuruluşun kimlik doğrulama sayfası için bir alan seçin",
|
||||
"domainPickerProvidedDomain": "Sağlanan Alan Adı",
|
||||
"domainPickerFreeProvidedDomain": "Ücretsiz Sağlanan Alan Adı",
|
||||
"domainPickerVerified": "Doğrulandı",
|
||||
"domainPickerUnverified": "Doğrulanmadı",
|
||||
"domainPickerInvalidSubdomainStructure": "Bu alt alan adı geçersiz karakterler veya yapı içeriyor. Kaydettiğinizde otomatik olarak temizlenecektir.",
|
||||
"domainPickerError": "Hata",
|
||||
"domainPickerErrorLoadDomains": "Organizasyon alan adları yüklenemedi",
|
||||
"domainPickerErrorCheckAvailability": "Alan adı kullanılabilirliği kontrol edilemedi",
|
||||
"domainPickerInvalidSubdomain": "Geçersiz alt alan adı",
|
||||
"domainPickerInvalidSubdomainRemoved": "Girdi \"{sub}\" geçersiz olduğu için kaldırıldı.",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" {domain} için geçerli yapılamadı.",
|
||||
"domainPickerSubdomainSanitized": "Alt alan adı temizlendi",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" \"{sanitized}\" olarak düzeltildi",
|
||||
"orgAuthSignInTitle": "Kuruluşunuza giriş yapın",
|
||||
"orgAuthChooseIdpDescription": "Devam etmek için kimlik sağlayıcınızı seçin",
|
||||
"orgAuthNoIdpConfigured": "Bu kuruluşta yapılandırılmış kimlik sağlayıcı yok. Bunun yerine Pangolin kimliğinizle giriş yapabilirsiniz.",
|
||||
"orgAuthSignInWithPangolin": "Pangolin ile Giriş Yap",
|
||||
"subscriptionRequiredToUse": "Bu özelliği kullanmak için abonelik gerekmektedir.",
|
||||
"idpDisabled": "Kimlik sağlayıcılar devre dışı bırakılmıştır.",
|
||||
"orgAuthPageDisabled": "Kuruluş kimlik doğrulama sayfası devre dışı bırakılmıştır.",
|
||||
"domainRestartedDescription": "Alan doğrulaması başarıyla yeniden başlatıldı",
|
||||
"resourceAddEntrypointsEditFile": "Dosyayı düzenle: config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "Dosyayı düzenle: docker-compose.yml",
|
||||
"emailVerificationRequired": "E-posta doğrulaması gereklidir. Bu adımı tamamlamak için lütfen tekrar {dashboardUrl}/auth/login üzerinden oturum açın. Sonra buraya geri dönün.",
|
||||
"twoFactorSetupRequired": "İki faktörlü kimlik doğrulama ayarı gereklidir. Bu adımı tamamlamak için lütfen tekrar {dashboardUrl}/auth/login üzerinden oturum açın. Sonra buraya geri dönün.",
|
||||
"additionalSecurityRequired": "Ek Güvenlik Gereklidir",
|
||||
"organizationRequiresAdditionalSteps": "Bu kuruluş, kaynaklara erişmeden önce ek güvenlik adımları gerektirir.",
|
||||
"completeTheseSteps": "Bu adımları tamamlayın",
|
||||
"enableTwoFactorAuthentication": "İki faktörlü kimlik doğrulamayı etkinleştir",
|
||||
"completeSecuritySteps": "Güvenlik Adımlarını Tamamla",
|
||||
"securitySettings": "Güvenlik Ayarları",
|
||||
"securitySettingsDescription": "Kuruluşunuz için güvenlik politikalarını yapılandırın",
|
||||
"requireTwoFactorForAllUsers": "Tüm Kullanıcılar için İki Faktörlü Kimlik Doğrulama Gerektir",
|
||||
"requireTwoFactorDescription": "Etkinleştirildiğinde, bu kuruluştaki tüm dahili kullanıcıların, kuruluşa erişmek için iki faktörlü kimlik doğrulama etkinleştirilmiş olmalıdır.",
|
||||
"requireTwoFactorDisabledDescription": "Bu özellik, geçerli bir lisans (Kurumsal) veya aktif bir abonelik (SaaS) gerektirir",
|
||||
"requireTwoFactorCannotEnableDescription": "Tüm kullanıcılar için etkinleştirilmeden önce hesabınızda iki faktörlü kimlik doğrulamayı etkinleştirmeniz gerekir",
|
||||
"maxSessionLength": "Maksimum Oturum Süresi",
|
||||
"maxSessionLengthDescription": "Kullanıcı oturumları için maksimum süreyi ayarlayın. Bu süre sonra kullanıcıların tekrar kimlik doğrulaması gerekecektir.",
|
||||
"maxSessionLengthDisabledDescription": "Bu özellik, geçerli bir lisans (Kurumsal) veya aktif bir abonelik (SaaS) gerektirir",
|
||||
"selectSessionLength": "Oturum süresini seçin",
|
||||
"unenforced": "Zorunlu Değil",
|
||||
"1Hour": "1 saat",
|
||||
"3Hours": "3 saat",
|
||||
"6Hours": "6 saat",
|
||||
"12Hours": "12 saat",
|
||||
"1DaySession": "1 gün",
|
||||
"3Days": "3 gün",
|
||||
"7Days": "7 gün",
|
||||
"14Days": "14 gün",
|
||||
"30DaysSession": "30 gün",
|
||||
"90DaysSession": "90 gün",
|
||||
"180DaysSession": "180 gün",
|
||||
"passwordExpiryDays": "Şifre Sona Ermesi",
|
||||
"editPasswordExpiryDescription": "Kullanıcıların parolalarını değiştirmeleri gereken gün sayısını ayarlayın.",
|
||||
"selectPasswordExpiry": "Şifre sona ermesini seçin",
|
||||
"30Days": "30 gün",
|
||||
"1Day": "1 gün",
|
||||
"60Days": "60 gün",
|
||||
"90Days": "90 gün",
|
||||
"180Days": "180 gün",
|
||||
"1Year": "1 yıl",
|
||||
"subscriptionBadge": "Abonelik Gerekiyor",
|
||||
"securityPolicyChangeWarning": "Güvenlik Politikası Değişiklik Uyarısı",
|
||||
"securityPolicyChangeDescription": "Güvenlik politikası ayarlarını değiştirmek üzeresiniz. Değişiklikleri kaydettikten sonra, bu politika güncellemelerine uyum sağlamak amacıyla tekrar kimlik doğrulamanız gerekebilir. Uyum sağlamayan tüm kullanıcıların da tekrar kimlik doğrulaması gerekecektir.",
|
||||
"securityPolicyChangeConfirmMessage": "Onaylıyorum",
|
||||
"securityPolicyChangeWarningText": "Bu, organizasyondaki tüm kullanıcıları etkileyecektir",
|
||||
"authPageErrorUpdateMessage": "Kimlik doğrulama sayfası ayarları güncellenirken bir hata oluştu.",
|
||||
"authPageErrorUpdate": "Kimlik doğrulama sayfası güncellenemedi",
|
||||
"authPageUpdated": "Kimlik doğrulama sayfası başarıyla güncellendi",
|
||||
"healthCheckNotAvailable": "Yerel",
|
||||
"rewritePath": "Yolu Yeniden Yaz",
|
||||
"rewritePathDescription": "Seçenek olarak hedefe iletmeden önce yolu yeniden yazın.",
|
||||
"continueToApplication": "Uygulamaya Devam Et",
|
||||
"checkingInvite": "Davet Kontrol Ediliyor",
|
||||
"setResourceHeaderAuth": "setResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "Başlık Kimlik Doğrulama Kaldır",
|
||||
"resourceHeaderAuthRemoveDescription": "Başlık kimlik doğrulama başarıyla kaldırıldı.",
|
||||
"resourceErrorHeaderAuthRemove": "Başlık Kimlik Doğrulama kaldırılamadı",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "Kaynak için başlık kimlik doğrulaması kaldırılamadı.",
|
||||
"resourceHeaderAuthProtectionEnabled": "Başlık Doğrulaması Etkin",
|
||||
"resourceHeaderAuthProtectionDisabled": "Başlık Doğrulaması Devre Dışı",
|
||||
"headerAuthRemove": "Başlık Doğrulaması Kaldır",
|
||||
"headerAuthAdd": "Başlık Doğrulaması Ekle",
|
||||
"resourceErrorHeaderAuthSetup": "Başlık Kimlik Doğrulama ayarlanamadı",
|
||||
"resourceErrorHeaderAuthSetupDescription": "Kaynak için başlık kimlik doğrulaması ayarlanamadı.",
|
||||
"resourceHeaderAuthSetup": "Başlık Kimlik Doğrulama başarıyla ayarlandı",
|
||||
"resourceHeaderAuthSetupDescription": "Başlık kimlik doğrulaması başarıyla ayarlandı.",
|
||||
"resourceHeaderAuthSetupTitle": "Başlık Kimlik Doğrulama Ayarla",
|
||||
"resourceHeaderAuthSetupTitleDescription": "Bu kaynağı HTTP Başlık Kimlik Doğrulaması ile korumak için temel kimlik bilgilerini (kullanıcı adı ve şifre) ayarlayın. Kaynağa erişim için https://username:password@resource.example.com formatını kullanın.",
|
||||
"resourceHeaderAuthSubmit": "Başlık Kimlik Doğrulama Ayarla",
|
||||
"actionSetResourceHeaderAuth": "Başlık Kimlik Doğrulama Ayarla",
|
||||
"enterpriseEdition": "Kurumsal Sürüm",
|
||||
"unlicensed": "Lisansız",
|
||||
"beta": "Beta",
|
||||
"manageClients": "Müşteri Yönetimi",
|
||||
"manageClientsDescription": "Müşteriler, sitelerinize bağlanabilen cihazlardır.",
|
||||
"licenseTableValidUntil": "Geçerli İki Tarih Kadar",
|
||||
"saasLicenseKeysSettingsTitle": "Kurumsal Lisanslar",
|
||||
"saasLicenseKeysSettingsDescription": "Kendi barındırdığınız Pangolin örnekleri için kurumsal lisans anahtarları oluşturun ve yönetin.",
|
||||
"sidebarEnterpriseLicenses": "Lisanslar",
|
||||
"generateLicenseKey": "Lisans Anahtarı Oluştur",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "Lütfen geçerli bir e-posta adresi girin.",
|
||||
"useCaseTypeRequired": "Lütfen bir kullanım alanı türü seçin.",
|
||||
"firstNameRequired": "İsim gereklidir.",
|
||||
"lastNameRequired": "Soyisim gereklidir.",
|
||||
"primaryUseRequired": "Lütfen öncelikli kullanımınızı açıklayın.",
|
||||
"jobTitleRequiredBusiness": "İş kullanımı için iş unvanı gereklidir.",
|
||||
"industryRequiredBusiness": "İş kullanımı için sektör gereklidir.",
|
||||
"stateProvinceRegionRequired": "Eyalet/İl/Bölge gereklidir.",
|
||||
"postalZipCodeRequired": "Posta/ZIP kodu gereklidir.",
|
||||
"companyNameRequiredBusiness": "İş kullanımı için şirket ismi gereklidir.",
|
||||
"countryOfResidenceRequiredBusiness": "İş kullanımı için ikamet edilen ülke gereklidir.",
|
||||
"countryRequiredPersonal": "Kişisel kullanım için ülke gereklidir.",
|
||||
"agreeToTermsRequired": "Şartları kabul etmelisiniz.",
|
||||
"complianceConfirmationRequired": "Fossorial Ticari Lisans ile uyumluluğu doğrulamalısınız."
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "Kişisel Kullanım",
|
||||
"description": "Bireysel, ticari olmayan kullanım için öğrenme, kişisel projeler veya denemeler gibi."
|
||||
},
|
||||
"business": {
|
||||
"title": "İş Kullanımı",
|
||||
"description": "Kuruluşlar, şirketler veya ticari veya gelir getirici faaliyetler bünyesinde kullanım için."
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "E-posta ve Lisans Türü",
|
||||
"description": "E-posta adresinizi girin ve lisans türünüzü seçin."
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "Kişisel Bilgiler",
|
||||
"description": "Kendinizden bahsedin."
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "İletişim Bilgileri",
|
||||
"description": "İletişim detaylarınız."
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "Şartlar ve Lisans Üret",
|
||||
"description": "Lisansınızı oluşturmak için şartları inceleyin ve kabul edin."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "Kullanım Açıklaması",
|
||||
"description": "Kullanım amacınızı doğru bir şekilde yansıtan lisans seviyesini seçin. Kişisel Lisans, yazılımın bireysel, ticari olmayan veya yıllık geliri 100,000 ABD Dolarının altında olan küçük ölçekli ticari faaliyetlerde ücretsiz kullanılmasına izin verir. Bu sınırların ötesinde kullanım — bir işletme, organizasyon veya diğer gelir getirici ortamlarda kullanım dahil olmak üzere — geçerli bir Kurumsal Lisans ve ilgili lisans ücretinin ödenmesini gerektirir. Tüm kullanıcılar, ister Kişisel ister Kurumsal, Fossorial Ticari Lisans Şartlarına uymalıdır."
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "Deneme Süresi Bilgileri",
|
||||
"description": "Bu Lisans Anahtarı, Kurumsal özellikleri 7 günlük bir değerlendirme süresi için etkinleştirir. Değerlendirme süresi bittikten sonra, Ücretli Özelliklere devam eden erişim, geçerli bir Kişisel veya Kurumsal Lisans altında etkinleşmeyi gerektirir. Kurumsal lisanslama için sales@pangolin.net ile iletişime geçin."
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "Pangolin'i kişisel veya iş kullanımı için mi kullanıyorsunuz?",
|
||||
"firstName": "İsim",
|
||||
"lastName": "Soyisim",
|
||||
"jobTitle": "İş Unvanı",
|
||||
"primaryUseQuestion": "Pangolin'i öncelikli olarak ne amacıyla kullanmayı planlıyorsunuz?",
|
||||
"industryQuestion": "Hangi sektördesiniz?",
|
||||
"prospectiveUsersQuestion": "Kaç potansiyel kullanıcı öngörüyorsunuz?",
|
||||
"prospectiveSitesQuestion": "Kaç potansiyel site (tünel) öngörüyorsunuz?",
|
||||
"companyName": "Şirket İsmi",
|
||||
"countryOfResidence": "İkamet edilen ülke",
|
||||
"stateProvinceRegion": "Eyalet / İl / Bölge",
|
||||
"postalZipCode": "Posta / ZIP Kodu",
|
||||
"companyWebsite": "Şirket web sitesi",
|
||||
"companyPhoneNumber": "Şirket telefon numarası",
|
||||
"country": "Ülke",
|
||||
"phoneNumberOptional": "Telefon numarası (isteğe bağlı)",
|
||||
"complianceConfirmation": "Sağladığım bilgilerin doğru olduğunu ve Fossorial Ticari Lisans ile uyumlu olduğumu teyit ederim. Yanlış bilgi raporlamak veya ürün kullanımını yanlış tanımlamak lisans ihlalidir ve anahtarınızın iptal edilmesine neden olabilir."
|
||||
},
|
||||
"buttons": {
|
||||
"close": "Kapat",
|
||||
"previous": "Önceki",
|
||||
"next": "Sonraki",
|
||||
"generateLicenseKey": "Lisans Anahtarı Oluştur"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "Lisans anahtarı başarıyla oluşturuldu",
|
||||
"description": "Lisans anahtarınız oluşturuldu ve kullanıma hazır."
|
||||
},
|
||||
"error": {
|
||||
"title": "Lisans anahtarı oluşturulamadı",
|
||||
"description": "Lisans anahtarı oluşturulurken bir hata oluştu."
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "Öncelik",
|
||||
"priorityDescription": "Daha yüksek öncelikli rotalar önce değerlendirilir. Öncelik = 100, otomatik sıralama anlamına gelir (sistem karar verir). Manuel öncelik uygulamak için başka bir numara kullanın.",
|
||||
"instanceName": "Örnek İsmi",
|
||||
"pathMatchModalTitle": "Yol Eşleşmesini Yapılandır",
|
||||
"pathMatchModalDescription": "Gelen isteklerin yolu temel alarak nasıl eşleştirilmesi gerektiğini ayarlayın.",
|
||||
"pathMatchType": "Eşleşme Türü",
|
||||
"pathMatchPrefix": "Önek",
|
||||
"pathMatchExact": "Tam",
|
||||
"pathMatchRegex": "Regex",
|
||||
"pathMatchValue": "Yol Değeri",
|
||||
"clear": "Temizle",
|
||||
"saveChanges": "Değişiklikleri Kaydet",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/path",
|
||||
"pathMatchPrefixHelp": "Örnek: /api, /api/users vb.'ni eşleştirir.",
|
||||
"pathMatchExactHelp": "Örnek: /api yalnızca /api'yi eşleştirir",
|
||||
"pathMatchRegexHelp": "Örnek: ^/api/.* her şeyi eşleştirir /api/anything",
|
||||
"pathRewriteModalTitle": "Yolu Yeniden Yazmayı Yapılandır",
|
||||
"pathRewriteModalDescription": "Hedefe iletilmeden önce eşleşen yolu dönüştürün.",
|
||||
"pathRewriteType": "Yeniden Yazma Türü",
|
||||
"pathRewritePrefixOption": "Önek - Ön ek değiştirme",
|
||||
"pathRewriteExactOption": "Tam - Tüm yolu değiştir",
|
||||
"pathRewriteRegexOption": "Regex - Desen değiştirme",
|
||||
"pathRewriteStripPrefixOption": "Ön Ek Kaldır - Ön eki sil",
|
||||
"pathRewriteValue": "Yeniden Yazma Değeri",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "Eşleşen öneki bu değerle değiştir",
|
||||
"pathRewriteExactHelp": "Yol tam olarak eşleştiğinde, yolun tamamını bu değerle değiştir",
|
||||
"pathRewriteRegexHelp": "Değiştirme için $1, $2 gibi yakalama gruplarını kullan",
|
||||
"pathRewriteStripPrefixHelp": "Öneki silmek veya yeni bir ön ek sağlamak için boş bırakın",
|
||||
"pathRewritePrefix": "Önek",
|
||||
"pathRewriteExact": "Tam",
|
||||
"pathRewriteRegex": "Regex",
|
||||
"pathRewriteStrip": "Sil",
|
||||
"pathRewriteStripLabel": "sil",
|
||||
"sidebarEnableEnterpriseLicense": "Kurumsal Lisans Etkinleştir",
|
||||
"cannotbeUndone": "Bu geri alınamaz.",
|
||||
"toConfirm": "doğrulamak için",
|
||||
"deleteClientQuestion": "Müşteriyi siteden ve organizasyondan kaldırmak istediğinizden emin misiniz?",
|
||||
"clientMessageRemove": "Kaldırıldıktan sonra müşteri siteye bağlanamayacaktır.",
|
||||
"sidebarLogs": "Kayıtlar",
|
||||
"request": "İstek",
|
||||
"logs": "Günlükler",
|
||||
"logsSettingsDescription": "Bu organizasyondan toplanan günlükleri izleyin",
|
||||
"searchLogs": "Günlüklerde ara...",
|
||||
"action": "Eylem",
|
||||
"actor": "Aktör",
|
||||
"timestamp": "Zaman damgası",
|
||||
"accessLogs": "Erişim Günlükleri",
|
||||
"exportCsv": "CSV Dışa Aktar",
|
||||
"actorId": "Aktör Kimliği",
|
||||
"allowedByRule": "Kurallara Göre İzin Verildi",
|
||||
"allowedNoAuth": "Kimlik Doğrulama Yok İzin Verildi",
|
||||
"validAccessToken": "Geçerli Erişim Jetonu",
|
||||
"validHeaderAuth": "Geçerli Başlık Doğrulama",
|
||||
"validPincode": "Geçerli Pincode",
|
||||
"validPassword": "Geçerli Şifre",
|
||||
"validEmail": "Geçerli E-posta",
|
||||
"validSSO": "Geçerli SSO",
|
||||
"resourceBlocked": "Kaynak Engellendi",
|
||||
"droppedByRule": "Kurallara Göre Çıkartıldı",
|
||||
"noSessions": "Oturum Yok",
|
||||
"temporaryRequestToken": "Geçici İstek Jetonu",
|
||||
"noMoreAuthMethods": "Daha Fazla Kimlik Doğrulama Yöntemi Yok",
|
||||
"ip": "IP",
|
||||
"reason": "Sebep",
|
||||
"requestLogs": "İstek Günlükleri",
|
||||
"host": "Sunucu",
|
||||
"location": "Konum",
|
||||
"actionLogs": "Eylem Günlükleri",
|
||||
"sidebarLogsRequest": "İstek Günlükleri",
|
||||
"sidebarLogsAccess": "Erişim Günlükleri",
|
||||
"sidebarLogsAction": "Eylem Günlükleri",
|
||||
"logRetention": "Kayıt Saklama",
|
||||
"logRetentionDescription": "Bu organizasyon için farklı türdeki günlüklerin ne kadar süre saklanacağını yönetin veya devre dışı bırakın",
|
||||
"requestLogsDescription": "Bu organizasyondaki kaynaklar için ayrıntılı istek günlüklerini görüntüleyin",
|
||||
"logRetentionRequestLabel": "İstek Günlüğü Saklama",
|
||||
"logRetentionRequestDescription": "İstek günlüklerini ne kadar süre tutacağını belirle",
|
||||
"logRetentionAccessLabel": "Erişim Günlüğü Saklama",
|
||||
"logRetentionAccessDescription": "Erişim günlüklerini ne kadar süre tutacağını belirle",
|
||||
"logRetentionActionLabel": "Eylem Günlüğü Saklama",
|
||||
"logRetentionActionDescription": "Eylem günlüklerini ne kadar süre tutacağını belirle",
|
||||
"logRetentionDisabled": "Devre Dışı",
|
||||
"logRetention3Days": "3 gün",
|
||||
"logRetention7Days": "7 gün",
|
||||
"logRetention14Days": "14 gün",
|
||||
"logRetention30Days": "30 gün",
|
||||
"logRetention90Days": "90 gün",
|
||||
"logRetentionForever": "Sonsuza kadar",
|
||||
"actionLogsDescription": "Bu organizasyondaki eylemler geçmişini görüntüleyin",
|
||||
"accessLogsDescription": "Bu organizasyondaki kaynaklar için erişim kimlik doğrulama isteklerini görüntüleyin",
|
||||
"licenseRequiredToUse": "Bu özelliği kullanmak için bir kurumsal lisans gereklidir.",
|
||||
"certResolver": "Sertifika Çözücü",
|
||||
"certResolverDescription": "Bu kaynak için kullanılacak sertifika çözücüsünü seçin.",
|
||||
"selectCertResolver": "Sertifika Çözücü Seçin",
|
||||
"enterCustomResolver": "Özel Çözücü Girin",
|
||||
"preferWildcardCert": "Joker Sertifikayı Tercih Et",
|
||||
"unverified": "Doğrulanmadı",
|
||||
"domainSetting": "Alan Adı Ayarları",
|
||||
"domainSettingDescription": "Alan adınız için ayarları yapılandırın",
|
||||
"preferWildcardCertDescription": "Joker sertifika üretmeye çalışın (doğru yapılandırılmış bir sertifika çözücü gereklidir).",
|
||||
"recordName": "Kayıt Adı",
|
||||
"auto": "Otomatik",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "Kayıtları Nasıl Ekleyebilirsiniz",
|
||||
"dnsRecord": "DNS Kayıtları",
|
||||
"required": "Gerekli",
|
||||
"domainSettingsUpdated": "Alan adına yönelik ayarlar başarıyla güncellendi",
|
||||
"orgOrDomainIdMissing": "Organizasyon veya Alan Adı Kimliği eksik",
|
||||
"loadingDNSRecords": "DNS kayıtları yükleniyor...",
|
||||
"olmUpdateAvailableInfo": "Olm'nin güncellenmiş bir sürümü mevcut. En iyi deneyim için lütfen en son sürüme güncelleyin.",
|
||||
"client": "İstemci",
|
||||
"proxyProtocol": "Proxy Protokol Ayarları",
|
||||
"proxyProtocolDescription": "TCP/UDP hizmetleri için istemci IP adreslerini korumak için Proxy Protokolünü yapılandırın.",
|
||||
"enableProxyProtocol": "Proxy Protokolünü Etkinleştir",
|
||||
"proxyProtocolInfo": "TCP/UDP arka uçları için istemci IP adreslerini koruyun",
|
||||
"proxyProtocolVersion": "Proxy Protokol Versiyonu",
|
||||
"version1": " Versiyon 1 (Önerilen)",
|
||||
"version2": "Versiyon 2",
|
||||
"versionDescription": "Versiyon 1 metin tabanlı ve yaygın olarak desteklenir. Versiyon 2 ise ikili ve daha verimlidir ama daha az uyumludur.",
|
||||
"warning": "Uyarı",
|
||||
"proxyProtocolWarning": "Arka uç uygulamanız, Proxy Protokol bağlantılarını kabul etmek üzere yapılandırılmalıdır. Arka ucunuz Proxy Protokolünü desteklemiyorsa, bunu etkinleştirmek tüm bağlantıları koparır. Traefik'ten gelen Proxy Protokol başlıklarına güvenecek şekilde arka ucunuzu yapılandırdığınızdan emin olun.",
|
||||
"restarting": "Yeniden Başlatılıyor...",
|
||||
"manual": "Manuel",
|
||||
"messageSupport": "Destek Mesajı Gönder",
|
||||
"supportNotAvailableTitle": "Destek Yok",
|
||||
"supportNotAvailableDescription": "Destek şu anda mevcut değil. Destek'e bir e-posta gönderebilirsiniz: support@pangolin.net.",
|
||||
"supportRequestSentTitle": "Destek İsteği Gönderildi",
|
||||
"supportRequestSentDescription": "Mesajınız başarıyla gönderildi.",
|
||||
"supportRequestFailedTitle": "İsteği Gönderme Başarısız",
|
||||
"supportRequestFailedDescription": "Destek isteği gönderilirken bir hata oluştu.",
|
||||
"supportSubjectRequired": "Konu gerekli",
|
||||
"supportSubjectMaxLength": "Konu en fazla 255 karakter olabilir",
|
||||
"supportMessageRequired": "Mesaj gerekli",
|
||||
"supportReplyTo": "Yanıtla",
|
||||
"supportSubject": "Konu",
|
||||
"supportSubjectPlaceholder": "Konu girin",
|
||||
"supportMessage": "Mesaj",
|
||||
"supportMessagePlaceholder": "Mesajınızı girin",
|
||||
"supportSending": "Gönderiliyor...",
|
||||
"supportSend": "Gönder",
|
||||
"supportMessageSent": "Mesaj Gönderildi!",
|
||||
"supportWillContact": "En kısa sürede size geri döneceğiz!",
|
||||
"selectLogRetention": "Kayıt saklama seç",
|
||||
"showColumns": "Sütunları Göster",
|
||||
"hideColumns": "Sütunları Gizle",
|
||||
"columnVisibility": "Sütun Görünürlüğü",
|
||||
"toggleColumn": "{columnName} sütununu aç/kapat",
|
||||
"allColumns": "Tüm Sütunlar",
|
||||
"defaultColumns": "Varsayılan Sütunlar",
|
||||
"customizeView": "Görünümü Özelleştir",
|
||||
"viewOptions": "Görünüm Seçenekleri",
|
||||
"selectAll": "Tümünü Seç",
|
||||
"selectNone": "Hiçbirini Seçme",
|
||||
"selectedResources": "Seçilen Kaynaklar",
|
||||
"enableSelected": "Seçilenleri Etkinleştir",
|
||||
"disableSelected": "Seçilenleri Devre Dışı Bırak",
|
||||
"checkSelectedStatus": "Seçilenlerin Durumunu Kontrol Et"
|
||||
}
|
||||
@@ -47,9 +47,8 @@
|
||||
"edit": "编辑",
|
||||
"siteConfirmDelete": "确认删除站点",
|
||||
"siteDelete": "删除站点",
|
||||
"siteMessageRemove": "一旦删除,该站点将无法访问。与该站点相关的所有资源和目标也将被删除。",
|
||||
"siteMessageConfirm": "请在下面输入站点名称以确认。",
|
||||
"siteQuestionRemove": "您确定要从组织中删除 {selectedSite} 站点吗?",
|
||||
"siteMessageRemove": "一旦移除,站点将无法访问。与站点相关的所有目标也将被移除。",
|
||||
"siteQuestionRemove": "您确定要从组织中删除该站点吗?",
|
||||
"siteManageSites": "管理站点",
|
||||
"siteDescription": "允许通过安全隧道连接到您的网络",
|
||||
"siteCreate": "创建站点",
|
||||
@@ -96,7 +95,7 @@
|
||||
"siteWgDescription": "使用任何 WireGuard 客户端来建立隧道。需要手动配置 NAT。",
|
||||
"siteWgDescriptionSaas": "使用任何WireGuard客户端建立隧道。需要手动配置NAT。仅适用于自托管节点。",
|
||||
"siteLocalDescription": "仅限本地资源。不需要隧道。",
|
||||
"siteLocalDescriptionSaas": "仅本地资源。无需隧道。仅适用于自托管节点。",
|
||||
"siteLocalDescriptionSaas": "仅本地资源。没有隧道。仅在远程节点上可用。",
|
||||
"siteSeeAll": "查看所有站点",
|
||||
"siteTunnelDescription": "确定如何连接到您的网站",
|
||||
"siteNewtCredentials": "Newt 凭据",
|
||||
@@ -132,7 +131,7 @@
|
||||
"expireIn": "过期时间",
|
||||
"neverExpire": "永不过期",
|
||||
"shareExpireDescription": "过期时间是链接可以使用并提供对资源的访问时间。 此时间后,链接将不再工作,使用此链接的用户将失去对资源的访问。",
|
||||
"shareSeeOnce": "您只能看到此链接。请确保复制它。",
|
||||
"shareSeeOnce": "您只能看到一次此链接。请确保复制它。",
|
||||
"shareAccessHint": "任何具有此链接的人都可以访问该资源。小心地分享它。",
|
||||
"shareTokenUsage": "查看访问令牌使用情况",
|
||||
"createLink": "创建链接",
|
||||
@@ -154,8 +153,7 @@
|
||||
"protected": "受到保护",
|
||||
"notProtected": "未受到保护",
|
||||
"resourceMessageRemove": "一旦删除,资源将不再可访问。与该资源相关的所有目标也将被删除。",
|
||||
"resourceMessageConfirm": "请在下面输入资源名称以确认。",
|
||||
"resourceQuestionRemove": "您确定要从组织中删除 {selectedResource} 吗?",
|
||||
"resourceQuestionRemove": "您确定要从组织中删除资源吗?",
|
||||
"resourceHTTP": "HTTPS 资源",
|
||||
"resourceHTTPDescription": "使用子域或根域名通过 HTTPS 向您的应用程序提出代理请求。",
|
||||
"resourceRaw": "TCP/UDP 资源",
|
||||
@@ -168,6 +166,9 @@
|
||||
"siteSelect": "选择站点",
|
||||
"siteSearch": "搜索站点",
|
||||
"siteNotFound": "未找到站点。",
|
||||
"selectCountry": "选择国家",
|
||||
"searchCountries": "搜索国家...",
|
||||
"noCountryFound": "找不到国家。",
|
||||
"siteSelectionDescription": "此站点将为目标提供连接。",
|
||||
"resourceType": "资源类型",
|
||||
"resourceTypeDescription": "确定如何访问您的资源",
|
||||
@@ -178,7 +179,7 @@
|
||||
"baseDomain": "根域名",
|
||||
"subdomnainDescription": "您的资源可以访问的子域名。",
|
||||
"resourceRawSettings": "TCP/UDP 设置",
|
||||
"resourceRawSettingsDescription": "配置如何通过 TCP/UDP 访问您的资源",
|
||||
"resourceRawSettingsDescription": "配置如何通过 TCP/UDP 访问您的资源。 您映射资源到主机Pangolin服务器上的端口,这样您就可以访问服务器-公共-ip:mapped端口的资源。",
|
||||
"protocol": "协议",
|
||||
"protocolSelect": "选择协议",
|
||||
"resourcePortNumber": "端口号",
|
||||
@@ -217,7 +218,7 @@
|
||||
"orgDeleteConfirm": "确认删除组织",
|
||||
"orgMessageRemove": "此操作不可逆,这将删除所有相关数据。",
|
||||
"orgMessageConfirm": "要确认,请在下面输入组织名称。",
|
||||
"orgQuestionRemove": "你确定要删除 \"{selectedOrg}\" 组织吗?",
|
||||
"orgQuestionRemove": "您确定要删除组织吗?",
|
||||
"orgUpdated": "组织已更新",
|
||||
"orgUpdatedDescription": "组织已更新。",
|
||||
"orgErrorUpdate": "更新组织失败",
|
||||
@@ -284,9 +285,8 @@
|
||||
"apiKeysAdd": "生成 API 密钥",
|
||||
"apiKeysErrorDelete": "删除 API 密钥出错",
|
||||
"apiKeysErrorDeleteMessage": "删除 API 密钥出错",
|
||||
"apiKeysQuestionRemove": "您确定要从组织中删除 \"{selectedApiKey}\" API密钥吗?",
|
||||
"apiKeysQuestionRemove": "您确定要从组织中删除 API 密钥吗?",
|
||||
"apiKeysMessageRemove": "一旦删除,此API密钥将无法被使用。",
|
||||
"apiKeysMessageConfirm": "要确认,请在下方输入API密钥名称。",
|
||||
"apiKeysDeleteConfirm": "确认删除 API 密钥",
|
||||
"apiKeysDelete": "删除 API 密钥",
|
||||
"apiKeysManage": "管理 API 密钥",
|
||||
@@ -302,8 +302,7 @@
|
||||
"userDeleteConfirm": "确认删除用户",
|
||||
"userDeleteServer": "从服务器删除用户",
|
||||
"userMessageRemove": "该用户将被从所有组织中删除并完全从服务器中删除。",
|
||||
"userMessageConfirm": "请在下面输入用户名称以确认。",
|
||||
"userQuestionRemove": "您确定要从服务器中永久删除 {selectedUser} 吗?",
|
||||
"userQuestionRemove": "您确定要从服务器永久删除用户吗?",
|
||||
"licenseKey": "许可证密钥",
|
||||
"valid": "有效",
|
||||
"numberOfSites": "站点数量",
|
||||
@@ -336,7 +335,7 @@
|
||||
"fossorialLicense": "查看Fossorial Commercial License和订阅条款",
|
||||
"licenseMessageRemove": "这将删除许可证密钥和它授予的所有相关权限。",
|
||||
"licenseMessageConfirm": "要确认,请在下面输入许可证密钥。",
|
||||
"licenseQuestionRemove": "您确定要删除 {selectedKey} 的邀请吗?",
|
||||
"licenseQuestionRemove": "您确定要删除许可证密钥?",
|
||||
"licenseKeyDelete": "删除许可证密钥",
|
||||
"licenseKeyDeleteConfirm": "确认删除许可证密钥",
|
||||
"licenseTitle": "管理许可证状态",
|
||||
@@ -369,7 +368,7 @@
|
||||
"inviteRemoveErrorDescription": "删除邀请时出错。",
|
||||
"inviteRemoved": "邀请已删除",
|
||||
"inviteRemovedDescription": "为 {email} 创建的邀请已删除",
|
||||
"inviteQuestionRemove": "您确定要删除 {email} 的邀请吗?",
|
||||
"inviteQuestionRemove": "您确定要删除邀请吗?",
|
||||
"inviteMessageRemove": "一旦删除,这个邀请将不再有效。",
|
||||
"inviteMessageConfirm": "要确认,请在下面输入邀请的电子邮件地址。",
|
||||
"inviteQuestionRegenerate": "您确定要重新邀请 {email} 吗?这将会撤销掉之前的邀请",
|
||||
@@ -395,9 +394,8 @@
|
||||
"userErrorOrgRemoveDescription": "删除用户时出错。",
|
||||
"userOrgRemoved": "用户已删除",
|
||||
"userOrgRemovedDescription": "已将 {email} 从组织中移除。",
|
||||
"userQuestionOrgRemove": "你确定要将 {email} 从组织中移除吗?",
|
||||
"userQuestionOrgRemove": "您确定要从组织中删除此用户吗?",
|
||||
"userMessageOrgRemove": "一旦删除,这个用户将不再能够访问组织。 你总是可以稍后重新邀请他们,但他们需要再次接受邀请。",
|
||||
"userMessageOrgConfirm": "请在下面输入用户名称以确认。",
|
||||
"userRemoveOrgConfirm": "确认删除用户",
|
||||
"userRemoveOrg": "从组织中删除用户",
|
||||
"users": "用户",
|
||||
@@ -454,6 +452,8 @@
|
||||
"accessRoleErrorAddDescription": "添加用户到角色时出错。",
|
||||
"userSaved": "用户已保存",
|
||||
"userSavedDescription": "用户已更新。",
|
||||
"autoProvisioned": "自动设置",
|
||||
"autoProvisionedDescription": "允许此用户由身份提供商自动管理",
|
||||
"accessControlsDescription": "管理此用户在组织中可以访问和做什么",
|
||||
"accessControlsSubmit": "保存访问控制",
|
||||
"roles": "角色",
|
||||
@@ -463,7 +463,10 @@
|
||||
"createdAt": "创建于",
|
||||
"proxyErrorInvalidHeader": "无效的自定义主机头值。使用域名格式,或将空保存为取消自定义主机头。",
|
||||
"proxyErrorTls": "无效的 TLS 服务器名称。使用域名格式,或保存空以删除 TLS 服务器名称。",
|
||||
"proxyEnableSSL": "启用 SSL (https)",
|
||||
"proxyEnableSSL": "启用 SSL",
|
||||
"proxyEnableSSLDescription": "启用 SSL/TLS 加密以确保您目标的 HTTPS 连接。",
|
||||
"target": "Target",
|
||||
"configureTarget": "配置目标",
|
||||
"targetErrorFetch": "获取目标失败",
|
||||
"targetErrorFetchDescription": "获取目标时出错",
|
||||
"siteErrorFetch": "获取资源失败",
|
||||
@@ -490,7 +493,7 @@
|
||||
"targetTlsSettings": "安全连接配置",
|
||||
"targetTlsSettingsDescription": "配置资源的 SSL/TLS 设置",
|
||||
"targetTlsSettingsAdvanced": "高级TLS设置",
|
||||
"targetTlsSni": "TLS 服务器名称 (SNI)",
|
||||
"targetTlsSni": "TLS 服务器名称",
|
||||
"targetTlsSniDescription": "SNI使用的 TLS 服务器名称。留空使用默认值。",
|
||||
"targetTlsSubmit": "保存设置",
|
||||
"targets": "目标配置",
|
||||
@@ -499,9 +502,21 @@
|
||||
"targetStickySessionsDescription": "将连接保持在同一个后端目标的整个会话中。",
|
||||
"methodSelect": "选择方法",
|
||||
"targetSubmit": "添加目标",
|
||||
"targetNoOne": "没有目标。使用表单添加目标。",
|
||||
"targetNoOne": "此资源没有任何目标。添加目标来配置向您后端发送请求的位置。",
|
||||
"targetNoOneDescription": "在上面添加多个目标将启用负载平衡。",
|
||||
"targetsSubmit": "保存目标",
|
||||
"addTarget": "添加目标",
|
||||
"targetErrorInvalidIp": "无效的 IP 地址",
|
||||
"targetErrorInvalidIpDescription": "请输入有效的IP地址或主机名",
|
||||
"targetErrorInvalidPort": "无效的端口",
|
||||
"targetErrorInvalidPortDescription": "请输入有效的端口号",
|
||||
"targetErrorNoSite": "没有选择站点",
|
||||
"targetErrorNoSiteDescription": "请选择目标站点",
|
||||
"targetCreated": "目标已创建",
|
||||
"targetCreatedDescription": "目标已成功创建",
|
||||
"targetErrorCreate": "创建目标失败",
|
||||
"targetErrorCreateDescription": "创建目标时出错",
|
||||
"save": "保存",
|
||||
"proxyAdditional": "附加代理设置",
|
||||
"proxyAdditionalDescription": "配置你的资源如何处理代理设置",
|
||||
"proxyCustomHeader": "自定义主机标题",
|
||||
@@ -511,6 +526,7 @@
|
||||
"ipAddressErrorInvalidFormat": "无效的 IP 地址格式",
|
||||
"ipAddressErrorInvalidOctet": "无效的 IP 地址",
|
||||
"path": "路径",
|
||||
"matchPath": "匹配路径",
|
||||
"ipAddressRange": "IP 范围",
|
||||
"rulesErrorFetch": "获取规则失败",
|
||||
"rulesErrorFetchDescription": "获取规则时出错",
|
||||
@@ -592,7 +608,7 @@
|
||||
"newtErrorFetchReleases": "无法获取版本信息: {err}",
|
||||
"newtErrorFetchLatest": "无法获取最新版信息: {err}",
|
||||
"newtEndpoint": "Newt 端点",
|
||||
"newtId": "Newt ID",
|
||||
"newtId": "Newt ID",
|
||||
"newtSecretKey": "Newt 私钥",
|
||||
"architecture": "架构",
|
||||
"sites": "站点",
|
||||
@@ -709,7 +725,7 @@
|
||||
"pangolinServerAdmin": "服务器管理员 - Pangolin",
|
||||
"licenseTierProfessional": "专业许可证",
|
||||
"licenseTierEnterprise": "企业许可证",
|
||||
"licenseTierCommercial": "商业许可证",
|
||||
"licenseTierPersonal": "个人许可证",
|
||||
"licensed": "已授权",
|
||||
"yes": "是",
|
||||
"no": "否",
|
||||
@@ -721,7 +737,7 @@
|
||||
"idpManageDescription": "查看和管理系统中的身份提供商",
|
||||
"idpDeletedDescription": "身份提供商删除成功",
|
||||
"idpOidc": "OAuth2/OIDC",
|
||||
"idpQuestionRemove": "你确定要永久删除 \"{name}\" 这个身份提供商吗?",
|
||||
"idpQuestionRemove": "您确定要永久删除身份提供者吗?",
|
||||
"idpMessageRemove": "这将删除身份提供者和所有相关的配置。通过此提供者进行身份验证的用户将无法登录。",
|
||||
"idpMessageConfirm": "要确认,请在下面输入身份提供者的名称。",
|
||||
"idpConfirmDelete": "确认删除身份提供商",
|
||||
@@ -744,7 +760,7 @@
|
||||
"idpDisplayName": "此身份提供商的显示名称",
|
||||
"idpAutoProvisionUsers": "自动提供用户",
|
||||
"idpAutoProvisionUsersDescription": "如果启用,用户将在首次登录时自动在系统中创建,并且能够映射用户到角色和组织。",
|
||||
"licenseBadge": "专业版",
|
||||
"licenseBadge": "EE",
|
||||
"idpType": "提供者类型",
|
||||
"idpTypeDescription": "选择您想要配置的身份提供者类型",
|
||||
"idpOidcConfigure": "OAuth2/OIDC 配置",
|
||||
@@ -895,6 +911,18 @@
|
||||
"passwordResetCodeDescription": "请检查您的电子邮件以获取验证码。",
|
||||
"passwordNew": "新密码",
|
||||
"passwordNewConfirm": "确认新密码",
|
||||
"changePassword": "更改密码",
|
||||
"changePasswordDescription": "更新您的帐户密码",
|
||||
"oldPassword": "当前密码",
|
||||
"newPassword": "新密码",
|
||||
"confirmNewPassword": "确认新密码",
|
||||
"changePasswordError": "更改密码失败",
|
||||
"changePasswordErrorDescription": "更改您的密码时出错",
|
||||
"changePasswordSuccess": "密码修改成功",
|
||||
"changePasswordSuccessDescription": "您的密码已成功更新",
|
||||
"passwordExpiryRequired": "需要密码过期",
|
||||
"passwordExpiryDescription": "该机构要求您每 {maxDays} 天更改一次密码。",
|
||||
"changePasswordNow": "现在更改密码",
|
||||
"pincodeAuth": "验证器代码",
|
||||
"pincodeSubmit2": "提交代码",
|
||||
"passwordResetSubmit": "请求重置",
|
||||
@@ -982,6 +1010,8 @@
|
||||
"licenseTierProfessionalRequired": "需要专业版",
|
||||
"licenseTierProfessionalRequiredDescription": "此功能仅在专业版可用。",
|
||||
"actionGetOrg": "获取组织",
|
||||
"updateOrgUser": "更新组织用户",
|
||||
"createOrgUser": "创建组织用户",
|
||||
"actionUpdateOrg": "更新组织",
|
||||
"actionUpdateUser": "更新用户",
|
||||
"actionGetUser": "获取用户",
|
||||
@@ -991,6 +1021,7 @@
|
||||
"actionDeleteSite": "删除站点",
|
||||
"actionGetSite": "获取站点",
|
||||
"actionListSites": "站点列表",
|
||||
"actionApplyBlueprint": "应用蓝图",
|
||||
"setupToken": "设置令牌",
|
||||
"setupTokenDescription": "从服务器控制台输入设置令牌。",
|
||||
"setupTokenRequired": "需要设置令牌",
|
||||
@@ -1075,7 +1106,6 @@
|
||||
"navbar": "导航菜单",
|
||||
"navbarDescription": "应用程序的主导航菜单",
|
||||
"navbarDocsLink": "文件",
|
||||
"commercialEdition": "商业版",
|
||||
"otpErrorEnable": "无法启用 2FA",
|
||||
"otpErrorEnableDescription": "启用 2FA 时出错",
|
||||
"otpSetupCheckCode": "请输入您的6位数字代码",
|
||||
@@ -1131,10 +1161,29 @@
|
||||
"sidebarAllUsers": "所有用户",
|
||||
"sidebarIdentityProviders": "身份提供商",
|
||||
"sidebarLicense": "证书",
|
||||
"sidebarClients": "客户端(测试版)",
|
||||
"sidebarClients": "客户端",
|
||||
"sidebarDomains": "域",
|
||||
"enableDockerSocket": "启用停靠套接字",
|
||||
"enableDockerSocketDescription": "启用 Docker Socket 发现以填充容器信息。必须向 Newt 提供 Socket 路径。",
|
||||
"sidebarBluePrints": "蓝图",
|
||||
"blueprints": "蓝图",
|
||||
"blueprintsDescription": "应用声明配置并查看先前运行的",
|
||||
"blueprintAdd": "添加蓝图",
|
||||
"blueprintGoBack": "查看所有蓝图",
|
||||
"blueprintCreate": "创建蓝图",
|
||||
"blueprintCreateDescription2": "按照下面的步骤创建和应用新的蓝图",
|
||||
"blueprintDetails": "蓝图详细信息",
|
||||
"blueprintDetailsDescription": "查看应用蓝图的结果和发生的任何错误",
|
||||
"blueprintInfo": "蓝图信息",
|
||||
"message": "留言",
|
||||
"blueprintContentsDescription": "定义描述您基础设施的 YAML 内容",
|
||||
"blueprintErrorCreateDescription": "应用蓝图时出错",
|
||||
"blueprintErrorCreate": "创建蓝图时出错",
|
||||
"searchBlueprintProgress": "搜索蓝图...",
|
||||
"appliedAt": "应用于",
|
||||
"source": "来源",
|
||||
"contents": "目录",
|
||||
"parsedContents": "解析内容 (只读)",
|
||||
"enableDockerSocket": "启用 Docker 蓝图",
|
||||
"enableDockerSocketDescription": "启用 Docker Socket 标签擦除蓝图标签。套接字路径必须提供给新的。",
|
||||
"enableDockerSocketLink": "了解更多",
|
||||
"viewDockerContainers": "查看停靠容器",
|
||||
"containersIn": "{siteName} 中的容器",
|
||||
@@ -1147,7 +1196,7 @@
|
||||
"containerLabels": "标签",
|
||||
"containerLabelsCount": "{count, plural, other {# 标签}}",
|
||||
"containerLabelsTitle": "容器标签",
|
||||
"containerLabelEmpty": "<empty>",
|
||||
"containerLabelEmpty": "<为空>",
|
||||
"containerPorts": "端口",
|
||||
"containerPortsMore": "+{count} 更多",
|
||||
"containerActions": "行动",
|
||||
@@ -1188,9 +1237,8 @@
|
||||
"domainCreate": "创建域",
|
||||
"domainCreatedDescription": "域创建成功",
|
||||
"domainDeletedDescription": "成功删除域",
|
||||
"domainQuestionRemove": "您确定要从您的账户中移除域{domain}吗?",
|
||||
"domainQuestionRemove": "您确定要从您的帐户中删除域名吗?",
|
||||
"domainMessageRemove": "移除后,该域将不再与您的账户关联。",
|
||||
"domainMessageConfirm": "要确认,请在下方输入域名。",
|
||||
"domainConfirmDelete": "确认删除域",
|
||||
"domainDelete": "删除域",
|
||||
"domain": "域",
|
||||
@@ -1234,7 +1282,7 @@
|
||||
"newtUpdateAvailable": "更新可用",
|
||||
"newtUpdateAvailableInfo": "新版本的 Newt 已可用。请更新到最新版本以获得最佳体验。",
|
||||
"domainPickerEnterDomain": "域名",
|
||||
"domainPickerPlaceholder": "myapp.example.com、api.v1.mydomain.com 或仅 myapp",
|
||||
"domainPickerPlaceholder": "example.com",
|
||||
"domainPickerDescription": "输入资源的完整域名以查看可用选项。",
|
||||
"domainPickerDescriptionSaas": "输入完整域名、子域或名称以查看可用选项。",
|
||||
"domainPickerTabAll": "所有",
|
||||
@@ -1249,6 +1297,48 @@
|
||||
"domainPickerSubdomain": "子域:{subdomain}",
|
||||
"domainPickerNamespace": "命名空间:{namespace}",
|
||||
"domainPickerShowMore": "显示更多",
|
||||
"regionSelectorTitle": "选择区域",
|
||||
"regionSelectorInfo": "选择区域以帮助提升您所在地的性能。您不必与服务器在相同的区域。",
|
||||
"regionSelectorPlaceholder": "选择一个区域",
|
||||
"regionSelectorComingSoon": "即将推出",
|
||||
"billingLoadingSubscription": "正在加载订阅...",
|
||||
"billingFreeTier": "免费层",
|
||||
"billingWarningOverLimit": "警告:您已超出一个或多个使用限制。在您修改订阅或调整使用情况之前,您的站点将无法连接。",
|
||||
"billingUsageLimitsOverview": "使用限制概览",
|
||||
"billingMonitorUsage": "监控您的使用情况以对比已配置的限制。如需提高限制请联系我们 support@pangolin.net。",
|
||||
"billingDataUsage": "数据使用情况",
|
||||
"billingOnlineTime": "站点在线时间",
|
||||
"billingUsers": "活跃用户",
|
||||
"billingDomains": "活跃域",
|
||||
"billingRemoteExitNodes": "活跃自托管节点",
|
||||
"billingNoLimitConfigured": "未配置限制",
|
||||
"billingEstimatedPeriod": "估计结算周期",
|
||||
"billingIncludedUsage": "包含的使用量",
|
||||
"billingIncludedUsageDescription": "您当前订阅计划中包含的使用量",
|
||||
"billingFreeTierIncludedUsage": "免费层使用额度",
|
||||
"billingIncluded": "包含",
|
||||
"billingEstimatedTotal": "预计总额:",
|
||||
"billingNotes": "备注",
|
||||
"billingEstimateNote": "这是根据您当前使用情况的估算。",
|
||||
"billingActualChargesMayVary": "实际费用可能会有变化。",
|
||||
"billingBilledAtEnd": "您将在结算周期结束时被计费。",
|
||||
"billingModifySubscription": "修改订阅",
|
||||
"billingStartSubscription": "开始订阅",
|
||||
"billingRecurringCharge": "周期性收费",
|
||||
"billingManageSubscriptionSettings": "管理您的订阅设置和偏好",
|
||||
"billingNoActiveSubscription": "您没有活跃的订阅。开始订阅以增加使用限制。",
|
||||
"billingFailedToLoadSubscription": "无法加载订阅",
|
||||
"billingFailedToLoadUsage": "无法加载使用情况",
|
||||
"billingFailedToGetCheckoutUrl": "无法获取结账网址",
|
||||
"billingPleaseTryAgainLater": "请稍后再试。",
|
||||
"billingCheckoutError": "结账错误",
|
||||
"billingFailedToGetPortalUrl": "无法获取门户网址",
|
||||
"billingPortalError": "门户错误",
|
||||
"billingDataUsageInfo": "当连接到云端时,您将为通过安全隧道传输的所有数据收取费用。 这包括您所有站点的进出流量。 当您达到上限时,您的站点将断开连接,直到您升级计划或减少使用。使用节点时不收取数据。",
|
||||
"billingOnlineTimeInfo": "您要根据您的网站连接到云端的时间长短收取费用。 例如,44,640分钟等于一个24/7全月运行的网站。 当您达到上限时,您的站点将断开连接,直到您升级计划或减少使用。使用节点时不收取费用。",
|
||||
"billingUsersInfo": "根据您组织中的活跃用户数量收费。按日计算账单。",
|
||||
"billingDomainInfo": "根据组织中活跃域的数量收费。按日计算账单。",
|
||||
"billingRemoteExitNodesInfo": "根据您组织中已管理节点的数量收费。按日计算账单。",
|
||||
"domainNotFound": "域未找到",
|
||||
"domainNotFoundDescription": "此资源已禁用,因为该域不再在我们的系统中存在。请为此资源设置一个新域。",
|
||||
"failed": "失败",
|
||||
@@ -1281,8 +1371,20 @@
|
||||
"securityKeyUnknownError": "使用安全密钥时出现问题。请再试一次。",
|
||||
"twoFactorRequired": "注册安全密钥需要两步验证。",
|
||||
"twoFactor": "两步验证",
|
||||
"twoFactorAuthentication": "两步验证",
|
||||
"twoFactorDescription": "这个组织需要双重身份验证。",
|
||||
"enableTwoFactor": "启用两步验证",
|
||||
"organizationSecurityPolicy": "组织安全政策",
|
||||
"organizationSecurityPolicyDescription": "此机构拥有安全要求,您必须先满足才能访问",
|
||||
"securityRequirements": "安全要求",
|
||||
"allRequirementsMet": "已满足所有要求",
|
||||
"completeRequirementsToContinue": "完成下面的要求以继续访问此组织",
|
||||
"youCanNowAccessOrganization": "您现在可以访问此组织",
|
||||
"reauthenticationRequired": "会话长度",
|
||||
"reauthenticationDescription": "该机构要求您每 {maxDays} 天登录一次。",
|
||||
"reauthenticationDescriptionHours": "该机构要求您每 {maxHours} 小时登录一次。",
|
||||
"reauthenticateNow": "再次登录",
|
||||
"adminEnabled2FaOnYourAccount": "管理员已为{email}启用两步验证。请完成设置以继续。",
|
||||
"continueToApplication": "继续到应用程序",
|
||||
"securityKeyAdd": "添加安全密钥",
|
||||
"securityKeyRegisterTitle": "注册新安全密钥",
|
||||
"securityKeyRegisterDescription": "连接您的安全密钥并输入名称以便识别",
|
||||
@@ -1312,6 +1414,7 @@
|
||||
"createDomainDnsPropagationDescription": "DNS 更改可能需要一些时间才能在互联网上传播。这可能需要从几分钟到 48 小时,具体取决于您的 DNS 提供商和 TTL 设置。",
|
||||
"resourcePortRequired": "非 HTTP 资源必须输入端口号",
|
||||
"resourcePortNotAllowed": "HTTP 资源不应设置端口号",
|
||||
"billingPricingCalculatorLink": "价格计算器",
|
||||
"signUpTerms": {
|
||||
"IAgreeToThe": "我同意",
|
||||
"termsOfService": "服务条款",
|
||||
@@ -1338,7 +1441,7 @@
|
||||
"clientOlmCredentials": "Olm 凭据",
|
||||
"clientOlmCredentialsDescription": "这是 Olm 服务器的身份验证方式",
|
||||
"olmEndpoint": "Olm 端点",
|
||||
"olmId": "Olm ID",
|
||||
"olmId": "Olm ID",
|
||||
"olmSecretKey": "Olm 私钥",
|
||||
"clientCredentialsSave": "保存您的凭据",
|
||||
"clientCredentialsSaveDescription": "该信息仅会显示一次,请确保将其复制到安全位置。",
|
||||
@@ -1359,7 +1462,43 @@
|
||||
"externalProxyEnabled": "外部代理已启用",
|
||||
"addNewTarget": "添加新目标",
|
||||
"targetsList": "目标列表",
|
||||
"advancedMode": "高级模式",
|
||||
"targetErrorDuplicateTargetFound": "找到重复的目标",
|
||||
"healthCheckHealthy": "正常",
|
||||
"healthCheckUnhealthy": "不正常",
|
||||
"healthCheckUnknown": "未知",
|
||||
"healthCheck": "健康检查",
|
||||
"configureHealthCheck": "配置健康检查",
|
||||
"configureHealthCheckDescription": "为 {target} 设置健康监控",
|
||||
"enableHealthChecks": "启用健康检查",
|
||||
"enableHealthChecksDescription": "监视此目标的健康状况。如果需要,您可以监视一个不同的终点。",
|
||||
"healthScheme": "方法",
|
||||
"healthSelectScheme": "选择方法",
|
||||
"healthCheckPath": "路径",
|
||||
"healthHostname": "IP / 主机",
|
||||
"healthPort": "端口",
|
||||
"healthCheckPathDescription": "用于检查健康状态的路径。",
|
||||
"healthyIntervalSeconds": "正常间隔",
|
||||
"unhealthyIntervalSeconds": "不正常间隔",
|
||||
"IntervalSeconds": "正常间隔",
|
||||
"timeoutSeconds": "超时",
|
||||
"timeIsInSeconds": "时间以秒为单位",
|
||||
"retryAttempts": "重试次数",
|
||||
"expectedResponseCodes": "期望响应代码",
|
||||
"expectedResponseCodesDescription": "HTTP 状态码表示健康状态。如留空,200-300 被视为健康。",
|
||||
"customHeaders": "自定义标题",
|
||||
"customHeadersDescription": "头部新行分隔:头部名称:值",
|
||||
"headersValidationError": "头部必须是格式:头部名称:值。",
|
||||
"saveHealthCheck": "保存健康检查",
|
||||
"healthCheckSaved": "健康检查已保存",
|
||||
"healthCheckSavedDescription": "健康检查配置已成功保存。",
|
||||
"healthCheckError": "健康检查错误",
|
||||
"healthCheckErrorDescription": "保存健康检查配置时出错",
|
||||
"healthCheckPathRequired": "健康检查路径为必填项",
|
||||
"healthCheckMethodRequired": "HTTP 方法为必填项",
|
||||
"healthCheckIntervalMin": "检查间隔必须至少为 5 秒",
|
||||
"healthCheckTimeoutMin": "超时必须至少为 1 秒",
|
||||
"healthCheckRetryMin": "重试次数必须至少为 1 次",
|
||||
"httpMethod": "HTTP 方法",
|
||||
"selectHttpMethod": "选择 HTTP 方法",
|
||||
"domainPickerSubdomainLabel": "子域名",
|
||||
@@ -1373,6 +1512,7 @@
|
||||
"domainPickerEnterSubdomainToSearch": "输入一个子域名以搜索并从可用免费域名中选择。",
|
||||
"domainPickerFreeDomains": "免费域名",
|
||||
"domainPickerSearchForAvailableDomains": "搜索可用域名",
|
||||
"domainPickerNotWorkSelfHosted": "注意:自托管实例当前不提供免费的域名。",
|
||||
"resourceDomain": "域名",
|
||||
"resourceEditDomain": "编辑域名",
|
||||
"siteName": "站点名称",
|
||||
@@ -1392,8 +1532,6 @@
|
||||
"editInternalResourceDialogProtocol": "协议",
|
||||
"editInternalResourceDialogSitePort": "站点端口",
|
||||
"editInternalResourceDialogTargetConfiguration": "目标配置",
|
||||
"editInternalResourceDialogDestinationIP": "目标IP",
|
||||
"editInternalResourceDialogDestinationPort": "目标端口",
|
||||
"editInternalResourceDialogCancel": "取消",
|
||||
"editInternalResourceDialogSaveResource": "保存资源",
|
||||
"editInternalResourceDialogSuccess": "成功",
|
||||
@@ -1424,9 +1562,7 @@
|
||||
"createInternalResourceDialogSitePort": "站点端口",
|
||||
"createInternalResourceDialogSitePortDescription": "使用此端口在连接到客户端时访问站点上的资源。",
|
||||
"createInternalResourceDialogTargetConfiguration": "目标配置",
|
||||
"createInternalResourceDialogDestinationIP": "目标IP",
|
||||
"createInternalResourceDialogDestinationIPDescription": "站点网络上资源的IP地址。",
|
||||
"createInternalResourceDialogDestinationPort": "目标端口",
|
||||
"createInternalResourceDialogDestinationIPDescription": "站点网络上资源的IP或主机名地址。",
|
||||
"createInternalResourceDialogDestinationPortDescription": "资源在目标IP上可访问的端口。",
|
||||
"createInternalResourceDialogCancel": "取消",
|
||||
"createInternalResourceDialogCreateResource": "创建资源",
|
||||
@@ -1459,6 +1595,71 @@
|
||||
"autoLoginError": "自动登录错误",
|
||||
"autoLoginErrorNoRedirectUrl": "未从身份提供商收到重定向URL。",
|
||||
"autoLoginErrorGeneratingUrl": "生成身份验证URL失败。",
|
||||
"remoteExitNodeManageRemoteExitNodes": "远程节点",
|
||||
"remoteExitNodeDescription": "自我主机一个或多个远程节点来扩展您的网络连接并减少对云的依赖性",
|
||||
"remoteExitNodes": "节点",
|
||||
"searchRemoteExitNodes": "搜索节点...",
|
||||
"remoteExitNodeAdd": "添加节点",
|
||||
"remoteExitNodeErrorDelete": "删除节点时出错",
|
||||
"remoteExitNodeQuestionRemove": "您确定要从组织中删除该节点吗?",
|
||||
"remoteExitNodeMessageRemove": "一旦删除,该节点将不再能够访问。",
|
||||
"remoteExitNodeConfirmDelete": "确认删除节点",
|
||||
"remoteExitNodeDelete": "删除节点",
|
||||
"sidebarRemoteExitNodes": "远程节点",
|
||||
"remoteExitNodeCreate": {
|
||||
"title": "创建节点",
|
||||
"description": "创建一个新节点来扩展您的网络连接",
|
||||
"viewAllButton": "查看所有节点",
|
||||
"strategy": {
|
||||
"title": "创建策略",
|
||||
"description": "选择此选项以手动配置您的节点或生成新凭据。",
|
||||
"adopt": {
|
||||
"title": "采纳节点",
|
||||
"description": "如果您已经拥有该节点的凭据,请选择此项。"
|
||||
},
|
||||
"generate": {
|
||||
"title": "生成密钥",
|
||||
"description": "如果您想为节点生成新密钥,请选择此选项"
|
||||
}
|
||||
},
|
||||
"adopt": {
|
||||
"title": "采纳现有节点",
|
||||
"description": "输入您想要采用的现有节点的凭据",
|
||||
"nodeIdLabel": "节点 ID",
|
||||
"nodeIdDescription": "您想要采用的现有节点的 ID",
|
||||
"secretLabel": "密钥",
|
||||
"secretDescription": "现有节点的秘密密钥",
|
||||
"submitButton": "采用节点"
|
||||
},
|
||||
"generate": {
|
||||
"title": "生成的凭据",
|
||||
"description": "使用这些生成的凭据来配置您的节点",
|
||||
"nodeIdTitle": "节点 ID",
|
||||
"secretTitle": "密钥",
|
||||
"saveCredentialsTitle": "将凭据添加到配置中",
|
||||
"saveCredentialsDescription": "将这些凭据添加到您的自托管 Pangolin 节点配置文件中以完成连接。",
|
||||
"submitButton": "创建节点"
|
||||
},
|
||||
"validation": {
|
||||
"adoptRequired": "在通过现有节点时需要节点ID和密钥"
|
||||
},
|
||||
"errors": {
|
||||
"loadDefaultsFailed": "无法加载默认值",
|
||||
"defaultsNotLoaded": "默认值未加载",
|
||||
"createFailed": "创建节点失败"
|
||||
},
|
||||
"success": {
|
||||
"created": "节点创建成功"
|
||||
}
|
||||
},
|
||||
"remoteExitNodeSelection": "节点选择",
|
||||
"remoteExitNodeSelectionDescription": "为此本地站点选择要路由流量的节点",
|
||||
"remoteExitNodeRequired": "必须为本地站点选择节点",
|
||||
"noRemoteExitNodesAvailable": "无可用节点",
|
||||
"noRemoteExitNodesAvailableDescription": "此组织没有可用的节点。首先创建一个节点来使用本地站点。",
|
||||
"exitNode": "出口节点",
|
||||
"country": "国家",
|
||||
"rulesMatchCountry": "当前基于源 IP",
|
||||
"managedSelfHosted": {
|
||||
"title": "托管自托管",
|
||||
"description": "更可靠和低维护自我托管的 Pangolin 服务器,带有额外的铃声和告密器",
|
||||
@@ -1496,5 +1697,403 @@
|
||||
"convertButton": "将此节点转换为管理自托管的"
|
||||
},
|
||||
"internationaldomaindetected": "检测到国际域",
|
||||
"willbestoredas": "储存为:"
|
||||
}
|
||||
"willbestoredas": "储存为:",
|
||||
"roleMappingDescription": "确定当用户启用自动配送时如何分配他们的角色。",
|
||||
"selectRole": "选择角色",
|
||||
"roleMappingExpression": "表达式",
|
||||
"selectRolePlaceholder": "选择角色",
|
||||
"selectRoleDescription": "选择一个角色,从此身份提供商分配给所有用户",
|
||||
"roleMappingExpressionDescription": "输入一个 JMESPath 表达式来从 ID 令牌提取角色信息",
|
||||
"idpTenantIdRequired": "租户ID是必需的",
|
||||
"invalidValue": "无效的值",
|
||||
"idpTypeLabel": "身份提供者类型",
|
||||
"roleMappingExpressionPlaceholder": "例如: contains(group, 'admin' &'Admin' || 'Member'",
|
||||
"idpGoogleConfiguration": "Google 配置",
|
||||
"idpGoogleConfigurationDescription": "配置您的 Google OAuth2 凭据",
|
||||
"idpGoogleClientIdDescription": "您的 Google OAuth2 客户端 ID",
|
||||
"idpGoogleClientSecretDescription": "您的 Google OAuth2 客户端密钥",
|
||||
"idpAzureConfiguration": "Azure Entra ID 配置",
|
||||
"idpAzureConfigurationDescription": "配置您的 Azure Entra ID OAuth2 凭据",
|
||||
"idpTenantId": "租户 ID",
|
||||
"idpTenantIdPlaceholder": "您的租户ID",
|
||||
"idpAzureTenantIdDescription": "您的 Azure 租户ID (在 Azure Active Directory 概览中发现)",
|
||||
"idpAzureClientIdDescription": "您的 Azure 应用程序注册客户端 ID",
|
||||
"idpAzureClientSecretDescription": "您的 Azure 应用程序注册客户端密钥",
|
||||
"idpGoogleTitle": "谷歌",
|
||||
"idpGoogleAlt": "Google",
|
||||
"idpAzureTitle": "Azure Entra ID",
|
||||
"idpAzureAlt": "Azure",
|
||||
"idpGoogleConfigurationTitle": "Google 配置",
|
||||
"idpAzureConfigurationTitle": "Azure Entra ID 配置",
|
||||
"idpTenantIdLabel": "租户 ID",
|
||||
"idpAzureClientIdDescription2": "您的 Azure 应用程序注册客户端 ID",
|
||||
"idpAzureClientSecretDescription2": "您的 Azure 应用程序注册客户端密钥",
|
||||
"idpGoogleDescription": "Google OAuth2/OIDC 提供商",
|
||||
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
|
||||
"subnet": "子网",
|
||||
"subnetDescription": "此组织网络配置的子网。",
|
||||
"authPage": "认证页面",
|
||||
"authPageDescription": "配置您的组织认证页面",
|
||||
"authPageDomain": "认证页面域",
|
||||
"noDomainSet": "没有域设置",
|
||||
"changeDomain": "更改域",
|
||||
"selectDomain": "选择域",
|
||||
"restartCertificate": "重新启动证书",
|
||||
"editAuthPageDomain": "编辑认证页面域",
|
||||
"setAuthPageDomain": "设置认证页面域",
|
||||
"failedToFetchCertificate": "获取证书失败",
|
||||
"failedToRestartCertificate": "重新启动证书失败",
|
||||
"addDomainToEnableCustomAuthPages": "为您的组织添加域名以启用自定义认证页面",
|
||||
"selectDomainForOrgAuthPage": "选择组织认证页面的域",
|
||||
"domainPickerProvidedDomain": "提供的域",
|
||||
"domainPickerFreeProvidedDomain": "免费提供的域",
|
||||
"domainPickerVerified": "已验证",
|
||||
"domainPickerUnverified": "未验证",
|
||||
"domainPickerInvalidSubdomainStructure": "此子域包含无效的字符或结构。当您保存时,它将被自动清除。",
|
||||
"domainPickerError": "错误",
|
||||
"domainPickerErrorLoadDomains": "加载组织域名失败",
|
||||
"domainPickerErrorCheckAvailability": "检查域可用性失败",
|
||||
"domainPickerInvalidSubdomain": "无效的子域",
|
||||
"domainPickerInvalidSubdomainRemoved": "输入 \"{sub}\" 已被移除,因为其无效。",
|
||||
"domainPickerInvalidSubdomainCannotMakeValid": "\"{sub}\" 无法为 {domain} 变为有效。",
|
||||
"domainPickerSubdomainSanitized": "子域已净化",
|
||||
"domainPickerSubdomainCorrected": "\"{sub}\" 已被更正为 \"{sanitized}\"",
|
||||
"orgAuthSignInTitle": "登录到您的组织",
|
||||
"orgAuthChooseIdpDescription": "选择您的身份提供商以继续",
|
||||
"orgAuthNoIdpConfigured": "此机构没有配置任何身份提供者。您可以使用您的 Pangolin 身份登录。",
|
||||
"orgAuthSignInWithPangolin": "使用 Pangolin 登录",
|
||||
"subscriptionRequiredToUse": "需要订阅才能使用此功能。",
|
||||
"idpDisabled": "身份提供者已禁用。",
|
||||
"orgAuthPageDisabled": "组织认证页面已禁用。",
|
||||
"domainRestartedDescription": "域验证重新启动成功",
|
||||
"resourceAddEntrypointsEditFile": "编辑文件:config/traefik/traefik_config.yml",
|
||||
"resourceExposePortsEditFile": "编辑文件:docker-compose.yml",
|
||||
"emailVerificationRequired": "需要电子邮件验证。 请通过 {dashboardUrl}/auth/login 再次登录以完成此步骤。 然后,回到这里。",
|
||||
"twoFactorSetupRequired": "需要设置双因素身份验证。 请通过 {dashboardUrl}/auth/login 再次登录以完成此步骤。 然后,回到这里。",
|
||||
"additionalSecurityRequired": "需要额外的安全",
|
||||
"organizationRequiresAdditionalSteps": "这个组织需要额外的安全步骤才能访问资源。",
|
||||
"completeTheseSteps": "完成这些步骤",
|
||||
"enableTwoFactorAuthentication": "启用两步验证",
|
||||
"completeSecuritySteps": "完成安全步骤",
|
||||
"securitySettings": "安全设置",
|
||||
"securitySettingsDescription": "配置您组织的安全策略",
|
||||
"requireTwoFactorForAllUsers": "所有用户需要两步验证",
|
||||
"requireTwoFactorDescription": "如果启用,此组织的所有内部用户必须启用双重身份验证才能访问组织。",
|
||||
"requireTwoFactorDisabledDescription": "此功能需要有效的许可证(企业)或活动订阅(SaS)",
|
||||
"requireTwoFactorCannotEnableDescription": "您必须为您的帐户启用双重身份验证才能对所有用户",
|
||||
"maxSessionLength": "最大会话长度",
|
||||
"maxSessionLengthDescription": "设置用户会话的最长时间。此后用户需要重新验证。",
|
||||
"maxSessionLengthDisabledDescription": "此功能需要有效的许可证(企业)或活动订阅(SaS)",
|
||||
"selectSessionLength": "选择会话长度",
|
||||
"unenforced": "未执行",
|
||||
"1Hour": "1 小时",
|
||||
"3Hours": "3 小时",
|
||||
"6Hours": "6 小时",
|
||||
"12Hours": "12 小时",
|
||||
"1DaySession": "1天",
|
||||
"3Days": "3 天",
|
||||
"7Days": "7 天",
|
||||
"14Days": "14 天",
|
||||
"30DaysSession": "30 天",
|
||||
"90DaysSession": "90 天",
|
||||
"180DaysSession": "180天",
|
||||
"passwordExpiryDays": "密码过期",
|
||||
"editPasswordExpiryDescription": "设置用户需要更改密码之前的天数。",
|
||||
"selectPasswordExpiry": "选择密码过期",
|
||||
"30Days": "30 天",
|
||||
"1Day": "1天",
|
||||
"60Days": "60天",
|
||||
"90Days": "90 天",
|
||||
"180Days": "180天",
|
||||
"1Year": "1 年",
|
||||
"subscriptionBadge": "需要订阅",
|
||||
"securityPolicyChangeWarning": "安全政策更改警告",
|
||||
"securityPolicyChangeDescription": "您即将更改安全政策设置。保存后,您可能需要重新认证以遵守这些政策更新。 所有不符合要求的用户也需要重新认证。",
|
||||
"securityPolicyChangeConfirmMessage": "我确认",
|
||||
"securityPolicyChangeWarningText": "这将影响组织中的所有用户",
|
||||
"authPageErrorUpdateMessage": "更新身份验证页面设置时出错",
|
||||
"authPageErrorUpdate": "无法更新认证页面",
|
||||
"authPageUpdated": "身份验证页面更新成功",
|
||||
"healthCheckNotAvailable": "本地的",
|
||||
"rewritePath": "重写路径",
|
||||
"rewritePathDescription": "在转发到目标之前,可以选择重写路径。",
|
||||
"continueToApplication": "继续应用",
|
||||
"checkingInvite": "正在检查邀请",
|
||||
"setResourceHeaderAuth": "设置 ResourceHeaderAuth",
|
||||
"resourceHeaderAuthRemove": "删除头部认证",
|
||||
"resourceHeaderAuthRemoveDescription": "已成功删除头部身份验证。",
|
||||
"resourceErrorHeaderAuthRemove": "删除头部身份验证失败",
|
||||
"resourceErrorHeaderAuthRemoveDescription": "无法删除资源的头部身份验证。",
|
||||
"resourceHeaderAuthProtectionEnabled": "头部认证已启用",
|
||||
"resourceHeaderAuthProtectionDisabled": "头部身份验证已禁用",
|
||||
"headerAuthRemove": "删除头部认证",
|
||||
"headerAuthAdd": "添加页眉认证",
|
||||
"resourceErrorHeaderAuthSetup": "设置页眉认证失败",
|
||||
"resourceErrorHeaderAuthSetupDescription": "无法设置资源的头部身份验证。",
|
||||
"resourceHeaderAuthSetup": "头部认证设置成功",
|
||||
"resourceHeaderAuthSetupDescription": "头部认证已成功设置。",
|
||||
"resourceHeaderAuthSetupTitle": "设置头部身份验证",
|
||||
"resourceHeaderAuthSetupTitleDescription": "使用HTTP 头身份验证来设置基本身份验证信息(用户名和密码)。使用 https://username:password@resource.example.com 访问它",
|
||||
"resourceHeaderAuthSubmit": "设置头部身份验证",
|
||||
"actionSetResourceHeaderAuth": "设置头部身份验证",
|
||||
"enterpriseEdition": "企业版",
|
||||
"unlicensed": "未授权",
|
||||
"beta": "测试版",
|
||||
"manageClients": "管理客户端",
|
||||
"manageClientsDescription": "客户端是可以连接到您的站点的设备",
|
||||
"licenseTableValidUntil": "有效期至",
|
||||
"saasLicenseKeysSettingsTitle": "企业许可证",
|
||||
"saasLicenseKeysSettingsDescription": "为自我托管的 Pangolin 实例生成和管理企业许可证密钥",
|
||||
"sidebarEnterpriseLicenses": "许可协议",
|
||||
"generateLicenseKey": "生成许可证密钥",
|
||||
"generateLicenseKeyForm": {
|
||||
"validation": {
|
||||
"emailRequired": "请输入一个有效的电子邮件地址",
|
||||
"useCaseTypeRequired": "请选择一个使用的案例类型",
|
||||
"firstNameRequired": "必填名",
|
||||
"lastNameRequired": "姓氏是必填项",
|
||||
"primaryUseRequired": "请描述您的主要使用",
|
||||
"jobTitleRequiredBusiness": "企业使用必须有职位头衔。",
|
||||
"industryRequiredBusiness": "商业使用需要工业",
|
||||
"stateProvinceRegionRequired": "州/省/地区是必填项",
|
||||
"postalZipCodeRequired": "邮政编码是必需的",
|
||||
"companyNameRequiredBusiness": "企业使用需要公司名称",
|
||||
"countryOfResidenceRequiredBusiness": "商业使用必须是居住国",
|
||||
"countryRequiredPersonal": "国家需要个人使用",
|
||||
"agreeToTermsRequired": "您必须同意条款",
|
||||
"complianceConfirmationRequired": "您必须确认遵守Fossorial Commercial License"
|
||||
},
|
||||
"useCaseOptions": {
|
||||
"personal": {
|
||||
"title": "个人使用",
|
||||
"description": "个人非商业用途,如学习、个人项目或实验。"
|
||||
},
|
||||
"business": {
|
||||
"title": "商业使用",
|
||||
"description": "供组织、公司或商业或创收活动使用。"
|
||||
}
|
||||
},
|
||||
"steps": {
|
||||
"emailLicenseType": {
|
||||
"title": "电子邮件和许可证类型",
|
||||
"description": "输入您的电子邮件并选择您的许可证类型"
|
||||
},
|
||||
"personalInformation": {
|
||||
"title": "个人信息",
|
||||
"description": "告诉我们自己的信息"
|
||||
},
|
||||
"contactInformation": {
|
||||
"title": "联系信息",
|
||||
"description": "您的联系信息"
|
||||
},
|
||||
"termsGenerate": {
|
||||
"title": "条款并生成",
|
||||
"description": "审阅并接受条款生成您的许可证"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"commercialUseDisclosure": {
|
||||
"title": "使用情况披露",
|
||||
"description": "选择能准确反映您预定用途的许可等级。 个人许可证允许对个人、非商业性或小型商业活动免费使用软件,年收入毛额不到100 000美元。 超出这些限度的任何用途,包括在企业、组织内的用途。 或其他创收环境——需要有效的企业许可证和支付适用的许可证费用。 所有用户,不论是个人还是企业,都必须遵守寄养商业许可证条款。"
|
||||
},
|
||||
"trialPeriodInformation": {
|
||||
"title": "试用期信息",
|
||||
"description": "此许可证密钥使企业特性能够持续7天的评价。 在评估期过后继续访问付费功能需要在有效的个人或企业许可证下激活。对于企业许可证,请联系Sales@pangolin.net。"
|
||||
}
|
||||
},
|
||||
"form": {
|
||||
"useCaseQuestion": "您是否正在使用 Pangolin 进行个人或商业使用?",
|
||||
"firstName": "名字",
|
||||
"lastName": "名字",
|
||||
"jobTitle": "工作头衔:",
|
||||
"primaryUseQuestion": "您主要计划使用 Pangolin 吗?",
|
||||
"industryQuestion": "您的行业是什么?",
|
||||
"prospectiveUsersQuestion": "您期望有多少预期用户?",
|
||||
"prospectiveSitesQuestion": "您期望有多少站点(隧道)?",
|
||||
"companyName": "公司名称",
|
||||
"countryOfResidence": "居住国",
|
||||
"stateProvinceRegion": "州/省/地区",
|
||||
"postalZipCode": "邮政编码",
|
||||
"companyWebsite": "公司网站",
|
||||
"companyPhoneNumber": "公司电话号码",
|
||||
"country": "国家",
|
||||
"phoneNumberOptional": "电话号码 (可选)",
|
||||
"complianceConfirmation": "我确认我提供的资料是准确的,我遵守了寄养商业许可证。 报告不准确的信息或错误的产品使用是违反许可证的行为,可能导致您的密钥被撤销。"
|
||||
},
|
||||
"buttons": {
|
||||
"close": "关闭",
|
||||
"previous": "上一个",
|
||||
"next": "下一个",
|
||||
"generateLicenseKey": "生成许可证密钥"
|
||||
},
|
||||
"toasts": {
|
||||
"success": {
|
||||
"title": "许可证密钥生成成功",
|
||||
"description": "您的许可证密钥已经生成并准备使用。"
|
||||
},
|
||||
"error": {
|
||||
"title": "生成许可证密钥失败",
|
||||
"description": "生成许可证密钥时出错。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": "优先权",
|
||||
"priorityDescription": "先评估更高优先级线路。优先级 = 100意味着自动排序(系统决定). 使用另一个数字强制执行手动优先级。",
|
||||
"instanceName": "实例名称",
|
||||
"pathMatchModalTitle": "配置路径匹配",
|
||||
"pathMatchModalDescription": "根据传入请求的路径设置匹配方式。",
|
||||
"pathMatchType": "匹配类型",
|
||||
"pathMatchPrefix": "前缀",
|
||||
"pathMatchExact": "精准的",
|
||||
"pathMatchRegex": "正则表达式",
|
||||
"pathMatchValue": "路径值",
|
||||
"clear": "清空",
|
||||
"saveChanges": "保存更改",
|
||||
"pathMatchRegexPlaceholder": "^/api/.*",
|
||||
"pathMatchDefaultPlaceholder": "/路径",
|
||||
"pathMatchPrefixHelp": "示例: /api 匹配/api, /api/users 等。",
|
||||
"pathMatchExactHelp": "示例:/api 匹配仅限/api",
|
||||
"pathMatchRegexHelp": "例如:^/api/.* 匹配/api/why",
|
||||
"pathRewriteModalTitle": "配置路径重写",
|
||||
"pathRewriteModalDescription": "在转发到目标之前变换匹配的路径。",
|
||||
"pathRewriteType": "重写类型",
|
||||
"pathRewritePrefixOption": "前缀 - 替换前缀",
|
||||
"pathRewriteExactOption": "精确-替换整个路径",
|
||||
"pathRewriteRegexOption": "正则表达式 - 替换模式",
|
||||
"pathRewriteStripPrefixOption": "删除前缀 - 删除前缀",
|
||||
"pathRewriteValue": "重写值",
|
||||
"pathRewriteRegexPlaceholder": "/new/$1",
|
||||
"pathRewriteDefaultPlaceholder": "/new-path",
|
||||
"pathRewritePrefixHelp": "用此值替换匹配的前缀",
|
||||
"pathRewriteExactHelp": "当路径匹配时用此值替换整个路径",
|
||||
"pathRewriteRegexHelp": "使用抓取组,如$1,$2来替换",
|
||||
"pathRewriteStripPrefixHelp": "留空以脱离前缀或提供新的前缀",
|
||||
"pathRewritePrefix": "前缀",
|
||||
"pathRewriteExact": "精准的",
|
||||
"pathRewriteRegex": "正则表达式",
|
||||
"pathRewriteStrip": "带状图",
|
||||
"pathRewriteStripLabel": "条形图",
|
||||
"sidebarEnableEnterpriseLicense": "启用企业许可证",
|
||||
"cannotbeUndone": "无法撤消。",
|
||||
"toConfirm": "确认",
|
||||
"deleteClientQuestion": "您确定要从站点和组织中删除客户吗?",
|
||||
"clientMessageRemove": "一旦删除,客户端将无法连接到站点。",
|
||||
"sidebarLogs": "日志",
|
||||
"request": "请求",
|
||||
"logs": "日志",
|
||||
"logsSettingsDescription": "监视从此orginization中收集的日志",
|
||||
"searchLogs": "搜索日志...",
|
||||
"action": "行 动",
|
||||
"actor": "执行者",
|
||||
"timestamp": "时间戳",
|
||||
"accessLogs": "访问日志",
|
||||
"exportCsv": "导出CSV",
|
||||
"actorId": "执行者ID",
|
||||
"allowedByRule": "根据规则允许",
|
||||
"allowedNoAuth": "无认证",
|
||||
"validAccessToken": "有效访问令牌",
|
||||
"validHeaderAuth": "Valid header auth",
|
||||
"validPincode": "Valid Pincode",
|
||||
"validPassword": "有效密码",
|
||||
"validEmail": "Valid email",
|
||||
"validSSO": "Valid SSO",
|
||||
"resourceBlocked": "资源被阻止",
|
||||
"droppedByRule": "被规则删除",
|
||||
"noSessions": "无会话",
|
||||
"temporaryRequestToken": "临时请求令牌",
|
||||
"noMoreAuthMethods": "No Valid Auth",
|
||||
"ip": "IP",
|
||||
"reason": "原因",
|
||||
"requestLogs": "请求日志",
|
||||
"host": "主机",
|
||||
"location": "地点",
|
||||
"actionLogs": "操作日志",
|
||||
"sidebarLogsRequest": "请求日志",
|
||||
"sidebarLogsAccess": "访问日志",
|
||||
"sidebarLogsAction": "操作日志",
|
||||
"logRetention": "日志保留",
|
||||
"logRetentionDescription": "管理不同类型的日志为这个机构保留多长时间或禁用这些日志",
|
||||
"requestLogsDescription": "查看此机构资源的详细请求日志",
|
||||
"logRetentionRequestLabel": "请求日志保留",
|
||||
"logRetentionRequestDescription": "保留请求日志的时间",
|
||||
"logRetentionAccessLabel": "访问日志保留",
|
||||
"logRetentionAccessDescription": "保留访问日志的时间",
|
||||
"logRetentionActionLabel": "动作日志保留",
|
||||
"logRetentionActionDescription": "保留操作日志的时间",
|
||||
"logRetentionDisabled": "已禁用",
|
||||
"logRetention3Days": "3 天",
|
||||
"logRetention7Days": "7 天",
|
||||
"logRetention14Days": "14 天",
|
||||
"logRetention30Days": "30 天",
|
||||
"logRetention90Days": "90 天",
|
||||
"logRetentionForever": "永远的",
|
||||
"actionLogsDescription": "查看此机构执行的操作历史",
|
||||
"accessLogsDescription": "查看此机构资源的访问认证请求",
|
||||
"licenseRequiredToUse": "需要企业许可证才能使用此功能。",
|
||||
"certResolver": "证书解决器",
|
||||
"certResolverDescription": "选择用于此资源的证书解析器。",
|
||||
"selectCertResolver": "选择证书解析",
|
||||
"enterCustomResolver": "输入自定义解析器",
|
||||
"preferWildcardCert": "喜欢通配符证书",
|
||||
"unverified": "未验证",
|
||||
"domainSetting": "域设置",
|
||||
"domainSettingDescription": "配置您的域的设置",
|
||||
"preferWildcardCertDescription": "尝试生成通配符证书(需要正确配置的证书解析器)。",
|
||||
"recordName": "记录名称",
|
||||
"auto": "自动操作",
|
||||
"TTL": "TTL",
|
||||
"howToAddRecords": "如何添加记录",
|
||||
"dnsRecord": "DNS记录",
|
||||
"required": "必填",
|
||||
"domainSettingsUpdated": "域设置更新成功",
|
||||
"orgOrDomainIdMissing": "缺少机构或域 ID",
|
||||
"loadingDNSRecords": "正在载入DNS记录...",
|
||||
"olmUpdateAvailableInfo": "有最新版本的 Olm 可用。请更新到最新版本以获取最佳体验。",
|
||||
"client": "客户端:",
|
||||
"proxyProtocol": "代理协议设置",
|
||||
"proxyProtocolDescription": "配置代理协议以保留TCP/UDP 服务的客户端IP地址。",
|
||||
"enableProxyProtocol": "启用代理协议",
|
||||
"proxyProtocolInfo": "为TCP/UDP 后端保留客户端IP地址",
|
||||
"proxyProtocolVersion": "代理协议版本",
|
||||
"version1": " 版本 1 (推荐)",
|
||||
"version2": "版本 2",
|
||||
"versionDescription": "版本 1 是基于文本和广泛支持的版本。版本 2 是二进制和更有效率但不那么兼容。",
|
||||
"warning": "警告",
|
||||
"proxyProtocolWarning": "您的后端应用程序必须配置为接受代理协议连接。如果您的后端不支持代理协议,启用这将会中断所有连接。 请务必从Traefik配置您的后端到信任代理协议标题。",
|
||||
"restarting": "正在重启...",
|
||||
"manual": "手动模式",
|
||||
"messageSupport": "消息支持",
|
||||
"supportNotAvailableTitle": "支持不可用",
|
||||
"supportNotAvailableDescription": "支持现在不可用。您可以发送电子邮件到 support@pangolin.net。",
|
||||
"supportRequestSentTitle": "支持请求已发送",
|
||||
"supportRequestSentDescription": "您的消息已成功发送。",
|
||||
"supportRequestFailedTitle": "发送请求失败",
|
||||
"supportRequestFailedDescription": "发送您的支持请求时出错。",
|
||||
"supportSubjectRequired": "主题是必填项",
|
||||
"supportSubjectMaxLength": "主题必须是255个或更少的字符",
|
||||
"supportMessageRequired": "消息是必填项",
|
||||
"supportReplyTo": "回复给",
|
||||
"supportSubject": "议 题",
|
||||
"supportSubjectPlaceholder": "输入主题",
|
||||
"supportMessage": "留言",
|
||||
"supportMessagePlaceholder": "输入您的消息",
|
||||
"supportSending": "正在发送...",
|
||||
"supportSend": "发送",
|
||||
"supportMessageSent": "消息已发送!",
|
||||
"supportWillContact": "我们很快就会联系起来!",
|
||||
"selectLogRetention": "选择保留日志",
|
||||
"showColumns": "显示列",
|
||||
"hideColumns": "隐藏列",
|
||||
"columnVisibility": "列可见性",
|
||||
"toggleColumn": "切换 {columnName} 列",
|
||||
"allColumns": "全部列",
|
||||
"defaultColumns": "默认列",
|
||||
"customizeView": "自定义视图",
|
||||
"viewOptions": "查看选项",
|
||||
"selectAll": "选择所有",
|
||||
"selectNone": "没有选择",
|
||||
"selectedResources": "选定的资源",
|
||||
"enableSelected": "启用选中的",
|
||||
"disableSelected": "禁用选中的",
|
||||
"checkSelectedStatus": "检查选中的状态"
|
||||
}
|
||||
@@ -7,7 +7,8 @@ const nextConfig = {
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true
|
||||
},
|
||||
output: "standalone"
|
||||
output: "standalone",
|
||||
|
||||
};
|
||||
|
||||
export default withNextIntl(nextConfig);
|
||||
|
||||
9139
package-lock.json
generated
9139
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
108
package.json
108
package.json
@@ -19,15 +19,23 @@
|
||||
"db:sqlite:studio": "drizzle-kit studio --config=./drizzle.sqlite.config.ts",
|
||||
"db:pg:studio": "drizzle-kit studio --config=./drizzle.pg.config.ts",
|
||||
"db:clear-migrations": "rm -rf server/migrations",
|
||||
"set:oss": "echo 'export const build = \"oss\" as any;' > server/build.ts && cp tsconfig.oss.json tsconfig.json",
|
||||
"set:saas": "echo 'export const build = \"saas\" as any;' > server/build.ts && cp tsconfig.saas.json tsconfig.json",
|
||||
"set:enterprise": "echo 'export const build = \"enterprise\" as any;' > server/build.ts && cp tsconfig.enterprise.json tsconfig.json",
|
||||
"set:sqlite": "echo 'export * from \"./sqlite\";' > server/db/index.ts",
|
||||
"set:pg": "echo 'export * from \"./pg\";' > server/db/index.ts",
|
||||
"next:build": "next build",
|
||||
"build:sqlite": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs",
|
||||
"build:pg": "mkdir -p dist && next build && node esbuild.mjs -e server/index.ts -o dist/server.mjs && node esbuild.mjs -e server/setup/migrationsPg.ts -o dist/migrations.mjs",
|
||||
"start": "DB_TYPE=sqlite NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'",
|
||||
"start": "ENVIRONMENT=prod node dist/migrations.mjs && ENVIRONMENT=prod NODE_ENV=development node --enable-source-maps dist/server.mjs",
|
||||
"email": "email dev --dir server/emails/templates --port 3005",
|
||||
"build:cli": "node esbuild.mjs -e cli/index.ts -o dist/cli.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@asteasolutions/zod-to-openapi": "^7.3.4",
|
||||
"@hookform/resolvers": "3.9.1",
|
||||
"@aws-sdk/client-s3": "3.922.0",
|
||||
"@hookform/resolvers": "5.2.2",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@node-rs/argon2": "^2.0.2",
|
||||
"@oslojs/crypto": "1.0.1",
|
||||
"@oslojs/encoding": "1.1.0",
|
||||
@@ -49,17 +57,17 @@
|
||||
"@radix-ui/react-tabs": "1.1.13",
|
||||
"@radix-ui/react-toast": "1.2.15",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@react-email/components": "0.5.0",
|
||||
"@react-email/render": "^1.2.0",
|
||||
"@react-email/components": "0.5.7",
|
||||
"@react-email/render": "^1.3.2",
|
||||
"@react-email/tailwind": "1.2.2",
|
||||
"@simplewebauthn/browser": "^13.1.0",
|
||||
"@simplewebauthn/server": "^9.0.3",
|
||||
"@simplewebauthn/browser": "^13.2.2",
|
||||
"@simplewebauthn/server": "^13.2.2",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
"arctic": "^3.7.0",
|
||||
"axios": "1.11.0",
|
||||
"axios": "^1.13.1",
|
||||
"better-sqlite3": "11.7.0",
|
||||
"canvas-confetti": "1.9.3",
|
||||
"canvas-confetti": "1.9.4",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "2.1.1",
|
||||
"cmdk": "1.1.1",
|
||||
@@ -68,84 +76,96 @@
|
||||
"cookies": "^0.9.1",
|
||||
"cors": "2.8.5",
|
||||
"crypto-js": "^4.2.0",
|
||||
"drizzle-orm": "0.44.4",
|
||||
"eslint": "9.33.0",
|
||||
"eslint-config-next": "15.4.6",
|
||||
"date-fns": "4.1.0",
|
||||
"drizzle-orm": "0.44.7",
|
||||
"eslint": "9.39.0",
|
||||
"eslint-config-next": "16.0.1",
|
||||
"express": "5.1.0",
|
||||
"express-rate-limit": "8.0.1",
|
||||
"express-rate-limit": "8.2.1",
|
||||
"glob": "11.0.3",
|
||||
"helmet": "8.1.0",
|
||||
"http-errors": "2.0.0",
|
||||
"i": "^0.3.7",
|
||||
"input-otp": "1.4.2",
|
||||
"ioredis": "5.8.2",
|
||||
"jmespath": "^0.16.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lucide-react": "0.539.0",
|
||||
"lucide-react": "^0.552.0",
|
||||
"maxmind": "5.0.0",
|
||||
"moment": "2.30.1",
|
||||
"next": "15.4.6",
|
||||
"next-intl": "^4.3.4",
|
||||
"next": "15.5.6",
|
||||
"next-intl": "^4.4.0",
|
||||
"next-themes": "0.4.6",
|
||||
"nextjs-toploader": "^3.9.17",
|
||||
"node-cache": "5.1.2",
|
||||
"node-fetch": "3.3.2",
|
||||
"nodemailer": "7.0.5",
|
||||
"npm": "^11.5.2",
|
||||
"nodemailer": "7.0.10",
|
||||
"npm": "^11.6.2",
|
||||
"nprogress": "^0.2.0",
|
||||
"oslo": "1.2.1",
|
||||
"pg": "^8.16.2",
|
||||
"posthog-node": "^5.7.0",
|
||||
"posthog-node": "^5.11.0",
|
||||
"qrcode.react": "4.2.0",
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"react-easy-sort": "^1.6.0",
|
||||
"react-hook-form": "7.62.0",
|
||||
"react": "19.2.0",
|
||||
"react-day-picker": "9.11.1",
|
||||
"react-dom": "19.2.0",
|
||||
"react-easy-sort": "^1.8.0",
|
||||
"react-hook-form": "7.66.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"rebuild": "0.1.2",
|
||||
"semver": "^7.7.2",
|
||||
"source-map-support": "0.5.21",
|
||||
"reodotdev": "^1.0.0",
|
||||
"resend": "^6.4.0",
|
||||
"semver": "^7.7.3",
|
||||
"stripe": "18.2.1",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"tailwind-merge": "3.3.1",
|
||||
"tw-animate-css": "^1.3.7",
|
||||
"uuid": "^11.1.0",
|
||||
"tw-animate-css": "^1.3.8",
|
||||
"uuid": "^13.0.0",
|
||||
"vaul": "1.1.2",
|
||||
"winston": "3.17.0",
|
||||
"winston": "3.18.3",
|
||||
"winston-daily-rotate-file": "5.0.0",
|
||||
"ws": "8.18.3",
|
||||
"yaml": "^2.8.1",
|
||||
"yargs": "18.0.0",
|
||||
"zod": "3.25.76",
|
||||
"zod-validation-error": "3.5.2"
|
||||
"zod-validation-error": "3.5.2",
|
||||
"@faker-js/faker": "^10.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "1.49.0",
|
||||
"@dotenvx/dotenvx": "1.51.1",
|
||||
"@esbuild-plugins/tsconfig-paths": "0.1.2",
|
||||
"@tailwindcss/postcss": "^4.1.12",
|
||||
"@react-email/preview-server": "4.3.2",
|
||||
"@tailwindcss/postcss": "^4.1.17",
|
||||
"@types/better-sqlite3": "7.6.12",
|
||||
"@types/cookie-parser": "1.4.9",
|
||||
"@types/cookie-parser": "1.4.10",
|
||||
"@types/cors": "2.8.19",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/express": "5.0.3",
|
||||
"@types/express": "5.0.5",
|
||||
"@types/express-session": "^1.18.2",
|
||||
"@types/jmespath": "^0.15.2",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/node": "^24",
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"@types/pg": "8.15.5",
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/node": "24.9.2",
|
||||
"@types/nodemailer": "7.0.3",
|
||||
"@types/pg": "8.15.6",
|
||||
"@types/react": "19.2.2",
|
||||
"@types/react-dom": "19.2.2",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"@types/ws": "8.18.1",
|
||||
"@types/yargs": "17.0.33",
|
||||
"drizzle-kit": "0.31.4",
|
||||
"esbuild": "0.25.9",
|
||||
"@types/yargs": "17.0.34",
|
||||
"drizzle-kit": "0.31.6",
|
||||
"esbuild": "0.25.12",
|
||||
"esbuild-node-externals": "1.18.0",
|
||||
"postcss": "^8",
|
||||
"react-email": "4.2.8",
|
||||
"react-email": "4.3.2",
|
||||
"tailwindcss": "^4.1.4",
|
||||
"tsc-alias": "1.8.16",
|
||||
"tsx": "4.20.5",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "^5",
|
||||
"typescript-eslint": "^8.40.0"
|
||||
"typescript-eslint": "^8.46.3"
|
||||
},
|
||||
"overrides": {
|
||||
"emblor": {
|
||||
|
||||
BIN
public/idp/azure.png
Normal file
BIN
public/idp/azure.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
public/idp/google.png
Normal file
BIN
public/idp/google.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 13 KiB |
@@ -7,16 +7,21 @@ import {
|
||||
errorHandlerMiddleware,
|
||||
notFoundMiddleware
|
||||
} from "@server/middlewares";
|
||||
import { authenticated, unauthenticated } from "@server/routers/external";
|
||||
import { router as wsRouter, handleWSUpgrade } from "@server/routers/ws";
|
||||
import { authenticated, unauthenticated } from "#dynamic/routers/external";
|
||||
import { router as wsRouter, handleWSUpgrade } from "#dynamic/routers/ws";
|
||||
import { logIncomingMiddleware } from "./middlewares/logIncoming";
|
||||
import { csrfProtectionMiddleware } from "./middlewares/csrfProtection";
|
||||
import helmet from "helmet";
|
||||
import { build } from "./build";
|
||||
import rateLimit, { ipKeyGenerator } from "express-rate-limit";
|
||||
import createHttpError from "http-errors";
|
||||
import HttpCode from "./types/HttpCode";
|
||||
import requestTimeoutMiddleware from "./middlewares/requestTimeout";
|
||||
import { createStore } from "./lib/rateLimitStore";
|
||||
import { createStore } from "#dynamic/lib/rateLimitStore";
|
||||
import { stripDuplicateSesions } from "./middlewares/stripDuplicateSessions";
|
||||
import { corsWithLoginPageSupport } from "@server/lib/corsWithLoginPage";
|
||||
import { hybridRouter } from "#dynamic/routers/hybrid";
|
||||
import { billingWebhookHandler } from "#dynamic/routers/billing/webhooks";
|
||||
|
||||
const dev = config.isDev;
|
||||
const externalPort = config.getRawConfig().server.external_port;
|
||||
@@ -30,8 +35,15 @@ export function createApiServer() {
|
||||
apiServer.set("trust proxy", trustProxy);
|
||||
}
|
||||
|
||||
const corsConfig = config.getRawConfig().server.cors;
|
||||
if (build == "saas") {
|
||||
apiServer.post(
|
||||
`${prefix}/billing/webhooks`,
|
||||
express.raw({ type: "application/json" }),
|
||||
billingWebhookHandler
|
||||
);
|
||||
}
|
||||
|
||||
const corsConfig = config.getRawConfig().server.cors;
|
||||
const options = {
|
||||
...(corsConfig?.origins
|
||||
? { origin: corsConfig.origins }
|
||||
@@ -47,21 +59,32 @@ export function createApiServer() {
|
||||
credentials: !(corsConfig?.credentials === false)
|
||||
};
|
||||
|
||||
logger.debug("Using CORS options", options);
|
||||
|
||||
apiServer.use(cors(options));
|
||||
if (build == "oss" || !corsConfig) {
|
||||
logger.debug("Using CORS options", options);
|
||||
apiServer.use(cors(options));
|
||||
} else if (corsConfig) {
|
||||
// Use the custom CORS middleware with loginPage support
|
||||
apiServer.use(corsWithLoginPageSupport(corsConfig));
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
apiServer.use(helmet());
|
||||
apiServer.use(csrfProtectionMiddleware);
|
||||
}
|
||||
|
||||
apiServer.use(stripDuplicateSesions);
|
||||
apiServer.use(cookieParser());
|
||||
apiServer.use(express.json());
|
||||
|
||||
// Add request timeout middleware
|
||||
apiServer.use(requestTimeoutMiddleware(60000)); // 60 second timeout
|
||||
|
||||
apiServer.use(logIncomingMiddleware);
|
||||
|
||||
if (build !== "oss") {
|
||||
apiServer.use(`${prefix}/hybrid`, hybridRouter); // put before rate limiting because we will rate limit there separately because some of the routes are heavily used
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
apiServer.use(
|
||||
rateLimit({
|
||||
@@ -70,7 +93,8 @@ export function createApiServer() {
|
||||
60 *
|
||||
1000,
|
||||
max: config.getRawConfig().rate_limits.global.max_requests,
|
||||
keyGenerator: (req) => `apiServerGlobal:${ipKeyGenerator(req.ip || "")}:${req.path}`,
|
||||
keyGenerator: (req) =>
|
||||
`apiServerGlobal:${ipKeyGenerator(req.ip || "")}:${req.path}`,
|
||||
handler: (req, res, next) => {
|
||||
const message = `Rate limit exceeded. You can make ${config.getRawConfig().rate_limits.global.max_requests} requests every ${config.getRawConfig().rate_limits.global.window_minutes} minute(s).`;
|
||||
return next(
|
||||
@@ -83,7 +107,6 @@ export function createApiServer() {
|
||||
}
|
||||
|
||||
// API routes
|
||||
apiServer.use(logIncomingMiddleware);
|
||||
apiServer.use(prefix, unauthenticated);
|
||||
apiServer.use(prefix, authenticated);
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ export enum ActionsEnum {
|
||||
getUser = "getUser",
|
||||
setResourcePassword = "setResourcePassword",
|
||||
setResourcePincode = "setResourcePincode",
|
||||
setResourceHeaderAuth = "setResourceHeaderAuth",
|
||||
setResourceWhitelist = "setResourceWhitelist",
|
||||
getResourceWhitelist = "getResourceWhitelist",
|
||||
generateAccessToken = "generateAccessToken",
|
||||
@@ -80,6 +81,9 @@ export enum ActionsEnum {
|
||||
listClients = "listClients",
|
||||
getClient = "getClient",
|
||||
listOrgDomains = "listOrgDomains",
|
||||
getDomain = "getDomain",
|
||||
updateOrgDomain = "updateOrgDomain",
|
||||
getDNSRecords = "getDNSRecords",
|
||||
createNewt = "createNewt",
|
||||
createIdp = "createIdp",
|
||||
updateIdp = "updateIdp",
|
||||
@@ -98,9 +102,28 @@ export enum ActionsEnum {
|
||||
listApiKeyActions = "listApiKeyActions",
|
||||
listApiKeys = "listApiKeys",
|
||||
getApiKey = "getApiKey",
|
||||
getCertificate = "getCertificate",
|
||||
restartCertificate = "restartCertificate",
|
||||
billing = "billing",
|
||||
createOrgDomain = "createOrgDomain",
|
||||
deleteOrgDomain = "deleteOrgDomain",
|
||||
restartOrgDomain = "restartOrgDomain"
|
||||
restartOrgDomain = "restartOrgDomain",
|
||||
sendUsageNotification = "sendUsageNotification",
|
||||
createRemoteExitNode = "createRemoteExitNode",
|
||||
updateRemoteExitNode = "updateRemoteExitNode",
|
||||
getRemoteExitNode = "getRemoteExitNode",
|
||||
listRemoteExitNode = "listRemoteExitNode",
|
||||
deleteRemoteExitNode = "deleteRemoteExitNode",
|
||||
updateOrgUser = "updateOrgUser",
|
||||
createLoginPage = "createLoginPage",
|
||||
updateLoginPage = "updateLoginPage",
|
||||
getLoginPage = "getLoginPage",
|
||||
deleteLoginPage = "deleteLoginPage",
|
||||
listBlueprints = "listBlueprints",
|
||||
getBlueprint = "getBlueprint",
|
||||
applyBlueprint = "applyBlueprint",
|
||||
viewLogs = "viewLogs",
|
||||
exportLogs = "exportLogs"
|
||||
}
|
||||
|
||||
export async function checkUserActionPermission(
|
||||
@@ -177,8 +200,6 @@ export async function checkUserActionPermission(
|
||||
.limit(1);
|
||||
|
||||
return roleActionPermission.length > 0;
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error("Error checking user action permission:", error);
|
||||
throw createHttpError(
|
||||
|
||||
@@ -3,13 +3,7 @@ import {
|
||||
encodeHexLowerCase
|
||||
} from "@oslojs/encoding";
|
||||
import { sha256 } from "@oslojs/crypto/sha2";
|
||||
import {
|
||||
resourceSessions,
|
||||
Session,
|
||||
sessions,
|
||||
User,
|
||||
users
|
||||
} from "@server/db";
|
||||
import { resourceSessions, Session, sessions, User, users } from "@server/db";
|
||||
import { db } from "@server/db";
|
||||
import { eq, inArray } from "drizzle-orm";
|
||||
import config from "@server/lib/config";
|
||||
@@ -24,8 +18,9 @@ export const SESSION_COOKIE_EXPIRES =
|
||||
60 *
|
||||
60 *
|
||||
config.getRawConfig().server.dashboard_session_length_hours;
|
||||
export const COOKIE_DOMAIN = config.getRawConfig().app.dashboard_url ?
|
||||
"." + new URL(config.getRawConfig().app.dashboard_url!).hostname : undefined;
|
||||
export const COOKIE_DOMAIN = config.getRawConfig().app.dashboard_url
|
||||
? new URL(config.getRawConfig().app.dashboard_url!).hostname
|
||||
: undefined;
|
||||
|
||||
export function generateSessionToken(): string {
|
||||
const bytes = new Uint8Array(20);
|
||||
@@ -44,7 +39,8 @@ export async function createSession(
|
||||
const session: Session = {
|
||||
sessionId: sessionId,
|
||||
userId,
|
||||
expiresAt: new Date(Date.now() + SESSION_COOKIE_EXPIRES).getTime()
|
||||
expiresAt: new Date(Date.now() + SESSION_COOKIE_EXPIRES).getTime(),
|
||||
issuedAt: new Date().getTime()
|
||||
};
|
||||
await db.insert(sessions).values(session);
|
||||
return session;
|
||||
@@ -98,8 +94,8 @@ export async function invalidateSession(sessionId: string): Promise<void> {
|
||||
try {
|
||||
await db.transaction(async (trx) => {
|
||||
await trx
|
||||
.delete(resourceSessions)
|
||||
.where(eq(resourceSessions.userSessionId, sessionId));
|
||||
.delete(resourceSessions)
|
||||
.where(eq(resourceSessions.userSessionId, sessionId));
|
||||
await trx.delete(sessions).where(eq(sessions.sessionId, sessionId));
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -111,9 +107,9 @@ export async function invalidateAllSessions(userId: string): Promise<void> {
|
||||
try {
|
||||
await db.transaction(async (trx) => {
|
||||
const userSessions = await trx
|
||||
.select()
|
||||
.from(sessions)
|
||||
.where(eq(sessions.userId, userId));
|
||||
.select()
|
||||
.from(sessions)
|
||||
.where(eq(sessions.userId, userId));
|
||||
await trx.delete(resourceSessions).where(
|
||||
inArray(
|
||||
resourceSessions.userSessionId,
|
||||
|
||||
@@ -4,9 +4,6 @@ import { resourceSessions, ResourceSession } from "@server/db";
|
||||
import { db } from "@server/db";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import config from "@server/lib/config";
|
||||
import axios from "axios";
|
||||
import logger from "@server/logger";
|
||||
import { tokenManager } from "@server/lib/tokenManager";
|
||||
|
||||
export const SESSION_COOKIE_NAME =
|
||||
config.getRawConfig().server.session_cookie_name;
|
||||
@@ -53,7 +50,8 @@ export async function createResourceSession(opts: {
|
||||
doNotExtend: opts.doNotExtend || false,
|
||||
accessTokenId: opts.accessTokenId || null,
|
||||
isRequestToken: opts.isRequestToken || false,
|
||||
userSessionId: opts.userSessionId || null
|
||||
userSessionId: opts.userSessionId || null,
|
||||
issuedAt: new Date().getTime()
|
||||
};
|
||||
|
||||
await db.insert(resourceSessions).values(session);
|
||||
@@ -65,29 +63,6 @@ export async function validateResourceSessionToken(
|
||||
token: string,
|
||||
resourceId: number
|
||||
): Promise<ResourceSessionValidationResult> {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.post(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/resource/${resourceId}/session/validate`, {
|
||||
token: token
|
||||
}, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error validating resource session token in hybrid mode:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error validating resource session token in hybrid mode:", error);
|
||||
}
|
||||
return { resourceSession: null };
|
||||
}
|
||||
}
|
||||
|
||||
const sessionId = encodeHexLowerCase(
|
||||
sha256(new TextEncoder().encode(token))
|
||||
);
|
||||
@@ -199,14 +174,14 @@ export function serializeResourceSessionCookie(
|
||||
const now = new Date().getTime();
|
||||
if (!isHttp) {
|
||||
if (expiresAt === undefined) {
|
||||
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Secure; Domain=${"." + domain}`;
|
||||
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Secure; Domain=${domain}`;
|
||||
}
|
||||
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Secure; Domain=${"." + domain}`;
|
||||
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Secure; Domain=${domain}`;
|
||||
} else {
|
||||
if (expiresAt === undefined) {
|
||||
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Domain=${"." + domain}`;
|
||||
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Domain=$domain}`;
|
||||
}
|
||||
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Domain=${"." + domain}`;
|
||||
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Domain=${domain}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,9 +191,9 @@ export function createBlankResourceSessionTokenCookie(
|
||||
isHttp: boolean = false
|
||||
): string {
|
||||
if (!isHttp) {
|
||||
return `${cookieName}_s=; HttpOnly; SameSite=Lax; Max-Age=0; Path=/; Secure; Domain=${"." + domain}`;
|
||||
return `${cookieName}_s=; HttpOnly; SameSite=Lax; Max-Age=0; Path=/; Secure; Domain=${domain}`;
|
||||
} else {
|
||||
return `${cookieName}=; HttpOnly; SameSite=Lax; Max-Age=0; Path=/; Domain=${"." + domain}`;
|
||||
return `${cookieName}=; HttpOnly; SameSite=Lax; Max-Age=0; Path=/; Domain=${domain}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const build = "oss" as any;
|
||||
13
server/cleanup.ts
Normal file
13
server/cleanup.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { cleanup as wsCleanup } from "@server/routers/ws";
|
||||
|
||||
async function cleanup() {
|
||||
await wsCleanup();
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
export async function initCleanup() {
|
||||
// Handle process termination
|
||||
process.on("SIGTERM", () => cleanup());
|
||||
process.on("SIGINT", () => cleanup());
|
||||
}
|
||||
1014
server/db/countries.ts
Normal file
1014
server/db/countries.ts
Normal file
File diff suppressed because it is too large
Load Diff
13
server/db/maxmind.ts
Normal file
13
server/db/maxmind.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import maxmind, { CountryResponse, Reader } from "maxmind";
|
||||
import config from "@server/lib/config";
|
||||
|
||||
let maxmindLookup: Reader<CountryResponse> | null;
|
||||
if (config.getRawConfig().server.maxmind_db_path) {
|
||||
maxmindLookup = await maxmind.open<CountryResponse>(
|
||||
config.getRawConfig().server.maxmind_db_path!
|
||||
);
|
||||
} else {
|
||||
maxmindLookup = null;
|
||||
}
|
||||
|
||||
export { maxmindLookup };
|
||||
@@ -1,6 +1,6 @@
|
||||
import { join } from "path";
|
||||
import { readFileSync } from "fs";
|
||||
import { db } from "@server/db";
|
||||
import { db, resources, siteResources } from "@server/db";
|
||||
import { exitNodes, sites } from "@server/db";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { __DIRNAME } from "@server/lib/consts";
|
||||
@@ -34,6 +34,44 @@ export async function getUniqueSiteName(orgId: string): Promise<string> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUniqueResourceName(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 count = await db
|
||||
.select({ niceId: resources.niceId, orgId: resources.orgId })
|
||||
.from(resources)
|
||||
.where(and(eq(resources.niceId, name), eq(resources.orgId, orgId)));
|
||||
if (count.length === 0) {
|
||||
return name;
|
||||
}
|
||||
loops++;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUniqueSiteResourceName(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 count = await db
|
||||
.select({ niceId: siteResources.niceId, orgId: siteResources.orgId })
|
||||
.from(siteResources)
|
||||
.where(and(eq(siteResources.niceId, name), eq(siteResources.orgId, orgId)));
|
||||
if (count.length === 0) {
|
||||
return name;
|
||||
}
|
||||
loops++;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUniqueExitNodeEndpointName(): Promise<string> {
|
||||
let loops = 0;
|
||||
const count = await db
|
||||
|
||||
@@ -7,9 +7,22 @@ function createDb() {
|
||||
const config = readConfigFile();
|
||||
|
||||
if (!config.postgres) {
|
||||
throw new Error(
|
||||
"Postgres configuration is missing in the configuration file."
|
||||
);
|
||||
// check the environment variables for postgres config
|
||||
if (process.env.POSTGRES_CONNECTION_STRING) {
|
||||
config.postgres = {
|
||||
connection_string: process.env.POSTGRES_CONNECTION_STRING
|
||||
};
|
||||
if (process.env.POSTGRES_REPLICA_CONNECTION_STRINGS) {
|
||||
const replicas = process.env.POSTGRES_REPLICA_CONNECTION_STRINGS.split(",").map((conn) => ({
|
||||
connection_string: conn.trim()
|
||||
}));
|
||||
config.postgres.replicas = replicas;
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
"Postgres configuration is missing in the configuration file."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const connectionString = config.postgres?.connection_string;
|
||||
@@ -22,11 +35,12 @@ function createDb() {
|
||||
}
|
||||
|
||||
// Create connection pools instead of individual connections
|
||||
const poolConfig = config.postgres.pool;
|
||||
const primaryPool = new Pool({
|
||||
connectionString,
|
||||
max: 20,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
max: poolConfig?.max_connections || 20,
|
||||
idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
|
||||
connectionTimeoutMillis: poolConfig?.connection_timeout_ms || 5000,
|
||||
});
|
||||
|
||||
const replicas = [];
|
||||
@@ -37,9 +51,9 @@ function createDb() {
|
||||
for (const conn of replicaConnections) {
|
||||
const replicaPool = new Pool({
|
||||
connectionString: conn.connection_string,
|
||||
max: 10,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
max: poolConfig?.max_replica_connections || 20,
|
||||
idleTimeoutMillis: poolConfig?.idle_timeout_ms || 30000,
|
||||
connectionTimeoutMillis: poolConfig?.connection_timeout_ms || 5000,
|
||||
});
|
||||
replicas.push(DrizzlePostgres(replicaPool));
|
||||
}
|
||||
@@ -50,3 +64,4 @@ function createDb() {
|
||||
|
||||
export const db = createDb();
|
||||
export default db;
|
||||
export type Transaction = Parameters<Parameters<typeof db["transaction"]>[0]>[0];
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./driver";
|
||||
export * from "./schema";
|
||||
export * from "./schema/schema";
|
||||
export * from "./schema/privateSchema";
|
||||
|
||||
273
server/db/pg/schema/privateSchema.ts
Normal file
273
server/db/pg/schema/privateSchema.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
import {
|
||||
pgTable,
|
||||
serial,
|
||||
varchar,
|
||||
boolean,
|
||||
integer,
|
||||
bigint,
|
||||
real,
|
||||
text,
|
||||
index
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { InferSelectModel } from "drizzle-orm";
|
||||
import { domains, orgs, targets, users, exitNodes, sessions } from "./schema";
|
||||
|
||||
export const certificates = pgTable("certificates", {
|
||||
certId: serial("certId").primaryKey(),
|
||||
domain: varchar("domain", { length: 255 }).notNull().unique(),
|
||||
domainId: varchar("domainId").references(() => domains.domainId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
wildcard: boolean("wildcard").default(false),
|
||||
status: varchar("status", { length: 50 }).notNull().default("pending"), // pending, requested, valid, expired, failed
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }),
|
||||
lastRenewalAttempt: bigint("lastRenewalAttempt", { mode: "number" }),
|
||||
createdAt: bigint("createdAt", { mode: "number" }).notNull(),
|
||||
updatedAt: bigint("updatedAt", { mode: "number" }).notNull(),
|
||||
orderId: varchar("orderId", { length: 500 }),
|
||||
errorMessage: text("errorMessage"),
|
||||
renewalCount: integer("renewalCount").default(0),
|
||||
certFile: text("certFile"),
|
||||
keyFile: text("keyFile")
|
||||
});
|
||||
|
||||
export const dnsChallenge = pgTable("dnsChallenges", {
|
||||
dnsChallengeId: serial("dnsChallengeId").primaryKey(),
|
||||
domain: varchar("domain", { length: 255 }).notNull(),
|
||||
token: varchar("token", { length: 255 }).notNull(),
|
||||
keyAuthorization: varchar("keyAuthorization", { length: 1000 }).notNull(),
|
||||
createdAt: bigint("createdAt", { mode: "number" }).notNull(),
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }).notNull(),
|
||||
completed: boolean("completed").default(false)
|
||||
});
|
||||
|
||||
export const account = pgTable("account", {
|
||||
accountId: serial("accountId").primaryKey(),
|
||||
userId: varchar("userId")
|
||||
.notNull()
|
||||
.references(() => users.userId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const customers = pgTable("customers", {
|
||||
customerId: varchar("customerId", { length: 255 }).primaryKey().notNull(),
|
||||
orgId: varchar("orgId", { length: 255 })
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
// accountId: integer("accountId")
|
||||
// .references(() => account.accountId, { onDelete: "cascade" }), // Optional, if using accounts
|
||||
email: varchar("email", { length: 255 }),
|
||||
name: varchar("name", { length: 255 }),
|
||||
phone: varchar("phone", { length: 50 }),
|
||||
address: text("address"),
|
||||
createdAt: bigint("createdAt", { mode: "number" }).notNull(),
|
||||
updatedAt: bigint("updatedAt", { mode: "number" }).notNull()
|
||||
});
|
||||
|
||||
export const subscriptions = pgTable("subscriptions", {
|
||||
subscriptionId: varchar("subscriptionId", { length: 255 })
|
||||
.primaryKey()
|
||||
.notNull(),
|
||||
customerId: varchar("customerId", { length: 255 })
|
||||
.notNull()
|
||||
.references(() => customers.customerId, { onDelete: "cascade" }),
|
||||
status: varchar("status", { length: 50 }).notNull().default("active"), // active, past_due, canceled, unpaid
|
||||
canceledAt: bigint("canceledAt", { mode: "number" }),
|
||||
createdAt: bigint("createdAt", { mode: "number" }).notNull(),
|
||||
updatedAt: bigint("updatedAt", { mode: "number" }),
|
||||
billingCycleAnchor: bigint("billingCycleAnchor", { mode: "number" })
|
||||
});
|
||||
|
||||
export const subscriptionItems = pgTable("subscriptionItems", {
|
||||
subscriptionItemId: serial("subscriptionItemId").primaryKey(),
|
||||
subscriptionId: varchar("subscriptionId", { length: 255 })
|
||||
.notNull()
|
||||
.references(() => subscriptions.subscriptionId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
planId: varchar("planId", { length: 255 }).notNull(),
|
||||
priceId: varchar("priceId", { length: 255 }),
|
||||
meterId: varchar("meterId", { length: 255 }),
|
||||
unitAmount: real("unitAmount"),
|
||||
tiers: text("tiers"),
|
||||
interval: varchar("interval", { length: 50 }),
|
||||
currentPeriodStart: bigint("currentPeriodStart", { mode: "number" }),
|
||||
currentPeriodEnd: bigint("currentPeriodEnd", { mode: "number" }),
|
||||
name: varchar("name", { length: 255 })
|
||||
});
|
||||
|
||||
export const accountDomains = pgTable("accountDomains", {
|
||||
accountId: integer("accountId")
|
||||
.notNull()
|
||||
.references(() => account.accountId, { onDelete: "cascade" }),
|
||||
domainId: varchar("domainId")
|
||||
.notNull()
|
||||
.references(() => domains.domainId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const usage = pgTable("usage", {
|
||||
usageId: varchar("usageId", { length: 255 }).primaryKey(),
|
||||
featureId: varchar("featureId", { length: 255 }).notNull(),
|
||||
orgId: varchar("orgId")
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
meterId: varchar("meterId", { length: 255 }),
|
||||
instantaneousValue: real("instantaneousValue"),
|
||||
latestValue: real("latestValue").notNull(),
|
||||
previousValue: real("previousValue"),
|
||||
updatedAt: bigint("updatedAt", { mode: "number" }).notNull(),
|
||||
rolledOverAt: bigint("rolledOverAt", { mode: "number" }),
|
||||
nextRolloverAt: bigint("nextRolloverAt", { mode: "number" })
|
||||
});
|
||||
|
||||
export const limits = pgTable("limits", {
|
||||
limitId: varchar("limitId", { length: 255 }).primaryKey(),
|
||||
featureId: varchar("featureId", { length: 255 }).notNull(),
|
||||
orgId: varchar("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
value: real("value"),
|
||||
description: text("description")
|
||||
});
|
||||
|
||||
export const usageNotifications = pgTable("usageNotifications", {
|
||||
notificationId: serial("notificationId").primaryKey(),
|
||||
orgId: varchar("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
featureId: varchar("featureId", { length: 255 }).notNull(),
|
||||
limitId: varchar("limitId", { length: 255 }).notNull(),
|
||||
notificationType: varchar("notificationType", { length: 50 }).notNull(),
|
||||
sentAt: bigint("sentAt", { mode: "number" }).notNull()
|
||||
});
|
||||
|
||||
export const domainNamespaces = pgTable("domainNamespaces", {
|
||||
domainNamespaceId: varchar("domainNamespaceId", {
|
||||
length: 255
|
||||
}).primaryKey(),
|
||||
domainId: varchar("domainId")
|
||||
.references(() => domains.domainId, {
|
||||
onDelete: "set null"
|
||||
})
|
||||
.notNull()
|
||||
});
|
||||
|
||||
export const exitNodeOrgs = pgTable("exitNodeOrgs", {
|
||||
exitNodeId: integer("exitNodeId")
|
||||
.notNull()
|
||||
.references(() => exitNodes.exitNodeId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const remoteExitNodes = pgTable("remoteExitNode", {
|
||||
remoteExitNodeId: varchar("id").primaryKey(),
|
||||
secretHash: varchar("secretHash").notNull(),
|
||||
dateCreated: varchar("dateCreated").notNull(),
|
||||
version: varchar("version"),
|
||||
secondaryVersion: varchar("secondaryVersion"), // This is to detect the new nodes after the transition to pangolin-node
|
||||
exitNodeId: integer("exitNodeId").references(() => exitNodes.exitNodeId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
});
|
||||
|
||||
export const remoteExitNodeSessions = pgTable("remoteExitNodeSession", {
|
||||
sessionId: varchar("id").primaryKey(),
|
||||
remoteExitNodeId: varchar("remoteExitNodeId")
|
||||
.notNull()
|
||||
.references(() => remoteExitNodes.remoteExitNodeId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }).notNull()
|
||||
});
|
||||
|
||||
export const loginPage = pgTable("loginPage", {
|
||||
loginPageId: serial("loginPageId").primaryKey(),
|
||||
subdomain: varchar("subdomain"),
|
||||
fullDomain: varchar("fullDomain"),
|
||||
exitNodeId: integer("exitNodeId").references(() => exitNodes.exitNodeId, {
|
||||
onDelete: "set null"
|
||||
}),
|
||||
domainId: varchar("domainId").references(() => domains.domainId, {
|
||||
onDelete: "set null"
|
||||
})
|
||||
});
|
||||
|
||||
export const loginPageOrg = pgTable("loginPageOrg", {
|
||||
loginPageId: integer("loginPageId")
|
||||
.notNull()
|
||||
.references(() => loginPage.loginPageId, { onDelete: "cascade" }),
|
||||
orgId: varchar("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const sessionTransferToken = pgTable("sessionTransferToken", {
|
||||
token: varchar("token").primaryKey(),
|
||||
sessionId: varchar("sessionId")
|
||||
.notNull()
|
||||
.references(() => sessions.sessionId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
encryptedSession: text("encryptedSession").notNull(),
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }).notNull()
|
||||
});
|
||||
|
||||
export const actionAuditLog = pgTable("actionAuditLog", {
|
||||
id: serial("id").primaryKey(),
|
||||
timestamp: bigint("timestamp", { mode: "number" }).notNull(), // this is EPOCH time in seconds
|
||||
orgId: varchar("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
actorType: varchar("actorType", { length: 50 }).notNull(),
|
||||
actor: varchar("actor", { length: 255 }).notNull(),
|
||||
actorId: varchar("actorId", { length: 255 }).notNull(),
|
||||
action: varchar("action", { length: 100 }).notNull(),
|
||||
metadata: text("metadata")
|
||||
}, (table) => ([
|
||||
index("idx_actionAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_actionAuditLog_org_timestamp").on(table.orgId, table.timestamp)
|
||||
]));
|
||||
|
||||
export const accessAuditLog = pgTable("accessAuditLog", {
|
||||
id: serial("id").primaryKey(),
|
||||
timestamp: bigint("timestamp", { mode: "number" }).notNull(), // this is EPOCH time in seconds
|
||||
orgId: varchar("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
actorType: varchar("actorType", { length: 50 }),
|
||||
actor: varchar("actor", { length: 255 }),
|
||||
actorId: varchar("actorId", { length: 255 }),
|
||||
resourceId: integer("resourceId"),
|
||||
ip: varchar("ip", { length: 45 }),
|
||||
type: varchar("type", { length: 100 }).notNull(),
|
||||
action: boolean("action").notNull(),
|
||||
location: text("location"),
|
||||
userAgent: text("userAgent"),
|
||||
metadata: text("metadata")
|
||||
}, (table) => ([
|
||||
index("idx_identityAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_identityAuditLog_org_timestamp").on(table.orgId, table.timestamp)
|
||||
]));
|
||||
|
||||
export type Limit = InferSelectModel<typeof limits>;
|
||||
export type Account = InferSelectModel<typeof account>;
|
||||
export type Certificate = InferSelectModel<typeof certificates>;
|
||||
export type DnsChallenge = InferSelectModel<typeof dnsChallenge>;
|
||||
export type Customer = InferSelectModel<typeof customers>;
|
||||
export type Subscription = InferSelectModel<typeof subscriptions>;
|
||||
export type SubscriptionItem = InferSelectModel<typeof subscriptionItems>;
|
||||
export type Usage = InferSelectModel<typeof usage>;
|
||||
export type UsageLimit = InferSelectModel<typeof limits>;
|
||||
export type AccountDomain = InferSelectModel<typeof accountDomains>;
|
||||
export type UsageNotification = InferSelectModel<typeof usageNotifications>;
|
||||
export type RemoteExitNode = InferSelectModel<typeof remoteExitNodes>;
|
||||
export type RemoteExitNodeSession = InferSelectModel<
|
||||
typeof remoteExitNodeSessions
|
||||
>;
|
||||
export type ExitNodeOrg = InferSelectModel<typeof exitNodeOrgs>;
|
||||
export type LoginPage = InferSelectModel<typeof loginPage>;
|
||||
export type ActionAuditLog = InferSelectModel<typeof actionAuditLog>;
|
||||
export type AccessAuditLog = InferSelectModel<typeof accessAuditLog>;
|
||||
@@ -6,9 +6,11 @@ import {
|
||||
integer,
|
||||
bigint,
|
||||
real,
|
||||
text
|
||||
text,
|
||||
index
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { InferSelectModel } from "drizzle-orm";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
export const domains = pgTable("domains", {
|
||||
domainId: varchar("domainId").primaryKey(),
|
||||
@@ -17,14 +19,40 @@ export const domains = pgTable("domains", {
|
||||
type: varchar("type"), // "ns", "cname", "wildcard"
|
||||
verified: boolean("verified").notNull().default(false),
|
||||
failed: boolean("failed").notNull().default(false),
|
||||
tries: integer("tries").notNull().default(0)
|
||||
tries: integer("tries").notNull().default(0),
|
||||
certResolver: varchar("certResolver"),
|
||||
customCertResolver: varchar("customCertResolver"),
|
||||
preferWildcardCert: boolean("preferWildcardCert")
|
||||
});
|
||||
|
||||
export const dnsRecords = pgTable("dnsRecords", {
|
||||
id: serial("id").primaryKey(),
|
||||
domainId: varchar("domainId")
|
||||
.notNull()
|
||||
.references(() => domains.domainId, { onDelete: "cascade" }),
|
||||
recordType: varchar("recordType").notNull(), // "NS" | "CNAME" | "A" | "TXT"
|
||||
baseDomain: varchar("baseDomain"),
|
||||
value: varchar("value").notNull(),
|
||||
verified: boolean("verified").notNull().default(false)
|
||||
});
|
||||
|
||||
export const orgs = pgTable("orgs", {
|
||||
orgId: varchar("orgId").primaryKey(),
|
||||
name: varchar("name").notNull(),
|
||||
subnet: varchar("subnet"),
|
||||
createdAt: text("createdAt")
|
||||
createdAt: text("createdAt"),
|
||||
requireTwoFactor: boolean("requireTwoFactor"),
|
||||
maxSessionLengthHours: integer("maxSessionLengthHours"),
|
||||
passwordExpiryDays: integer("passwordExpiryDays"),
|
||||
settingsLogRetentionDaysRequest: integer("settingsLogRetentionDaysRequest") // where 0 = dont keep logs and -1 = keep forever
|
||||
.notNull()
|
||||
.default(7),
|
||||
settingsLogRetentionDaysAccess: integer("settingsLogRetentionDaysAccess")
|
||||
.notNull()
|
||||
.default(0),
|
||||
settingsLogRetentionDaysAction: integer("settingsLogRetentionDaysAction")
|
||||
.notNull()
|
||||
.default(0)
|
||||
});
|
||||
|
||||
export const orgDomains = pgTable("orgDomains", {
|
||||
@@ -66,11 +94,16 @@ export const sites = pgTable("sites", {
|
||||
|
||||
export const resources = pgTable("resources", {
|
||||
resourceId: serial("resourceId").primaryKey(),
|
||||
resourceGuid: varchar("resourceGuid", { length: 36 })
|
||||
.unique()
|
||||
.notNull()
|
||||
.$defaultFn(() => randomUUID()),
|
||||
orgId: varchar("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
niceId: text("niceId").notNull(),
|
||||
name: varchar("name").notNull(),
|
||||
subdomain: varchar("subdomain"),
|
||||
fullDomain: varchar("fullDomain"),
|
||||
@@ -93,8 +126,11 @@ export const resources = pgTable("resources", {
|
||||
setHostHeader: varchar("setHostHeader"),
|
||||
enableProxy: boolean("enableProxy").default(true),
|
||||
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
||||
onDelete: "cascade"
|
||||
onDelete: "set null"
|
||||
}),
|
||||
headers: text("headers"), // comma-separated list of headers to add to the request
|
||||
proxyProtocol: boolean("proxyProtocol").notNull().default(false),
|
||||
proxyProtocolVersion: integer("proxyProtocolVersion").default(1)
|
||||
});
|
||||
|
||||
export const targets = pgTable("targets", {
|
||||
@@ -113,7 +149,33 @@ export const targets = pgTable("targets", {
|
||||
method: varchar("method"),
|
||||
port: integer("port").notNull(),
|
||||
internalPort: integer("internalPort"),
|
||||
enabled: boolean("enabled").notNull().default(true)
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
path: text("path"),
|
||||
pathMatchType: text("pathMatchType"), // exact, prefix, regex
|
||||
rewritePath: text("rewritePath"), // if set, rewrites the path to this value before sending to the target
|
||||
rewritePathType: text("rewritePathType"), // exact, prefix, regex, stripPrefix
|
||||
priority: integer("priority").notNull().default(100)
|
||||
});
|
||||
|
||||
export const targetHealthCheck = pgTable("targetHealthCheck", {
|
||||
targetHealthCheckId: serial("targetHealthCheckId").primaryKey(),
|
||||
targetId: integer("targetId")
|
||||
.notNull()
|
||||
.references(() => targets.targetId, { onDelete: "cascade" }),
|
||||
hcEnabled: boolean("hcEnabled").notNull().default(false),
|
||||
hcPath: varchar("hcPath"),
|
||||
hcScheme: varchar("hcScheme"),
|
||||
hcMode: varchar("hcMode").default("http"),
|
||||
hcHostname: varchar("hcHostname"),
|
||||
hcPort: integer("hcPort"),
|
||||
hcInterval: integer("hcInterval").default(30), // in seconds
|
||||
hcUnhealthyInterval: integer("hcUnhealthyInterval").default(30), // in seconds
|
||||
hcTimeout: integer("hcTimeout").default(5), // in seconds
|
||||
hcHeaders: varchar("hcHeaders"),
|
||||
hcFollowRedirects: boolean("hcFollowRedirects").default(true),
|
||||
hcMethod: varchar("hcMethod").default("GET"),
|
||||
hcStatus: integer("hcStatus"), // http code
|
||||
hcHealth: text("hcHealth").default("unknown") // "unknown", "healthy", "unhealthy"
|
||||
});
|
||||
|
||||
export const exitNodes = pgTable("exitNodes", {
|
||||
@@ -127,10 +189,12 @@ export const exitNodes = pgTable("exitNodes", {
|
||||
maxConnections: integer("maxConnections"),
|
||||
online: boolean("online").notNull().default(false),
|
||||
lastPing: integer("lastPing"),
|
||||
type: text("type").default("gerbil") // gerbil, remoteExitNode
|
||||
type: text("type").default("gerbil"), // gerbil, remoteExitNode
|
||||
region: varchar("region")
|
||||
});
|
||||
|
||||
export const siteResources = pgTable("siteResources", { // this is for the clients
|
||||
export const siteResources = pgTable("siteResources", {
|
||||
// this is for the clients
|
||||
siteResourceId: serial("siteResourceId").primaryKey(),
|
||||
siteId: integer("siteId")
|
||||
.notNull()
|
||||
@@ -138,12 +202,13 @@ export const siteResources = pgTable("siteResources", { // this is for the clien
|
||||
orgId: varchar("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
niceId: varchar("niceId").notNull(),
|
||||
name: varchar("name").notNull(),
|
||||
protocol: varchar("protocol").notNull(),
|
||||
proxyPort: integer("proxyPort").notNull(),
|
||||
destinationPort: integer("destinationPort").notNull(),
|
||||
destinationIp: varchar("destinationIp").notNull(),
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
enabled: boolean("enabled").notNull().default(true)
|
||||
});
|
||||
|
||||
export const users = pgTable("user", {
|
||||
@@ -163,7 +228,8 @@ export const users = pgTable("user", {
|
||||
dateCreated: varchar("dateCreated").notNull(),
|
||||
termsAcceptedTimestamp: varchar("termsAcceptedTimestamp"),
|
||||
termsVersion: varchar("termsVersion"),
|
||||
serverAdmin: boolean("serverAdmin").notNull().default(false)
|
||||
serverAdmin: boolean("serverAdmin").notNull().default(false),
|
||||
lastPasswordChange: bigint("lastPasswordChange", { mode: "number" })
|
||||
});
|
||||
|
||||
export const newts = pgTable("newt", {
|
||||
@@ -189,7 +255,8 @@ export const sessions = pgTable("session", {
|
||||
userId: varchar("userId")
|
||||
.notNull()
|
||||
.references(() => users.userId, { onDelete: "cascade" }),
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }).notNull()
|
||||
expiresAt: bigint("expiresAt", { mode: "number" }).notNull(),
|
||||
issuedAt: bigint("issuedAt", { mode: "number" })
|
||||
});
|
||||
|
||||
export const newtSessions = pgTable("newtSession", {
|
||||
@@ -212,7 +279,8 @@ export const userOrgs = pgTable("userOrgs", {
|
||||
roleId: integer("roleId")
|
||||
.notNull()
|
||||
.references(() => roles.roleId),
|
||||
isOwner: boolean("isOwner").notNull().default(false)
|
||||
isOwner: boolean("isOwner").notNull().default(false),
|
||||
autoProvisioned: boolean("autoProvisioned").default(false)
|
||||
});
|
||||
|
||||
export const emailVerificationCodes = pgTable("emailVerificationCodes", {
|
||||
@@ -343,6 +411,14 @@ export const resourcePassword = pgTable("resourcePassword", {
|
||||
passwordHash: varchar("passwordHash").notNull()
|
||||
});
|
||||
|
||||
export const resourceHeaderAuth = pgTable("resourceHeaderAuth", {
|
||||
headerAuthId: serial("headerAuthId").primaryKey(),
|
||||
resourceId: integer("resourceId")
|
||||
.notNull()
|
||||
.references(() => resources.resourceId, { onDelete: "cascade" }),
|
||||
headerAuthHash: varchar("headerAuthHash").notNull()
|
||||
});
|
||||
|
||||
export const resourceAccessToken = pgTable("resourceAccessToken", {
|
||||
accessTokenId: varchar("accessTokenId").primaryKey(),
|
||||
orgId: varchar("orgId")
|
||||
@@ -397,7 +473,8 @@ export const resourceSessions = pgTable("resourceSessions", {
|
||||
{
|
||||
onDelete: "cascade"
|
||||
}
|
||||
)
|
||||
),
|
||||
issuedAt: bigint("issuedAt", { mode: "number" })
|
||||
});
|
||||
|
||||
export const resourceWhitelist = pgTable("resourceWhitelist", {
|
||||
@@ -458,6 +535,7 @@ export const idpOidcConfig = pgTable("idpOidcConfig", {
|
||||
idpId: integer("idpId")
|
||||
.notNull()
|
||||
.references(() => idp.idpId, { onDelete: "cascade" }),
|
||||
variant: varchar("variant").notNull().default("oidc"),
|
||||
clientId: varchar("clientId").notNull(),
|
||||
clientSecret: varchar("clientSecret").notNull(),
|
||||
authUrl: varchar("authUrl").notNull(),
|
||||
@@ -624,6 +702,57 @@ export const setupTokens = pgTable("setupTokens", {
|
||||
dateUsed: varchar("dateUsed")
|
||||
});
|
||||
|
||||
// Blueprint runs
|
||||
export const blueprints = pgTable("blueprints", {
|
||||
blueprintId: serial("blueprintId").primaryKey(),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
name: varchar("name").notNull(),
|
||||
source: varchar("source").notNull(),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
succeeded: boolean("succeeded").notNull(),
|
||||
contents: text("contents").notNull(),
|
||||
message: text("message")
|
||||
});
|
||||
export const requestAuditLog = pgTable(
|
||||
"requestAuditLog",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId").references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
action: boolean("action").notNull(),
|
||||
reason: integer("reason").notNull(),
|
||||
actorType: text("actorType"),
|
||||
actor: text("actor"),
|
||||
actorId: text("actorId"),
|
||||
resourceId: integer("resourceId"),
|
||||
ip: text("ip"),
|
||||
location: text("location"),
|
||||
userAgent: text("userAgent"),
|
||||
metadata: text("metadata"),
|
||||
headers: text("headers"), // JSON blob
|
||||
query: text("query"), // JSON blob
|
||||
originalRequestURL: text("originalRequestURL"),
|
||||
scheme: text("scheme"),
|
||||
host: text("host"),
|
||||
path: text("path"),
|
||||
method: text("method"),
|
||||
tls: boolean("tls")
|
||||
},
|
||||
(table) => [
|
||||
index("idx_requestAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_requestAuditLog_org_timestamp").on(
|
||||
table.orgId,
|
||||
table.timestamp
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
export type Org = InferSelectModel<typeof orgs>;
|
||||
export type User = InferSelectModel<typeof users>;
|
||||
export type Site = InferSelectModel<typeof sites>;
|
||||
@@ -651,6 +780,7 @@ export type UserOrg = InferSelectModel<typeof userOrgs>;
|
||||
export type ResourceSession = InferSelectModel<typeof resourceSessions>;
|
||||
export type ResourcePincode = InferSelectModel<typeof resourcePincode>;
|
||||
export type ResourcePassword = InferSelectModel<typeof resourcePassword>;
|
||||
export type ResourceHeaderAuth = InferSelectModel<typeof resourceHeaderAuth>;
|
||||
export type ResourceOtp = InferSelectModel<typeof resourceOtp>;
|
||||
export type ResourceAccessToken = InferSelectModel<typeof resourceAccessToken>;
|
||||
export type ResourceWhitelist = InferSelectModel<typeof resourceWhitelist>;
|
||||
@@ -672,3 +802,10 @@ export type OrgDomains = InferSelectModel<typeof orgDomains>;
|
||||
export type SiteResource = InferSelectModel<typeof siteResources>;
|
||||
export type SetupToken = InferSelectModel<typeof setupTokens>;
|
||||
export type HostMeta = InferSelectModel<typeof hostMeta>;
|
||||
export type TargetHealthCheck = InferSelectModel<typeof targetHealthCheck>;
|
||||
export type IdpOidcConfig = InferSelectModel<typeof idpOidcConfig>;
|
||||
export type Blueprint = InferSelectModel<typeof blueprints>;
|
||||
export type LicenseKey = InferSelectModel<typeof licenseKey>;
|
||||
export type SecurityKey = InferSelectModel<typeof securityKeys>;
|
||||
export type WebauthnChallenge = InferSelectModel<typeof webauthnChallenge>;
|
||||
export type RequestAuditLog = InferSelectModel<typeof requestAuditLog>;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db } from "@server/db";
|
||||
import { db, loginPage, LoginPage, loginPageOrg, Org, orgs } from "@server/db";
|
||||
import {
|
||||
Resource,
|
||||
ResourcePassword,
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
ResourceRule,
|
||||
resourcePassword,
|
||||
resourcePincode,
|
||||
resourceHeaderAuth,
|
||||
ResourceHeaderAuth,
|
||||
resourceRules,
|
||||
resources,
|
||||
roleResources,
|
||||
@@ -15,15 +17,13 @@ import {
|
||||
users
|
||||
} from "@server/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import axios from "axios";
|
||||
import config from "@server/lib/config";
|
||||
import logger from "@server/logger";
|
||||
import { tokenManager } from "@server/lib/tokenManager";
|
||||
|
||||
export type ResourceWithAuth = {
|
||||
resource: Resource | null;
|
||||
pincode: ResourcePincode | null;
|
||||
password: ResourcePassword | null;
|
||||
headerAuth: ResourceHeaderAuth | null;
|
||||
org: Org;
|
||||
};
|
||||
|
||||
export type UserSessionWithUser = {
|
||||
@@ -37,27 +37,6 @@ export type UserSessionWithUser = {
|
||||
export async function getResourceByDomain(
|
||||
domain: string
|
||||
): Promise<ResourceWithAuth | null> {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/resource/domain/${domain}`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const [result] = await db
|
||||
.select()
|
||||
.from(resources)
|
||||
@@ -69,6 +48,14 @@ export async function getResourceByDomain(
|
||||
resourcePassword,
|
||||
eq(resourcePassword.resourceId, resources.resourceId)
|
||||
)
|
||||
.leftJoin(
|
||||
resourceHeaderAuth,
|
||||
eq(resourceHeaderAuth.resourceId, resources.resourceId)
|
||||
)
|
||||
.innerJoin(
|
||||
orgs,
|
||||
eq(orgs.orgId, resources.orgId)
|
||||
)
|
||||
.where(eq(resources.fullDomain, domain))
|
||||
.limit(1);
|
||||
|
||||
@@ -79,7 +66,9 @@ export async function getResourceByDomain(
|
||||
return {
|
||||
resource: result.resources,
|
||||
pincode: result.resourcePincode,
|
||||
password: result.resourcePassword
|
||||
password: result.resourcePassword,
|
||||
headerAuth: result.resourceHeaderAuth,
|
||||
org: result.orgs
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,27 +78,6 @@ export async function getResourceByDomain(
|
||||
export async function getUserSessionWithUser(
|
||||
userSessionId: string
|
||||
): Promise<UserSessionWithUser | null> {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/session/${userSessionId}`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const [res] = await db
|
||||
.select()
|
||||
.from(sessions)
|
||||
@@ -130,36 +98,10 @@ export async function getUserSessionWithUser(
|
||||
* Get user organization role
|
||||
*/
|
||||
export async function getUserOrgRole(userId: string, orgId: string) {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/user/${userId}/org/${orgId}/role`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const userOrgRole = await db
|
||||
.select()
|
||||
.from(userOrgs)
|
||||
.where(
|
||||
and(
|
||||
eq(userOrgs.userId, userId),
|
||||
eq(userOrgs.orgId, orgId)
|
||||
)
|
||||
)
|
||||
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId)))
|
||||
.limit(1);
|
||||
|
||||
return userOrgRole.length > 0 ? userOrgRole[0] : null;
|
||||
@@ -168,28 +110,10 @@ export async function getUserOrgRole(userId: string, orgId: string) {
|
||||
/**
|
||||
* Check if role has access to resource
|
||||
*/
|
||||
export async function getRoleResourceAccess(resourceId: number, roleId: number) {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/role/${roleId}/resource/${resourceId}/access`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getRoleResourceAccess(
|
||||
resourceId: number,
|
||||
roleId: number
|
||||
) {
|
||||
const roleResourceAccess = await db
|
||||
.select()
|
||||
.from(roleResources)
|
||||
@@ -207,28 +131,10 @@ export async function getRoleResourceAccess(resourceId: number, roleId: number)
|
||||
/**
|
||||
* Check if user has direct access to resource
|
||||
*/
|
||||
export async function getUserResourceAccess(userId: string, resourceId: number) {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/user/${userId}/resource/${resourceId}/access`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUserResourceAccess(
|
||||
userId: string,
|
||||
resourceId: number
|
||||
) {
|
||||
const userResourceAccess = await db
|
||||
.select()
|
||||
.from(userResources)
|
||||
@@ -246,28 +152,9 @@ export async function getUserResourceAccess(userId: string, resourceId: number)
|
||||
/**
|
||||
* Get resource rules for a given resource
|
||||
*/
|
||||
export async function getResourceRules(resourceId: number): Promise<ResourceRule[]> {
|
||||
if (config.isManagedMode()) {
|
||||
try {
|
||||
const response = await axios.get(`${config.getRawConfig().managed?.endpoint}/api/v1/hybrid/resource/${resourceId}/rules`, await tokenManager.getAuthHeader());
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error("Error fetching config in verify session:", {
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
url: error.config?.url,
|
||||
method: error.config?.method
|
||||
});
|
||||
} else {
|
||||
logger.error("Error fetching config in verify session:", error);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getResourceRules(
|
||||
resourceId: number
|
||||
): Promise<ResourceRule[]> {
|
||||
const rules = await db
|
||||
.select()
|
||||
.from(resourceRules)
|
||||
@@ -275,3 +162,26 @@ export async function getResourceRules(resourceId: number): Promise<ResourceRule
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get organization login page
|
||||
*/
|
||||
export async function getOrgLoginPage(
|
||||
orgId: string
|
||||
): Promise<LoginPage | null> {
|
||||
const [result] = await db
|
||||
.select()
|
||||
.from(loginPageOrg)
|
||||
.where(eq(loginPageOrg.orgId, orgId))
|
||||
.innerJoin(
|
||||
loginPage,
|
||||
eq(loginPageOrg.loginPageId, loginPage.loginPageId)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result?.loginPage;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { drizzle as DrizzleSqlite } from "drizzle-orm/better-sqlite3";
|
||||
import Database from "better-sqlite3";
|
||||
import * as schema from "./schema";
|
||||
import * as schema from "./schema/schema";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { APP_PATH } from "@server/lib/consts";
|
||||
@@ -13,11 +13,16 @@ bootstrapVolume();
|
||||
|
||||
function createDb() {
|
||||
const sqlite = new Database(location);
|
||||
return DrizzleSqlite(sqlite, { schema });
|
||||
return DrizzleSqlite(sqlite, {
|
||||
schema
|
||||
});
|
||||
}
|
||||
|
||||
export const db = createDb();
|
||||
export default db;
|
||||
export type Transaction = Parameters<
|
||||
Parameters<(typeof db)["transaction"]>[0]
|
||||
>[0];
|
||||
|
||||
function checkFileExists(filePath: string): boolean {
|
||||
try {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./driver";
|
||||
export * from "./schema";
|
||||
export * from "./schema/schema";
|
||||
export * from "./schema/privateSchema";
|
||||
|
||||
268
server/db/sqlite/schema/privateSchema.ts
Normal file
268
server/db/sqlite/schema/privateSchema.ts
Normal file
@@ -0,0 +1,268 @@
|
||||
import {
|
||||
sqliteTable,
|
||||
integer,
|
||||
text,
|
||||
real,
|
||||
index
|
||||
} from "drizzle-orm/sqlite-core";
|
||||
import { InferSelectModel } from "drizzle-orm";
|
||||
import { domains, orgs, targets, users, exitNodes, sessions } from "./schema";
|
||||
import { metadata } from "@app/app/[orgId]/settings/layout";
|
||||
|
||||
export const certificates = sqliteTable("certificates", {
|
||||
certId: integer("certId").primaryKey({ autoIncrement: true }),
|
||||
domain: text("domain").notNull().unique(),
|
||||
domainId: text("domainId").references(() => domains.domainId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
wildcard: integer("wildcard", { mode: "boolean" }).default(false),
|
||||
status: text("status").notNull().default("pending"), // pending, requested, valid, expired, failed
|
||||
expiresAt: integer("expiresAt"),
|
||||
lastRenewalAttempt: integer("lastRenewalAttempt"),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
updatedAt: integer("updatedAt").notNull(),
|
||||
orderId: text("orderId"),
|
||||
errorMessage: text("errorMessage"),
|
||||
renewalCount: integer("renewalCount").default(0),
|
||||
certFile: text("certFile"),
|
||||
keyFile: text("keyFile")
|
||||
});
|
||||
|
||||
export const dnsChallenge = sqliteTable("dnsChallenges", {
|
||||
dnsChallengeId: integer("dnsChallengeId").primaryKey({ autoIncrement: true }),
|
||||
domain: text("domain").notNull(),
|
||||
token: text("token").notNull(),
|
||||
keyAuthorization: text("keyAuthorization").notNull(),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
expiresAt: integer("expiresAt").notNull(),
|
||||
completed: integer("completed", { mode: "boolean" }).default(false)
|
||||
});
|
||||
|
||||
export const account = sqliteTable("account", {
|
||||
accountId: integer("accountId").primaryKey({ autoIncrement: true }),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users.userId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const customers = sqliteTable("customers", {
|
||||
customerId: text("customerId").primaryKey().notNull(),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
// accountId: integer("accountId")
|
||||
// .references(() => account.accountId, { onDelete: "cascade" }), // Optional, if using accounts
|
||||
email: text("email"),
|
||||
name: text("name"),
|
||||
phone: text("phone"),
|
||||
address: text("address"),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
updatedAt: integer("updatedAt").notNull()
|
||||
});
|
||||
|
||||
export const subscriptions = sqliteTable("subscriptions", {
|
||||
subscriptionId: text("subscriptionId")
|
||||
.primaryKey()
|
||||
.notNull(),
|
||||
customerId: text("customerId")
|
||||
.notNull()
|
||||
.references(() => customers.customerId, { onDelete: "cascade" }),
|
||||
status: text("status").notNull().default("active"), // active, past_due, canceled, unpaid
|
||||
canceledAt: integer("canceledAt"),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
updatedAt: integer("updatedAt"),
|
||||
billingCycleAnchor: integer("billingCycleAnchor")
|
||||
});
|
||||
|
||||
export const subscriptionItems = sqliteTable("subscriptionItems", {
|
||||
subscriptionItemId: integer("subscriptionItemId").primaryKey({ autoIncrement: true }),
|
||||
subscriptionId: text("subscriptionId")
|
||||
.notNull()
|
||||
.references(() => subscriptions.subscriptionId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
planId: text("planId").notNull(),
|
||||
priceId: text("priceId"),
|
||||
meterId: text("meterId"),
|
||||
unitAmount: real("unitAmount"),
|
||||
tiers: text("tiers"),
|
||||
interval: text("interval"),
|
||||
currentPeriodStart: integer("currentPeriodStart"),
|
||||
currentPeriodEnd: integer("currentPeriodEnd"),
|
||||
name: text("name")
|
||||
});
|
||||
|
||||
export const accountDomains = sqliteTable("accountDomains", {
|
||||
accountId: integer("accountId")
|
||||
.notNull()
|
||||
.references(() => account.accountId, { onDelete: "cascade" }),
|
||||
domainId: text("domainId")
|
||||
.notNull()
|
||||
.references(() => domains.domainId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const usage = sqliteTable("usage", {
|
||||
usageId: text("usageId").primaryKey(),
|
||||
featureId: text("featureId").notNull(),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
meterId: text("meterId"),
|
||||
instantaneousValue: real("instantaneousValue"),
|
||||
latestValue: real("latestValue").notNull(),
|
||||
previousValue: real("previousValue"),
|
||||
updatedAt: integer("updatedAt").notNull(),
|
||||
rolledOverAt: integer("rolledOverAt"),
|
||||
nextRolloverAt: integer("nextRolloverAt")
|
||||
});
|
||||
|
||||
export const limits = sqliteTable("limits", {
|
||||
limitId: text("limitId").primaryKey(),
|
||||
featureId: text("featureId").notNull(),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
value: real("value"),
|
||||
description: text("description")
|
||||
});
|
||||
|
||||
export const usageNotifications = sqliteTable("usageNotifications", {
|
||||
notificationId: integer("notificationId").primaryKey({ autoIncrement: true }),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
featureId: text("featureId").notNull(),
|
||||
limitId: text("limitId").notNull(),
|
||||
notificationType: text("notificationType").notNull(),
|
||||
sentAt: integer("sentAt").notNull()
|
||||
});
|
||||
|
||||
export const domainNamespaces = sqliteTable("domainNamespaces", {
|
||||
domainNamespaceId: text("domainNamespaceId").primaryKey(),
|
||||
domainId: text("domainId")
|
||||
.references(() => domains.domainId, {
|
||||
onDelete: "set null"
|
||||
})
|
||||
.notNull()
|
||||
});
|
||||
|
||||
export const exitNodeOrgs = sqliteTable("exitNodeOrgs", {
|
||||
exitNodeId: integer("exitNodeId")
|
||||
.notNull()
|
||||
.references(() => exitNodes.exitNodeId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const remoteExitNodes = sqliteTable("remoteExitNode", {
|
||||
remoteExitNodeId: text("id").primaryKey(),
|
||||
secretHash: text("secretHash").notNull(),
|
||||
dateCreated: text("dateCreated").notNull(),
|
||||
version: text("version"),
|
||||
secondaryVersion: text("secondaryVersion"), // This is to detect the new nodes after the transition to pangolin-node
|
||||
exitNodeId: integer("exitNodeId").references(() => exitNodes.exitNodeId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
});
|
||||
|
||||
export const remoteExitNodeSessions = sqliteTable("remoteExitNodeSession", {
|
||||
sessionId: text("id").primaryKey(),
|
||||
remoteExitNodeId: text("remoteExitNodeId")
|
||||
.notNull()
|
||||
.references(() => remoteExitNodes.remoteExitNodeId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
expiresAt: integer("expiresAt").notNull()
|
||||
});
|
||||
|
||||
export const loginPage = sqliteTable("loginPage", {
|
||||
loginPageId: integer("loginPageId").primaryKey({ autoIncrement: true }),
|
||||
subdomain: text("subdomain"),
|
||||
fullDomain: text("fullDomain"),
|
||||
exitNodeId: integer("exitNodeId").references(() => exitNodes.exitNodeId, {
|
||||
onDelete: "set null"
|
||||
}),
|
||||
domainId: text("domainId").references(() => domains.domainId, {
|
||||
onDelete: "set null"
|
||||
})
|
||||
});
|
||||
|
||||
export const loginPageOrg = sqliteTable("loginPageOrg", {
|
||||
loginPageId: integer("loginPageId")
|
||||
.notNull()
|
||||
.references(() => loginPage.loginPageId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const sessionTransferToken = sqliteTable("sessionTransferToken", {
|
||||
token: text("token").primaryKey(),
|
||||
sessionId: text("sessionId")
|
||||
.notNull()
|
||||
.references(() => sessions.sessionId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
encryptedSession: text("encryptedSession").notNull(),
|
||||
expiresAt: integer("expiresAt").notNull()
|
||||
});
|
||||
|
||||
export const actionAuditLog = sqliteTable("actionAuditLog", {
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
actorType: text("actorType").notNull(),
|
||||
actor: text("actor").notNull(),
|
||||
actorId: text("actorId").notNull(),
|
||||
action: text("action").notNull(),
|
||||
metadata: text("metadata")
|
||||
}, (table) => ([
|
||||
index("idx_actionAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_actionAuditLog_org_timestamp").on(table.orgId, table.timestamp)
|
||||
]));
|
||||
|
||||
export const accessAuditLog = sqliteTable("accessAuditLog", {
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
actorType: text("actorType"),
|
||||
actor: text("actor"),
|
||||
actorId: text("actorId"),
|
||||
resourceId: integer("resourceId"),
|
||||
ip: text("ip"),
|
||||
location: text("location"),
|
||||
type: text("type").notNull(),
|
||||
action: integer("action", { mode: "boolean" }).notNull(),
|
||||
userAgent: text("userAgent"),
|
||||
metadata: text("metadata")
|
||||
}, (table) => ([
|
||||
index("idx_identityAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_identityAuditLog_org_timestamp").on(table.orgId, table.timestamp)
|
||||
]));
|
||||
|
||||
export type Limit = InferSelectModel<typeof limits>;
|
||||
export type Account = InferSelectModel<typeof account>;
|
||||
export type Certificate = InferSelectModel<typeof certificates>;
|
||||
export type DnsChallenge = InferSelectModel<typeof dnsChallenge>;
|
||||
export type Customer = InferSelectModel<typeof customers>;
|
||||
export type Subscription = InferSelectModel<typeof subscriptions>;
|
||||
export type SubscriptionItem = InferSelectModel<typeof subscriptionItems>;
|
||||
export type Usage = InferSelectModel<typeof usage>;
|
||||
export type UsageLimit = InferSelectModel<typeof limits>;
|
||||
export type AccountDomain = InferSelectModel<typeof accountDomains>;
|
||||
export type UsageNotification = InferSelectModel<typeof usageNotifications>;
|
||||
export type RemoteExitNode = InferSelectModel<typeof remoteExitNodes>;
|
||||
export type RemoteExitNodeSession = InferSelectModel<
|
||||
typeof remoteExitNodeSessions
|
||||
>;
|
||||
export type ExitNodeOrg = InferSelectModel<typeof exitNodeOrgs>;
|
||||
export type LoginPage = InferSelectModel<typeof loginPage>;
|
||||
export type ActionAuditLog = InferSelectModel<typeof actionAuditLog>;
|
||||
export type AccessAuditLog = InferSelectModel<typeof accessAuditLog>;
|
||||
@@ -1,5 +1,7 @@
|
||||
import { randomUUID } from "crypto";
|
||||
import { InferSelectModel } from "drizzle-orm";
|
||||
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
||||
import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
|
||||
import { boolean } from "yargs";
|
||||
|
||||
export const domains = sqliteTable("domains", {
|
||||
domainId: text("domainId").primaryKey(),
|
||||
@@ -10,14 +12,41 @@ export const domains = sqliteTable("domains", {
|
||||
type: text("type"), // "ns", "cname", "wildcard"
|
||||
verified: integer("verified", { mode: "boolean" }).notNull().default(false),
|
||||
failed: integer("failed", { mode: "boolean" }).notNull().default(false),
|
||||
tries: integer("tries").notNull().default(0)
|
||||
tries: integer("tries").notNull().default(0),
|
||||
certResolver: text("certResolver"),
|
||||
preferWildcardCert: integer("preferWildcardCert", { mode: "boolean" })
|
||||
});
|
||||
|
||||
export const dnsRecords = sqliteTable("dnsRecords", {
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
domainId: text("domainId")
|
||||
.notNull()
|
||||
.references(() => domains.domainId, { onDelete: "cascade" }),
|
||||
|
||||
recordType: text("recordType").notNull(), // "NS" | "CNAME" | "A" | "TXT"
|
||||
baseDomain: text("baseDomain"),
|
||||
value: text("value").notNull(),
|
||||
verified: integer("verified", { mode: "boolean" }).notNull().default(false),
|
||||
});
|
||||
|
||||
|
||||
export const orgs = sqliteTable("orgs", {
|
||||
orgId: text("orgId").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
subnet: text("subnet"),
|
||||
createdAt: text("createdAt")
|
||||
createdAt: text("createdAt"),
|
||||
requireTwoFactor: integer("requireTwoFactor", { mode: "boolean" }),
|
||||
maxSessionLengthHours: integer("maxSessionLengthHours"), // hours
|
||||
passwordExpiryDays: integer("passwordExpiryDays"), // days
|
||||
settingsLogRetentionDaysRequest: integer("settingsLogRetentionDaysRequest") // where 0 = dont keep logs and -1 = keep forever
|
||||
.notNull()
|
||||
.default(7),
|
||||
settingsLogRetentionDaysAccess: integer("settingsLogRetentionDaysAccess")
|
||||
.notNull()
|
||||
.default(0),
|
||||
settingsLogRetentionDaysAction: integer("settingsLogRetentionDaysAction")
|
||||
.notNull()
|
||||
.default(0)
|
||||
});
|
||||
|
||||
export const userDomains = sqliteTable("userDomains", {
|
||||
@@ -72,11 +101,16 @@ export const sites = sqliteTable("sites", {
|
||||
|
||||
export const resources = sqliteTable("resources", {
|
||||
resourceId: integer("resourceId").primaryKey({ autoIncrement: true }),
|
||||
resourceGuid: text("resourceGuid", { length: 36 })
|
||||
.unique()
|
||||
.notNull()
|
||||
.$defaultFn(() => randomUUID()),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
niceId: text("niceId").notNull(),
|
||||
name: text("name").notNull(),
|
||||
subdomain: text("subdomain"),
|
||||
fullDomain: text("fullDomain"),
|
||||
@@ -105,8 +139,12 @@ export const resources = sqliteTable("resources", {
|
||||
setHostHeader: text("setHostHeader"),
|
||||
enableProxy: integer("enableProxy", { mode: "boolean" }).default(true),
|
||||
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
||||
onDelete: "cascade"
|
||||
onDelete: "set null"
|
||||
}),
|
||||
headers: text("headers"), // comma-separated list of headers to add to the request
|
||||
proxyProtocol: integer("proxyProtocol", { mode: "boolean" }).notNull().default(false),
|
||||
proxyProtocolVersion: integer("proxyProtocolVersion").default(1)
|
||||
|
||||
});
|
||||
|
||||
export const targets = sqliteTable("targets", {
|
||||
@@ -125,7 +163,39 @@ export const targets = sqliteTable("targets", {
|
||||
method: text("method"),
|
||||
port: integer("port").notNull(),
|
||||
internalPort: integer("internalPort"),
|
||||
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true)
|
||||
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
||||
path: text("path"),
|
||||
pathMatchType: text("pathMatchType"), // exact, prefix, regex
|
||||
rewritePath: text("rewritePath"), // if set, rewrites the path to this value before sending to the target
|
||||
rewritePathType: text("rewritePathType"), // exact, prefix, regex, stripPrefix
|
||||
priority: integer("priority").notNull().default(100)
|
||||
});
|
||||
|
||||
export const targetHealthCheck = sqliteTable("targetHealthCheck", {
|
||||
targetHealthCheckId: integer("targetHealthCheckId").primaryKey({
|
||||
autoIncrement: true
|
||||
}),
|
||||
targetId: integer("targetId")
|
||||
.notNull()
|
||||
.references(() => targets.targetId, { onDelete: "cascade" }),
|
||||
hcEnabled: integer("hcEnabled", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
hcPath: text("hcPath"),
|
||||
hcScheme: text("hcScheme"),
|
||||
hcMode: text("hcMode").default("http"),
|
||||
hcHostname: text("hcHostname"),
|
||||
hcPort: integer("hcPort"),
|
||||
hcInterval: integer("hcInterval").default(30), // in seconds
|
||||
hcUnhealthyInterval: integer("hcUnhealthyInterval").default(30), // in seconds
|
||||
hcTimeout: integer("hcTimeout").default(5), // in seconds
|
||||
hcHeaders: text("hcHeaders"),
|
||||
hcFollowRedirects: integer("hcFollowRedirects", {
|
||||
mode: "boolean"
|
||||
}).default(true),
|
||||
hcMethod: text("hcMethod").default("GET"),
|
||||
hcStatus: integer("hcStatus"), // http code
|
||||
hcHealth: text("hcHealth").default("unknown") // "unknown", "healthy", "unhealthy"
|
||||
});
|
||||
|
||||
export const exitNodes = sqliteTable("exitNodes", {
|
||||
@@ -139,23 +209,28 @@ export const exitNodes = sqliteTable("exitNodes", {
|
||||
maxConnections: integer("maxConnections"),
|
||||
online: integer("online", { mode: "boolean" }).notNull().default(false),
|
||||
lastPing: integer("lastPing"),
|
||||
type: text("type").default("gerbil") // gerbil, remoteExitNode
|
||||
type: text("type").default("gerbil"), // gerbil, remoteExitNode
|
||||
region: text("region")
|
||||
});
|
||||
|
||||
export const siteResources = sqliteTable("siteResources", { // this is for the clients
|
||||
siteResourceId: integer("siteResourceId").primaryKey({ autoIncrement: true }),
|
||||
export const siteResources = sqliteTable("siteResources", {
|
||||
// this is for the clients
|
||||
siteResourceId: integer("siteResourceId").primaryKey({
|
||||
autoIncrement: true
|
||||
}),
|
||||
siteId: integer("siteId")
|
||||
.notNull()
|
||||
.references(() => sites.siteId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId")
|
||||
.notNull()
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
niceId: text("niceId").notNull(),
|
||||
name: text("name").notNull(),
|
||||
protocol: text("protocol").notNull(),
|
||||
proxyPort: integer("proxyPort").notNull(),
|
||||
destinationPort: integer("destinationPort").notNull(),
|
||||
destinationIp: text("destinationIp").notNull(),
|
||||
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
||||
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true)
|
||||
});
|
||||
|
||||
export const users = sqliteTable("user", {
|
||||
@@ -183,7 +258,8 @@ export const users = sqliteTable("user", {
|
||||
termsVersion: text("termsVersion"),
|
||||
serverAdmin: integer("serverAdmin", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false)
|
||||
.default(false),
|
||||
lastPasswordChange: integer("lastPasswordChange")
|
||||
});
|
||||
|
||||
export const securityKeys = sqliteTable("webauthnCredentials", {
|
||||
@@ -259,7 +335,9 @@ export const clientSites = sqliteTable("clientSites", {
|
||||
siteId: integer("siteId")
|
||||
.notNull()
|
||||
.references(() => sites.siteId, { onDelete: "cascade" }),
|
||||
isRelayed: integer("isRelayed", { mode: "boolean" }).notNull().default(false),
|
||||
isRelayed: integer("isRelayed", { mode: "boolean" })
|
||||
.notNull()
|
||||
.default(false),
|
||||
endpoint: text("endpoint")
|
||||
});
|
||||
|
||||
@@ -286,7 +364,8 @@ export const sessions = sqliteTable("session", {
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users.userId, { onDelete: "cascade" }),
|
||||
expiresAt: integer("expiresAt").notNull()
|
||||
expiresAt: integer("expiresAt").notNull(),
|
||||
issuedAt: integer("issuedAt")
|
||||
});
|
||||
|
||||
export const newtSessions = sqliteTable("newtSession", {
|
||||
@@ -317,7 +396,10 @@ export const userOrgs = sqliteTable("userOrgs", {
|
||||
roleId: integer("roleId")
|
||||
.notNull()
|
||||
.references(() => roles.roleId),
|
||||
isOwner: integer("isOwner", { mode: "boolean" }).notNull().default(false)
|
||||
isOwner: integer("isOwner", { mode: "boolean" }).notNull().default(false),
|
||||
autoProvisioned: integer("autoProvisioned", {
|
||||
mode: "boolean"
|
||||
}).default(false)
|
||||
});
|
||||
|
||||
export const emailVerificationCodes = sqliteTable("emailVerificationCodes", {
|
||||
@@ -436,18 +518,6 @@ export const userResources = sqliteTable("userResources", {
|
||||
.references(() => resources.resourceId, { onDelete: "cascade" })
|
||||
});
|
||||
|
||||
export const limitsTable = sqliteTable("limits", {
|
||||
limitId: integer("limitId").primaryKey({ autoIncrement: true }),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
name: text("name").notNull(),
|
||||
value: integer("value").notNull(),
|
||||
description: text("description")
|
||||
});
|
||||
|
||||
export const userInvites = sqliteTable("userInvites", {
|
||||
inviteId: text("inviteId").primaryKey(),
|
||||
orgId: text("orgId")
|
||||
@@ -482,6 +552,16 @@ export const resourcePassword = sqliteTable("resourcePassword", {
|
||||
passwordHash: text("passwordHash").notNull()
|
||||
});
|
||||
|
||||
export const resourceHeaderAuth = sqliteTable("resourceHeaderAuth", {
|
||||
headerAuthId: integer("headerAuthId").primaryKey({
|
||||
autoIncrement: true
|
||||
}),
|
||||
resourceId: integer("resourceId")
|
||||
.notNull()
|
||||
.references(() => resources.resourceId, { onDelete: "cascade" }),
|
||||
headerAuthHash: text("headerAuthHash").notNull()
|
||||
});
|
||||
|
||||
export const resourceAccessToken = sqliteTable("resourceAccessToken", {
|
||||
accessTokenId: text("accessTokenId").primaryKey(),
|
||||
orgId: text("orgId")
|
||||
@@ -535,7 +615,8 @@ export const resourceSessions = sqliteTable("resourceSessions", {
|
||||
{
|
||||
onDelete: "cascade"
|
||||
}
|
||||
)
|
||||
),
|
||||
issuedAt: integer("issuedAt")
|
||||
});
|
||||
|
||||
export const resourceWhitelist = sqliteTable("resourceWhitelist", {
|
||||
@@ -603,6 +684,7 @@ export const idpOidcConfig = sqliteTable("idpOidcConfig", {
|
||||
idpOauthConfigId: integer("idpOauthConfigId").primaryKey({
|
||||
autoIncrement: true
|
||||
}),
|
||||
variant: text("variant").notNull().default("oidc"),
|
||||
idpId: integer("idpId")
|
||||
.notNull()
|
||||
.references(() => idp.idpId, { onDelete: "cascade" }),
|
||||
@@ -667,6 +749,59 @@ export const idpOrg = sqliteTable("idpOrg", {
|
||||
orgMapping: text("orgMapping")
|
||||
});
|
||||
|
||||
// Blueprint runs
|
||||
export const blueprints = sqliteTable("blueprints", {
|
||||
blueprintId: integer("blueprintId").primaryKey({
|
||||
autoIncrement: true
|
||||
}),
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
})
|
||||
.notNull(),
|
||||
name: text("name").notNull(),
|
||||
source: text("source").notNull(),
|
||||
createdAt: integer("createdAt").notNull(),
|
||||
succeeded: integer("succeeded", { mode: "boolean" }).notNull(),
|
||||
contents: text("contents").notNull(),
|
||||
message: text("message")
|
||||
});
|
||||
export const requestAuditLog = sqliteTable(
|
||||
"requestAuditLog",
|
||||
{
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId").references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
action: integer("action", { mode: "boolean" }).notNull(),
|
||||
reason: integer("reason").notNull(),
|
||||
actorType: text("actorType"),
|
||||
actor: text("actor"),
|
||||
actorId: text("actorId"),
|
||||
resourceId: integer("resourceId"),
|
||||
ip: text("ip"),
|
||||
location: text("location"),
|
||||
userAgent: text("userAgent"),
|
||||
metadata: text("metadata"),
|
||||
headers: text("headers"), // JSON blob
|
||||
query: text("query"), // JSON blob
|
||||
originalRequestURL: text("originalRequestURL"),
|
||||
scheme: text("scheme"),
|
||||
host: text("host"),
|
||||
path: text("path"),
|
||||
method: text("method"),
|
||||
tls: integer("tls", { mode: "boolean" })
|
||||
},
|
||||
(table) => [
|
||||
index("idx_requestAuditLog_timestamp").on(table.timestamp),
|
||||
index("idx_requestAuditLog_org_timestamp").on(
|
||||
table.orgId,
|
||||
table.timestamp
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
export type Org = InferSelectModel<typeof orgs>;
|
||||
export type User = InferSelectModel<typeof users>;
|
||||
export type Site = InferSelectModel<typeof sites>;
|
||||
@@ -691,18 +826,19 @@ export type RoleSite = InferSelectModel<typeof roleSites>;
|
||||
export type UserSite = InferSelectModel<typeof userSites>;
|
||||
export type RoleResource = InferSelectModel<typeof roleResources>;
|
||||
export type UserResource = InferSelectModel<typeof userResources>;
|
||||
export type Limit = InferSelectModel<typeof limitsTable>;
|
||||
export type UserInvite = InferSelectModel<typeof userInvites>;
|
||||
export type UserOrg = InferSelectModel<typeof userOrgs>;
|
||||
export type ResourceSession = InferSelectModel<typeof resourceSessions>;
|
||||
export type ResourcePincode = InferSelectModel<typeof resourcePincode>;
|
||||
export type ResourcePassword = InferSelectModel<typeof resourcePassword>;
|
||||
export type ResourceHeaderAuth = InferSelectModel<typeof resourceHeaderAuth>;
|
||||
export type ResourceOtp = InferSelectModel<typeof resourceOtp>;
|
||||
export type ResourceAccessToken = InferSelectModel<typeof resourceAccessToken>;
|
||||
export type ResourceWhitelist = InferSelectModel<typeof resourceWhitelist>;
|
||||
export type VersionMigration = InferSelectModel<typeof versionMigrations>;
|
||||
export type ResourceRule = InferSelectModel<typeof resourceRules>;
|
||||
export type Domain = InferSelectModel<typeof domains>;
|
||||
export type DnsRecord = InferSelectModel<typeof dnsRecords>;
|
||||
export type Client = InferSelectModel<typeof clients>;
|
||||
export type ClientSite = InferSelectModel<typeof clientSites>;
|
||||
export type RoleClient = InferSelectModel<typeof roleClients>;
|
||||
@@ -716,3 +852,10 @@ export type SiteResource = InferSelectModel<typeof siteResources>;
|
||||
export type OrgDomains = InferSelectModel<typeof orgDomains>;
|
||||
export type SetupToken = InferSelectModel<typeof setupTokens>;
|
||||
export type HostMeta = InferSelectModel<typeof hostMeta>;
|
||||
export type TargetHealthCheck = InferSelectModel<typeof targetHealthCheck>;
|
||||
export type IdpOidcConfig = InferSelectModel<typeof idpOidcConfig>;
|
||||
export type Blueprint = InferSelectModel<typeof blueprints>;
|
||||
export type LicenseKey = InferSelectModel<typeof licenseKey>;
|
||||
export type SecurityKey = InferSelectModel<typeof securityKeys>;
|
||||
export type WebauthnChallenge = InferSelectModel<typeof webauthnChallenge>;
|
||||
export type RequestAuditLog = InferSelectModel<typeof requestAuditLog>;
|
||||
@@ -6,11 +6,6 @@ import logger from "@server/logger";
|
||||
import SMTPTransport from "nodemailer/lib/smtp-transport";
|
||||
|
||||
function createEmailClient() {
|
||||
if (config.isManagedMode()) {
|
||||
// LETS NOT WORRY ABOUT EMAILS IN HYBRID
|
||||
return;
|
||||
}
|
||||
|
||||
const emailConfig = config.getRawConfig().email;
|
||||
if (!emailConfig) {
|
||||
logger.warn(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user