mirror of
https://github.com/Athou/commafeed.git
synced 2026-11-03 19:05:03 +00:00
Compare commits
574 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e1e5257b4 | ||
|
|
bc6e767953 | ||
|
|
b9eceaae73 | ||
|
|
8ad9ba7d74 | ||
|
|
10bb4b7936 | ||
|
|
ab3127cef9 | ||
|
|
5d64e2f21e | ||
|
|
e404c9ce3b | ||
|
|
0c5a71650c | ||
|
|
8ce9eb8537 | ||
|
|
1ce0e4af97 | ||
|
|
44ad42a8a5 | ||
|
|
f213726c40 | ||
|
|
972d424846 | ||
|
|
6049263137 | ||
|
|
ae2dc7f066 | ||
|
|
503d129f22 | ||
|
|
543ec3bbb1 | ||
|
|
bed45127c4 | ||
|
|
71f10b0a62 | ||
|
|
cb235289c4 | ||
|
|
0b07c65320 | ||
|
|
868f65d7c9 | ||
|
|
07715383f4 | ||
|
|
29d10debdb | ||
|
|
cd640da960 | ||
|
|
56ecb4a2f4 | ||
|
|
00161fd549 | ||
|
|
a602ce17cd | ||
|
|
672588d08b | ||
|
|
5fa2579275 | ||
|
|
09bc317797 | ||
|
|
440c1ada50 | ||
|
|
911a5ca099 | ||
|
|
65017f6b76 | ||
|
|
64fb5ef3a2 | ||
|
|
dda389a50f | ||
|
|
419ad4fb6a | ||
|
|
ebae46f06b | ||
|
|
ac25accb31 | ||
|
|
3c7eb90e50 | ||
|
|
4b3973f3fa | ||
|
|
6ddbe40c3c | ||
|
|
d5164750e4 | ||
|
|
822fbd8add | ||
|
|
3a341d0707 | ||
|
|
23884fcbda | ||
|
|
3b16674f98 | ||
|
|
d5eb3e1bb1 | ||
|
|
8d47b38fd4 | ||
|
|
04fb3282fa | ||
|
|
bcce130b82 | ||
|
|
e5d336f6ba | ||
|
|
2d741f6e1e | ||
|
|
2968dff118 | ||
|
|
0c244ec154 | ||
|
|
34cd337992 | ||
|
|
1703cb7b93 | ||
|
|
dc89faa4a1 | ||
|
|
3eccfe8ccc | ||
|
|
6e34f6831c | ||
|
|
b7ebcd6a23 | ||
|
|
8b7efe056d | ||
|
|
87cb392516 | ||
|
|
aa11cb48f2 | ||
|
|
36a29a393c | ||
|
|
99f1b45866 | ||
|
|
9e8d529af3 | ||
|
|
bb80641b40 | ||
|
|
a2ed16c6fd | ||
|
|
4f10f57837 | ||
|
|
28f40cd6fe | ||
|
|
89a84a0c83 | ||
|
|
ebcda50a34 | ||
|
|
8640e62b77 | ||
|
|
d0418eea89 | ||
|
|
41ba067daf | ||
|
|
53346997b6 | ||
|
|
87a632761e | ||
|
|
998ebc43a3 | ||
|
|
945e312c41 | ||
|
|
963a562100 | ||
|
|
4be961b68b | ||
|
|
02a9140c13 | ||
|
|
5ea60ce6d6 | ||
|
|
e9e7be0fc6 | ||
|
|
60c30f2683 | ||
|
|
a17e69d37d | ||
|
|
157f75d33e | ||
|
|
30a14c73ff | ||
|
|
27cece3afb | ||
|
|
8124ecb51f | ||
|
|
e67c4c8670 | ||
|
|
fcc6798d63 | ||
|
|
d313ebfc69 | ||
|
|
6edb8f00f6 | ||
|
|
98a261d457 | ||
|
|
e97a69f475 | ||
|
|
e9dc284b26 | ||
|
|
856c52c64b | ||
|
|
386a4a32ef | ||
|
|
dbdb40ff01 | ||
|
|
1bd9b71215 | ||
|
|
f4dc279ec9 | ||
|
|
ca8438623d | ||
|
|
b81aac71f5 | ||
|
|
a4e0d28fa2 | ||
|
|
56d4e4bbb1 | ||
|
|
af1d10529b | ||
|
|
a5f84a3f6d | ||
|
|
69dfbc81cc | ||
|
|
34408ccdb0 | ||
|
|
b0522a6e5d | ||
|
|
2a559a07c0 | ||
|
|
bdf2a6a915 | ||
|
|
e814f75872 | ||
|
|
c0e0791854 | ||
|
|
17dbdb66bf | ||
|
|
6e3e9add36 | ||
|
|
5b25011853 | ||
|
|
804b24b2d6 | ||
|
|
de98b0f7c2 | ||
|
|
709de70fa9 | ||
|
|
1b7bc11f9d | ||
|
|
bbcaacf3dd | ||
|
|
e816b1262c | ||
|
|
fc019333dc | ||
|
|
56b0ddbc34 | ||
|
|
bb74d27d52 | ||
|
|
7b1d19ca71 | ||
|
|
af961678bd | ||
|
|
1579242644 | ||
|
|
2a45f5c596 | ||
|
|
c4560c49b0 | ||
|
|
2b7f75d9ef | ||
|
|
5f68bcbd46 | ||
|
|
c93c072259 | ||
|
|
516344a993 | ||
|
|
4d42fe5a0b | ||
|
|
47bf132fff | ||
|
|
04a9d48505 | ||
|
|
3716ddcf15 | ||
|
|
6c3ab40cb6 | ||
|
|
b7270974e5 | ||
|
|
9bfc53e77a | ||
|
|
f34fac8d17 | ||
|
|
555c11649e | ||
|
|
c308c5d606 | ||
|
|
54e9615994 | ||
|
|
b0b3b323fd | ||
|
|
f740a0b8ba | ||
|
|
e154675e72 | ||
|
|
2b3d3261de | ||
|
|
fab525ca56 | ||
|
|
1c273d1c1a | ||
|
|
90d684367c | ||
|
|
1ffc544ab0 | ||
|
|
cde0cceee1 | ||
|
|
1604fbc55c | ||
|
|
6f586e8866 | ||
|
|
c53455ad61 | ||
|
|
77b3c609f3 | ||
|
|
3b84598d99 | ||
|
|
6f536c0981 | ||
|
|
1f881ea252 | ||
|
|
b14df1b3cb | ||
|
|
e13763baa3 | ||
|
|
502ef67a71 | ||
|
|
05cab626df | ||
|
|
c7d54af7ad | ||
|
|
ad195fcd80 | ||
|
|
b87c68d598 | ||
|
|
33af37ed2e | ||
|
|
c4113fc92b | ||
|
|
ed40025d26 | ||
|
|
752008a551 | ||
|
|
a8bf970dca | ||
|
|
5b94bcdfdd | ||
|
|
a66a0e9485 | ||
|
|
80755e15b8 | ||
|
|
8cede0c6e0 | ||
|
|
9556f0f7d2 | ||
|
|
1b80f3060c | ||
|
|
00811f0be3 | ||
|
|
0fdfc2c59c | ||
|
|
8d25562a76 | ||
|
|
1d0d9d4be6 | ||
|
|
9ed4559625 | ||
|
|
2a53e8f15d | ||
|
|
15fbd18f31 | ||
|
|
2c248a7ca1 | ||
|
|
94d8fdb4ab | ||
|
|
3596439ed4 | ||
|
|
bc732a52ce | ||
|
|
ef096899a2 | ||
|
|
bf4bcf740e | ||
|
|
679281ac26 | ||
|
|
bde3d1408b | ||
|
|
3621a96d3f | ||
|
|
6583ad114f | ||
|
|
f4e42165bf | ||
|
|
00d7be735a | ||
|
|
1388fba8e4 | ||
|
|
c43644861f | ||
|
|
831ca599b8 | ||
|
|
43fbd03292 | ||
|
|
1efd04f6c5 | ||
|
|
e89ccfd74b | ||
|
|
622486160c | ||
|
|
6d172cae9e | ||
|
|
91b60fb147 | ||
|
|
3f9b7f48d5 | ||
|
|
3599fdec65 | ||
|
|
00e86974b3 | ||
|
|
2aa897eb80 | ||
|
|
ce9706b860 | ||
|
|
e140dfe556 | ||
|
|
4a1b845ac2 | ||
|
|
573f8af57e | ||
|
|
33445c93e8 | ||
|
|
f7fcb659f7 | ||
|
|
b0aa723c2f | ||
|
|
48dca41738 | ||
|
|
873d6f487f | ||
|
|
c8d73b129e | ||
|
|
c63e9e1cd2 | ||
|
|
def2ad84bb | ||
|
|
52510e9817 | ||
|
|
69a95488ce | ||
|
|
636841f647 | ||
|
|
1ea521236c | ||
|
|
6966efeda5 | ||
|
|
66ad0c3548 | ||
|
|
e061ccbf79 | ||
|
|
30cc6a111d | ||
|
|
8416ce5124 | ||
|
|
0cacfe391b | ||
|
|
c0eaab48cd | ||
|
|
c696bc3545 | ||
|
|
72505954a9 | ||
|
|
49159dba5c | ||
|
|
41e2d89abc | ||
|
|
6e7de97d93 | ||
|
|
2f20e6b498 | ||
|
|
ecf9158fd7 | ||
|
|
dc7e7321f3 | ||
|
|
0f087ad2a0 | ||
|
|
ff19a6e9eb | ||
|
|
8cec0c0779 | ||
|
|
314384f8e7 | ||
|
|
6c75ad95ad | ||
|
|
76e3b3caff | ||
|
|
c8f71480c9 | ||
|
|
9172a0cf9c | ||
|
|
eb476c6023 | ||
|
|
da4f3bd38e | ||
|
|
c65d628a36 | ||
|
|
589b8c3afc | ||
|
|
2684051da0 | ||
|
|
200db68d05 | ||
|
|
f6d8d32a01 | ||
|
|
72d5af5bb0 | ||
|
|
aabbc54cbb | ||
|
|
09b523bf56 | ||
|
|
5dc7f522bf | ||
|
|
fd58a42824 | ||
|
|
0a6d1c85ed | ||
|
|
13f84a260c | ||
|
|
4132ad9a97 | ||
|
|
1faba92ecc | ||
|
|
b93fc86663 | ||
|
|
7123036e8d | ||
|
|
cce4ea4dc6 | ||
|
|
b8f7df1555 | ||
|
|
ba8cc0477c | ||
|
|
010026bc88 | ||
|
|
a1ba34caf2 | ||
|
|
1214380bee | ||
|
|
03eb09c68c | ||
|
|
055d503862 | ||
|
|
5755ff762b | ||
|
|
88e24787e8 | ||
|
|
ed32d07ac4 | ||
|
|
3a917fcebe | ||
|
|
3535068ca8 | ||
|
|
4c39d4b96b | ||
|
|
8e864c6793 | ||
|
|
aeffecced3 | ||
|
|
4be42dc1e2 | ||
|
|
bdf6c62c29 | ||
|
|
a4592e5199 | ||
|
|
a5268f082d | ||
|
|
b556e72922 | ||
|
|
3602d2533a | ||
|
|
681f2c766a | ||
|
|
6e0a136cd1 | ||
|
|
9e9945a1cc | ||
|
|
3368cead8b | ||
|
|
a7b5126b4a | ||
|
|
a9ef1a03dc | ||
|
|
bc0ec8dbfa | ||
|
|
7bef009922 | ||
|
|
9a467bc27b | ||
|
|
e3934c9403 | ||
|
|
af337aa4d0 | ||
|
|
313d3a01ec | ||
|
|
feb9876cf5 | ||
|
|
9c3a5cb820 | ||
|
|
e219f781bf | ||
|
|
21ecd6ae05 | ||
|
|
2449902c3d | ||
|
|
c1a55037ba | ||
|
|
646a8122c0 | ||
|
|
edc4e6c508 | ||
|
|
5ddeb7b156 | ||
|
|
306624e55f | ||
|
|
6a9ca65cbc | ||
|
|
7db0026a0c | ||
|
|
7358705248 | ||
|
|
0b9ee2eec9 | ||
|
|
42eaf7fc39 | ||
|
|
6783cac9b4 | ||
|
|
628106ce88 | ||
|
|
1ce69b31a7 | ||
|
|
912ac11842 | ||
|
|
5f2fad560c | ||
|
|
b300f364a7 | ||
|
|
049ec41d13 | ||
|
|
f0d17bc84e | ||
|
|
cc442d7409 | ||
|
|
80bac26f21 | ||
|
|
015c39e6f4 | ||
|
|
e0ec3a4ebd | ||
|
|
a022de5cc3 | ||
|
|
a7b5e1e18c | ||
|
|
b8695df1c8 | ||
|
|
5e4382d1d2 | ||
|
|
ce983f4906 | ||
|
|
4a8be29616 | ||
|
|
1622eb642a | ||
|
|
422d992484 | ||
|
|
1065af1233 | ||
|
|
dde39d83be | ||
|
|
94fe7617bf | ||
|
|
e781d85b7c | ||
|
|
c30c9ca380 | ||
|
|
c395916af9 | ||
|
|
1a4037e360 | ||
|
|
f207bfaddd | ||
|
|
3dd298c0c8 | ||
|
|
8e2e4da7c3 | ||
|
|
418e3c109c | ||
|
|
cfda63a609 | ||
|
|
ba68276bfb | ||
|
|
97c700024a | ||
|
|
d4f67d726c | ||
|
|
ea87fa3e5a | ||
|
|
d12d247b3e | ||
|
|
c4a23915bd | ||
|
|
8645c57d13 | ||
|
|
b170e0bc17 | ||
|
|
4199f514f9 | ||
|
|
c96efb3bb4 | ||
|
|
d5571e0196 | ||
|
|
9f7f87b4ae | ||
|
|
4b03fce85d | ||
|
|
4b28d1c635 | ||
|
|
a5e803177f | ||
|
|
9462f284a4 | ||
|
|
4b0f6bd61b | ||
|
|
d6c85214ef | ||
|
|
de770cf801 | ||
|
|
dae0f740c2 | ||
|
|
9452c3e74c | ||
|
|
f826f1d543 | ||
|
|
fd13c80e5a | ||
|
|
75871348d5 | ||
|
|
0140e88595 | ||
|
|
e620b1254b | ||
|
|
77cfcf6c58 | ||
|
|
04e9df3d0a | ||
|
|
a953134089 | ||
|
|
88b9c0d783 | ||
|
|
ff7e0ba95b | ||
|
|
53dfbcaf00 | ||
|
|
d8fca22c00 | ||
|
|
4fb5963bd9 | ||
|
|
862d81f446 | ||
|
|
8ae7943b94 | ||
|
|
46e947d779 | ||
|
|
7780d6020f | ||
|
|
e5803b46f2 | ||
|
|
d776090298 | ||
|
|
f2f3111d49 | ||
|
|
dff1b957cd | ||
|
|
b1ec50c3cb | ||
|
|
85aa188287 | ||
|
|
e7d6526da9 | ||
|
|
d67c6fcc00 | ||
|
|
d9bf084300 | ||
|
|
da3977b0e2 | ||
|
|
7df930bccc | ||
|
|
11f73a1a53 | ||
|
|
2bbcd55e48 | ||
|
|
43890b8d5c | ||
|
|
b6b8e3741b | ||
|
|
c39f00c336 | ||
|
|
e48eaacfef | ||
|
|
6d97691388 | ||
|
|
d64cc996bc | ||
|
|
617d66c9b9 | ||
|
|
0fc50d2105 | ||
|
|
2bb9f28569 | ||
|
|
c1580b8359 | ||
|
|
dde235825d | ||
|
|
eac13b4025 | ||
|
|
59cc9c2706 | ||
|
|
40e20a0d33 | ||
|
|
a42679acaa | ||
|
|
fd2e8fcdb8 | ||
|
|
ebd5a15152 | ||
|
|
6cdd110304 | ||
|
|
3181cda2e0 | ||
|
|
2659c7fc02 | ||
|
|
5747ae3429 | ||
|
|
8d60be0e3f | ||
|
|
7e3f801a5a | ||
|
|
687ef53c65 | ||
|
|
a1fe9e727e | ||
|
|
6d625c88d3 | ||
|
|
c314e2de6b | ||
|
|
bd08b95390 | ||
|
|
aed0cca7e1 | ||
|
|
7d7761fb8d | ||
|
|
6d2fb5acc2 | ||
|
|
ec35d846cf | ||
|
|
1d23907652 | ||
|
|
efc6c10ace | ||
|
|
47a8ad5244 | ||
|
|
5d879c4619 | ||
|
|
6e0dd3d064 | ||
|
|
4657a403d0 | ||
|
|
bf09a07fe2 | ||
|
|
927802ca88 | ||
|
|
3d5bc9ef0e | ||
|
|
706ad7e44d | ||
|
|
88206f521b | ||
|
|
af786b4c11 | ||
|
|
d4c749c997 | ||
|
|
b5aa25cd0b | ||
|
|
ae49fb6dad | ||
|
|
3e24d17951 | ||
|
|
22030e6907 | ||
|
|
39fdcb9af3 | ||
|
|
866998f98b | ||
|
|
0fa71f76e8 | ||
|
|
317f655128 | ||
|
|
a871426f31 | ||
|
|
2caf9ff38a | ||
|
|
1de3a57d50 | ||
|
|
bed1355d63 | ||
|
|
189f9b4f26 | ||
|
|
931b5a22e6 | ||
|
|
4c9e0a8b74 | ||
|
|
589472314b | ||
|
|
f11657fdee | ||
|
|
e4ec081357 | ||
|
|
9e55527a2b | ||
|
|
cca70ffcec | ||
|
|
2a6a717ef2 | ||
|
|
11043554c2 | ||
|
|
cdbef468d7 | ||
|
|
4705b75580 | ||
|
|
245ccf889e | ||
|
|
2ad0a3d622 | ||
|
|
e775f774b5 | ||
|
|
ad2aec44e5 | ||
|
|
11d3effc28 | ||
|
|
2ef12e2868 | ||
|
|
ed8c5ce1ea | ||
|
|
33e507efe5 | ||
|
|
c425f5cf6a | ||
|
|
fc76d7e609 | ||
|
|
1b24bf33ed | ||
|
|
16036897cb | ||
|
|
58ff378735 | ||
|
|
1cee04a233 | ||
|
|
ac11a0efb8 | ||
|
|
f2ea1e3f7a | ||
|
|
76dbbdfbf9 | ||
|
|
153970c146 | ||
|
|
c21287e642 | ||
|
|
284942a82e | ||
|
|
e796916e73 | ||
|
|
004db1762c | ||
|
|
8e05ba8820 | ||
|
|
f4f386b5e5 | ||
|
|
ecbf8bec23 | ||
|
|
5d8c09ccda | ||
|
|
47c5c3d8a0 | ||
|
|
3ddce16d5b | ||
|
|
acefdc44d9 | ||
|
|
d05c5b9d7f | ||
|
|
5d1237d1f4 | ||
|
|
6bac8631ac | ||
|
|
2c803327ad | ||
|
|
451ae5bc51 | ||
|
|
f41ce8c878 | ||
|
|
177c54c813 | ||
|
|
3765e32fd4 | ||
|
|
aab7a16d18 | ||
|
|
f2463af63c | ||
|
|
212c2c3b56 | ||
|
|
3ab00b0cdd | ||
|
|
fad85e9299 | ||
|
|
3cd5e203e2 | ||
|
|
7b081fa870 | ||
|
|
5ce22051d4 | ||
|
|
1e59489fa5 | ||
|
|
1e691b1255 | ||
|
|
61e1bef63f | ||
|
|
46dbb78fbf | ||
|
|
99890707b3 | ||
|
|
f54c841fdc | ||
|
|
e2a6009ee9 | ||
|
|
a34dd15040 | ||
|
|
24c934003d | ||
|
|
5300e1a245 | ||
|
|
90381c670b | ||
|
|
23edea93db | ||
|
|
a51712e363 | ||
|
|
4310e979e1 | ||
|
|
f690b76d87 | ||
|
|
ac29594b67 | ||
|
|
93f535bb87 | ||
|
|
076eb3cf42 | ||
|
|
7b2e0fffbd | ||
|
|
8eaab0dbc3 | ||
|
|
eaa5bc896e | ||
|
|
42d1db5fc3 | ||
|
|
78c017ddaf | ||
|
|
231551d743 | ||
|
|
d0984eaba7 | ||
|
|
15854a72d1 | ||
|
|
7fd2bf0eda | ||
|
|
6a10a2167e | ||
|
|
1ba99d255c | ||
|
|
ff1c2947b6 | ||
|
|
a690d2e0db | ||
|
|
a3df327396 | ||
|
|
ede0016d8e | ||
|
|
c19b091795 | ||
|
|
9e62c8b9f3 | ||
|
|
9f30dc181c | ||
|
|
37fe44f860 | ||
|
|
68aaab8467 | ||
|
|
b951ed1fcd | ||
|
|
9bd9dc568a | ||
|
|
29e4356fee | ||
|
|
0ed31eaa99 | ||
|
|
1e9869b217 | ||
|
|
78cfc2c827 | ||
|
|
a6e5a0d125 | ||
|
|
ea13aecd27 | ||
|
|
d838e8f28f | ||
|
|
c9a7b9e17c | ||
|
|
8fe2d0bc0e | ||
|
|
71e2f1e1e6 | ||
|
|
1ce9d1b9b2 | ||
|
|
b3d6ae467f | ||
|
|
da8d720dc4 | ||
|
|
824c38f8ce | ||
|
|
b0579a70d8 | ||
|
|
f9fe2d0976 |
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@@ -7,6 +7,7 @@ exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- enhancement
|
||||
- feature-request
|
||||
- bug
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
|
||||
52
.github/workflows/ci.yml
vendored
52
.github/workflows/ci.yml
vendored
@@ -23,18 +23,24 @@ jobs:
|
||||
steps:
|
||||
# Checkout
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Setup
|
||||
- name: Set up GraalVM
|
||||
uses: graalvm/setup-graalvm@54b4f5a65c1a84b2fdfdc2078fe43df32819e4b1 # v1
|
||||
uses: graalvm/setup-graalvm@0def53c0fd8534bc13416c9469f5be45265824fd # v1.6.3
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: "graalvm"
|
||||
cache: "maven"
|
||||
|
||||
- name: Set up NodeJS cache
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||
with:
|
||||
cache: "npm"
|
||||
cache-dependency-path: 'commafeed-client/package-lock.json'
|
||||
|
||||
- name: Install Playwright dependencies
|
||||
run: sudo apt-get install -y libgbm1
|
||||
if: matrix.os != 'windows-latest'
|
||||
@@ -67,20 +73,20 @@ jobs:
|
||||
|
||||
# Upload artifacts
|
||||
- name: Upload cross-platform app
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: matrix.os == 'ubuntu-latest' # we only need to upload the cross-platform artifact once per database
|
||||
with:
|
||||
name: commafeed-${{ matrix.database }}-jvm
|
||||
path: commafeed-server/target/commafeed-*.zip
|
||||
|
||||
- name: Upload native executable
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: commafeed-${{ matrix.database }}-${{ runner.os }}-${{ runner.arch }}
|
||||
path: commafeed-server/target/commafeed-*-runner*
|
||||
|
||||
- name: Upload pages
|
||||
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4
|
||||
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.database == 'h2' # we only need to upload the pages once
|
||||
with:
|
||||
path: target/pages
|
||||
@@ -98,23 +104,23 @@ jobs:
|
||||
steps:
|
||||
# Checkout
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Setup
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
|
||||
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Install required packages
|
||||
run: sudo apt-get install -y rename unzip
|
||||
|
||||
# Prepare artifacts
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: commafeed-${{ matrix.database }}-*
|
||||
path: ./artifacts
|
||||
@@ -135,7 +141,7 @@ jobs:
|
||||
|
||||
# Docker
|
||||
- name: Login to Container Registry
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
if: ${{ env.DOCKERHUB_USERNAME != '' }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
@@ -143,7 +149,7 @@ jobs:
|
||||
|
||||
## build but don't push for PRs and renovate
|
||||
- name: Docker build - native
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
with:
|
||||
context: .
|
||||
file: commafeed-server/src/main/docker/Dockerfile.native
|
||||
@@ -151,7 +157,7 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
- name: Docker build - jvm
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
with:
|
||||
context: .
|
||||
file: commafeed-server/src/main/docker/Dockerfile.jvm
|
||||
@@ -160,7 +166,7 @@ jobs:
|
||||
|
||||
## build and push tag
|
||||
- name: Docker build and push tag - native
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
with:
|
||||
context: .
|
||||
@@ -172,7 +178,7 @@ jobs:
|
||||
athou/commafeed:${{ github.ref_name }}-${{ matrix.database }}
|
||||
|
||||
- name: Docker build and push tag - jvm
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
with:
|
||||
context: .
|
||||
@@ -185,7 +191,7 @@ jobs:
|
||||
|
||||
## build and push master
|
||||
- name: Docker build and push master - native
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
with:
|
||||
context: .
|
||||
@@ -195,7 +201,7 @@ jobs:
|
||||
tags: athou/commafeed:master-${{ matrix.database }}
|
||||
|
||||
- name: Docker build and push master - jvm
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
with:
|
||||
context: .
|
||||
@@ -215,12 +221,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: commafeed-*
|
||||
path: ./artifacts
|
||||
@@ -230,13 +236,13 @@ jobs:
|
||||
run: chmod +x artifacts/*-runner
|
||||
|
||||
- name: Extract Changelog Entry
|
||||
uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656 # v2
|
||||
uses: mindsers/changelog-reader-action@1faaf50aa09d5793d9a100819973df801febfb31 # v2.4.0
|
||||
id: changelog_reader
|
||||
with:
|
||||
version: ${{ github.ref_name }}
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
|
||||
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1.21.0
|
||||
with:
|
||||
name: CommaFeed ${{ github.ref_name }}
|
||||
body: ${{ steps.changelog_reader.outputs.changes }}
|
||||
@@ -249,12 +255,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Update Docker Hub Description
|
||||
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5
|
||||
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -274,5 +280,5 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
|
||||
- uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||
id: deployment
|
||||
|
||||
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1,3 +1,3 @@
|
||||
wrapperVersion=3.3.4
|
||||
distributionType=only-script
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
|
||||
|
||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -1,5 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## [7.2.1]
|
||||
|
||||
- correctly handle favicons hosted at the root of the domain for feeds with non-default ports
|
||||
- prevent XXS injections in third party apps. The CommaFeed React client was already stripping malicious "javascript:" URLs, they are now filtered during feed parsing and no longer stored in the database/served through the REST API.
|
||||
|
||||
## [7.2.0]
|
||||
|
||||
- Add support for icons declared in feeds. This is useful for feeds exposed by RSS bridges (#2048)
|
||||
- Search now also works for starred entries (#2217)
|
||||
- The error message when subscribing to a feed is now properly displayed again
|
||||
- Small performance improvements to the feed refresh engine
|
||||
- Removed the Pocket sharing feature because the Pocket service has been discontinued
|
||||
- Prevent the image proxy feature to access any URL to avoid SSRF attacks
|
||||
- Strengthened the SSRF protection by also blocking ULA and CGNAT ranges
|
||||
- Prevent DDOS attacks by filtering OPML files during imports
|
||||
|
||||
## [7.1.0]
|
||||
|
||||
- Display the unread count in the header on mobile, since the tree is hidden by default and the unread count is not visible otherwise (#2055)
|
||||
- The feed refresh engine is now a little bit more performant (#2089)
|
||||
- On shutdown, give the feed refresh engine some time to finish refreshing feeds before killing it. This is controlled by the new `commafeed.shutdown-timeout` setting, which defaults to 2 seconds
|
||||
|
||||
## [7.0.0]
|
||||
|
||||
- Replaced the JEXL filter expression for marking feed entries as read automatically with a user-friendly visual query builder. Expressions are now evaluated with Common Expression Language, which is safer than JEXL and sanboxed by default.
|
||||
|
||||
@@ -70,8 +70,8 @@ memory usage.
|
||||
./mvnw clean package [-P<database> [-Pnative]] [-DskipTests]
|
||||
|
||||
- `<database>` can be one of `h2`, `postgresql`, `mysql` or `mariadb`. The default is `h2`.
|
||||
- `-Pnative` compiles the application to native code. This requires GraalVM to be installed (`GRAALVM_HOME` environment
|
||||
variable pointing to a GraalVM installation).
|
||||
- `-Pnative` compiles the application to native code. This requires either GraalVM to be installed (`GRAALVM_HOME` environment
|
||||
variable pointing to a GraalVM installation) or a container environment to be available (docker/podman/...).
|
||||
- `-DskipTests` to speed up the build process by skipping tests.
|
||||
|
||||
When the build is complete:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
cd commafeed-client && npx lint-staged
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.4.2/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/2.5.6/schema.json",
|
||||
"formatter": {
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 4,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { LinguiConfig } from "@lingui/conf"
|
||||
import { formatter } from "@lingui/format-po"
|
||||
|
||||
const config: LinguiConfig = {
|
||||
locales: [
|
||||
@@ -38,11 +39,9 @@ const config: LinguiConfig = {
|
||||
exclude: ["src/locales/**"],
|
||||
},
|
||||
],
|
||||
format: "po",
|
||||
formatOptions: {
|
||||
origins: true,
|
||||
format: formatter({
|
||||
lineNumbers: false,
|
||||
},
|
||||
}),
|
||||
sourceLocale: "en",
|
||||
fallbackLocales: {
|
||||
default: "en",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export default {
|
||||
"src/**/*.{js,jsx,ts,tsx}": () => ["npm run i18n:extract", "git diff --exit-code commafeed-client/src/locales/en/messages.po"],
|
||||
}
|
||||
5815
commafeed-client/package-lock.json
generated
5815
commafeed-client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,75 +12,73 @@
|
||||
"test:ci": "vitest run",
|
||||
"lint": "biome check",
|
||||
"lint:fix": "biome check --write",
|
||||
"i18n:extract": "lingui extract --clean",
|
||||
"prepare": "cd .. && husky ./commafeed-client/.husky"
|
||||
"i18n:extract": "lingui extract --clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@fontsource/open-sans": "^5.2.7",
|
||||
"@lingui/core": "^5.9.1",
|
||||
"@lingui/react": "^5.9.1",
|
||||
"@mantine/core": "^8.3.15",
|
||||
"@mantine/form": "^8.3.15",
|
||||
"@mantine/hooks": "^8.3.15",
|
||||
"@mantine/modals": "^8.3.15",
|
||||
"@mantine/notifications": "^8.3.15",
|
||||
"@mantine/spotlight": "^8.3.15",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@react-querybuilder/mantine": "^8.14.0",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"axios": "^1.13.5",
|
||||
"dayjs": "^1.11.19",
|
||||
"escape-string-regexp": "^5.0.0",
|
||||
"interweave": "^13.1.1",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"mousetrap": "^1.6.5",
|
||||
"react": "^19.2.4",
|
||||
"react-async-hook": "^4.0.0",
|
||||
"react-contexify": "^6.0.0",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-draggable": "^4.5.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-infinite-scroller": "^1.2.6",
|
||||
"react-querybuilder": "^8.14.0",
|
||||
"react-redux": "^9.2.0",
|
||||
"react-router-dom": "^7.13.0",
|
||||
"react-swipeable": "^7.0.2",
|
||||
"style-to-object": "^1.0.14",
|
||||
"throttle-debounce": "^5.0.2",
|
||||
"tinycon": "^0.6.8",
|
||||
"tss-react": "^4.9.20",
|
||||
"websocket-heartbeat-js": "^1.1.3"
|
||||
"@emotion/react": "11.14.0",
|
||||
"@fontsource/open-sans": "5.3.0",
|
||||
"@lingui/core": "6.6.0",
|
||||
"@lingui/react": "6.6.0",
|
||||
"@mantine/core": "9.5.0",
|
||||
"@mantine/dates": "9.5.0",
|
||||
"@mantine/form": "9.5.0",
|
||||
"@mantine/hooks": "9.5.0",
|
||||
"@mantine/modals": "9.5.0",
|
||||
"@mantine/notifications": "9.5.0",
|
||||
"@mantine/spotlight": "9.5.0",
|
||||
"@monaco-editor/react": "4.7.0",
|
||||
"@react-querybuilder/mantine": "8.21.2",
|
||||
"@reduxjs/toolkit": "2.12.0",
|
||||
"@rolldown/plugin-babel": "0.2.3",
|
||||
"axios": "1.19.0",
|
||||
"dayjs": "1.11.21",
|
||||
"escape-string-regexp": "5.0.0",
|
||||
"interweave": "13.1.1",
|
||||
"monaco-editor": "0.56.0",
|
||||
"mousetrap": "1.6.5",
|
||||
"react": "19.2.8",
|
||||
"react-async-hook": "4.0.0",
|
||||
"react-contexify": "6.0.0",
|
||||
"react-dom": "19.2.8",
|
||||
"react-draggable": "4.7.1",
|
||||
"react-icons": "5.7.0",
|
||||
"react-infinite-scroller": "1.2.6",
|
||||
"react-querybuilder": "8.21.2",
|
||||
"react-redux": "9.3.0",
|
||||
"react-router-dom": "7.18.2",
|
||||
"react-swipeable": "7.0.2",
|
||||
"style-to-object": "2.0.2",
|
||||
"throttle-debounce": "5.0.2",
|
||||
"tinycon": "0.6.8",
|
||||
"tss-react": "4.9.21",
|
||||
"websocket-heartbeat-js": "1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.4.2",
|
||||
"@lingui/babel-plugin-lingui-macro": "^5.9.1",
|
||||
"@lingui/cli": "^5.9.1",
|
||||
"@lingui/vite-plugin": "^5.9.1",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-infinite-scroller": "^1.2.5",
|
||||
"@types/throttle-debounce": "^5.0.2",
|
||||
"@types/tinycon": "^0.6.7",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"@biomejs/biome": "2.5.6",
|
||||
"@lingui/babel-plugin-lingui-macro": "6.6.0",
|
||||
"@lingui/cli": "6.6.0",
|
||||
"@lingui/vite-plugin": "6.6.0",
|
||||
"@testing-library/jest-dom": "7.0.0",
|
||||
"@testing-library/react": "16.3.2",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/mousetrap": "1.6.15",
|
||||
"@types/react": "19.2.18",
|
||||
"@types/react-dom": "19.2.4",
|
||||
"@types/react-infinite-scroller": "1.2.5",
|
||||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/tinycon": "0.6.7",
|
||||
"@vitejs/plugin-react": "6.0.5",
|
||||
"babel-plugin-react-compiler": "1.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^28.1.0",
|
||||
"lint-staged": "^16.2.7",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.3.1",
|
||||
"vite-plugin-checker": "^0.12.0",
|
||||
"vite-tsconfig-paths": "^6.1.1",
|
||||
"vitest": "^4.0.18",
|
||||
"yaml": "^2.8.2"
|
||||
"jsdom": "30.0.1",
|
||||
"typescript": "7.0.2",
|
||||
"vite": "8.2.0",
|
||||
"vite-plugin-checker": "0.14.5",
|
||||
"vitest": "4.1.10",
|
||||
"yaml": "2.9.0"
|
||||
},
|
||||
"overrides": {
|
||||
"react-infinite-scroller": {
|
||||
"react": "^19.2.4"
|
||||
"react": "19.2.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
<parent>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.2.1</version>
|
||||
</parent>
|
||||
<artifactId>commafeed-client</artifactId>
|
||||
<name>CommaFeed Client</name>
|
||||
|
||||
<properties>
|
||||
<!-- renovate: datasource=node-version depName=node -->
|
||||
<node.version>v24.13.1</node.version>
|
||||
<node.version>v24.18.1</node.version>
|
||||
<!-- renovate: datasource=npm depName=npm -->
|
||||
<npm.version>11.10.0</npm.version>
|
||||
<npm.version>12.0.2</npm.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -23,7 +23,7 @@
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.2</version>
|
||||
<?m2e ignore?>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -72,7 +72,7 @@
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy web interface to resources</id>
|
||||
@@ -94,4 +94,49 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<!-- This profile is used to kill the Biome process on Windows -->
|
||||
<!-- npm ci can fail if Biome is running (e.g., in the IDE) because it locks some files -->
|
||||
<profile>
|
||||
<id>kill-biome</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>Windows</family>
|
||||
</os>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.6.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>kill-biome</id>
|
||||
<phase>initialize</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>taskkill</executable>
|
||||
<arguments>
|
||||
<argument>/F</argument>
|
||||
<argument>/IM</argument>
|
||||
<argument>biome.exe</argument>
|
||||
</arguments>
|
||||
<successCodes>
|
||||
<successCode>0</successCode>
|
||||
<!-- taskkill returns 128 if the process is not found, which is fine in this case -->
|
||||
<successCode>128</successCode>
|
||||
</successCodes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
@@ -5,32 +5,10 @@
|
||||
viewBox="0 0 5.0480766 5.0480766"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="favicon.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<title>CommaFeed favicon</title>
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
id="namedview3"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.21875"
|
||||
inkscape:cx="207.17949"
|
||||
inkscape:cy="187.07692"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="855"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3" />
|
||||
<rect
|
||||
fill="#f88a14"
|
||||
rx="0.53846151"
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,24 +1,19 @@
|
||||
import { i18n } from "@lingui/core"
|
||||
import { I18nProvider } from "@lingui/react"
|
||||
import { MantineProvider } from "@mantine/core"
|
||||
import { MantineProvider, v8CssVariablesResolver } from "@mantine/core"
|
||||
import { ModalsProvider } from "@mantine/modals"
|
||||
import { Notifications } from "@mantine/notifications"
|
||||
import type React from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useEffect } from "react"
|
||||
import { HashRouter, Navigate, Route, Routes, useNavigate } from "react-router-dom"
|
||||
import Tinycon from "tinycon"
|
||||
import { Constants } from "@/app/constants"
|
||||
import { redirectTo } from "@/app/redirect/slice"
|
||||
import { redirectToInitialSetup } from "@/app/redirect/thunks"
|
||||
import { reloadServerInfos } from "@/app/server/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import { categoryUnreadCount } from "@/app/utils"
|
||||
import { DisablePullToRefresh } from "@/components/DisablePullToRefresh"
|
||||
import { ErrorBoundary } from "@/components/ErrorBoundary"
|
||||
import { Header } from "@/components/header/Header"
|
||||
import { Tree } from "@/components/sidebar/Tree"
|
||||
import { useAppLoading } from "@/hooks/useAppLoading"
|
||||
import { useBrowserExtension } from "@/hooks/useBrowserExtension"
|
||||
import { useI18n } from "@/i18n"
|
||||
import { AdminUsersPage } from "@/pages/admin/AdminUsersPage"
|
||||
import { MetricsPage } from "@/pages/admin/MetricsPage"
|
||||
@@ -48,6 +43,8 @@ function Providers(
|
||||
<I18nProvider i18n={i18n}>
|
||||
<MantineProvider
|
||||
defaultColorScheme="auto"
|
||||
// keep using css variables from mantine v8
|
||||
cssVariablesResolver={v8CssVariablesResolver}
|
||||
theme={{
|
||||
primaryColor: primaryColor,
|
||||
fontFamily: "Open Sans",
|
||||
@@ -144,83 +141,8 @@ function RedirectHandler() {
|
||||
return null
|
||||
}
|
||||
|
||||
function UnreadCountTitleHandler({
|
||||
enabled,
|
||||
}: Readonly<{
|
||||
enabled?: boolean
|
||||
}>) {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
return <title>{enabled && unreadCount > 0 ? `(${unreadCount}) CommaFeed` : "CommaFeed"}</title>
|
||||
}
|
||||
|
||||
function UnreadCountFaviconHandler({ enabled }: { enabled?: boolean }) {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
useEffect(() => {
|
||||
if (enabled && unreadCount > 0) {
|
||||
Tinycon.setBubble(unreadCount)
|
||||
} else {
|
||||
Tinycon.reset()
|
||||
}
|
||||
}, [unreadCount, enabled])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function BrowserExtensionBadgeUnreadCountHandler() {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const { setBadgeUnreadCount } = useBrowserExtension()
|
||||
useEffect(() => {
|
||||
if (!root) return
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
setBadgeUnreadCount(unreadCount)
|
||||
}, [root, setBadgeUnreadCount])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function CustomJsHandler() {
|
||||
const [scriptLoaded, setScriptLoaded] = useState(false)
|
||||
const { loading } = useAppLoading()
|
||||
|
||||
useEffect(() => {
|
||||
if (scriptLoaded || loading) {
|
||||
return
|
||||
}
|
||||
|
||||
const script = document.createElement("script")
|
||||
script.src = "custom_js.js"
|
||||
script.async = true
|
||||
document.body.appendChild(script)
|
||||
|
||||
setScriptLoaded(true)
|
||||
|
||||
return () => script.remove()
|
||||
}, [scriptLoaded, loading])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function CustomCssHandler() {
|
||||
useEffect(() => {
|
||||
const link = document.createElement("link")
|
||||
link.rel = "stylesheet"
|
||||
link.type = "text/css"
|
||||
link.href = "custom_css.css"
|
||||
document.head.appendChild(link)
|
||||
|
||||
return () => link.remove()
|
||||
}, [])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function App() {
|
||||
useI18n()
|
||||
const unreadCountTitle = useAppSelector(state => state.user.settings?.unreadCountTitle)
|
||||
const unreadCountFavicon = useAppSelector(state => state.user.settings?.unreadCountFavicon)
|
||||
const disablePullToRefresh = useAppSelector(state => state.user.settings?.disablePullToRefresh)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -229,13 +151,6 @@ export function App() {
|
||||
|
||||
return (
|
||||
<Providers>
|
||||
<UnreadCountTitleHandler enabled={unreadCountTitle} />
|
||||
<UnreadCountFaviconHandler enabled={unreadCountFavicon} />
|
||||
<BrowserExtensionBadgeUnreadCountHandler />
|
||||
<CustomJsHandler />
|
||||
<CustomCssHandler />
|
||||
<DisablePullToRefresh enabled={disablePullToRefresh} />
|
||||
|
||||
<HashRouter>
|
||||
<InitialSetupHandler />
|
||||
<RedirectHandler />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { IconType } from "react-icons"
|
||||
import { FaAt } from "react-icons/fa"
|
||||
import { SiBuffer, SiFacebook, SiGmail, SiInstapaper, SiPocket, SiTumblr, SiX } from "react-icons/si"
|
||||
import { SiBuffer, SiFacebook, SiGmail, SiInstapaper, SiTumblr, SiX } from "react-icons/si"
|
||||
import type { Category, Entry, SharingSettings } from "./types"
|
||||
|
||||
const categories: Record<string, Omit<Category, "name">> = {
|
||||
@@ -58,12 +58,6 @@ const sharing: {
|
||||
color: "#375672",
|
||||
url: (url, desc) => `https://www.tumblr.com/share/link?url=${url}&name=${desc}`,
|
||||
},
|
||||
pocket: {
|
||||
label: "Pocket",
|
||||
icon: SiPocket,
|
||||
color: "#EF4154",
|
||||
url: (url, desc) => `https://getpocket.com/save?url=${url}&title=${desc}`,
|
||||
},
|
||||
instapaper: {
|
||||
label: "Instapaper",
|
||||
icon: SiInstapaper,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { configureStore } from "@reduxjs/toolkit"
|
||||
import { type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"
|
||||
import { shallowEqual, type TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"
|
||||
import { entriesSlice } from "@/app/entries/slice"
|
||||
import { redirectSlice } from "@/app/redirect/slice"
|
||||
import { serverSlice } from "@/app/server/slice"
|
||||
@@ -41,3 +41,4 @@ export type AppDispatch = typeof store.dispatch
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
|
||||
export const useShallowEqualAppSelector: TypedUseSelectorHook<RootState> = selector => useSelector(selector, shallowEqual)
|
||||
|
||||
@@ -249,7 +249,6 @@ export interface SharingSettings {
|
||||
facebook: boolean
|
||||
twitter: boolean
|
||||
tumblr: boolean
|
||||
pocket: boolean
|
||||
instapaper: boolean
|
||||
buffer: boolean
|
||||
}
|
||||
|
||||
@@ -1,32 +1,8 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { showNotification } from "@mantine/notifications"
|
||||
import { createSlice, isAnyOf, type PayloadAction } from "@reduxjs/toolkit"
|
||||
import { createSlice, type PayloadAction } from "@reduxjs/toolkit"
|
||||
import type { LocalSettings, Settings, UserModel, ViewMode } from "@/app/types"
|
||||
import {
|
||||
changeCustomContextMenu,
|
||||
changeDisablePullToRefresh,
|
||||
changeEntriesToKeepOnTopWhenScrolling,
|
||||
changeExternalLinkIconDisplayMode,
|
||||
changeLanguage,
|
||||
changeMarkAllAsReadConfirmation,
|
||||
changeMarkAllAsReadNavigateToUnread,
|
||||
changeMobileFooter,
|
||||
changePrimaryColor,
|
||||
changePushNotificationSettings,
|
||||
changeReadingMode,
|
||||
changeReadingOrder,
|
||||
changeScrollMarks,
|
||||
changeScrollMode,
|
||||
changeScrollSpeed,
|
||||
changeSharingSetting,
|
||||
changeShowRead,
|
||||
changeStarIconDisplayMode,
|
||||
changeUnreadCountFavicon,
|
||||
changeUnreadCountTitle,
|
||||
reloadProfile,
|
||||
reloadSettings,
|
||||
reloadTags,
|
||||
} from "./thunks"
|
||||
import { changeSettings, reloadProfile, reloadSettings, reloadTags } from "./thunks"
|
||||
|
||||
interface UserState {
|
||||
settings?: Settings
|
||||
@@ -73,115 +49,16 @@ export const userSlice = createSlice({
|
||||
builder.addCase(reloadTags.fulfilled, (state, action) => {
|
||||
state.tags = action.payload
|
||||
})
|
||||
builder.addCase(changeReadingMode.pending, (state, action) => {
|
||||
builder.addCase(changeSettings.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.readingMode = action.meta.arg
|
||||
state.settings = { ...state.settings, ...action.meta.arg }
|
||||
})
|
||||
builder.addCase(changeReadingOrder.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.readingOrder = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeLanguage.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.language = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollSpeed.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollSpeed = action.meta.arg ? 400 : 0
|
||||
})
|
||||
builder.addCase(changeShowRead.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.showRead = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollMarks.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollMarks = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeScrollMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.scrollMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeEntriesToKeepOnTopWhenScrolling.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.entriesToKeepOnTopWhenScrolling = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeStarIconDisplayMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.starIconDisplayMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeExternalLinkIconDisplayMode.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.externalLinkIconDisplayMode = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMarkAllAsReadConfirmation.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.markAllAsReadConfirmation = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMarkAllAsReadNavigateToUnread.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.markAllAsReadNavigateToNextUnread = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeCustomContextMenu.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.customContextMenu = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMobileFooter.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.mobileFooter = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeUnreadCountTitle.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.unreadCountTitle = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeUnreadCountFavicon.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.unreadCountFavicon = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeDisablePullToRefresh.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.disablePullToRefresh = action.meta.arg
|
||||
})
|
||||
builder.addCase(changePrimaryColor.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.primaryColor = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeSharingSetting.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.sharingSettings[action.meta.arg.site] = action.meta.arg.value
|
||||
})
|
||||
builder.addCase(changePushNotificationSettings.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.pushNotificationSettings = action.meta.arg
|
||||
})
|
||||
|
||||
builder.addMatcher(
|
||||
isAnyOf(
|
||||
changeLanguage.fulfilled,
|
||||
changeScrollSpeed.fulfilled,
|
||||
changeShowRead.fulfilled,
|
||||
changeScrollMarks.fulfilled,
|
||||
changeScrollMode.fulfilled,
|
||||
changeEntriesToKeepOnTopWhenScrolling.fulfilled,
|
||||
changeStarIconDisplayMode.fulfilled,
|
||||
changeExternalLinkIconDisplayMode.fulfilled,
|
||||
changeMarkAllAsReadConfirmation.fulfilled,
|
||||
changeMarkAllAsReadNavigateToUnread.fulfilled,
|
||||
changeCustomContextMenu.fulfilled,
|
||||
changeMobileFooter.fulfilled,
|
||||
changeUnreadCountTitle.fulfilled,
|
||||
changeUnreadCountFavicon.fulfilled,
|
||||
changeDisablePullToRefresh.fulfilled,
|
||||
changePrimaryColor.fulfilled,
|
||||
changeSharingSetting.fulfilled,
|
||||
changePushNotificationSettings.fulfilled
|
||||
),
|
||||
() => {
|
||||
builder.addCase(changeSettings.fulfilled, () => {
|
||||
showNotification({
|
||||
message: t`Settings saved.`,
|
||||
color: "green",
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createAppAsyncThunk } from "@/app/async-thunk"
|
||||
import { client } from "@/app/client"
|
||||
import { reloadEntries } from "@/app/entries/thunks"
|
||||
import type { IconDisplayMode, PushNotificationSettings, ReadingMode, ReadingOrder, ScrollMode, SharingSettings } from "@/app/types"
|
||||
import type { Settings } from "@/app/types"
|
||||
|
||||
export const reloadSettings = createAppAsyncThunk("settings/reload", async () => await client.user.getSettings().then(r => r.data))
|
||||
|
||||
@@ -9,163 +8,8 @@ export const reloadProfile = createAppAsyncThunk("profile/reload", async () => a
|
||||
|
||||
export const reloadTags = createAppAsyncThunk("entries/tags", async () => await client.entry.getTags().then(r => r.data))
|
||||
|
||||
export const changeReadingMode = createAppAsyncThunk("settings/readingMode", (readingMode: ReadingMode, thunkApi) => {
|
||||
export const changeSettings = createAppAsyncThunk("settings/change", async (newSettings: Partial<Settings>, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, readingMode })
|
||||
thunkApi.dispatch(reloadEntries())
|
||||
await client.user.saveSettings({ ...settings, ...newSettings })
|
||||
})
|
||||
|
||||
export const changeReadingOrder = createAppAsyncThunk("settings/readingOrder", (readingOrder: ReadingOrder, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, readingOrder })
|
||||
thunkApi.dispatch(reloadEntries())
|
||||
})
|
||||
|
||||
export const changeLanguage = createAppAsyncThunk("settings/language", (language: string, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, language })
|
||||
})
|
||||
|
||||
export const changeScrollSpeed = createAppAsyncThunk("settings/scrollSpeed", (speed: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollSpeed: speed ? 400 : 0 })
|
||||
})
|
||||
|
||||
export const changeShowRead = createAppAsyncThunk("settings/showRead", (showRead: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, showRead })
|
||||
})
|
||||
|
||||
export const changeScrollMarks = createAppAsyncThunk("settings/scrollMarks", (scrollMarks: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollMarks })
|
||||
})
|
||||
|
||||
export const changeScrollMode = createAppAsyncThunk("settings/scrollMode", (scrollMode: ScrollMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, scrollMode })
|
||||
})
|
||||
|
||||
export const changeEntriesToKeepOnTopWhenScrolling = createAppAsyncThunk(
|
||||
"settings/entriesToKeepOnTopWhenScrolling",
|
||||
(entriesToKeepOnTopWhenScrolling: number, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, entriesToKeepOnTopWhenScrolling })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeStarIconDisplayMode = createAppAsyncThunk(
|
||||
"settings/starIconDisplayMode",
|
||||
(starIconDisplayMode: IconDisplayMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, starIconDisplayMode })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeExternalLinkIconDisplayMode = createAppAsyncThunk(
|
||||
"settings/externalLinkIconDisplayMode",
|
||||
(externalLinkIconDisplayMode: IconDisplayMode, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, externalLinkIconDisplayMode })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeMarkAllAsReadConfirmation = createAppAsyncThunk(
|
||||
"settings/markAllAsReadConfirmation",
|
||||
(markAllAsReadConfirmation: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, markAllAsReadConfirmation })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeMarkAllAsReadNavigateToUnread = createAppAsyncThunk(
|
||||
"settings/markAllAsReadNavigateToUnread",
|
||||
(markAllAsReadNavigateToNextUnread: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, markAllAsReadNavigateToNextUnread })
|
||||
}
|
||||
)
|
||||
|
||||
export const changeCustomContextMenu = createAppAsyncThunk("settings/customContextMenu", (customContextMenu: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, customContextMenu })
|
||||
})
|
||||
|
||||
export const changeMobileFooter = createAppAsyncThunk("settings/mobileFooter", (mobileFooter: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, mobileFooter })
|
||||
})
|
||||
|
||||
export const changeUnreadCountTitle = createAppAsyncThunk("settings/unreadCountTitle", (unreadCountTitle: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, unreadCountTitle })
|
||||
})
|
||||
|
||||
export const changeUnreadCountFavicon = createAppAsyncThunk("settings/unreadCountFavicon", (unreadCountFavicon: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, unreadCountFavicon })
|
||||
})
|
||||
|
||||
export const changeDisablePullToRefresh = createAppAsyncThunk(
|
||||
"settings/disablePullToRefresh",
|
||||
(disablePullToRefresh: boolean, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, disablePullToRefresh })
|
||||
}
|
||||
)
|
||||
|
||||
export const changePrimaryColor = createAppAsyncThunk("settings/primaryColor", (primaryColor: string, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, primaryColor })
|
||||
})
|
||||
|
||||
export const changeSharingSetting = createAppAsyncThunk(
|
||||
"settings/sharingSetting",
|
||||
(
|
||||
sharingSetting: {
|
||||
site: keyof SharingSettings
|
||||
value: boolean
|
||||
},
|
||||
thunkApi
|
||||
) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({
|
||||
...settings,
|
||||
sharingSettings: {
|
||||
...settings.sharingSettings,
|
||||
[sharingSetting.site]: sharingSetting.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
export const changePushNotificationSettings = createAppAsyncThunk(
|
||||
"settings/pushNotificationSettings",
|
||||
(pushNotificationSettings: PushNotificationSettings, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({
|
||||
...settings,
|
||||
pushNotificationSettings,
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg height="512" width="512" viewBox="0 0 6.5625 6.5625" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>CommaFeed logo</title>
|
||||
<rect fill="#f88a14" rx="0.7" ry="0.7" height="6.5625" width="6.5625" />
|
||||
<path d="m1.9761,1.5289c2.9002,0,2.9002,2.9101,2.9002,2.9101" fill="none" stroke="#FFF" stroke-linecap="round"
|
||||
stroke-width="0.78125" />
|
||||
|
||||
|
Before Width: | Height: | Size: 791 B After Width: | Height: | Size: 831 B |
@@ -1,7 +1,6 @@
|
||||
import type { MessageDescriptor } from "@lingui/core"
|
||||
import { useLingui } from "@lingui/react"
|
||||
import { ActionIcon, Box, Button, type ButtonVariant, Tooltip, useMantineTheme } from "@mantine/core"
|
||||
import type { ActionIconVariant } from "@mantine/core/lib/components/ActionIcon/ActionIcon"
|
||||
import { ActionIcon, type ActionIconVariant, Box, Button, type ButtonVariant, Tooltip, useMantineTheme } from "@mantine/core"
|
||||
import { forwardRef, type MouseEventHandler, type ReactNode } from "react"
|
||||
import { Constants } from "@/app/constants"
|
||||
import { useActionButton } from "@/hooks/useActionButton"
|
||||
|
||||
@@ -14,6 +14,7 @@ interface ImageWithPlaceholderWhileLoadingProps {
|
||||
placeholderHeight?: number
|
||||
placeholderBackgroundColor?: string
|
||||
placeholderIconSize?: number
|
||||
onError?: (e: React.SyntheticEvent<HTMLImageElement, Event>) => void
|
||||
}
|
||||
|
||||
const useStyles = tss
|
||||
@@ -44,6 +45,7 @@ export function ImageWithPlaceholderWhileLoading({
|
||||
title,
|
||||
width,
|
||||
style,
|
||||
onError,
|
||||
}: Readonly<ImageWithPlaceholderWhileLoadingProps>) {
|
||||
const { classes } = useStyles({
|
||||
placeholderWidth,
|
||||
@@ -70,6 +72,7 @@ export function ImageWithPlaceholderWhileLoading({
|
||||
width={width}
|
||||
height={height}
|
||||
onLoad={() => setLoading(false)}
|
||||
onError={onError}
|
||||
style={{
|
||||
...style,
|
||||
display: loading ? "none" : (style?.display ?? "initial"),
|
||||
|
||||
@@ -7,11 +7,11 @@ const init = async () => {
|
||||
async getWorker(_, label) {
|
||||
let worker: typeof import("*?worker")
|
||||
if (label === "css") {
|
||||
worker = await import("monaco-editor/esm/vs/language/css/css.worker?worker")
|
||||
worker = await import("monaco-editor/language/css/css.worker?worker")
|
||||
} else if (label === "javascript") {
|
||||
worker = await import("monaco-editor/esm/vs/language/typescript/ts.worker?worker")
|
||||
worker = await import("monaco-editor/language/typescript/ts.worker?worker")
|
||||
} else {
|
||||
worker = await import("monaco-editor/esm/vs/editor/editor.worker?worker")
|
||||
worker = await import("monaco-editor/editor/editor.worker?worker")
|
||||
}
|
||||
return new worker.default()
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useTimeout } from "@mantine/hooks"
|
||||
import { useState } from "react"
|
||||
import { ImageWithPlaceholderWhileLoading } from "@/components/ImageWithPlaceholderWhileLoading"
|
||||
|
||||
export interface FeedFaviconProps {
|
||||
@@ -6,9 +8,23 @@ export interface FeedFaviconProps {
|
||||
}
|
||||
|
||||
export function FeedFavicon({ url, size = 18 }: Readonly<FeedFaviconProps>) {
|
||||
// the backend always returns a favicon except when the feed has never been fetched
|
||||
// this can happen when the user subscribes to a feed, the feed is added to the tree but the feed has not been fetched yet
|
||||
// in this case we retry every second up to 3 times until the feed is fetched and the favicon is available
|
||||
const [timestamp, setTimestamp] = useState(0)
|
||||
const [retryCount, setRetryCount] = useState(0)
|
||||
const { start: retry } = useTimeout(() => setTimestamp(Date.now()), 1000)
|
||||
|
||||
const urlWithTimestamp = url + (timestamp === 0 ? "" : `?t=${timestamp}`)
|
||||
const handleError = () => {
|
||||
if (retryCount < 3) {
|
||||
setRetryCount(c => c + 1)
|
||||
retry()
|
||||
}
|
||||
}
|
||||
return (
|
||||
<ImageWithPlaceholderWhileLoading
|
||||
src={url}
|
||||
src={urlWithTimestamp}
|
||||
alt="feed favicon"
|
||||
width={size}
|
||||
height={size}
|
||||
@@ -16,6 +32,7 @@ export function FeedFavicon({ url, size = 18 }: Readonly<FeedFaviconProps>) {
|
||||
placeholderHeight={size}
|
||||
placeholderBackgroundColor="inherit"
|
||||
placeholderIconSize={size}
|
||||
onError={handleError}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { msg } from "@lingui/core/macro"
|
||||
import { useLingui } from "@lingui/react"
|
||||
import { Select, type SelectProps } from "@mantine/core"
|
||||
import type { ComboboxItem } from "@mantine/core/lib/components/Combobox/Combobox.types"
|
||||
import { type ComboboxItem, Select, type SelectProps } from "@mantine/core"
|
||||
import { Constants } from "@/app/constants"
|
||||
import { useAppSelector } from "@/app/store"
|
||||
import type { Category } from "@/app/types"
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
import { Highlight } from "@mantine/core"
|
||||
import { useAppSelector } from "@/app/store"
|
||||
import type { Entry } from "@/app/types"
|
||||
import { tss } from "@/tss"
|
||||
|
||||
export interface FeedEntryTitleProps {
|
||||
entry: Entry
|
||||
}
|
||||
|
||||
const useStyles = tss.create(() => ({
|
||||
content: {
|
||||
textWrap: "inherit",
|
||||
},
|
||||
}))
|
||||
|
||||
export function FeedEntryTitle(props: Readonly<FeedEntryTitleProps>) {
|
||||
const search = useAppSelector(state => state.entries.search)
|
||||
const keywords = search?.split(" ")
|
||||
|
||||
const { classes } = useStyles()
|
||||
return (
|
||||
<Highlight
|
||||
inherit
|
||||
highlight={keywords ?? ""}
|
||||
// make sure ellipsis is shown when title is too long
|
||||
span
|
||||
className={classes.content}
|
||||
>
|
||||
{props.entry.title}
|
||||
</Highlight>
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "react-icons/tb"
|
||||
import { markAllAsReadWithConfirmationIfRequired, reloadEntries, search, selectNextEntry, selectPreviousEntry } from "@/app/entries/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import { changeReadingMode, changeReadingOrder } from "@/app/user/thunks"
|
||||
import { changeSettings } from "@/app/user/thunks"
|
||||
import { ActionButton } from "@/components/ActionButton"
|
||||
import { Loader } from "@/components/Loader"
|
||||
import { useActionButton } from "@/hooks/useActionButton"
|
||||
@@ -73,6 +73,25 @@ export function Header() {
|
||||
}, [setValues, searchFromStore])
|
||||
|
||||
if (!settings) return <Loader />
|
||||
|
||||
const toggleReadingMode = async () => {
|
||||
await dispatch(
|
||||
changeSettings({
|
||||
readingMode: settings.readingMode === "all" ? "unread" : "all",
|
||||
})
|
||||
)
|
||||
dispatch(reloadEntries())
|
||||
}
|
||||
|
||||
const toggleReadingOrder = async () => {
|
||||
await dispatch(
|
||||
changeSettings({
|
||||
readingOrder: settings.readingOrder === "asc" ? "desc" : "asc",
|
||||
})
|
||||
)
|
||||
dispatch(reloadEntries())
|
||||
}
|
||||
|
||||
return (
|
||||
<Center className="cf-toolbar-wrapper">
|
||||
<HeaderToolbar>
|
||||
@@ -121,12 +140,12 @@ export function Header() {
|
||||
<ActionButton
|
||||
icon={settings.readingMode === "all" ? <TbEye size={iconSize} /> : <TbEyeOff size={iconSize} />}
|
||||
label={settings.readingMode === "all" ? msg`All` : msg`Unread`}
|
||||
onClick={async () => await dispatch(changeReadingMode(settings.readingMode === "all" ? "unread" : "all"))}
|
||||
onClick={toggleReadingMode}
|
||||
/>
|
||||
<ActionButton
|
||||
icon={settings.readingOrder === "asc" ? <TbSortAscending size={iconSize} /> : <TbSortDescending size={iconSize} />}
|
||||
label={settings.readingOrder === "asc" ? msg`Asc` : msg`Desc`}
|
||||
onClick={async () => await dispatch(changeReadingOrder(settings.readingOrder === "asc" ? "desc" : "asc"))}
|
||||
onClick={toggleReadingOrder}
|
||||
/>
|
||||
|
||||
<Popover>
|
||||
|
||||
@@ -1,51 +1,29 @@
|
||||
import { msg } from "@lingui/core/macro"
|
||||
import { useLingui } from "@lingui/react"
|
||||
import { Trans } from "@lingui/react/macro"
|
||||
import { Box, Divider, Group, NumberInput, Radio, Select, type SelectProps, SimpleGrid, Stack, Switch } from "@mantine/core"
|
||||
import type { ComboboxData } from "@mantine/core/lib/components/Combobox/Combobox.types"
|
||||
import {
|
||||
Box,
|
||||
type ComboboxData,
|
||||
Divider,
|
||||
Group,
|
||||
Loader,
|
||||
NumberInput,
|
||||
Radio,
|
||||
Select,
|
||||
type SelectProps,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Switch,
|
||||
} from "@mantine/core"
|
||||
import type { ReactNode } from "react"
|
||||
import { Constants } from "@/app/constants"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import type { IconDisplayMode, ScrollMode, SharingSettings } from "@/app/types"
|
||||
import {
|
||||
changeCustomContextMenu,
|
||||
changeDisablePullToRefresh,
|
||||
changeEntriesToKeepOnTopWhenScrolling,
|
||||
changeExternalLinkIconDisplayMode,
|
||||
changeLanguage,
|
||||
changeMarkAllAsReadConfirmation,
|
||||
changeMarkAllAsReadNavigateToUnread,
|
||||
changeMobileFooter,
|
||||
changePrimaryColor,
|
||||
changeScrollMarks,
|
||||
changeScrollMode,
|
||||
changeScrollSpeed,
|
||||
changeSharingSetting,
|
||||
changeShowRead,
|
||||
changeStarIconDisplayMode,
|
||||
changeUnreadCountFavicon,
|
||||
changeUnreadCountTitle,
|
||||
} from "@/app/user/thunks"
|
||||
import { changeSettings } from "@/app/user/thunks"
|
||||
import { locales } from "@/i18n"
|
||||
|
||||
export function DisplaySettings() {
|
||||
const language = useAppSelector(state => state.user.settings?.language)
|
||||
const scrollSpeed = useAppSelector(state => state.user.settings?.scrollSpeed)
|
||||
const showRead = useAppSelector(state => state.user.settings?.showRead)
|
||||
const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks)
|
||||
const scrollMode = useAppSelector(state => state.user.settings?.scrollMode)
|
||||
const entriesToKeepOnTop = useAppSelector(state => state.user.settings?.entriesToKeepOnTopWhenScrolling)
|
||||
const starIconDisplayMode = useAppSelector(state => state.user.settings?.starIconDisplayMode)
|
||||
const externalLinkIconDisplayMode = useAppSelector(state => state.user.settings?.externalLinkIconDisplayMode)
|
||||
const markAllAsReadConfirmation = useAppSelector(state => state.user.settings?.markAllAsReadConfirmation)
|
||||
const markAllAsReadNavigateToNextUnread = useAppSelector(state => state.user.settings?.markAllAsReadNavigateToNextUnread)
|
||||
const customContextMenu = useAppSelector(state => state.user.settings?.customContextMenu)
|
||||
const mobileFooter = useAppSelector(state => state.user.settings?.mobileFooter)
|
||||
const unreadCountTitle = useAppSelector(state => state.user.settings?.unreadCountTitle)
|
||||
const unreadCountFavicon = useAppSelector(state => state.user.settings?.unreadCountFavicon)
|
||||
const disablePullToRefresh = useAppSelector(state => state.user.settings?.disablePullToRefresh)
|
||||
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
|
||||
const primaryColor = useAppSelector(state => state.user.settings?.primaryColor) || Constants.theme.defaultPrimaryColor
|
||||
const settings = useAppSelector(state => state.user.settings)
|
||||
const { _ } = useLingui()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
@@ -97,50 +75,51 @@ export function DisplaySettings() {
|
||||
</Group>
|
||||
)
|
||||
|
||||
if (!settings) return <Loader />
|
||||
return (
|
||||
<Stack>
|
||||
<Divider label={<Trans>Display</Trans>} labelPosition="center" />
|
||||
|
||||
<Select
|
||||
label={<Trans>Language</Trans>}
|
||||
value={language}
|
||||
value={settings.language}
|
||||
data={locales.map(l => ({
|
||||
value: l.key,
|
||||
label: l.label,
|
||||
}))}
|
||||
onChange={async s => await (s && dispatch(changeLanguage(s)))}
|
||||
onChange={language => language && dispatch(changeSettings({ language }))}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={<Trans>Primary color</Trans>}
|
||||
data={colorData}
|
||||
value={primaryColor}
|
||||
onChange={async value => value && (await dispatch(changePrimaryColor(value)))}
|
||||
value={settings.primaryColor}
|
||||
onChange={primaryColor => primaryColor && dispatch(changeSettings({ primaryColor }))}
|
||||
renderOption={colorRenderer}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show feeds and categories with no unread entries</Trans>}
|
||||
checked={showRead}
|
||||
onChange={async e => await dispatch(changeShowRead(e.currentTarget.checked))}
|
||||
checked={settings.showRead}
|
||||
onChange={e => dispatch(changeSettings({ showRead: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show confirmation when marking all entries as read</Trans>}
|
||||
checked={markAllAsReadConfirmation}
|
||||
onChange={async e => await dispatch(changeMarkAllAsReadConfirmation(e.currentTarget.checked))}
|
||||
checked={settings.markAllAsReadConfirmation}
|
||||
onChange={e => dispatch(changeSettings({ markAllAsReadConfirmation: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Navigate to the next category/feed with unread entries when marking all entries as read</Trans>}
|
||||
checked={markAllAsReadNavigateToNextUnread}
|
||||
onChange={async e => await dispatch(changeMarkAllAsReadNavigateToUnread(e.currentTarget.checked))}
|
||||
checked={settings.markAllAsReadNavigateToNextUnread}
|
||||
onChange={e => dispatch(changeSettings({ markAllAsReadNavigateToNextUnread: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>On mobile, show action buttons at the bottom of the screen</Trans>}
|
||||
checked={mobileFooter}
|
||||
onChange={async e => await dispatch(changeMobileFooter(e.currentTarget.checked))}
|
||||
checked={settings.mobileFooter}
|
||||
onChange={e => dispatch(changeSettings({ mobileFooter: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Scrolling</Trans>} labelPosition="center" />
|
||||
@@ -148,14 +127,14 @@ export function DisplaySettings() {
|
||||
<Switch
|
||||
label={<Trans>Disable "Pull to refresh" browser behavior</Trans>}
|
||||
description={<Trans>This setting can cause scrolling issues on some browsers (e.g. Safari)</Trans>}
|
||||
checked={disablePullToRefresh}
|
||||
onChange={async e => await dispatch(changeDisablePullToRefresh(e.currentTarget.checked))}
|
||||
checked={settings.disablePullToRefresh}
|
||||
onChange={e => dispatch(changeSettings({ disablePullToRefresh: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Radio.Group
|
||||
label={<Trans>Scroll selected entry to the top of the page</Trans>}
|
||||
value={scrollMode}
|
||||
onChange={async value => await dispatch(changeScrollMode(value as ScrollMode))}
|
||||
value={settings.scrollMode}
|
||||
onChange={value => dispatch(changeSettings({ scrollMode: value }))}
|
||||
>
|
||||
<Group mt="xs">
|
||||
{Object.entries(scrollModeOptions).map(e => (
|
||||
@@ -168,56 +147,56 @@ export function DisplaySettings() {
|
||||
label={<Trans>Entries to keep above the selected entry when scrolling</Trans>}
|
||||
description={<Trans>Only applies to compact, cozy and detailed modes</Trans>}
|
||||
min={0}
|
||||
value={entriesToKeepOnTop}
|
||||
onChange={async value => await dispatch(changeEntriesToKeepOnTopWhenScrolling(+value))}
|
||||
value={settings.entriesToKeepOnTopWhenScrolling}
|
||||
onChange={value => dispatch(changeSettings({ entriesToKeepOnTopWhenScrolling: +value }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Scroll smoothly when navigating between entries</Trans>}
|
||||
checked={scrollSpeed ? scrollSpeed > 0 : false}
|
||||
onChange={async e => await dispatch(changeScrollSpeed(e.currentTarget.checked))}
|
||||
checked={settings.scrollSpeed ? settings.scrollSpeed > 0 : false}
|
||||
onChange={e => dispatch(changeSettings({ scrollSpeed: e.currentTarget.checked ? 400 : 0 }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>In expanded view, scrolling through entries mark them as read</Trans>}
|
||||
checked={scrollMarks}
|
||||
onChange={async e => await dispatch(changeScrollMarks(e.currentTarget.checked))}
|
||||
checked={settings.scrollMarks}
|
||||
onChange={e => dispatch(changeSettings({ scrollMarks: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Browser tab</Trans>} labelPosition="center" />
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show unread count in tab title</Trans>}
|
||||
checked={unreadCountTitle}
|
||||
onChange={async e => await dispatch(changeUnreadCountTitle(e.currentTarget.checked))}
|
||||
checked={settings.unreadCountTitle}
|
||||
onChange={e => dispatch(changeSettings({ unreadCountTitle: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show unread count in tab favicon</Trans>}
|
||||
checked={unreadCountFavicon}
|
||||
onChange={async e => await dispatch(changeUnreadCountFavicon(e.currentTarget.checked))}
|
||||
checked={settings.unreadCountFavicon}
|
||||
onChange={e => dispatch(changeSettings({ unreadCountFavicon: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Entry headers</Trans>} labelPosition="center" />
|
||||
|
||||
<Select
|
||||
label={<Trans>Show star icon</Trans>}
|
||||
value={starIconDisplayMode}
|
||||
value={settings.starIconDisplayMode}
|
||||
data={displayModeData}
|
||||
onChange={async s => await dispatch(changeStarIconDisplayMode(s as IconDisplayMode))}
|
||||
onChange={value => dispatch(changeSettings({ starIconDisplayMode: value as IconDisplayMode }))}
|
||||
/>
|
||||
|
||||
<Select
|
||||
label={<Trans>Show external link icon</Trans>}
|
||||
value={externalLinkIconDisplayMode}
|
||||
value={settings.externalLinkIconDisplayMode}
|
||||
data={displayModeData}
|
||||
onChange={async s => await dispatch(changeExternalLinkIconDisplayMode(s as IconDisplayMode))}
|
||||
onChange={value => dispatch(changeSettings({ externalLinkIconDisplayMode: value as IconDisplayMode }))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show CommaFeed's own context menu on right click</Trans>}
|
||||
checked={customContextMenu}
|
||||
onChange={async e => await dispatch(changeCustomContextMenu(e.currentTarget.checked))}
|
||||
checked={settings.customContextMenu}
|
||||
onChange={e => dispatch(changeSettings({ customContextMenu: e.currentTarget.checked }))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Sharing sites</Trans>} labelPosition="center" />
|
||||
@@ -227,12 +206,14 @@ export function DisplaySettings() {
|
||||
<Switch
|
||||
key={site}
|
||||
label={Constants.sharing[site].label}
|
||||
checked={sharingSettings?.[site]}
|
||||
onChange={async e =>
|
||||
await dispatch(
|
||||
changeSharingSetting({
|
||||
site,
|
||||
value: e.currentTarget.checked,
|
||||
checked={settings.sharingSettings[site]}
|
||||
onChange={e =>
|
||||
dispatch(
|
||||
changeSettings({
|
||||
sharingSettings: {
|
||||
...settings.sharingSettings,
|
||||
[site]: e.currentTarget.checked,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { client, errorToStrings } from "@/app/client"
|
||||
import { redirectToSelectedSource } from "@/app/redirect/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import type { PushNotificationSettings as PushNotificationSettingsModel } from "@/app/types"
|
||||
import { changePushNotificationSettings } from "@/app/user/thunks"
|
||||
import { changeSettings } from "@/app/user/thunks"
|
||||
import { Alert } from "@/components/Alert"
|
||||
|
||||
export function PushNotificationSettings() {
|
||||
@@ -25,7 +25,7 @@ export function PushNotificationSettings() {
|
||||
}, [form.initialize, notificationSettings])
|
||||
|
||||
const handleSubmit = (values: PushNotificationSettingsModel) => {
|
||||
dispatch(changePushNotificationSettings(values))
|
||||
dispatch(changeSettings({ pushNotificationSettings: values }))
|
||||
}
|
||||
|
||||
const sendTestPushNotification = useAsyncCallback(client.user.sendTestPushNotification)
|
||||
|
||||
@@ -6,7 +6,11 @@ const useStyles = tss.create(() => ({
|
||||
badge: {
|
||||
width: "3.2rem",
|
||||
// for some reason, mantine Badge has "cursor: 'default'"
|
||||
cursor: "pointer",
|
||||
cursor: "inherit",
|
||||
},
|
||||
indicator: {
|
||||
// ensure the indicator is not shown above the app header
|
||||
zIndex: 0,
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -23,7 +27,15 @@ export function UnreadCount(
|
||||
const count = props.unreadCount >= 10000 ? "10k+" : props.unreadCount
|
||||
return (
|
||||
<Tooltip label={props.unreadCount} disabled={props.unreadCount === count} openDelay={Constants.tooltip.delay}>
|
||||
<Indicator disabled={!props.showIndicator} size={4} offset={10} position="middle-start">
|
||||
<Indicator
|
||||
disabled={!props.showIndicator}
|
||||
size={4}
|
||||
offset={10}
|
||||
position="middle-start"
|
||||
classNames={{
|
||||
indicator: classes.indicator,
|
||||
}}
|
||||
>
|
||||
<Badge className={`${classes.badge} cf-badge`} variant="light" fullWidth>
|
||||
{count}
|
||||
</Badge>
|
||||
|
||||
3
commafeed-client/src/globals.d.ts
vendored
Normal file
3
commafeed-client/src/globals.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// required because of noUncheckedSideEffectImports
|
||||
// https://www.typescriptlang.org/tsconfig/#noUncheckedSideEffectImports
|
||||
declare module "@fontsource/open-sans"
|
||||
@@ -60,7 +60,6 @@ msgstr "إضافة مستخدم"
|
||||
msgid "Admin"
|
||||
msgstr "إداري"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "اسم مستخدم المسؤول"
|
||||
@@ -73,7 +72,6 @@ msgstr "اسم مستخدم المسؤول"
|
||||
msgid "All"
|
||||
msgstr "الكل"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "دائمًا"
|
||||
@@ -173,18 +171,14 @@ msgstr "قم ببناء تعبير تصفية لتحديد ما تريد قرا
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "إلغاء"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "تأكيد"
|
||||
msgid "Confirm password"
|
||||
msgstr "تأكيد كلمة المرور"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "تأكيد كلمة المرور"
|
||||
@@ -294,7 +287,6 @@ msgstr "أيام"
|
||||
msgid "Delete"
|
||||
msgstr "حذف"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "حذف الحساب"
|
||||
@@ -342,13 +334,10 @@ msgstr "اسحب الرابط إلى شريط الإشارات"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "البريد الإلكتروني"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "عنوان البريد الإلكتروني"
|
||||
@@ -399,7 +388,6 @@ msgstr "خيارات الإضافة"
|
||||
msgid "Feed name"
|
||||
msgstr "اسم الخلاصة"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "تحميل الاشتراكات ..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "تحميل العلامات ..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "انتقل إلى اشتراك بإدخال اسمه"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "انتقل إلى الفئة/الخلاصة التالية التي تحتوي على إدخالات غير مقروءة عند تمييز الكل كمقروء"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "أبدا"
|
||||
@@ -657,7 +643,6 @@ msgstr "أبدا"
|
||||
msgid "New password"
|
||||
msgstr "كلمة مرور جديدة"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "كلمة مرور جديدة"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "تصدير OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "ملف OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "الفئة الأصل"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "كلمة المرور"
|
||||
@@ -874,7 +855,6 @@ msgstr "تحديث"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "تم إغلاق التسجيلات في مثيل CommaFeed هذا"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "إعادة تعيين كلمة المرور"
|
||||
@@ -883,7 +863,6 @@ msgstr "إعادة تعيين كلمة المرور"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "نقرة بالزر الأيمن"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "التمرير"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "بحث"
|
||||
@@ -924,7 +901,6 @@ msgstr "تحديد الخلاصة/الفئة التالية غير المقرو
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "تحديد الخلاصة/الفئة السابقة غير المقروءة"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "رابط الخادم"
|
||||
@@ -953,8 +929,6 @@ msgstr "مشاركة"
|
||||
msgid "Sharing sites"
|
||||
msgstr "مشاركة المواقع"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "الحلقة"
|
||||
@@ -1003,7 +977,6 @@ msgstr "إظهار عدد غير المقروء في أيقونة التبويب
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "إظهار عدد غير المقروء في عنوان التبويب"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "قم بالتسجيل"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "شيء سيء حدث للتو ..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "فضاء"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "النجم"
|
||||
msgid "Starred"
|
||||
msgstr "مميز بنجمة"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "قم بالتبديل إلى النسق الفاتح"
|
||||
msgid "System"
|
||||
msgstr "النظام"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "الكلمات"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "غير مقروءة"
|
||||
msgid "Unstar"
|
||||
msgstr "إلغاء النجم"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "إلغاء الاشتراك"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "مفتاح المستخدم"
|
||||
msgid "User name"
|
||||
msgstr "اسم المستخدم"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "اسم المستخدم أو البريد الإلكتروني"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Afegeix usuari"
|
||||
msgid "Admin"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nom d'usuari de l'administrador"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nom d'usuari de l'administrador"
|
||||
msgid "All"
|
||||
msgstr "Tot"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
@@ -173,18 +171,14 @@ msgstr "Creeu una expressió de filtratge per indicar què voleu llegir. Les ent
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Confirma"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmeu la contrasenya"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirma la contrasenya"
|
||||
@@ -294,7 +287,6 @@ msgstr "dies"
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Suprimeix el compte"
|
||||
@@ -342,13 +334,10 @@ msgstr "Arrossegueu l'enllaç a la barra d'adreces d'interès"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Correu electrònic"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Adreça de correu electrònic"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opcions de l'extensió"
|
||||
msgid "Feed name"
|
||||
msgstr "Nom del canal"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "S'estan carregant les subscripcions..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Carregant les etiquetes..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navegueu a una subscripció introduint-ne el nom"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navega a la següent categoria/canal amb entrades no llegides quan es marquen totes les entrades com a llegides"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Mai"
|
||||
@@ -657,7 +643,6 @@ msgstr "Mai"
|
||||
msgid "New password"
|
||||
msgstr "Contrasenya nova"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Contrasenya nova"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Exportació OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Fitxer OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Categoria pare"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Contrasenya"
|
||||
@@ -874,7 +855,6 @@ msgstr "Actualitzar"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Els registres estan tancats en aquesta instància de CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Restableix la contrasenya"
|
||||
@@ -883,7 +863,6 @@ msgstr "Restableix la contrasenya"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic dret"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Desplaçament"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
@@ -924,7 +901,6 @@ msgstr "Selecciona el següent canal/categoria no llegit"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Selecciona el canal/categoria anterior sense llegir"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL del servidor"
|
||||
@@ -953,8 +929,6 @@ msgstr "Comparteix"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartir a altres llocs web"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "canvi"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Mostra el recompte de no llegits a la icona de favorits de la pestanya"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Mostra el recompte de no llegits al títol de la pestanya"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Registra't"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Acaba de passar una cosa dolenta..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Espai"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Estrella"
|
||||
msgid "Starred"
|
||||
msgstr "Estrellat"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Canvia al tema clar"
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetes"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Sense llegir"
|
||||
msgid "Unstar"
|
||||
msgstr "Desestrellar"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Donar-se de baixa"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Clau d'usuari"
|
||||
msgid "User name"
|
||||
msgstr "Nom d'usuari"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nom d'usuari o correu electrònic"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Přidat uživatele"
|
||||
msgid "Admin"
|
||||
msgstr "Správce"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Uživatelské jméno správce"
|
||||
@@ -73,7 +72,6 @@ msgstr "Uživatelské jméno správce"
|
||||
msgid "All"
|
||||
msgstr "Všechny"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Vždy"
|
||||
@@ -173,18 +171,14 @@ msgstr "Vytvořte výraz filtru pro určení toho, co chcete číst. Položky, k
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušit"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Potvrdit"
|
||||
msgid "Confirm password"
|
||||
msgstr "Potvrďte heslo"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Potvrdit heslo"
|
||||
@@ -294,7 +287,6 @@ msgstr "dní"
|
||||
msgid "Delete"
|
||||
msgstr "Smazat"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Smazat účet"
|
||||
@@ -342,13 +334,10 @@ msgstr "Přetáhněte odkaz na lištu záložek"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mailová adresa"
|
||||
@@ -399,7 +388,6 @@ msgstr "Možnosti rozšíření"
|
||||
msgid "Feed name"
|
||||
msgstr "Název zdroje"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Načítání odběrů..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Načítání značek..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Přejděte na předplatné zadáním jeho názvu"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Po označení všech položek jako přečtených přejít na další kategorii/zdroj s nepřečtenými položkami"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nikdy"
|
||||
@@ -657,7 +643,6 @@ msgstr "Nikdy"
|
||||
msgid "New password"
|
||||
msgstr "Nové heslo"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nové heslo"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Export OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "soubor OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Rodičovská kategorie"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
@@ -874,7 +855,6 @@ msgstr "Obnovit"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "V této instanci CommaFeed jsou registrace uzavřeny"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Obnovit heslo"
|
||||
@@ -883,7 +863,6 @@ msgstr "Obnovit heslo"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Kliknutí pravým tlačítkem"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Posouvání"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Hledej"
|
||||
@@ -924,7 +901,6 @@ msgstr "Vybrat další nepřečtený zdroj/kategorii"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Vybrat předchozí nepřečtený zdroj/kategorii"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL serveru"
|
||||
@@ -953,8 +929,6 @@ msgstr "Sdílejte"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Stránky pro sdílení"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Směna"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Zobrazovat počet nepřečtených v ikoně karty"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Zobrazovat počet nepřečtených v názvu karty"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Zaregistrovat se"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Právě se stalo něco špatného..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Vesmír"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Hvězda"
|
||||
msgid "Starred"
|
||||
msgstr "S hvězdičkou"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Přepnout na světlý motiv"
|
||||
msgid "System"
|
||||
msgstr "Systémový"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Štítky"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Nepřečteno"
|
||||
msgid "Unstar"
|
||||
msgstr "Odstranit hvězdu"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Odhlásit odběr"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Uživatelský klíč"
|
||||
msgid "User name"
|
||||
msgstr "Uživatelské jméno"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Uživatelské jméno nebo e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Ychwanegu defnyddiwr"
|
||||
msgid "Admin"
|
||||
msgstr "Gweinyddol"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Enw defnyddiwr gweinyddwr"
|
||||
@@ -73,7 +72,6 @@ msgstr "Enw defnyddiwr gweinyddwr"
|
||||
msgid "All"
|
||||
msgstr "Pawb"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Bob amser"
|
||||
@@ -173,18 +171,14 @@ msgstr "Adeiladwch fynegiant hidlo i nodi'r hyn rydych chi am ei ddarllen. Bydd
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Diddymu"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Cadarnhau"
|
||||
msgid "Confirm password"
|
||||
msgstr "Cadarnhau'r cyfrinair"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Cadarnhau Cyfrinair"
|
||||
@@ -294,7 +287,6 @@ msgstr "diwrnodau"
|
||||
msgid "Delete"
|
||||
msgstr "Dileu"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Dileu cyfrif"
|
||||
@@ -342,13 +334,10 @@ msgstr "Llusgwch y ddolen i'r bar nod tudalen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-bost"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "cyfeiriad e-bost"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opsiynau estyniad"
|
||||
msgid "Feed name"
|
||||
msgstr "Enw porthiant"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Yn llwytho tanysgrifiadau..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Wrthi'n llwytho tagiau..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Llywiwch i danysgrifiad trwy nodi ei enw"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Llywiwch i'r categori/porthiant nesaf gyda chofnodion heb eu darllen wrth farcio pob cofnod fel un wedi'i ddarllen"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Byth"
|
||||
@@ -657,7 +643,6 @@ msgstr "Byth"
|
||||
msgid "New password"
|
||||
msgstr "Cyfrinair newydd"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Cyfrinair Newydd"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Allforio OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Ffeil OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Categori Rhiant"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "cyfrinair"
|
||||
@@ -874,7 +855,6 @@ msgstr "Adnewyddu"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Mae cofrestriadau ar gau ar yr achos CommaFeed hwn"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Ailosod Cyfrinair"
|
||||
@@ -883,7 +863,6 @@ msgstr "Ailosod Cyfrinair"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic dde"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Sgrolio"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Chwilio"
|
||||
@@ -924,7 +901,6 @@ msgstr "Dewiswch y porthiant/categori nesaf heb ei ddarllen"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Dewiswch y porthiant/categori blaenorol heb ei ddarllen"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL y gweinydd"
|
||||
@@ -953,8 +929,6 @@ msgstr "Rhannu"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Rhannu gwefannau"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "shifft"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Dangos nifer heb ei ddarllen yn ffaficon y tab"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Dangos nifer heb ei ddarllen yn nheitl y tab"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Cofrestrwch"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Mae rhywbeth drwg newydd ddigwydd ..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Gofod"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "seren"
|
||||
msgid "Starred"
|
||||
msgstr "serennog"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Newid i thema golau"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tagiau"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Heb ei ddarllen"
|
||||
msgid "Unstar"
|
||||
msgstr "dad-seren"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Dad-danysgrifio"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Allwedd defnyddiwr"
|
||||
msgid "User name"
|
||||
msgstr "Enw defnyddiwr"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Enw Defnyddiwr neu E-bost"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Tilføj bruger"
|
||||
msgid "Admin"
|
||||
msgstr "Administrator"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Administrator brugernavn"
|
||||
@@ -73,7 +72,6 @@ msgstr "Administrator brugernavn"
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Altid"
|
||||
@@ -173,18 +171,14 @@ msgstr "Byg et filterudtryk for at angive, hvad du vil læse. Indlæg, der ikke
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Annuller"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bekræft"
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekræft adgangskode"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Bekræft adgangskode"
|
||||
@@ -294,7 +287,6 @@ msgstr "dage"
|
||||
msgid "Delete"
|
||||
msgstr "Slet"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Slet konto"
|
||||
@@ -342,13 +334,10 @@ msgstr "Træk linket til bogmærkelinjen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mailadresse"
|
||||
@@ -399,7 +388,6 @@ msgstr "Indstillinger for udvidelse"
|
||||
msgid "Feed name"
|
||||
msgstr "Feednavn"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Indlæser abonnementer..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Indlæser tags..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Naviger til et abonnement ved at indtaste dets navn"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Naviger til næste kategori/feed med ulæste indlæg, når alle indlæg markeres som læst"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Aldrig"
|
||||
@@ -657,7 +643,6 @@ msgstr "Aldrig"
|
||||
msgid "New password"
|
||||
msgstr "Ny adgangskode"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Ny adgangskode"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML eksport"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML fil"
|
||||
@@ -791,10 +775,7 @@ msgstr "Forældrekategori"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Adgangskode"
|
||||
@@ -874,7 +855,6 @@ msgstr "Opdater"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registreringer er lukket på denne CommaFeed-instans"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Nulstil adgangskode"
|
||||
@@ -883,7 +863,6 @@ msgstr "Nulstil adgangskode"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Højreklik"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Rulning"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Søg"
|
||||
@@ -924,7 +901,6 @@ msgstr "Vælg næste ulæste feed/kategori"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Vælg forrige ulæste feed/kategori"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Vis ulæst antal i fanens favicon"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Vis ulæst antal i fanens titel"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Tilmeld dig"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Der er lige sket noget slemt..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Rum"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stjerne"
|
||||
msgid "Starred"
|
||||
msgstr "Medvirkende"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Skift til lystema"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Ulæst"
|
||||
msgid "Unstar"
|
||||
msgstr "Fjern stjerne"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Afmeld"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Brugernøgle"
|
||||
msgid "User name"
|
||||
msgstr "Brugernavn"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Brugernavn eller e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Benutzer hinzufügen"
|
||||
msgid "Admin"
|
||||
msgstr "Verwaltung"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Administrator-Benutzername"
|
||||
@@ -73,7 +72,6 @@ msgstr "Administrator-Benutzername"
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Immer"
|
||||
@@ -173,18 +171,14 @@ msgstr "Erstellen Sie einen Filterausdruck, um anzugeben, was Sie lesen möchten
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bestätigen"
|
||||
msgid "Confirm password"
|
||||
msgstr "Passwort bestätigen"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Passwort bestätigen"
|
||||
@@ -294,7 +287,6 @@ msgstr "Tage"
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Konto löschen"
|
||||
@@ -342,13 +334,10 @@ msgstr "Link in Lesezeichenleiste ziehen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-Mail-Adresse"
|
||||
@@ -399,7 +388,6 @@ msgstr "Erweiterungsoptionen"
|
||||
msgid "Feed name"
|
||||
msgstr "Feedname"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Abonnements werden geladen..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Tags werden geladen..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigieren Sie zu einem Abonnement, indem Sie seinen Namen eingeben"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigieren Sie zum nächsten Feed/Kategorie mit ungelesenen Einträgen, wenn Sie alle Einträge als gelesen markieren"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Niemals"
|
||||
@@ -657,7 +643,6 @@ msgstr "Niemals"
|
||||
msgid "New password"
|
||||
msgstr "Neues Passwort"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Neues Passwort"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-Export"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-Datei"
|
||||
@@ -791,10 +775,7 @@ msgstr "Übergeordnete Kategorie"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Passwort"
|
||||
@@ -874,7 +855,6 @@ msgstr "Aktualisieren"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registrierungen sind für diese CommaFeed-Instanz geschlossen"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Passwort zurücksetzen"
|
||||
@@ -883,7 +863,6 @@ msgstr "Passwort zurücksetzen"
|
||||
msgid "REST API"
|
||||
msgstr "REST-API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Rechtsklick"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Scrollen"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Suche"
|
||||
@@ -924,7 +901,6 @@ msgstr "Nächsten ungelesenen Feed/Kategorie auswählen"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Vorherigen ungelesenen Feed/Kategorie auswählen"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Teilen"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Seiten teilen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Verschiebung"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Anzahl ungelesener Nachrichten im Tab-Favicon anzeigen"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Anzahl ungelesener Nachrichten im Tab-Titel anzeigen"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Melden Sie sich an"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Etwas Schlimmes ist gerade passiert..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Raum"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stern"
|
||||
msgid "Starred"
|
||||
msgstr "Markiert"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Zum Lightmode wechseln"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Ungelesen"
|
||||
msgid "Unstar"
|
||||
msgstr "Stern entfernen"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Abbestellen"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Benutzerschlüssel"
|
||||
msgid "User name"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Benutzername oder E-Mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Add user"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Admin user name"
|
||||
@@ -73,7 +72,6 @@ msgstr "Admin user name"
|
||||
msgid "All"
|
||||
msgstr "All"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Always"
|
||||
@@ -173,18 +171,14 @@ msgstr "Build a filter expression to indicate what you want to read. Entries tha
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Confirm"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirm password"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirm Password"
|
||||
@@ -294,7 +287,6 @@ msgstr "days"
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Delete account"
|
||||
@@ -342,13 +334,10 @@ msgstr "Drag link to bookmark bar"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mail address"
|
||||
@@ -399,7 +388,6 @@ msgstr "Extension options"
|
||||
msgid "Feed name"
|
||||
msgstr "Feed name"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Loading subscriptions..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Loading tags..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigate to a subscription by entering its name"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Never"
|
||||
@@ -657,7 +643,6 @@ msgstr "Never"
|
||||
msgid "New password"
|
||||
msgstr "New password"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "New Password"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML export"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML file"
|
||||
@@ -791,10 +775,7 @@ msgstr "Parent Category"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
@@ -874,7 +855,6 @@ msgstr "Refresh"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registrations are closed on this CommaFeed instance"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Reset Password"
|
||||
@@ -883,7 +863,6 @@ msgstr "Reset Password"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Right click"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Scrolling"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
@@ -924,7 +901,6 @@ msgstr "Select next unread feed/category"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Select previous unread feed/category"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Share"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sharing sites"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Show unread count in tab favicon"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Show unread count in tab title"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Sign up"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Something bad just happened..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Space"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Star"
|
||||
msgid "Starred"
|
||||
msgstr "Starred"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Switch to light theme"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Unread"
|
||||
msgid "Unstar"
|
||||
msgstr "Unstar"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Unsubscribe"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "User key"
|
||||
msgid "User name"
|
||||
msgstr "User name"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "User Name or E-mail"
|
||||
|
||||
@@ -61,7 +61,6 @@ msgstr "Añadir usuario"
|
||||
msgid "Admin"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nombre de usuario administrador"
|
||||
@@ -74,7 +73,6 @@ msgstr "Nombre de usuario administrador"
|
||||
msgid "All"
|
||||
msgstr "Todo"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Siempre"
|
||||
@@ -174,18 +172,14 @@ msgstr "Crea una expresión de filtrado para indicar lo que quieres leer. Las en
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -241,7 +235,6 @@ msgstr "Confirmar"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmar contraseña"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirmar contraseña"
|
||||
@@ -295,7 +288,6 @@ msgstr "días"
|
||||
msgid "Delete"
|
||||
msgstr "Borrar"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Borrar cuenta"
|
||||
@@ -343,13 +335,10 @@ msgstr "Arrastra el enlace a la barra de marcadores"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Correo electrónico"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Dirección de correo electrónico"
|
||||
@@ -400,7 +389,6 @@ msgstr "Opciones de la extensión"
|
||||
msgid "Feed name"
|
||||
msgstr "Nombre del feed"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -571,7 +559,6 @@ msgstr "Cargando suscripciones..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Cargando etiquetas..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -649,7 +636,6 @@ msgstr "Navegar a una suscripción introduciendo su nombre"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navegar a la siguiente categoría/feed con entradas no leídas al marcar todas como leídas"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nunca"
|
||||
@@ -658,7 +644,6 @@ msgstr "Nunca"
|
||||
msgid "New password"
|
||||
msgstr "Nueva contraseña"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nueva contraseña"
|
||||
@@ -765,7 +750,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Exportar OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Archivo OPML"
|
||||
@@ -792,10 +776,7 @@ msgstr "Categoría principal"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
@@ -875,7 +856,6 @@ msgstr "Actualizar"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Los registros están cerrados en esta instancia de CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Restablecer contraseña"
|
||||
@@ -884,7 +864,6 @@ msgstr "Restablecer contraseña"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic derecho"
|
||||
@@ -911,8 +890,6 @@ msgid "Scrolling"
|
||||
msgstr "Desplazarse"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
@@ -925,7 +902,6 @@ msgstr "Seleccionar el siguiente feed/categoría no leído"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Seleccionar el anterior feed/categoría no leído"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL del servidor"
|
||||
@@ -954,8 +930,6 @@ msgstr "Compartir"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartir sitios"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1004,7 +978,6 @@ msgstr "Mostrar recuento de no leídos en la pestaña favicon"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Mostrar recuento de no leídos en el título de la pestaña"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1014,7 +987,6 @@ msgstr "Registrarse"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Algo malo acaba de pasar..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Espacio"
|
||||
@@ -1031,7 +1003,6 @@ msgstr "Estrella"
|
||||
msgid "Starred"
|
||||
msgstr "Destacado"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1065,7 +1036,6 @@ msgstr "Cambiar a tema claro"
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetas"
|
||||
@@ -1137,7 +1107,6 @@ msgstr "No leído"
|
||||
msgid "Unstar"
|
||||
msgstr "Desmarcar"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Cancelar suscripción"
|
||||
@@ -1150,7 +1119,6 @@ msgstr "Clave de usuario"
|
||||
msgid "User name"
|
||||
msgstr "Nombre de usuario"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nombre de usuario o correo electrónico"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "افزودن کاربر"
|
||||
msgid "Admin"
|
||||
msgstr "مدیر"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "نام کاربری مدیر"
|
||||
@@ -73,7 +72,6 @@ msgstr "نام کاربری مدیر"
|
||||
msgid "All"
|
||||
msgstr "همه"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "همیشه"
|
||||
@@ -173,18 +171,14 @@ msgstr "یک عبارت فیلتر بسازید تا نشان دهید چه چی
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "لغو"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "تأیید کنید"
|
||||
msgid "Confirm password"
|
||||
msgstr "رمز عبور را تأیید کنید"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "تأیید رمز عبور"
|
||||
@@ -294,7 +287,6 @@ msgstr "روز"
|
||||
msgid "Delete"
|
||||
msgstr "حذف کنید"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "حذف حساب"
|
||||
@@ -342,13 +334,10 @@ msgstr "پیوند را به نوار نشانک بکشید"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "ایمیل"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "آدرس ایمیل"
|
||||
@@ -399,7 +388,6 @@ msgstr "گزینه های افزونه"
|
||||
msgid "Feed name"
|
||||
msgstr "نام فید"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "بارگیری اشتراک ها..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "بارگیری برچسب ها..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "با وارد کردن نام اشتراک، به آن بروید"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "هنگام علامتگذاری همه ورودیها بهعنوان خواندهشده، به دستهبندی/فید بعدی با ورودیهای خواندهنشده بروید"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "هرگز"
|
||||
@@ -657,7 +643,6 @@ msgstr "هرگز"
|
||||
msgid "New password"
|
||||
msgstr "رمز عبور جدید"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "رمز عبور جدید"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "خروجی OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "فایل OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "دسته والد"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "رمز عبور"
|
||||
@@ -874,7 +855,6 @@ msgstr "تازه کردن"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "ثبت نام در این نمونه CommaFeed بسته شده است"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "بازنشانی رمز عبور"
|
||||
@@ -883,7 +863,6 @@ msgstr "بازنشانی رمز عبور"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "راست کلیک"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "پیمایش"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "جستجو"
|
||||
@@ -924,7 +901,6 @@ msgstr "انتخاب فید/دسته بعدی خوانده نشده"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "انتخاب فید/دسته قبلی خوانده نشده"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "آدرس سرور"
|
||||
@@ -953,8 +929,6 @@ msgstr "به اشتراک بگذارید"
|
||||
msgid "Sharing sites"
|
||||
msgstr "اشتراک گذاری سایت ها"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "شیفت"
|
||||
@@ -1003,7 +977,6 @@ msgstr "نمایش تعداد خوانده نشده در فاویکون زبان
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "نمایش تعداد خوانده نشده در عنوان زبانه"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "ثبت نام کنید"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "اتفاق بدی افتاد..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "فضا"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "ستاره"
|
||||
msgid "Starred"
|
||||
msgstr "ستاره دار"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "تغییر به تم روشن"
|
||||
msgid "System"
|
||||
msgstr "سیستم"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "برچسبها"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "خوانده نشده"
|
||||
msgid "Unstar"
|
||||
msgstr "برداشتن ستاره"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "لغو اشتراک"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "کلید کاربر"
|
||||
msgid "User name"
|
||||
msgstr "نام کاربری"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "نام کاربری یا ایمیل"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Lisää käyttäjä"
|
||||
msgid "Admin"
|
||||
msgstr "Järjestelmänvalvoja"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Järjestelmänvalvojan käyttäjänimi"
|
||||
@@ -73,7 +72,6 @@ msgstr "Järjestelmänvalvojan käyttäjänimi"
|
||||
msgid "All"
|
||||
msgstr "Kaikki"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Aina"
|
||||
@@ -173,18 +171,14 @@ msgstr "Rakenna suodatinlauseke määrittääksesi, mitä haluat lukea. Merkinn
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Peruuta"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Vahvista"
|
||||
msgid "Confirm password"
|
||||
msgstr "Vahvista salasana"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Vahvista salasana"
|
||||
@@ -294,7 +287,6 @@ msgstr "päivää"
|
||||
msgid "Delete"
|
||||
msgstr "Poista"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Poista tili"
|
||||
@@ -342,13 +334,10 @@ msgstr "Vedä linkki kirjanmerkkipalkkiin"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Sähköposti"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Sähköpostiosoite"
|
||||
@@ -399,7 +388,6 @@ msgstr "Laajennuksen asetukset"
|
||||
msgid "Feed name"
|
||||
msgstr "Syötteen nimi"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Ladataan tilauksia..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Ladataan tunnisteita..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Siirry tilaukseen kirjoittamalla sen nimi"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Siirry seuraavaan luokkaan/syötteeseen, jossa on lukemattomia merkintöjä, kun kaikki merkinnät merkitään luetuiksi"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Ei koskaan"
|
||||
@@ -657,7 +643,6 @@ msgstr "Ei koskaan"
|
||||
msgid "New password"
|
||||
msgstr "Uusi salasana"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Uusi salasana"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-vienti"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-tiedosto"
|
||||
@@ -791,10 +775,7 @@ msgstr "Pääluokka"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Salasana"
|
||||
@@ -874,7 +855,6 @@ msgstr "Päivitä"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Tämän CommaFeed-esiintymän rekisteröinnit on suljettu"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Nollaa salasana"
|
||||
@@ -883,7 +863,6 @@ msgstr "Nollaa salasana"
|
||||
msgid "REST API"
|
||||
msgstr "REST-API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Oikea napsautus"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Vieritys"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Etsi"
|
||||
@@ -924,7 +901,6 @@ msgstr "Valitse seuraava lukematon syöte/luokka"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Valitse edellinen lukematon syöte/luokka"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Palvelimen URL-osoite"
|
||||
@@ -953,8 +929,6 @@ msgstr "Jaa"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sivustojen jakaminen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Vaihto"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Näytä lukemattomien määrä välilehden kuvakkeessa"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Näytä lukemattomien määrä välilehden otsikossa"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Rekisteröidy"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Jotain pahaa tapahtui juuri..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Avaruus"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Tähti"
|
||||
msgid "Starred"
|
||||
msgstr "Tähdellä merkitty"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Vaihda vaaleaan teemaan"
|
||||
msgid "System"
|
||||
msgstr "Järjestelmä"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tunnisteet"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Lukematon"
|
||||
msgid "Unstar"
|
||||
msgstr "Poista tähti"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Peruuta tilaus"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Käyttäjäavain"
|
||||
msgid "User name"
|
||||
msgstr "Käyttäjänimi"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Käyttäjänimi tai sähköpostiosoite"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Ajouter un utilisateur"
|
||||
msgid "Admin"
|
||||
msgstr "Administrateur"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nom de l'administrateur"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nom de l'administrateur"
|
||||
msgid "All"
|
||||
msgstr "Tout"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Toujours"
|
||||
@@ -173,18 +171,14 @@ msgstr "Créez une expression régulière pour filtrer ce que vous voulez lire.
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Confirmer"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmer le mot de passe"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirmer le mot de passe"
|
||||
@@ -294,7 +287,6 @@ msgstr "jours"
|
||||
msgid "Delete"
|
||||
msgstr "Effacer"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Effacer le compte"
|
||||
@@ -342,13 +334,10 @@ msgstr "Déplacez le lien vers la barre de favoris"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Adresse e-mail"
|
||||
@@ -399,7 +388,6 @@ msgstr "Options de l'extension"
|
||||
msgid "Feed name"
|
||||
msgstr "Nom du flux"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Chargement des abonnements..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Chargement des marqueurs..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Naviguer vers un abonnement en entrant son nom"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Aller vers la catégorie/le flux comportant des entrées non lues suivant après avoir marqué toutes les entrées lues"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Jamais"
|
||||
@@ -657,7 +643,6 @@ msgstr "Jamais"
|
||||
msgid "New password"
|
||||
msgstr "Nouveau mot de passe"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nouveau mot de passe"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Export du fichier OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Fichier OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Catégorie parente"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
@@ -874,7 +855,6 @@ msgstr "Rafraîchir"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Les inscriptions sont fermées sur cette instance de CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Réinitialiser le mot de passe"
|
||||
@@ -883,7 +863,6 @@ msgstr "Réinitialiser le mot de passe"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic droit"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Défilement"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Rechercher"
|
||||
@@ -924,7 +901,6 @@ msgstr "Sélectionner l'article non lu suivant/la catégorie non lue suivante"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Sélectionner l'article non lu précédent/la catégorie non lue précédente"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL du serveur"
|
||||
@@ -953,8 +929,6 @@ msgstr "Partager"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sites de partage"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Maj"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Afficher le nombre d'entrées non lues dans la favicône de l'onglet"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Afficher le nombre d'entrées non lues dans le titre de l'onglet"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Créer un compte"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Quelque chose s'est mal passé..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Espace"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Ajouter aux favoris"
|
||||
msgid "Starred"
|
||||
msgstr "Favoris"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Activer le mode clair"
|
||||
msgid "System"
|
||||
msgstr "Système"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Marqueurs"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Non lu"
|
||||
msgid "Unstar"
|
||||
msgstr "Retirer des favoris"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Se désabonner"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Clé utilisateur"
|
||||
msgid "User name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nom d'utilisateur ou e-mail"
|
||||
|
||||
@@ -61,7 +61,6 @@ msgstr "Engadir persoa usuaria"
|
||||
msgid "Admin"
|
||||
msgstr "Administración"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Identificador de admin"
|
||||
@@ -74,7 +73,6 @@ msgstr "Identificador de admin"
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
@@ -174,18 +172,14 @@ msgstr "Crea unha expresión de filtrado para indicar o que queres ler. Os artig
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -241,7 +235,6 @@ msgstr "Confirmar"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmar contrasinal"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirmar contrasinal"
|
||||
@@ -295,7 +288,6 @@ msgstr "días"
|
||||
msgid "Delete"
|
||||
msgstr "Eliminar"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Eliminar conta"
|
||||
@@ -343,13 +335,10 @@ msgstr "Arrastra a ligazón á barra de marcadores"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Correo electrónico"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Enderezo de correo electrónico"
|
||||
@@ -400,7 +389,6 @@ msgstr "Opcións do complemento"
|
||||
msgid "Feed name"
|
||||
msgstr "Nome da canle"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -571,7 +559,6 @@ msgstr "Cargando subscricións..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Cargando etiquetas..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -649,7 +636,6 @@ msgstr "Vai a unha subscrición ao escribir o seu nome"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Vai á seguinte categoría/canle con artigos sen ler cando marques todos artigos como lidos"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nunca"
|
||||
@@ -658,7 +644,6 @@ msgstr "Nunca"
|
||||
msgid "New password"
|
||||
msgstr "Novo contrasinal"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Novo contrasinal"
|
||||
@@ -765,7 +750,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Exportación OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Ficheiro OPML"
|
||||
@@ -792,10 +776,7 @@ msgstr "Categoría superior"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Contrasinal"
|
||||
@@ -875,7 +856,6 @@ msgstr "Actualizar"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Non se admiten novas contas nesta instancia de CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Restablecer contrasinal"
|
||||
@@ -884,7 +864,6 @@ msgstr "Restablecer contrasinal"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Botón dereito"
|
||||
@@ -911,8 +890,6 @@ msgid "Scrolling"
|
||||
msgstr "Desprazamento"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Busca"
|
||||
@@ -925,7 +902,6 @@ msgstr "Seleccionar a seguinte canle/categoría sen ler"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Seleccionar a canle/categoría anterior sen ler"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL do servidor"
|
||||
@@ -954,8 +930,6 @@ msgstr "Compartir"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Servizos para compartir"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Maiúsculas"
|
||||
@@ -1004,7 +978,6 @@ msgstr "Mostrar a conta de artigos sen ler na icona da pestana"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Mostar a conta de artigos sen ler no título da pestana"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1014,7 +987,6 @@ msgstr "Crear conta"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Algo malo pasou..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Espazo"
|
||||
@@ -1031,7 +1003,6 @@ msgstr "Pór estrela"
|
||||
msgid "Starred"
|
||||
msgstr "Con estrela"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1065,7 +1036,6 @@ msgstr "Cambiar ao decorado claro"
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetas"
|
||||
@@ -1137,7 +1107,6 @@ msgstr "Sen ler"
|
||||
msgid "Unstar"
|
||||
msgstr "Retirar estrela"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Cancelar a subscrición"
|
||||
@@ -1150,7 +1119,6 @@ msgstr "Clave de usuario"
|
||||
msgid "User name"
|
||||
msgstr "Identificador"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Identificador ou correo electrónico"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Felhasználó hozzáadása"
|
||||
msgid "Admin"
|
||||
msgstr "Adminisztráció"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Adminisztrátor felhasználóneve"
|
||||
@@ -73,7 +72,6 @@ msgstr "Adminisztrátor felhasználóneve"
|
||||
msgid "All"
|
||||
msgstr "Mind"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Mindig"
|
||||
@@ -173,18 +171,14 @@ msgstr "Hozzon létre egy szűrőkifejezést annak megjelölésére, hogy mit sz
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Mégse"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Erősítse meg"
|
||||
msgid "Confirm password"
|
||||
msgstr "Erősítse meg a jelszót"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Jelszó megerősítése"
|
||||
@@ -294,7 +287,6 @@ msgstr "nap"
|
||||
msgid "Delete"
|
||||
msgstr "Törlés"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Fiók törlése"
|
||||
@@ -342,13 +334,10 @@ msgstr "Húzza a hivatkozást a könyvjelzősávra"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mail cím"
|
||||
@@ -399,7 +388,6 @@ msgstr "Bővítmény beállításai"
|
||||
msgid "Feed name"
|
||||
msgstr "Hírcsatorna neve"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Előfizetések betöltése..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Címkék betöltése..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigáljon egy előfizetéshez a nevének megadásával"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigálás a következő olvasatlan bejegyzéseket tartalmazó kategóriára/hírcsatornára, ha minden bejegyzést olvasottnak jelöl"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Soha"
|
||||
@@ -657,7 +643,6 @@ msgstr "Soha"
|
||||
msgid "New password"
|
||||
msgstr "Új jelszó"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Új jelszó"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML exportálás"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML fájl"
|
||||
@@ -791,10 +775,7 @@ msgstr "Szülő kategória"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Jelszó"
|
||||
@@ -874,7 +855,6 @@ msgstr "Frissítés"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "A regisztrációk le vannak zárva ezen a CommaFeed példányon"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Jelszó visszaállítása"
|
||||
@@ -883,7 +863,6 @@ msgstr "Jelszó visszaállítása"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Jobb klikk"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Görgetés"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Keresés"
|
||||
@@ -924,7 +901,6 @@ msgstr "Következő olvasatlan feed/kategória kiválasztása"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Előző olvasatlan feed/kategória kiválasztása"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Szerver URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Oszd meg"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Webhelyek megosztása"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Olvasatlan darabszám megjelenítése a tab faviconján"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Olvasatlan darabszám megjelenítése a tab címében"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Regisztráció"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Valami rossz történt..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Szóköz"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Csillag"
|
||||
msgid "Starred"
|
||||
msgstr "Csillaggal megjelölve"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Váltás világos témára"
|
||||
msgid "System"
|
||||
msgstr "Rendszer"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Címkék"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Olvasatlan"
|
||||
msgid "Unstar"
|
||||
msgstr "Csillag eltávolítása"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Leiratkozás"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Felhasználói kulcs"
|
||||
msgid "User name"
|
||||
msgstr "Felhasználónév"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Felhasználói név vagy e-mail cím"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Tambahkan pengguna"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nama pengguna admin"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nama pengguna admin"
|
||||
msgid "All"
|
||||
msgstr "Semua"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Selalu"
|
||||
@@ -173,18 +171,14 @@ msgstr "Bangun ekspresi filter untuk menunjukkan apa yang ingin Anda baca. Entri
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Batal"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Konfirmasi"
|
||||
msgid "Confirm password"
|
||||
msgstr "Konfirmasi kata sandi"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Konfirmasi Kata Sandi"
|
||||
@@ -294,7 +287,6 @@ msgstr "hari"
|
||||
msgid "Delete"
|
||||
msgstr "Hapus"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Hapus akun"
|
||||
@@ -342,13 +334,10 @@ msgstr "Seret tautan ke bilah bookmark"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Email"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Alamat email"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opsi ekstensi"
|
||||
msgid "Feed name"
|
||||
msgstr "Nama umpan"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Memuat langganan..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Memuat tag..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigasikan ke langganan dengan memasukkan namanya"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigasikan ke kategori/umpan berikutnya dengan entri yang belum dibaca saat menandai semua entri sebagai telah dibaca"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Tidak pernah"
|
||||
@@ -657,7 +643,6 @@ msgstr "Tidak pernah"
|
||||
msgid "New password"
|
||||
msgstr "Kata sandi baru"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Kata Sandi Baru"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "ekspor OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "file OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Kategori Induk"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Kata Sandi"
|
||||
@@ -874,7 +855,6 @@ msgstr "Segarkan"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Pendaftaran ditutup pada instans CommaFeed ini"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Atur Ulang Kata Sandi"
|
||||
@@ -883,7 +863,6 @@ msgstr "Atur Ulang Kata Sandi"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Klik kanan"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Menggulir"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Pencarian"
|
||||
@@ -924,7 +901,6 @@ msgstr "Pilih umpan/kategori belum dibaca berikutnya"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Pilih umpan/kategori belum dibaca sebelumnya"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL Server"
|
||||
@@ -953,8 +929,6 @@ msgstr "Bagikan"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Berbagi situs"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Pergeseran"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Tampilkan jumlah yang belum dibaca di favicon tab"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Tampilkan jumlah yang belum dibaca di judul tab"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Daftar"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Sesuatu yang buruk baru saja terjadi..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Spasi"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Bintang"
|
||||
msgid "Starred"
|
||||
msgstr "Berbintang"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Beralih ke tema terang"
|
||||
msgid "System"
|
||||
msgstr "Sistem"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tag"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Belum Dibaca"
|
||||
msgid "Unstar"
|
||||
msgstr "Hapus bintang"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Berhenti berlangganan"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Kunci pengguna"
|
||||
msgid "User name"
|
||||
msgstr "Nama pengguna"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nama Pengguna atau Email"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Aggiungi utente"
|
||||
msgid "Admin"
|
||||
msgstr "Ammin"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nome utente amministratore"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nome utente amministratore"
|
||||
msgid "All"
|
||||
msgstr "Tutto"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
@@ -173,18 +171,14 @@ msgstr "Crea un'espressione di filtro per indicare cosa vuoi leggere. Le voci ch
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Annulla"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Conferma"
|
||||
msgid "Confirm password"
|
||||
msgstr "Conferma password"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Conferma password"
|
||||
@@ -294,7 +287,6 @@ msgstr "giorni"
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Elimina account"
|
||||
@@ -342,13 +334,10 @@ msgstr "Trascina il collegamento sulla barra dei preferiti"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Indirizzo e-mail"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opzioni estensione"
|
||||
msgid "Feed name"
|
||||
msgstr "Nome del feed"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Caricamento abbonamenti..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Caricamento tag..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigare verso un abbonamento inserendo il suo nome"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Passa alla categoria/feed successivo con voci non lette quando contrassegni tutte le voci come lette"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Mai"
|
||||
@@ -657,7 +643,6 @@ msgstr "Mai"
|
||||
msgid "New password"
|
||||
msgstr "Nuova password"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nuova password"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Esportazione OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "File OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Categoria padre"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
@@ -874,7 +855,6 @@ msgstr "Aggiorna"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Le registrazioni sono chiuse su questa istanza CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Reimposta password"
|
||||
@@ -883,7 +863,6 @@ msgstr "Reimposta password"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic destro"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Scorrimento"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
@@ -924,7 +901,6 @@ msgstr "Seleziona il feed/categoria non letto successivo"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Seleziona il feed/categoria non letto precedente"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL del server"
|
||||
@@ -953,8 +929,6 @@ msgstr "Condividi"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Condivisione di siti"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Cambio"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Mostra il numero di non letti nella favicon della scheda"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Mostra il numero di non letti nel titolo della scheda"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Iscriviti"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "È appena successo qualcosa di brutto..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Spazio"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stella"
|
||||
msgid "Starred"
|
||||
msgstr "Speciali"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Passa al tema chiaro"
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tag"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Non letto"
|
||||
msgid "Unstar"
|
||||
msgstr "Elimina le stelle"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Annulla iscrizione"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Chiave utente"
|
||||
msgid "User name"
|
||||
msgstr "Nome utente"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nome utente o e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "ユーザー追加"
|
||||
msgid "Admin"
|
||||
msgstr "管理者"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "管理者ユーザー名"
|
||||
@@ -73,7 +72,6 @@ msgstr "管理者ユーザー名"
|
||||
msgid "All"
|
||||
msgstr "すべて"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "常に"
|
||||
@@ -173,18 +171,14 @@ msgstr "読みたい内容を指定するためのフィルタ式を作成しま
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "確認"
|
||||
msgid "Confirm password"
|
||||
msgstr "パスワード確認"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "パスワードの確認"
|
||||
@@ -294,7 +287,6 @@ msgstr "日"
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "アカウント削除"
|
||||
@@ -342,13 +334,10 @@ msgstr "リンクをブックマークバーにドラッグ"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "メール"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "メールアドレス"
|
||||
@@ -399,7 +388,6 @@ msgstr "拡張機能オプション"
|
||||
msgid "Feed name"
|
||||
msgstr "フィード名"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "サブスクリプションを読み込んでいます..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "タグを読み込んでいます..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "名前を入力してサブスクリプションに移動します"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "すべてのエントリーを既読にするとき、未読エントリーのある次のカテゴリ/フィードに移動する"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "しない"
|
||||
@@ -657,7 +643,6 @@ msgstr "しない"
|
||||
msgid "New password"
|
||||
msgstr "新しいパスワード"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "新しいパスワード"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML エクスポート"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPMLファイル"
|
||||
@@ -791,10 +775,7 @@ msgstr "親カテゴリ"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "パスワード"
|
||||
@@ -874,7 +855,6 @@ msgstr "リフレッシュ"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "このCommaFeedインスタンスの登録は終了しています"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "パスワードをリセット"
|
||||
@@ -883,7 +863,6 @@ msgstr "パスワードをリセット"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "右クリック"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "スクロール"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "検索"
|
||||
@@ -924,7 +901,6 @@ msgstr "次の未読フィード/カテゴリを選択"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "前の未読フィード/カテゴリを選択"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "サーバーURL"
|
||||
@@ -953,8 +929,6 @@ msgstr "シェア"
|
||||
msgid "Sharing sites"
|
||||
msgstr "共有サイト"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "未読数をタブのアイコンに表示する"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "未読数をタブのタイトルに表示する"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "サインアップ"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "何か悪いことが起きました..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Space"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "スター"
|
||||
msgid "Starred"
|
||||
msgstr "スター付き"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "ライトテーマに切り替え"
|
||||
msgid "System"
|
||||
msgstr "システム"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "タグ"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "未読"
|
||||
msgid "Unstar"
|
||||
msgstr "スターを外す"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "退会"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "ユーザーキー"
|
||||
msgid "User name"
|
||||
msgstr "ユーザー名"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "ユーザー名またはメールアドレス"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "사용자 추가"
|
||||
msgid "Admin"
|
||||
msgstr "관리자"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "관리자 사용자 이름"
|
||||
@@ -73,7 +72,6 @@ msgstr "관리자 사용자 이름"
|
||||
msgid "All"
|
||||
msgstr "전체"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "항상"
|
||||
@@ -173,18 +171,14 @@ msgstr "읽고 싶은 항목을 지정하기 위한 필터 표현식을 작성
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "확인"
|
||||
msgid "Confirm password"
|
||||
msgstr "비밀번호 확인"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "비밀번호 확인"
|
||||
@@ -294,7 +287,6 @@ msgstr "일"
|
||||
msgid "Delete"
|
||||
msgstr "삭제"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "계정 삭제"
|
||||
@@ -342,13 +334,10 @@ msgstr "링크를 북마크바로 드래그"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "이메일"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "이메일 주소"
|
||||
@@ -399,7 +388,6 @@ msgstr "확장 프로그램 옵션"
|
||||
msgid "Feed name"
|
||||
msgstr "피드 이름"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "구독 로드 중..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "태그 로드 중..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "이름을 입력하여 구독으로 이동"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "모든 항목을 읽음으로 표시할 때 읽지 않은 항목이 있는 다음 카테고리/피드로 이동"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "안 함"
|
||||
@@ -657,7 +643,6 @@ msgstr "안 함"
|
||||
msgid "New password"
|
||||
msgstr "새 비밀번호"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "새 비밀번호"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML 내보내기"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML 파일"
|
||||
@@ -791,10 +775,7 @@ msgstr "부모 카테고리"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "비밀번호"
|
||||
@@ -874,7 +855,6 @@ msgstr "새로 고침"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "이 CommaFeed 인스턴스에 대한 등록이 마감되었습니다."
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "비밀번호 재설정"
|
||||
@@ -883,7 +863,6 @@ msgstr "비밀번호 재설정"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "오른쪽 클릭"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "스크롤"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "검색"
|
||||
@@ -924,7 +901,6 @@ msgstr "다음 읽지 않은 피드/카테고리 선택"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "이전 읽지 않은 피드/카테고리 선택"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "서버 URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "공유"
|
||||
msgid "Sharing sites"
|
||||
msgstr "사이트 공유"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "시프트"
|
||||
@@ -1003,7 +977,6 @@ msgstr "탭 파비콘에 읽지 않은 개수 표시"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "탭 제목에 읽지 않은 개수 표시"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "가입"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "뭔가 안 좋은 일이 일어났어..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "우주"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "스타"
|
||||
msgid "Starred"
|
||||
msgstr "별표"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "밝은 테마로 전환"
|
||||
msgid "System"
|
||||
msgstr "시스템"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "태그"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "읽지 않음"
|
||||
msgid "Unstar"
|
||||
msgstr "별표 제거"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "구독 취소"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "사용자 키"
|
||||
msgid "User name"
|
||||
msgstr "사용자 이름"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "사용자 이름 또는 이메일"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Tambah pengguna"
|
||||
msgid "Admin"
|
||||
msgstr "Pentadbir"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nama pengguna pentadbir"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nama pengguna pentadbir"
|
||||
msgid "All"
|
||||
msgstr "Semua"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Sentiasa"
|
||||
@@ -173,18 +171,14 @@ msgstr "Bina ungkapan penapis untuk menunjukkan perkara yang anda mahu baca. Ent
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Batal"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Sahkan"
|
||||
msgid "Confirm password"
|
||||
msgstr "Sahkan kata laluan"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Sahkan Kata Laluan"
|
||||
@@ -294,7 +287,6 @@ msgstr "hari"
|
||||
msgid "Delete"
|
||||
msgstr "Padam"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Padam akaun"
|
||||
@@ -342,13 +334,10 @@ msgstr "Seret pautan ke bar penanda halaman"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mel"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Alamat e-mel"
|
||||
@@ -399,7 +388,6 @@ msgstr "Pilihan ekstensi"
|
||||
msgid "Feed name"
|
||||
msgstr "Nama suapan"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Memuatkan langganan..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Memuatkan tag..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigasi ke langganan dengan memasukkan namanya"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigasi ke kategori/suapan seterusnya dengan entri yang belum dibaca apabila menandakan semua entri sebagai dibaca"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Tidak pernah"
|
||||
@@ -657,7 +643,6 @@ msgstr "Tidak pernah"
|
||||
msgid "New password"
|
||||
msgstr "Kata laluan baharu"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Kata Laluan Baharu"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML eksport"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Fail OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Kategori Induk"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Kata Laluan"
|
||||
@@ -874,7 +855,6 @@ msgstr "Muat semula"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Pendaftaran ditutup pada contoh CommaFeed ini"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Tetap Semula Kata Laluan"
|
||||
@@ -883,7 +863,6 @@ msgstr "Tetap Semula Kata Laluan"
|
||||
msgid "REST API"
|
||||
msgstr "REHAT API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Klik kanan"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Menatal"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Cari"
|
||||
@@ -924,7 +901,6 @@ msgstr "Pilih suapan/kategori belum dibaca seterusnya"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Pilih suapan/kategori belum dibaca sebelumnya"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL Pelayan"
|
||||
@@ -953,8 +929,6 @@ msgstr "Kongsi"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Berkongsi tapak"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Anjakan"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Tunjukkan kiraan belum dibaca dalam favicon tab"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Tunjukkan kiraan belum dibaca dalam tajuk tab"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Daftar"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Sesuatu yang buruk baru saja berlaku..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Angkasa"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Bintang"
|
||||
msgid "Starred"
|
||||
msgstr "Dibintangi"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Tukar kepada tema cahaya"
|
||||
msgid "System"
|
||||
msgstr "Sistem"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tag"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Belum dibaca"
|
||||
msgid "Unstar"
|
||||
msgstr "Nyahbintang"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Nyahlanggan"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Kunci pengguna"
|
||||
msgid "User name"
|
||||
msgstr "Nama pengguna"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nama Pengguna atau E-mel"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Legg til bruker"
|
||||
msgid "Admin"
|
||||
msgstr "Administrator"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Administrator brukernavn"
|
||||
@@ -73,7 +72,6 @@ msgstr "Administrator brukernavn"
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Alltid"
|
||||
@@ -173,18 +171,14 @@ msgstr "Bygg et filteruttrykk for å angi hva du vil lese. Oppføringer som ikke
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bekreft"
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekreft passord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Bekreft passord"
|
||||
@@ -294,7 +287,6 @@ msgstr "dager"
|
||||
msgid "Delete"
|
||||
msgstr "Slett"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Slett konto"
|
||||
@@ -342,13 +334,10 @@ msgstr "Dra lenken til bokmerkelinjen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-post"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-postadresse"
|
||||
@@ -399,7 +388,6 @@ msgstr "Utvidelsesvalg"
|
||||
msgid "Feed name"
|
||||
msgstr "Feednavn"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Laster abonnementer..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Laster tagger..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Naviger til et abonnement ved å skrive inn navnet"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Naviger til neste kategori/feed med uleste oppføringer når du markerer alle oppføringer som lest"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Aldri"
|
||||
@@ -657,7 +643,6 @@ msgstr "Aldri"
|
||||
msgid "New password"
|
||||
msgstr "Nytt passord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nytt passord"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-eksport"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-fil"
|
||||
@@ -791,10 +775,7 @@ msgstr "Overordnet kategori"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Passord"
|
||||
@@ -874,7 +855,6 @@ msgstr "Oppdater"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registreringer er stengt på denne CommaFeed-forekomsten"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Tilbakestill passord"
|
||||
@@ -883,7 +863,6 @@ msgstr "Tilbakestill passord"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Høyreklikk"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Rulling"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Søk"
|
||||
@@ -924,7 +901,6 @@ msgstr "Velg neste uleste feed/kategori"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Velg forrige uleste feed/kategori"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Vis antall uleste i fanens favicon"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Vis antall uleste i fanetittelen"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Meld deg på"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Noe ille skjedde akkurat..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Mellomrom"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stjerne"
|
||||
msgid "Starred"
|
||||
msgstr "Stjerne"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Bytt til lystema"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tagger"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Ulest"
|
||||
msgid "Unstar"
|
||||
msgstr "Fjern stjerne"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Avslutt abonnement"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Brukernøkkel"
|
||||
msgid "User name"
|
||||
msgstr "Brukernavn"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Brukernavn eller e-post"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Gebruiker toevoegen"
|
||||
msgid "Admin"
|
||||
msgstr "Beheerder"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Gebruikersnaam beheerder"
|
||||
@@ -73,7 +72,6 @@ msgstr "Gebruikersnaam beheerder"
|
||||
msgid "All"
|
||||
msgstr "Alles"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Altijd"
|
||||
@@ -173,18 +171,14 @@ msgstr "Maak een filterexpressie om aan te geven wat u wilt lezen. Items die nie
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Annuleren"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bevestigen"
|
||||
msgid "Confirm password"
|
||||
msgstr "Bevestig wachtwoord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Bevestig wachtwoord"
|
||||
@@ -294,7 +287,6 @@ msgstr "dagen"
|
||||
msgid "Delete"
|
||||
msgstr "Verwijderen"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Account verwijderen"
|
||||
@@ -342,13 +334,10 @@ msgstr "Link naar bladwijzerbalk slepen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mailadres"
|
||||
@@ -399,7 +388,6 @@ msgstr "Extensie opties"
|
||||
msgid "Feed name"
|
||||
msgstr "Feednaam"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Abonnementen laden..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Tags laden..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigeer naar een abonnement door de naam in te voeren"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigeer naar de volgende categorie/feed met ongelezen items wanneer alle items als gelezen worden gemarkeerd"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nooit"
|
||||
@@ -657,7 +643,6 @@ msgstr "Nooit"
|
||||
msgid "New password"
|
||||
msgstr "Nieuw wachtwoord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nieuw wachtwoord"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-export"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-bestand"
|
||||
@@ -791,10 +775,7 @@ msgstr "Oudercategorie"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Wachtwoord"
|
||||
@@ -874,7 +855,6 @@ msgstr "Vernieuwen"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registraties zijn gesloten op deze CommaFeed-instantie"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Wachtwoord herstellen"
|
||||
@@ -883,7 +863,6 @@ msgstr "Wachtwoord herstellen"
|
||||
msgid "REST API"
|
||||
msgstr "REST-API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Rechtermuisklik"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Scrollen"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Zoeken"
|
||||
@@ -924,7 +901,6 @@ msgstr "Selecteer volgende ongelezen feed/categorie"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Selecteer vorige ongelezen feed/categorie"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Delen"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sites delen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Toon aantal ongelezen in tabblad-favicon"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Toon aantal ongelezen in tabbladtitel"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Aanmelden"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Er is net iets ergs gebeurd..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Ruimte"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Ster"
|
||||
msgid "Starred"
|
||||
msgstr "Met ster"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Schakel over naar licht thema"
|
||||
msgid "System"
|
||||
msgstr "Systeem"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tags"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Ongelezen"
|
||||
msgid "Unstar"
|
||||
msgstr "Sterren uit"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Afmelden"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Gebruikerssleutel"
|
||||
msgid "User name"
|
||||
msgstr "Gebruikersnaam"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Gebruikersnaam of e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Legg til brukar"
|
||||
msgid "Admin"
|
||||
msgstr "Administrator"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Brukarnamn for administrator"
|
||||
@@ -73,7 +72,6 @@ msgstr "Brukarnamn for administrator"
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Alltid"
|
||||
@@ -173,18 +171,14 @@ msgstr "Bygg eit filteruttrykk for å angis kva du vil lesa. Innlegg som ikkje s
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bekreft"
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekreft passord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Stadfest passord"
|
||||
@@ -294,7 +287,6 @@ msgstr "dagar"
|
||||
msgid "Delete"
|
||||
msgstr "Slett"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Slett konto"
|
||||
@@ -342,13 +334,10 @@ msgstr "Dra lenken til bokmerkelinjen"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-post"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-postadresse"
|
||||
@@ -399,7 +388,6 @@ msgstr "Val for utviding"
|
||||
msgid "Feed name"
|
||||
msgstr "Feednavn"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Laster abonnementer..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Laster tagger..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Naviger til et abonnement ved å skrive inn navnet"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Naviger til neste kategori/suap med ulesne innlegg når du markerer alle innlegg som lesne"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Aldri"
|
||||
@@ -657,7 +643,6 @@ msgstr "Aldri"
|
||||
msgid "New password"
|
||||
msgstr "Nytt passord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nytt passord"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-eksport"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-fil"
|
||||
@@ -791,10 +775,7 @@ msgstr "Overordnet kategori"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Passord"
|
||||
@@ -874,7 +855,6 @@ msgstr "Oppdater"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registreringer er stengt på denne CommaFeed-forekomsten"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Tilbakestill passord"
|
||||
@@ -883,7 +863,6 @@ msgstr "Tilbakestill passord"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Høgreklikk"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Rulling"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Søk"
|
||||
@@ -924,7 +901,6 @@ msgstr "Vel neste ulesne suap/kategori"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Vel førre ulesne suap/kategori"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Vis talet på ulesne i favicon for fana"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Vis talet på ulesne i tittelen på fana"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Meld deg på"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Noe ille skjedde akkurat..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Mellomrom"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stjerne"
|
||||
msgid "Starred"
|
||||
msgstr "Stjernemerka"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Bytt til lyst tema"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tagger"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Ulesen"
|
||||
msgid "Unstar"
|
||||
msgstr "Fjern stjerne"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Avslutt abonnement"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Brukarnøkkel"
|
||||
msgid "User name"
|
||||
msgstr "Brukarnamn"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Brukarnamn eller e-post"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Dodaj użytkownika"
|
||||
msgid "Admin"
|
||||
msgstr "Administracja"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nazwa użytkownika administratora"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nazwa użytkownika administratora"
|
||||
msgid "All"
|
||||
msgstr "Wszystkie"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Zawsze"
|
||||
@@ -173,18 +171,14 @@ msgstr "Zbuduj wyrażenie filtrujące, aby wskazać, co chcesz czytać. Wpisy, k
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Anuluj"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Potwierdź"
|
||||
msgid "Confirm password"
|
||||
msgstr "Potwierdź hasło"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Potwierdź hasło"
|
||||
@@ -294,7 +287,6 @@ msgstr "dni"
|
||||
msgid "Delete"
|
||||
msgstr "Usuń"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Usuń konto"
|
||||
@@ -342,13 +334,10 @@ msgstr "Przeciągnij link do paska zakładek"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Adres e-mail"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opcje rozszerzenia"
|
||||
msgid "Feed name"
|
||||
msgstr "nazwa kanału"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Ładowanie subskrypcji..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Ładowanie tagów..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Przejdź do subskrypcji, wpisując jej nazwę"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Przejdź do następnej kategorii/kanału z nieprzeczytanymi wpisami po oznaczeniu wszystkich wpisów jako przeczytane"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nigdy"
|
||||
@@ -657,7 +643,6 @@ msgstr "Nigdy"
|
||||
msgid "New password"
|
||||
msgstr "Nowe hasło"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nowe hasło"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Eksport OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Plik OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Kategoria nadrzędna"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Hasło"
|
||||
@@ -874,7 +855,6 @@ msgstr "Odśwież"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Rejestracje są zamknięte w tej instancji CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Zresetuj hasło"
|
||||
@@ -883,7 +863,6 @@ msgstr "Zresetuj hasło"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Prawe kliknięcie"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Przewijanie"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Szukaj"
|
||||
@@ -924,7 +901,6 @@ msgstr "Wybierz następny nieprzeczytany kanał/kategorię"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Wybierz poprzedni nieprzeczytany kanał/kategorię"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL serwera"
|
||||
@@ -953,8 +929,6 @@ msgstr "Udostępnij"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Udostępnianie witryn"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "zmiana"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Pokazuj liczbę nieprzeczytanych na ikonie karty"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Pokazuj liczbę nieprzeczytanych w tytule karty"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Zarejestruj się"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Coś złego właśnie się stało..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Przestrzeń"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Gwiazda"
|
||||
msgid "Starred"
|
||||
msgstr "Oznaczone gwiazdką"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Przełącz na jasny motyw"
|
||||
msgid "System"
|
||||
msgstr "Systemowy"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Tagi"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Nieprzeczytane"
|
||||
msgid "Unstar"
|
||||
msgstr "Usuń gwiazdkę"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Anuluj subskrypcję"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Klucz użytkownika"
|
||||
msgid "User name"
|
||||
msgstr "Nazwa użytkownika"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nazwa użytkownika lub e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Adicionar usuário"
|
||||
msgid "Admin"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Nome de usuário do administrador"
|
||||
@@ -73,7 +72,6 @@ msgstr "Nome de usuário do administrador"
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
@@ -173,18 +171,14 @@ msgstr "Crie uma expressão de filtro para indicar o que você deseja ler. As en
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Confirmar"
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmar senha"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Confirmar senha"
|
||||
@@ -294,7 +287,6 @@ msgstr "dias"
|
||||
msgid "Delete"
|
||||
msgstr "Excluir"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Excluir conta"
|
||||
@@ -342,13 +334,10 @@ msgstr "Arraste o link para a barra de favoritos"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Endereço de e-mail"
|
||||
@@ -399,7 +388,6 @@ msgstr "Opções da extensão"
|
||||
msgid "Feed name"
|
||||
msgstr "Nome do feed"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Carregando assinaturas..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Carregando tags..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navegue até uma assinatura digitando seu nome"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navegar para a próxima categoria/feed com entradas não lidas quando todas as entrafas forem lidas"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nunca"
|
||||
@@ -657,7 +643,6 @@ msgstr "Nunca"
|
||||
msgid "New password"
|
||||
msgstr "Nova senha"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nova senha"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Exportação OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Arquivo OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Categoria Pai"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Senha"
|
||||
@@ -874,7 +855,6 @@ msgstr "Atualizar"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Os registros estão fechados nesta instância do CommaFeed"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Redefinir senha"
|
||||
@@ -883,7 +863,6 @@ msgstr "Redefinir senha"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clique com o botão direito"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Deslizar"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Pesquisar"
|
||||
@@ -924,7 +901,6 @@ msgstr "Selecionar próximo feed/categoria não lido"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Selecionar feed/categoria não lido anterior"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL do servidor"
|
||||
@@ -953,8 +929,6 @@ msgstr "Compartilhar"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartilhando sites"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Mostrar contagem de não lidos no favion da aba"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Mostrar contagem de não lidos no título da aba"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Inscreva-se"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Algo ruim acabou de acontecer..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Espaço"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Estrela"
|
||||
msgid "Starred"
|
||||
msgstr "Com estrela"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Mudar para tema claro"
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Etiquetas"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Não lido"
|
||||
msgid "Unstar"
|
||||
msgstr "Desestrelar"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Cancelar inscrição"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Chave do usuário"
|
||||
msgid "User name"
|
||||
msgstr "Nome de usuário"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Nome de usuário ou e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Добавить пользователя"
|
||||
msgid "Admin"
|
||||
msgstr "Админ"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Имя администратора"
|
||||
@@ -73,7 +72,6 @@ msgstr "Имя администратора"
|
||||
msgid "All"
|
||||
msgstr "Все"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Всегда"
|
||||
@@ -173,18 +171,14 @@ msgstr "Создайте выражение фильтра, чтобы указ
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Подтвердить"
|
||||
msgid "Confirm password"
|
||||
msgstr "Подтвердить пароль"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Подтвердите пароль"
|
||||
@@ -294,7 +287,6 @@ msgstr "дней"
|
||||
msgid "Delete"
|
||||
msgstr "Удалить"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Удалить учетную запись"
|
||||
@@ -342,13 +334,10 @@ msgstr "Перетащите ссылку на панель закладок"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "Электронная почта"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "Адрес электронной почты"
|
||||
@@ -399,7 +388,6 @@ msgstr "Параметры расширения"
|
||||
msgid "Feed name"
|
||||
msgstr "Имя фида"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Загрузка подписок..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Загрузка тегов..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Перейдите к подписке, введя ее имя."
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Переходить к следующей категории/фиду с непрочитанными записями при пометке всех записей как прочитанных"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Никогда"
|
||||
@@ -657,7 +643,6 @@ msgstr "Никогда"
|
||||
msgid "New password"
|
||||
msgstr "Новый пароль"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Новый пароль"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Экспорт OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML файл"
|
||||
@@ -791,10 +775,7 @@ msgstr "Родительская категория"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Пароль"
|
||||
@@ -874,7 +855,6 @@ msgstr "Обновить"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Регистрация закрыта для этого экземпляра CommaFeed."
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Сброс пароля"
|
||||
@@ -883,7 +863,6 @@ msgstr "Сброс пароля"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Правый клик"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Прокрутка"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
@@ -924,7 +901,6 @@ msgstr "Выбрать следующий непрочитанный фид/ка
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Выбрать предыдущий непрочитанный фид/категорию"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL сервера"
|
||||
@@ -953,8 +929,6 @@ msgstr "Поделиться"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Обмен сайтами"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Показывать количество непрочитанных в
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Показывать количество непрочитанных в заголовке вкладки"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Зарегистрироваться"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Только что случилось что-то плохое..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Пробел"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "В избранное"
|
||||
msgid "Starred"
|
||||
msgstr "Избранное"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Переключиться на светлую тему"
|
||||
msgid "System"
|
||||
msgstr "Системная"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Теги"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Не прочитано"
|
||||
msgid "Unstar"
|
||||
msgstr "Удалить из избранного"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Отписаться"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Ключ пользователя"
|
||||
msgid "User name"
|
||||
msgstr "Имя пользователя"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Имя пользователя или адрес электронной почты"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Pridať užívateľa"
|
||||
msgid "Admin"
|
||||
msgstr "Správca"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Meno správcu"
|
||||
@@ -73,7 +72,6 @@ msgstr "Meno správcu"
|
||||
msgid "All"
|
||||
msgstr "Všetky"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Vždy"
|
||||
@@ -173,18 +171,14 @@ msgstr "Vytvorte výraz filtra na určenie toho, čo chcete čítať. Záznamy,
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušiť"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Potvrdiť"
|
||||
msgid "Confirm password"
|
||||
msgstr "Potvrďte heslo"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Potvrdiť heslo"
|
||||
@@ -294,7 +287,6 @@ msgstr "dni"
|
||||
msgid "Delete"
|
||||
msgstr "Vymazať"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Vymažte účet"
|
||||
@@ -342,13 +334,10 @@ msgstr "Presuňte odkaz na lištu so záložkami"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-mailová adresa"
|
||||
@@ -399,7 +388,6 @@ msgstr "Možnosti rozšírenia"
|
||||
msgid "Feed name"
|
||||
msgstr "Názov informačného kanála"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Načítavam odbery..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Načítavam značky..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Prejdite na predplatné zadaním jeho názvu"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Pri označovaní všetkých položiek ako prečítaných prejdite na ďalšiu kategóriu/kanál s neprečítanými položkami"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Nikdy"
|
||||
@@ -657,7 +643,6 @@ msgstr "Nikdy"
|
||||
msgid "New password"
|
||||
msgstr "Nové heslo"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nové heslo"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "Export OPML"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "Súbor OPML"
|
||||
@@ -791,10 +775,7 @@ msgstr "Rodičovská kategória"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Heslo"
|
||||
@@ -874,7 +855,6 @@ msgstr "Obnoviť"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "V tejto inštancii CommaFeed sú registrácie uzavreté"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Obnoviť heslo"
|
||||
@@ -883,7 +863,6 @@ msgstr "Obnoviť heslo"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Kliknutie pravým tlačidlom"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Rolovanie"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Hľadaj"
|
||||
@@ -924,7 +901,6 @@ msgstr "Vybrať ďalší neprečítaný kanál/kategóriu"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Vybrať predchádzajúci neprečítaný kanál/kategóriu"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "URL servera"
|
||||
@@ -953,8 +929,6 @@ msgstr "Zdieľať"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Zdieľanie stránok"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Smena"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Zobraziť počet neprečítaných v ikone karty"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Zobraziť počet neprečítaných v názve karty"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Zaregistrujte sa"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Práve sa stalo niečo zlé..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Medzera"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Hviezda"
|
||||
msgid "Starred"
|
||||
msgstr "S hviezdičkou"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Prepnite na svetlú tému"
|
||||
msgid "System"
|
||||
msgstr "Systém"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Značky"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Neprečítané"
|
||||
msgid "Unstar"
|
||||
msgstr "Odobrať hviezdičku"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Zrušte odber"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Používateľský kľúč"
|
||||
msgid "User name"
|
||||
msgstr "Meno používateľa"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Meno používateľa alebo e-mail"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Lägg till användare"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Administratörsanvändarnamn"
|
||||
@@ -73,7 +72,6 @@ msgstr "Administratörsanvändarnamn"
|
||||
msgid "All"
|
||||
msgstr "Alla"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Alltid"
|
||||
@@ -173,18 +171,14 @@ msgstr "Skapa ett filteruttryck för att ange vad du vill läsa. Poster som inte
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Bekräfta"
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekräfta lösenord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Bekräfta lösenord"
|
||||
@@ -294,7 +287,6 @@ msgstr "dagar"
|
||||
msgid "Delete"
|
||||
msgstr "Ta bort"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Radera konto"
|
||||
@@ -342,13 +334,10 @@ msgstr "Dra länken till bokmärkesfältet"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-post"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-postadress"
|
||||
@@ -399,7 +388,6 @@ msgstr "Tilläggsalternativ"
|
||||
msgid "Feed name"
|
||||
msgstr "Flödesnamn"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Laddar prenumerationer..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Laddar taggar..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Navigera till ett abonnemang genom att ange dess namn"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Navigera till nästa kategori/flöde med olästa poster när alla poster markeras som lästa"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Aldrig"
|
||||
@@ -657,7 +643,6 @@ msgstr "Aldrig"
|
||||
msgid "New password"
|
||||
msgstr "Nytt lösenord"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Nytt lösenord"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML-export"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML-fil"
|
||||
@@ -791,10 +775,7 @@ msgstr "Föräldrakategori"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Lösenord"
|
||||
@@ -874,7 +855,6 @@ msgstr "Uppdatera"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Registreringar är stängda på denna CommaFeed-instans"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Återställ lösenord"
|
||||
@@ -883,7 +863,6 @@ msgstr "Återställ lösenord"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Högerklick"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Rullning"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Sök"
|
||||
@@ -924,7 +901,6 @@ msgstr "Välj nästa olästa flöde/kategori"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Välj föregående olästa flöde/kategori"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Server-URL"
|
||||
@@ -953,8 +929,6 @@ msgstr "Dela"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delningssajter"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Visa antal olästa i flikikonen"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Visa antal olästa i fliktiteln"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Anmäl dig"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Något dåligt hände precis..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Rymden"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Stjärna"
|
||||
msgid "Starred"
|
||||
msgstr "Starmed"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Byt till ljustema"
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Taggar"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Oläst"
|
||||
msgid "Unstar"
|
||||
msgstr "Ta bort stjärna"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Avsluta prenumeration"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Användarnyckel"
|
||||
msgid "User name"
|
||||
msgstr "Användarnamn"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Användarnamn eller e-post"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "Kullanıcı ekle"
|
||||
msgid "Admin"
|
||||
msgstr "Yönetici"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "Yönetici kullanıcı adı"
|
||||
@@ -73,7 +72,6 @@ msgstr "Yönetici kullanıcı adı"
|
||||
msgid "All"
|
||||
msgstr "Tümü"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "Her zaman"
|
||||
@@ -173,18 +171,14 @@ msgstr "Ne okumak istediğinizi belirtmek için bir filtre ifadesi oluşturun. E
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "İptal"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "Onayla"
|
||||
msgid "Confirm password"
|
||||
msgstr "Şifreyi onayla"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "Şifreyi Onayla"
|
||||
@@ -294,7 +287,6 @@ msgstr "gün"
|
||||
msgid "Delete"
|
||||
msgstr "Sil"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "Hesabı sil"
|
||||
@@ -342,13 +334,10 @@ msgstr "Bağlantıyı yer işareti çubuğuna sürükleyin"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "E-posta"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "E-posta adresi"
|
||||
@@ -399,7 +388,6 @@ msgstr "Eklenti ayarları"
|
||||
msgid "Feed name"
|
||||
msgstr "Yayın adı"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "Abonelikler yükleniyor..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "Etiketler yükleniyor..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "Adını girerek bir aboneliğe gidin"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "Tüm girişleri okundu olarak işaretlerken okunmamış girişleri olan bir sonraki kategoriye/beslemeye git"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "Asla"
|
||||
@@ -657,7 +643,6 @@ msgstr "Asla"
|
||||
msgid "New password"
|
||||
msgstr "Yeni şifre"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "Yeni Şifre"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML dışa aktarma"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML dosyası"
|
||||
@@ -791,10 +775,7 @@ msgstr "Üst Kategori"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "Şifre"
|
||||
@@ -874,7 +855,6 @@ msgstr "Yenile"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "Bu CommaFeed örneğinde kayıtlar kapalı"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "Şifreyi Sıfırla"
|
||||
@@ -883,7 +863,6 @@ msgstr "Şifreyi Sıfırla"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Sağ tık"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "Kaydırma"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "Ara"
|
||||
@@ -924,7 +901,6 @@ msgstr "Sonraki okunmamış beslemeyi/kategoriyi seç"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "Önceki okunmamış beslemeyi/kategoriyi seç"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "Sunucu URL'si"
|
||||
@@ -953,8 +929,6 @@ msgstr "Paylaş"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Siteleri paylaşma"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Vardiya"
|
||||
@@ -1003,7 +977,6 @@ msgstr "Sekme simgesinde okunmamış sayısını göster"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "Sekme başlığında okunmamış sayısını göster"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "Kaydolun"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "Az önce kötü bir şey oldu..."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "Uzay"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "Yıldız"
|
||||
msgid "Starred"
|
||||
msgstr "Yıldızlı"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "Aydınlık temaya geç"
|
||||
msgid "System"
|
||||
msgstr "Sistem"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "Etiketler"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "Okunmamış"
|
||||
msgid "Unstar"
|
||||
msgstr "Yıldızı kaldır"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Aboneliği iptal et"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "Kullanıcı anahtarı"
|
||||
msgid "User name"
|
||||
msgstr "Kullanıcı adı"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "Kullanıcı Adı veya E-posta"
|
||||
|
||||
@@ -60,7 +60,6 @@ msgstr "添加用户"
|
||||
msgid "Admin"
|
||||
msgstr "管理员"
|
||||
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
msgid "Admin user name"
|
||||
msgstr "管理员用户名"
|
||||
@@ -73,7 +72,6 @@ msgstr "管理员用户名"
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always"
|
||||
msgstr "总是"
|
||||
@@ -173,18 +171,14 @@ msgstr "构建过滤表达式以指示您想阅读的内容。不匹配的条目
|
||||
#: src/components/MarkAllAsReadConfirmationDialog.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/CategoryDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/TagDetailsPage.tsx
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
@@ -240,7 +234,6 @@ msgstr "确认"
|
||||
msgid "Confirm password"
|
||||
msgstr "确认密码"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Confirm Password"
|
||||
msgstr "确认密码"
|
||||
@@ -294,7 +287,6 @@ msgstr "天"
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Delete account"
|
||||
msgstr "删除帐号"
|
||||
@@ -342,13 +334,10 @@ msgstr "拖动链接到书签栏"
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "E-mail"
|
||||
msgstr "电子邮件"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "E-mail address"
|
||||
msgstr "电子邮件地址"
|
||||
@@ -399,7 +388,6 @@ msgstr "扩展选项"
|
||||
msgid "Feed name"
|
||||
msgstr "信息流名称"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Feed URL"
|
||||
@@ -570,7 +558,6 @@ msgstr "正在加载订阅..."
|
||||
msgid "Loading tags..."
|
||||
msgstr "正在加载标签..."
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Log in"
|
||||
@@ -648,7 +635,6 @@ msgstr "通过输入订阅名称导航到订阅"
|
||||
msgid "Navigate to the next category/feed with unread entries when marking all entries as read"
|
||||
msgstr "将所有条目标记为已读时导航到下一个包含未读条目的类别/信息流"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Never"
|
||||
msgstr "从不"
|
||||
@@ -657,7 +643,6 @@ msgstr "从不"
|
||||
msgid "New password"
|
||||
msgstr "新密码"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "New Password"
|
||||
msgstr "新密码"
|
||||
@@ -764,7 +749,6 @@ msgstr "OPML"
|
||||
msgid "OPML export"
|
||||
msgstr "OPML 导出"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "OPML file"
|
||||
msgstr "OPML 文件"
|
||||
@@ -791,10 +775,7 @@ msgstr "父类别"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/InitialSetupPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
@@ -874,7 +855,6 @@ msgstr "刷新"
|
||||
msgid "Registrations are closed on this CommaFeed instance"
|
||||
msgstr "此 CommaFeed 实例上的注册已关闭"
|
||||
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
#: src/pages/auth/PasswordResetPage.tsx
|
||||
msgid "Reset Password"
|
||||
msgstr "重置密码"
|
||||
@@ -883,7 +863,6 @@ msgstr "重置密码"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "右键单击"
|
||||
@@ -910,8 +889,6 @@ msgid "Scrolling"
|
||||
msgstr "滚动"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
#: src/components/sidebar/TreeSearch.tsx
|
||||
msgid "Search"
|
||||
msgstr "搜索"
|
||||
@@ -924,7 +901,6 @@ msgstr "选择下一个未读信息流/类别"
|
||||
msgid "Select previous unread feed/category"
|
||||
msgstr "选择上一个未读信息流/类别"
|
||||
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
#: src/components/settings/PushNotificationSettings.tsx
|
||||
msgid "Server URL"
|
||||
msgstr "服务器网址"
|
||||
@@ -953,8 +929,6 @@ msgstr "分享"
|
||||
msgid "Sharing sites"
|
||||
msgstr "共享站点"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
@@ -1003,7 +977,6 @@ msgstr "在标签页图标上显示未读数量"
|
||||
msgid "Show unread count in tab title"
|
||||
msgstr "在标签页标题中显示未读数量"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Sign up"
|
||||
@@ -1013,7 +986,6 @@ msgstr "注册"
|
||||
msgid "Something bad just happened..."
|
||||
msgstr "刚刚发生了不好的事情……"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Space"
|
||||
msgstr "空格"
|
||||
@@ -1030,7 +1002,6 @@ msgstr "星标"
|
||||
msgid "Starred"
|
||||
msgstr "已加星标"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "Subscribe"
|
||||
@@ -1064,7 +1035,6 @@ msgstr "切换到浅色主题"
|
||||
msgid "System"
|
||||
msgstr "跟随系统"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
msgstr "标签"
|
||||
@@ -1136,7 +1106,6 @@ msgstr "未读"
|
||||
msgid "Unstar"
|
||||
msgstr "取消星标"
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "Unsubscribe"
|
||||
msgstr "取消订阅"
|
||||
@@ -1149,7 +1118,6 @@ msgstr "用户密钥"
|
||||
msgid "User name"
|
||||
msgstr "用户名"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "User Name or E-mail"
|
||||
msgstr "用户名或电子邮件"
|
||||
|
||||
@@ -8,9 +8,11 @@ import { Constants } from "@/app/constants"
|
||||
import type { EntrySourceType } from "@/app/entries/slice"
|
||||
import { loadEntries } from "@/app/entries/thunks"
|
||||
import { redirectToCategoryDetails, redirectToFeedDetails, redirectToTagDetails } from "@/app/redirect/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
import { flattenCategoryTree } from "@/app/utils"
|
||||
import { useAppDispatch, useAppSelector, useShallowEqualAppSelector } from "@/app/store"
|
||||
import { categoryHasNewEntries, categoryUnreadCount, flattenCategoryTree } from "@/app/utils"
|
||||
import { FeedEntries } from "@/components/content/FeedEntries"
|
||||
import { UnreadCount } from "@/components/sidebar/UnreadCount"
|
||||
import { useMobile } from "@/hooks/useMobile"
|
||||
import { tss } from "@/tss"
|
||||
|
||||
function NoSubscriptionHelp() {
|
||||
@@ -33,6 +35,12 @@ const useStyles = tss.create(() => ({
|
||||
sourceWebsiteLink: {
|
||||
color: "inherit",
|
||||
textDecoration: "none",
|
||||
overflow: "hidden",
|
||||
},
|
||||
titleText: {
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -48,6 +56,33 @@ export function FeedEntriesPage(props: Readonly<FeedEntriesPageProps>) {
|
||||
const sourceLabel = useAppSelector(state => state.entries.sourceLabel)
|
||||
const sourceWebsiteUrl = useAppSelector(state => state.entries.sourceWebsiteUrl)
|
||||
const hasMore = useAppSelector(state => state.entries.hasMore)
|
||||
const mobile = useMobile()
|
||||
const sidebarVisible = useAppSelector(state => state.tree.sidebarVisible)
|
||||
const { unreadCount, hasNewEntries } = useShallowEqualAppSelector(state => {
|
||||
const root = state.tree.rootCategory
|
||||
if (!root) return { unreadCount: 0, hasNewEntries: false }
|
||||
|
||||
if (props.sourceType === "category") {
|
||||
const category = id === Constants.categories.all.id ? root : flattenCategoryTree(root).find(c => c.id === id)
|
||||
return {
|
||||
unreadCount: categoryUnreadCount(category),
|
||||
hasNewEntries: categoryHasNewEntries(category),
|
||||
}
|
||||
}
|
||||
|
||||
if (props.sourceType === "feed") {
|
||||
const feed = flattenCategoryTree(root)
|
||||
.flatMap(c => c.feeds)
|
||||
.find(f => f.id === +id)
|
||||
return {
|
||||
unreadCount: feed?.unread ?? 0,
|
||||
hasNewEntries: !!feed?.hasNewEntries,
|
||||
}
|
||||
}
|
||||
|
||||
return { unreadCount: 0, hasNewEntries: false }
|
||||
})
|
||||
const showUnreadCount = mobile || !sidebarVisible
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
let title: React.ReactNode = sourceLabel
|
||||
@@ -89,16 +124,23 @@ export function FeedEntriesPage(props: Readonly<FeedEntriesPageProps>) {
|
||||
return (
|
||||
// add some room at the bottom of the page in order to be able to scroll the current entry at the top of the page when expanding
|
||||
<Box mb={viewport.height * 0.7}>
|
||||
<Group gap="xl" className="cf-entries-title">
|
||||
<Group className="cf-entries-title" wrap="nowrap">
|
||||
{sourceWebsiteUrl && (
|
||||
<a href={sourceWebsiteUrl} target="_blank" rel="noreferrer" className={classes.sourceWebsiteLink}>
|
||||
<Title order={3}>{title}</Title>
|
||||
<Title order={3} className={classes.titleText}>
|
||||
{title}
|
||||
</Title>
|
||||
</a>
|
||||
)}
|
||||
{!sourceWebsiteUrl && <Title order={3}>{title}</Title>}
|
||||
{!sourceWebsiteUrl && (
|
||||
<Title order={3} className={classes.titleText}>
|
||||
{title}
|
||||
</Title>
|
||||
)}
|
||||
<ActionIcon onClick={titleClicked} variant="subtle" color={theme.primaryColor}>
|
||||
<TbEdit size={18} />
|
||||
</ActionIcon>
|
||||
{showUnreadCount && <UnreadCount unreadCount={unreadCount} showIndicator={hasNewEntries} />}
|
||||
</Group>
|
||||
|
||||
<FeedEntries />
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { msg } from "@lingui/core/macro"
|
||||
import { ActionIcon, AppShell, Box, Center, Group, ScrollArea, Title, useMantineTheme } from "@mantine/core"
|
||||
import { type ReactNode, type RefObject, Suspense, useEffect, useRef } from "react"
|
||||
import { type ReactNode, type RefObject, Suspense, useEffect, useRef, useState } from "react"
|
||||
import Draggable from "react-draggable"
|
||||
import { TbMenu2, TbPlus, TbX } from "react-icons/tb"
|
||||
import { Outlet } from "react-router-dom"
|
||||
import { useSwipeable } from "react-swipeable"
|
||||
import Tinycon from "tinycon"
|
||||
import { Constants } from "@/app/constants"
|
||||
import { redirectToAdd, redirectToRootCategory } from "@/app/redirect/thunks"
|
||||
import { useAppDispatch, useAppSelector } from "@/app/store"
|
||||
@@ -12,8 +13,10 @@ import { setMobileMenuOpen } from "@/app/tree/slice"
|
||||
import { reloadTree } from "@/app/tree/thunks"
|
||||
import { setSidebarWidth } from "@/app/user/slice"
|
||||
import { reloadProfile, reloadSettings, reloadTags } from "@/app/user/thunks"
|
||||
import { categoryUnreadCount } from "@/app/utils"
|
||||
import { ActionButton } from "@/components/ActionButton"
|
||||
import { AnnouncementDialog } from "@/components/AnnouncementDialog"
|
||||
import { DisablePullToRefresh } from "@/components/DisablePullToRefresh"
|
||||
import { Loader } from "@/components/Loader"
|
||||
import { Logo } from "@/components/Logo"
|
||||
import { MarkAllAsReadConfirmationDialog } from "@/components/MarkAllAsReadConfirmationDialog"
|
||||
@@ -51,6 +54,78 @@ function LogoAndTitle() {
|
||||
)
|
||||
}
|
||||
|
||||
function UnreadCountTitleHandler({
|
||||
enabled,
|
||||
}: Readonly<{
|
||||
enabled?: boolean
|
||||
}>) {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
return <title>{enabled && unreadCount > 0 ? `(${unreadCount}) CommaFeed` : "CommaFeed"}</title>
|
||||
}
|
||||
|
||||
function UnreadCountFaviconHandler({ enabled }: { enabled?: boolean }) {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
useEffect(() => {
|
||||
if (enabled && unreadCount > 0) {
|
||||
Tinycon.setBubble(unreadCount)
|
||||
} else {
|
||||
Tinycon.reset()
|
||||
}
|
||||
}, [unreadCount, enabled])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function BrowserExtensionBadgeUnreadCountHandler() {
|
||||
const root = useAppSelector(state => state.tree.rootCategory)
|
||||
const { setBadgeUnreadCount } = useBrowserExtension()
|
||||
useEffect(() => {
|
||||
if (!root) return
|
||||
const unreadCount = categoryUnreadCount(root)
|
||||
setBadgeUnreadCount(unreadCount)
|
||||
}, [root, setBadgeUnreadCount])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function CustomJsHandler() {
|
||||
const [scriptLoaded, setScriptLoaded] = useState(false)
|
||||
const { loading } = useAppLoading()
|
||||
|
||||
useEffect(() => {
|
||||
if (scriptLoaded || loading) {
|
||||
return
|
||||
}
|
||||
|
||||
const script = document.createElement("script")
|
||||
script.src = "custom_js.js"
|
||||
script.async = true
|
||||
document.body.appendChild(script)
|
||||
|
||||
setScriptLoaded(true)
|
||||
|
||||
return () => script.remove()
|
||||
}, [scriptLoaded, loading])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function CustomCssHandler() {
|
||||
useEffect(() => {
|
||||
const link = document.createElement("link")
|
||||
link.rel = "stylesheet"
|
||||
link.type = "text/css"
|
||||
link.href = "custom_css.css"
|
||||
document.head.appendChild(link)
|
||||
|
||||
return () => link.remove()
|
||||
}, [])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const useStyles = tss
|
||||
.withParams<{
|
||||
sidebarWidth: number
|
||||
@@ -75,6 +150,9 @@ export default function Layout(props: Readonly<LayoutProps>) {
|
||||
const draggableSeparator = useRef<HTMLDivElement>(null)
|
||||
|
||||
const { loading } = useAppLoading()
|
||||
const unreadCountTitle = useAppSelector(state => state.user.settings?.unreadCountTitle)
|
||||
const unreadCountFavicon = useAppSelector(state => state.user.settings?.unreadCountFavicon)
|
||||
const disablePullToRefresh = useAppSelector(state => state.user.settings?.disablePullToRefresh)
|
||||
const mobileMenuOpen = useAppSelector(state => state.tree.mobileMenuOpen)
|
||||
const webSocketConnected = useAppSelector(state => state.server.webSocketConnected)
|
||||
const treeReloadInterval = useAppSelector(state => state.server.serverInfos?.treeReloadInterval)
|
||||
@@ -173,6 +251,13 @@ export default function Layout(props: Readonly<LayoutProps>) {
|
||||
|
||||
if (loading) return <LoadingPage />
|
||||
return (
|
||||
<>
|
||||
<UnreadCountTitleHandler enabled={unreadCountTitle} />
|
||||
<UnreadCountFaviconHandler enabled={unreadCountFavicon} />
|
||||
<BrowserExtensionBadgeUnreadCountHandler />
|
||||
<CustomJsHandler />
|
||||
<CustomCssHandler />
|
||||
<DisablePullToRefresh enabled={disablePullToRefresh} />
|
||||
<Box {...swipeHandlers}>
|
||||
<AppShell
|
||||
header={{ height: Constants.layout.headerHeight, collapsed: headerInFooter }}
|
||||
@@ -229,5 +314,6 @@ export default function Layout(props: Readonly<LayoutProps>) {
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
import { lingui } from "@lingui/vite-plugin"
|
||||
import react from "@vitejs/plugin-react"
|
||||
import babel from "@rolldown/plugin-babel"
|
||||
import react, { reactCompilerPreset } from "@vitejs/plugin-react"
|
||||
import { defineConfig } from "vite"
|
||||
import checker from "vite-plugin-checker"
|
||||
import tsconfigPaths from "vite-tsconfig-paths"
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(() => ({
|
||||
plugins: [
|
||||
react({
|
||||
babel: {
|
||||
plugins: [
|
||||
// support for lingui macros
|
||||
// needs to be before the react compiler plugin
|
||||
"@lingui/babel-plugin-lingui-macro",
|
||||
// react compiler
|
||||
["babel-plugin-react-compiler", { target: "19" }],
|
||||
],
|
||||
},
|
||||
react(),
|
||||
babel({
|
||||
presets: [reactCompilerPreset()],
|
||||
plugins: ["@lingui/babel-plugin-lingui-macro"],
|
||||
}),
|
||||
lingui(),
|
||||
tsconfigPaths(),
|
||||
checker({
|
||||
typescript: true,
|
||||
// temporary disabled until TypeScript 7 exposes a stable api
|
||||
// typescript: true,
|
||||
biome: {
|
||||
command: "check",
|
||||
flags: "--error-on-warnings",
|
||||
@@ -43,22 +36,32 @@ export default defineConfig(() => ({
|
||||
"/logout": "http://localhost:8083",
|
||||
},
|
||||
},
|
||||
build: {
|
||||
chunkSizeWarningLimit: 3500,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: id => {
|
||||
// output mantine as its own chunk because it is quite large
|
||||
if (id.includes("@mantine")) {
|
||||
return "mantine"
|
||||
}
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
tsconfigPaths: true,
|
||||
},
|
||||
legacy: {
|
||||
// required for websocket-heartbeat-js
|
||||
inconsistentCjsInterop: true,
|
||||
},
|
||||
test: {
|
||||
environment: "jsdom",
|
||||
globals: true,
|
||||
setupFiles: "./src/setupTests.ts",
|
||||
},
|
||||
build: {
|
||||
chunkSizeWarningLimit: 4000,
|
||||
rolldownOptions: {
|
||||
output: {
|
||||
codeSplitting: {
|
||||
groups: [
|
||||
// output mantine as its own chunk because it is quite large
|
||||
{
|
||||
name: "mantine",
|
||||
test: "@mantine",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -1,401 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="23">
|
||||
<profile kind="CodeFormatterProfile" name="CommaFeed" version="23">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="140"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="48"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="140"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
@@ -40,11 +40,6 @@
|
||||
<module name="AvoidStarImport" />
|
||||
<module name="AvoidStaticImport" />
|
||||
<module name="IllegalImport" />
|
||||
<module name="ImportOrder">
|
||||
<property name="groups" value="/^java\./,javax,jakarta,org,com" />
|
||||
<property name="ordered" value="true" />
|
||||
<property name="separated" value="true" />
|
||||
</module>
|
||||
<module name="RedundantImport" />
|
||||
<module name="UnusedImports" />
|
||||
|
||||
@@ -113,12 +108,6 @@
|
||||
<module name="NoLineWrap" />
|
||||
<module name="NoWhitespaceBefore" />
|
||||
<module name="ParenPad" />
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="^\t* +\t*\S" />
|
||||
<property name="message" value="Line has leading space characters; indentation should be performed with tabs only." />
|
||||
<property name="ignoreComments" value="true" />
|
||||
</module>
|
||||
<module name="WhitespaceAround" />
|
||||
|
||||
</module>
|
||||
</module>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#Organize Import Order
|
||||
#Wed Jan 29 15:15:04 CET 2025
|
||||
0=java
|
||||
1=javax
|
||||
2=jakarta
|
||||
3=org
|
||||
4=com
|
||||
@@ -6,16 +6,18 @@
|
||||
<parent>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.2.1</version>
|
||||
</parent>
|
||||
<artifactId>commafeed-server</artifactId>
|
||||
<name>CommaFeed Server</name>
|
||||
<packaging>quarkus</packaging>
|
||||
|
||||
<properties>
|
||||
<quarkus.version>3.31.4</quarkus.version>
|
||||
<querydsl.version>7.1</querydsl.version>
|
||||
<quarkus.version>3.38.0</quarkus.version>
|
||||
<querydsl.version>7.5</querydsl.version>
|
||||
<rome.version>2.1.0</rome.version>
|
||||
<!-- renovate: depName=com.google.googlejavaformat:google-java-format -->
|
||||
<google-java-format.version>1.36.1</google-java-format.version>
|
||||
|
||||
<build.database>h2</build.database>
|
||||
</properties>
|
||||
@@ -29,6 +31,12 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<!-- the quarkus bom declares a dependency on an old version of protobuf, we need to override it for cel-java -->
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>4.35.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -43,7 +51,7 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-help-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.5.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>initialize</phase>
|
||||
@@ -156,7 +164,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.5</version>
|
||||
<version>3.5.6</version>
|
||||
<configuration>
|
||||
<argLine>@{argLine}</argLine>
|
||||
<systemPropertyVariables>
|
||||
@@ -168,7 +176,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.5.5</version>
|
||||
<version>3.5.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@@ -213,7 +221,7 @@
|
||||
<plugin>
|
||||
<groupId>io.github.git-commit-id</groupId>
|
||||
<artifactId>git-commit-id-maven-plugin</artifactId>
|
||||
<version>9.0.2</version>
|
||||
<version>10.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@@ -237,7 +245,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>13.2.0</version>
|
||||
<version>13.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -266,7 +274,7 @@
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.9.0</version>
|
||||
<?m2e ignore?>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -279,12 +287,11 @@
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<java>
|
||||
<eclipse>
|
||||
<file>${project.basedir}/dev/EclipseCodeFormatter.xml</file>
|
||||
</eclipse>
|
||||
<importOrder>
|
||||
<file>${project.basedir}/dev/eclipse.importorder</file>
|
||||
</importOrder>
|
||||
<googleJavaFormat>
|
||||
<version>${google-java-format.version}</version>
|
||||
<style>AOSP</style>
|
||||
<reorderImports>true</reorderImports>
|
||||
</googleJavaFormat>
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -295,15 +302,14 @@
|
||||
<dependency>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed-client</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- compile-time processors -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
<scope>provided</scope>
|
||||
<version>1.18.46</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kohsuke.metainf-services</groupId>
|
||||
@@ -362,7 +368,7 @@
|
||||
<dependency>
|
||||
<groupId>io.dropwizard.metrics</groupId>
|
||||
<artifactId>metrics-json</artifactId>
|
||||
<version>4.2.38</version>
|
||||
<version>4.2.39</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.querydsl</groupId>
|
||||
@@ -393,12 +399,12 @@
|
||||
<dependency>
|
||||
<groupId>dev.cel</groupId>
|
||||
<artifactId>cel</artifactId>
|
||||
<version>0.11.1</version>
|
||||
<version>0.13.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.passay</groupId>
|
||||
<artifactId>passay</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rometools</groupId>
|
||||
@@ -423,12 +429,12 @@
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.22.1</version>
|
||||
<version>1.23.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ibm.icu</groupId>
|
||||
<artifactId>icu4j</artifactId>
|
||||
<version>78.2</version>
|
||||
<version>78.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.cssparser</groupId>
|
||||
@@ -443,18 +449,23 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.6</version>
|
||||
<version>5.6.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.hakky54</groupId>
|
||||
<artifactId>ayza-for-apache5</artifactId>
|
||||
<version>10.0.3</version>
|
||||
<version>10.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.brotli</groupId>
|
||||
<artifactId>dec</artifactId>
|
||||
<version>0.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.seancfoley</groupId>
|
||||
<artifactId>ipaddress</artifactId>
|
||||
<version>5.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<dependency>
|
||||
@@ -465,13 +476,13 @@
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.playwright</groupId>
|
||||
<artifactId>quarkus-playwright</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<version>2.3.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-junit-jupiter</artifactId>
|
||||
<version>5.15.0</version>
|
||||
<version>7.5.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ibm-semeru-runtimes:open-jdk-25.0.2_10-jre@sha256:b02e4cd184d9ece59b01129af1d0a069fa01e4f0f798f0bc4f3ff1a8391ba694
|
||||
FROM ibm-semeru-runtimes:open-jdk-25.0.3.0-jre@sha256:43ec947fee9c4c2ed880620ae9e78911ac5eef66391e5a2c43f956dcc9000491
|
||||
EXPOSE 8082
|
||||
|
||||
RUN mkdir -p /commafeed/data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM debian:13.3@sha256:2c91e484d93f0830a7e05a2b9d92a7b102be7cab562198b984a84fdbc7806d91
|
||||
FROM debian:13.6@sha256:fac46bff2e02f51425b6e33b0e1169f55dfb053d83511ca28aa50c09fd5ed7a4
|
||||
ARG TARGETARCH
|
||||
|
||||
EXPOSE 8082
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package com.commafeed;
|
||||
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import com.commafeed.backend.feed.FeedRefreshEngine;
|
||||
import com.commafeed.backend.feed.ImageProxyUrl;
|
||||
import com.commafeed.backend.task.TaskScheduler;
|
||||
import com.commafeed.security.password.PasswordConstraintValidator;
|
||||
|
||||
import io.quarkus.runtime.ShutdownEvent;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
@RequiredArgsConstructor
|
||||
public class CommaFeedApplication {
|
||||
@@ -20,15 +24,23 @@ public class CommaFeedApplication {
|
||||
private final CommaFeedConfiguration config;
|
||||
|
||||
public void start(@Observes StartupEvent ev) {
|
||||
PasswordConstraintValidator.setMinimumPasswordLength(config.users().minimumPasswordLength());
|
||||
log.info("starting up...");
|
||||
|
||||
PasswordConstraintValidator.setMinimumPasswordLength(
|
||||
config.users().minimumPasswordLength());
|
||||
|
||||
if (config.imageProxyEnabled()) {
|
||||
ImageProxyUrl.generateKey();
|
||||
}
|
||||
|
||||
feedRefreshEngine.start();
|
||||
taskScheduler.start();
|
||||
}
|
||||
|
||||
public void stop(@Observes ShutdownEvent ev) {
|
||||
log.info("shutting down...");
|
||||
|
||||
feedRefreshEngine.stop();
|
||||
taskScheduler.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
package com.commafeed;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
|
||||
import com.commafeed.backend.feed.FeedRefreshIntervalCalculator;
|
||||
|
||||
import io.quarkus.runtime.annotations.ConfigDocSection;
|
||||
@@ -16,10 +9,18 @@ import io.quarkus.runtime.configuration.MemorySize;
|
||||
import io.smallrye.config.ConfigMapping;
|
||||
import io.smallrye.config.WithDefault;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* CommaFeed configuration
|
||||
*
|
||||
* Default values are for production, they can be overridden in application.properties for other profiles
|
||||
* <p>Default values are for production, they can be overridden in application.properties for other
|
||||
* profiles
|
||||
*/
|
||||
@ConfigMapping(prefix = "commafeed")
|
||||
@ConfigRoot(phase = ConfigPhase.RUN_TIME)
|
||||
@@ -31,9 +32,11 @@ public interface CommaFeedConfiguration {
|
||||
boolean hideFromWebCrawlers();
|
||||
|
||||
/**
|
||||
* If enabled, images in feed entries will be proxied through the server instead of accessed directly by the browser.
|
||||
* If enabled, images in feed entries will be proxied through the server instead of accessed
|
||||
* directly by the browser.
|
||||
*
|
||||
* This is useful if commafeed is accessed through a restricting proxy that blocks some feeds that are followed.
|
||||
* <p>This is useful if commafeed is accessed through a restricting proxy that blocks some feeds
|
||||
* that are followed.
|
||||
*/
|
||||
@WithDefault("false")
|
||||
boolean imageProxyEnabled();
|
||||
@@ -41,228 +44,198 @@ public interface CommaFeedConfiguration {
|
||||
/**
|
||||
* Enable password recovery via email.
|
||||
*
|
||||
* Quarkus mailer will need to be configured.
|
||||
* <p>Quarkus mailer will need to be configured.
|
||||
*/
|
||||
@WithDefault("false")
|
||||
boolean passwordRecoveryEnabled();
|
||||
|
||||
/**
|
||||
* Message displayed in a notification at the bottom of the page.
|
||||
*/
|
||||
/** Message displayed in a notification at the bottom of the page. */
|
||||
Optional<String> announcement();
|
||||
|
||||
/**
|
||||
* Google Auth key for fetching Youtube channel favicons.
|
||||
*/
|
||||
/** Google Auth key for fetching Youtube channel favicons. */
|
||||
Optional<String> googleAuthKey();
|
||||
|
||||
/**
|
||||
* HTTP client configuration
|
||||
*/
|
||||
/** HTTP client configuration */
|
||||
@ConfigDocSection
|
||||
HttpClient httpClient();
|
||||
|
||||
/**
|
||||
* Feed refresh engine settings.
|
||||
*/
|
||||
/** Feed refresh engine settings. */
|
||||
@ConfigDocSection
|
||||
FeedRefresh feedRefresh();
|
||||
|
||||
/**
|
||||
* Push notification settings.
|
||||
*/
|
||||
/** Push notification settings. */
|
||||
@ConfigDocSection
|
||||
PushNotifications pushNotifications();
|
||||
|
||||
/**
|
||||
* Database settings.
|
||||
*/
|
||||
/** Database settings. */
|
||||
@ConfigDocSection
|
||||
Database database();
|
||||
|
||||
/**
|
||||
* Users settings.
|
||||
*/
|
||||
/** Users settings. */
|
||||
@ConfigDocSection
|
||||
Users users();
|
||||
|
||||
/**
|
||||
* Websocket settings.
|
||||
*/
|
||||
/** Websocket settings. */
|
||||
@ConfigDocSection
|
||||
Websocket websocket();
|
||||
|
||||
/**
|
||||
* Duration to wait for the feed refresh engine and the task scheduler to stop when the
|
||||
* application is shutting down.
|
||||
*/
|
||||
@WithDefault("2s")
|
||||
Duration shutdownTimeout();
|
||||
|
||||
interface HttpClient {
|
||||
/**
|
||||
* User-Agent string that will be used by the http client, leave empty for the default one.
|
||||
*/
|
||||
Optional<String> userAgent();
|
||||
|
||||
/**
|
||||
* Time to wait for a connection to be established.
|
||||
*/
|
||||
/** Time to wait for a connection to be established. */
|
||||
@WithDefault("5s")
|
||||
Duration connectTimeout();
|
||||
|
||||
/**
|
||||
* Time to wait for SSL handshake to complete.
|
||||
*/
|
||||
/** Time to wait for SSL handshake to complete. */
|
||||
@WithDefault("5s")
|
||||
Duration sslHandshakeTimeout();
|
||||
|
||||
/**
|
||||
* Time to wait between two packets before timeout.
|
||||
*/
|
||||
/** Time to wait between two packets before timeout. */
|
||||
@WithDefault("10s")
|
||||
Duration socketTimeout();
|
||||
|
||||
/**
|
||||
* Time to wait for the full response to be received.
|
||||
*/
|
||||
/** Time to wait for the full response to be received. */
|
||||
@WithDefault("10s")
|
||||
Duration responseTimeout();
|
||||
|
||||
/**
|
||||
* Time to live for a connection in the pool.
|
||||
*/
|
||||
/** Time to live for a connection in the pool. */
|
||||
@WithDefault("30s")
|
||||
Duration connectionTimeToLive();
|
||||
|
||||
/**
|
||||
* Time between eviction runs for idle connections.
|
||||
*/
|
||||
/** Time between eviction runs for idle connections. */
|
||||
@WithDefault("1m")
|
||||
Duration idleConnectionsEvictionInterval();
|
||||
|
||||
/**
|
||||
* If a feed is larger than this, it will be discarded to prevent memory issues while parsing the feed.
|
||||
* If a feed is larger than this, it will be discarded to prevent memory issues while
|
||||
* parsing the feed.
|
||||
*/
|
||||
@WithDefault("5M")
|
||||
MemorySize maxResponseSize();
|
||||
|
||||
/**
|
||||
* Prevent access to local addresses to mitigate server-side request forgery (SSRF) attacks, which could potentially expose internal
|
||||
* resources.
|
||||
* Prevent access to local addresses to mitigate server-side request forgery (SSRF) attacks,
|
||||
* which could potentially expose internal resources.
|
||||
*
|
||||
* You may want to enable this if you host a public instance of CommaFeed with regisration open.
|
||||
* <p>You may want to enable this if you host a public instance of CommaFeed with
|
||||
* registrations open.
|
||||
*/
|
||||
@WithDefault("false")
|
||||
boolean blockLocalAddresses();
|
||||
|
||||
/**
|
||||
* HTTP client cache configuration
|
||||
*/
|
||||
/** HTTP client cache configuration */
|
||||
@ConfigDocSection
|
||||
HttpClientCache cache();
|
||||
}
|
||||
|
||||
interface HttpClientCache {
|
||||
/**
|
||||
* Whether to enable the cache. This cache is used to avoid spamming feeds in short bursts (e.g. when subscribing to a feed for the
|
||||
* first time or when clicking "fetch all my feeds now").
|
||||
* Whether to enable the cache. This cache is used to avoid spamming feeds in short bursts
|
||||
* (e.g. when subscribing to a feed for the first time or when clicking "fetch all my feeds
|
||||
* now").
|
||||
*/
|
||||
@WithDefault("true")
|
||||
boolean enabled();
|
||||
|
||||
/**
|
||||
* Maximum amount of memory the cache can use.
|
||||
*/
|
||||
/** Maximum amount of memory the cache can use. */
|
||||
@WithDefault("10M")
|
||||
MemorySize maximumMemorySize();
|
||||
|
||||
/**
|
||||
* Duration after which an entry is removed from the cache.
|
||||
*/
|
||||
/** Duration after which an entry is removed from the cache. */
|
||||
@WithDefault("1m")
|
||||
Duration expiration();
|
||||
}
|
||||
|
||||
interface FeedRefresh {
|
||||
/**
|
||||
* Default amount of time CommaFeed will wait before refreshing a feed.
|
||||
*/
|
||||
/** Default amount of time CommaFeed will wait before refreshing a feed. */
|
||||
@WithDefault("5m")
|
||||
Duration interval();
|
||||
|
||||
/**
|
||||
* Maximum amount of time CommaFeed will wait before refreshing a feed. This is used as an upper bound when:
|
||||
* Maximum amount of time CommaFeed will wait before refreshing a feed. This is used as an
|
||||
* upper bound when:
|
||||
*
|
||||
* <ul>
|
||||
* <li>an error occurs while refreshing a feed and we're backing off exponentially</li>
|
||||
* <li>we receive a Cache-Control header from the feed</li>
|
||||
* <li>we receive a Retry-After header from the feed</li>
|
||||
* <li>an error occurs while refreshing a feed and we're backing off exponentially
|
||||
* <li>we receive a Cache-Control header from the feed
|
||||
* <li>we receive a Retry-After header from the feed
|
||||
* </ul>
|
||||
*/
|
||||
@WithDefault("4h")
|
||||
Duration maxInterval();
|
||||
|
||||
/**
|
||||
* If enabled, CommaFeed will calculate the next refresh time based on the feed's average time between entries and the time since
|
||||
* the last entry was published. The interval will be sometimes between the default refresh interval
|
||||
* (`commafeed.feed-refresh.interval`) and the maximum refresh interval (`commafeed.feed-refresh.max-interval`).
|
||||
* If enabled, CommaFeed will calculate the next refresh time based on the feed's average
|
||||
* time between entries and the time since the last entry was published. The interval will
|
||||
* be sometimes between the default refresh interval (`commafeed.feed-refresh.interval`) and
|
||||
* the maximum refresh interval (`commafeed.feed-refresh.max-interval`).
|
||||
*
|
||||
* See {@link FeedRefreshIntervalCalculator} for details.
|
||||
* <p>See {@link FeedRefreshIntervalCalculator} for details.
|
||||
*/
|
||||
@WithDefault("true")
|
||||
boolean intervalEmpirical();
|
||||
|
||||
/**
|
||||
* Feed refresh engine error handling settings.
|
||||
*/
|
||||
/** Feed refresh engine error handling settings. */
|
||||
@ConfigDocSection
|
||||
FeedRefreshErrorHandling errors();
|
||||
|
||||
/**
|
||||
* Amount of http threads used to fetch feeds.
|
||||
*/
|
||||
/** Amount of http threads used to fetch feeds. */
|
||||
@Min(1)
|
||||
@WithDefault("3")
|
||||
int httpThreads();
|
||||
|
||||
/**
|
||||
* Amount of threads used to insert new entries in the database.
|
||||
*/
|
||||
/** Amount of threads used to insert new entries in the database. */
|
||||
@Min(1)
|
||||
@WithDefault("1")
|
||||
int databaseThreads();
|
||||
|
||||
/**
|
||||
* Duration after which a user is considered inactive. Feeds for inactive users are not refreshed until they log in again.
|
||||
* Duration after which a user is considered inactive. Feeds for inactive users are not
|
||||
* refreshed until they log in again.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("0")
|
||||
Duration userInactivityPeriod();
|
||||
|
||||
/**
|
||||
* Duration after which the evaluation of a filtering expresion to mark an entry as read is considered to have timed out.
|
||||
* Duration after which the evaluation of a filtering expresion to mark an entry as read is
|
||||
* considered to have timed out.
|
||||
*/
|
||||
@WithDefault("500ms")
|
||||
Duration filteringExpressionEvaluationTimeout();
|
||||
|
||||
/**
|
||||
* Duration after which the "Fetch all my feeds now" action is available again after use to avoid spamming feeds.
|
||||
* Duration after which the "Fetch all my feeds now" action is available again after use to
|
||||
* avoid spamming feeds.
|
||||
*/
|
||||
@WithDefault("0")
|
||||
Duration forceRefreshCooldownDuration();
|
||||
}
|
||||
|
||||
interface PushNotifications {
|
||||
/**
|
||||
* Whether to enable push notifications to notify users of new entries in their feeds.
|
||||
*/
|
||||
/** Whether to enable push notifications to notify users of new entries in their feeds. */
|
||||
@WithDefault("true")
|
||||
boolean enabled();
|
||||
|
||||
/**
|
||||
* Amount of threads used to send external notifications about new entries.
|
||||
*/
|
||||
/** Amount of threads used to send external notifications about new entries. */
|
||||
@Min(1)
|
||||
@WithDefault("5")
|
||||
int threads();
|
||||
|
||||
/**
|
||||
* Maximum amount of notifications that can be queued before new notifications are discarded.
|
||||
* Maximum amount of notifications that can be queued before new notifications are
|
||||
* discarded.
|
||||
*/
|
||||
@Min(1)
|
||||
@WithDefault("100")
|
||||
@@ -270,15 +243,14 @@ public interface CommaFeedConfiguration {
|
||||
}
|
||||
|
||||
interface FeedRefreshErrorHandling {
|
||||
/**
|
||||
* Number of retries before backoff is applied.
|
||||
*/
|
||||
/** Number of retries before backoff is applied. */
|
||||
@Min(0)
|
||||
@WithDefault("3")
|
||||
int retriesBeforeBackoff();
|
||||
|
||||
/**
|
||||
* Duration to wait before retrying after an error. Will be multiplied by the number of errors since the last successful fetch.
|
||||
* Duration to wait before retrying after an error. Will be multiplied by the number of
|
||||
* errors since the last successful fetch.
|
||||
*/
|
||||
@WithDefault("1h")
|
||||
Duration backoffInterval();
|
||||
@@ -288,14 +260,12 @@ public interface CommaFeedConfiguration {
|
||||
/**
|
||||
* Timeout applied to all database queries.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("0")
|
||||
Duration queryTimeout();
|
||||
|
||||
/**
|
||||
* Database cleanup settings.
|
||||
*/
|
||||
/** Database cleanup settings. */
|
||||
@ConfigDocSection
|
||||
Cleanup cleanup();
|
||||
|
||||
@@ -303,15 +273,16 @@ public interface CommaFeedConfiguration {
|
||||
/**
|
||||
* Maximum age of feed entries in the database. Older entries will be deleted.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("365d")
|
||||
Duration entriesMaxAge();
|
||||
|
||||
/**
|
||||
* Maximum age of feed entry statuses (read/unread) in the database. Older statuses will be deleted.
|
||||
* Maximum age of feed entry statuses (read/unread) in the database. Older statuses will
|
||||
* be deleted.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("0")
|
||||
Duration statusesMaxAge();
|
||||
@@ -319,7 +290,7 @@ public interface CommaFeedConfiguration {
|
||||
/**
|
||||
* Maximum number of entries per feed to keep in the database.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("500")
|
||||
int maxFeedCapacity();
|
||||
@@ -327,74 +298,66 @@ public interface CommaFeedConfiguration {
|
||||
/**
|
||||
* Limit the number of feeds a user can subscribe to.
|
||||
*
|
||||
* 0 to disable.
|
||||
* <p>0 to disable.
|
||||
*/
|
||||
@WithDefault("0")
|
||||
int maxFeedsPerUser();
|
||||
|
||||
/**
|
||||
* Rows to delete per query while cleaning up old entries.
|
||||
*/
|
||||
/** Rows to delete per query while cleaning up old entries. */
|
||||
@Positive
|
||||
@WithDefault("100")
|
||||
int batchSize();
|
||||
|
||||
/**
|
||||
* Whether to keep starred entries when cleaning up old entries.
|
||||
*/
|
||||
/** Whether to keep starred entries when cleaning up old entries. */
|
||||
@WithDefault("true")
|
||||
boolean keepStarredEntries();
|
||||
|
||||
default Instant statusesInstantThreshold() {
|
||||
return statusesMaxAge().toMillis() > 0 ? Instant.now().minus(statusesMaxAge()) : null;
|
||||
return statusesMaxAge().toMillis() > 0
|
||||
? Instant.now().minus(statusesMaxAge())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Users {
|
||||
/**
|
||||
* Whether to let users create accounts for themselves.
|
||||
*/
|
||||
/** Whether to let users create accounts for themselves. */
|
||||
@WithDefault("false")
|
||||
boolean allowRegistrations();
|
||||
|
||||
/**
|
||||
* Minimum password length for user accounts.
|
||||
*/
|
||||
/** Minimum password length for user accounts. */
|
||||
@WithDefault("4")
|
||||
int minimumPasswordLength();
|
||||
|
||||
/**
|
||||
* Whether an email address is required when creating a user account.
|
||||
*/
|
||||
/** Whether an email address is required when creating a user account. */
|
||||
@WithDefault("false")
|
||||
boolean emailAddressRequired();
|
||||
|
||||
/**
|
||||
* Whether to create a demo account the first time the app starts.
|
||||
*/
|
||||
/** Whether to create a demo account the first time the app starts. */
|
||||
@WithDefault("false")
|
||||
boolean createDemoAccount();
|
||||
}
|
||||
|
||||
interface Websocket {
|
||||
/**
|
||||
* Enable websocket connection so the server can notify web clients that there are new entries for feeds.
|
||||
* Enable websocket connection so the server can notify web clients that there are new
|
||||
* entries for feeds.
|
||||
*/
|
||||
@WithDefault("true")
|
||||
boolean enabled();
|
||||
|
||||
/**
|
||||
* Interval at which the client will send a ping message on the websocket to keep the connection alive.
|
||||
* Interval at which the client will send a ping message on the websocket to keep the
|
||||
* connection alive.
|
||||
*/
|
||||
@WithDefault("15m")
|
||||
Duration pingInterval();
|
||||
|
||||
/**
|
||||
* If the websocket connection is disabled or the connection is lost, the client will reload the feed tree at this interval.
|
||||
* If the websocket connection is disabled or the connection is lost, the client will reload
|
||||
* the feed tree at this interval.
|
||||
*/
|
||||
@WithDefault("30s")
|
||||
Duration treeReloadInterval();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.commafeed;
|
||||
|
||||
import java.time.InstantSource;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
|
||||
import jakarta.enterprise.inject.Produces;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import java.time.InstantSource;
|
||||
|
||||
@Singleton
|
||||
public class CommaFeedProducers {
|
||||
@@ -21,5 +21,4 @@ public class CommaFeedProducers {
|
||||
public MetricRegistry metricRegistry() {
|
||||
return new MetricRegistry();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.commafeed;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
@Singleton
|
||||
@Getter
|
||||
public class CommaFeedVersion {
|
||||
@@ -26,5 +26,4 @@ public class CommaFeedVersion {
|
||||
this.version = properties.getProperty("git.build.version", "unknown");
|
||||
this.gitCommit = properties.getProperty("git.commit.id.abbrev", "unknown");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
package com.commafeed;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.validation.ValidationException;
|
||||
import jakarta.ws.rs.core.NewCookie;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
import org.jboss.resteasy.reactive.RestResponse.ResponseBuilder;
|
||||
import org.jboss.resteasy.reactive.RestResponse.Status;
|
||||
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
|
||||
|
||||
import com.commafeed.security.CookieService;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.security.AuthenticationFailedException;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.validation.ValidationException;
|
||||
import jakarta.ws.rs.core.NewCookie;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.jboss.resteasy.reactive.RestResponse;
|
||||
import org.jboss.resteasy.reactive.RestResponse.ResponseBuilder;
|
||||
import org.jboss.resteasy.reactive.RestResponse.Status;
|
||||
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Provider
|
||||
@Priority(1)
|
||||
@@ -27,13 +28,18 @@ public class ExceptionMappers {
|
||||
|
||||
@ServerExceptionMapper(UnauthorizedException.class)
|
||||
public RestResponse<UnauthorizedResponse> unauthorized(UnauthorizedException e) {
|
||||
return RestResponse.status(Status.UNAUTHORIZED, new UnauthorizedResponse(e.getMessage(), config.users().allowRegistrations()));
|
||||
return RestResponse.status(
|
||||
Status.UNAUTHORIZED,
|
||||
new UnauthorizedResponse(e.getMessage(), config.users().allowRegistrations()));
|
||||
}
|
||||
|
||||
@ServerExceptionMapper(AuthenticationFailedException.class)
|
||||
public RestResponse<AuthenticationFailed> authenticationFailed(AuthenticationFailedException e) {
|
||||
public RestResponse<AuthenticationFailed> authenticationFailed(
|
||||
AuthenticationFailedException e) {
|
||||
NewCookie logoutCookie = cookieService.buildLogoutCookie();
|
||||
return ResponseBuilder.create(Status.UNAUTHORIZED, new AuthenticationFailed(e.getMessage())).cookie(logoutCookie).build();
|
||||
return ResponseBuilder.create(Status.UNAUTHORIZED, new AuthenticationFailed(e.getMessage()))
|
||||
.cookie(logoutCookie)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ServerExceptionMapper(ValidationException.class)
|
||||
@@ -42,14 +48,11 @@ public class ExceptionMappers {
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record UnauthorizedResponse(String message, boolean allowRegistrations) {
|
||||
}
|
||||
public record UnauthorizedResponse(String message, boolean allowRegistrations) {}
|
||||
|
||||
@RegisterForReflection
|
||||
public record AuthenticationFailed(String message) {
|
||||
}
|
||||
public record AuthenticationFailed(String message) {}
|
||||
|
||||
@RegisterForReflection
|
||||
public record ValidationFailed(String message) {
|
||||
}
|
||||
public record ValidationFailed(String message) {}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package com.commafeed;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import com.codahale.metrics.json.MetricsModule;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -12,6 +8,10 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
|
||||
import io.quarkus.jackson.ObjectMapperCustomizer;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class JacksonCustomizer implements ObjectMapperCustomizer {
|
||||
@Override
|
||||
@@ -19,7 +19,8 @@ public class JacksonCustomizer implements ObjectMapperCustomizer {
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
|
||||
// read and write instants as milliseconds instead of nanoseconds
|
||||
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true)
|
||||
objectMapper
|
||||
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true)
|
||||
.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
|
||||
.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
|
||||
|
||||
|
||||
@@ -12,215 +12,338 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
@RegisterForReflection(
|
||||
targets = {
|
||||
// metrics
|
||||
MetricRegistry.class, Meter.class, Gauge.class, Counter.class, Timer.class, Histogram.class,
|
||||
MetricRegistry.class,
|
||||
Meter.class,
|
||||
Gauge.class,
|
||||
Counter.class,
|
||||
Timer.class,
|
||||
Histogram.class,
|
||||
|
||||
// rome
|
||||
java.util.Date.class, com.rometools.opml.feed.synd.impl.TreeCategoryImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndFeedImpl.class, com.rometools.rome.feed.module.DCSubjectImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndEntryImpl.class, com.rometools.modules.psc.types.SimpleChapter.class,
|
||||
com.rometools.rome.feed.synd.SyndCategoryImpl.class, com.rometools.rome.feed.synd.SyndImageImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndContentImpl.class, com.rometools.rome.feed.synd.SyndEnclosureImpl.class,
|
||||
java.util.Date.class,
|
||||
com.rometools.opml.feed.synd.impl.TreeCategoryImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndFeedImpl.class,
|
||||
com.rometools.rome.feed.module.DCSubjectImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndEntryImpl.class,
|
||||
com.rometools.modules.psc.types.SimpleChapter.class,
|
||||
com.rometools.rome.feed.synd.SyndCategoryImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndImageImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndContentImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndEnclosureImpl.class,
|
||||
|
||||
// rome cloneable
|
||||
com.rometools.modules.activitystreams.types.Article.class, com.rometools.modules.activitystreams.types.Audio.class,
|
||||
com.rometools.modules.activitystreams.types.Bookmark.class, com.rometools.modules.activitystreams.types.Comment.class,
|
||||
com.rometools.modules.activitystreams.types.Event.class, com.rometools.modules.activitystreams.types.File.class,
|
||||
com.rometools.modules.activitystreams.types.Folder.class, com.rometools.modules.activitystreams.types.List.class,
|
||||
com.rometools.modules.activitystreams.types.Note.class, com.rometools.modules.activitystreams.types.Person.class,
|
||||
com.rometools.modules.activitystreams.types.Photo.class, com.rometools.modules.activitystreams.types.PhotoAlbum.class,
|
||||
com.rometools.modules.activitystreams.types.Place.class, com.rometools.modules.activitystreams.types.Playlist.class,
|
||||
com.rometools.modules.activitystreams.types.Product.class, com.rometools.modules.activitystreams.types.Review.class,
|
||||
com.rometools.modules.activitystreams.types.Service.class, com.rometools.modules.activitystreams.types.Song.class,
|
||||
com.rometools.modules.activitystreams.types.Status.class, com.rometools.modules.base.types.DateTimeRange.class,
|
||||
com.rometools.modules.base.types.FloatUnit.class, com.rometools.modules.base.types.GenderEnumeration.class,
|
||||
com.rometools.modules.base.types.IntUnit.class, com.rometools.modules.base.types.PriceTypeEnumeration.class,
|
||||
com.rometools.modules.base.types.ShippingType.class, com.rometools.modules.base.types.ShortDate.class,
|
||||
com.rometools.modules.base.types.Size.class, com.rometools.modules.base.types.YearType.class,
|
||||
com.rometools.modules.content.ContentItem.class, com.rometools.modules.georss.GeoRSSPoint.class,
|
||||
com.rometools.modules.georss.geometries.Envelope.class, com.rometools.modules.georss.geometries.LineString.class,
|
||||
com.rometools.modules.georss.geometries.LinearRing.class, com.rometools.modules.georss.geometries.Point.class,
|
||||
com.rometools.modules.georss.geometries.Polygon.class, com.rometools.modules.georss.geometries.Position.class,
|
||||
com.rometools.modules.georss.geometries.PositionList.class, com.rometools.modules.mediarss.types.MediaGroup.class,
|
||||
com.rometools.modules.mediarss.types.Metadata.class, com.rometools.modules.mediarss.types.Thumbnail.class,
|
||||
com.rometools.modules.opensearch.entity.OSQuery.class, com.rometools.modules.photocast.types.PhotoDate.class,
|
||||
com.rometools.modules.sle.types.DateValue.class, com.rometools.modules.sle.types.Group.class,
|
||||
com.rometools.modules.sle.types.NumberValue.class, com.rometools.modules.sle.types.Sort.class,
|
||||
com.rometools.modules.sle.types.StringValue.class, com.rometools.modules.yahooweather.types.Astronomy.class,
|
||||
com.rometools.modules.yahooweather.types.Atmosphere.class, com.rometools.modules.yahooweather.types.Condition.class,
|
||||
com.rometools.modules.yahooweather.types.Forecast.class, com.rometools.modules.yahooweather.types.Location.class,
|
||||
com.rometools.modules.yahooweather.types.Units.class, com.rometools.modules.yahooweather.types.Wind.class,
|
||||
com.rometools.opml.feed.opml.Attribute.class, com.rometools.opml.feed.opml.Opml.class,
|
||||
com.rometools.opml.feed.opml.Outline.class, com.rometools.rome.feed.atom.Category.class,
|
||||
com.rometools.rome.feed.atom.Content.class, com.rometools.rome.feed.atom.Entry.class,
|
||||
com.rometools.rome.feed.atom.Feed.class, com.rometools.rome.feed.atom.Generator.class,
|
||||
com.rometools.rome.feed.atom.Link.class, com.rometools.rome.feed.atom.Person.class,
|
||||
com.rometools.rome.feed.rss.Category.class, com.rometools.rome.feed.rss.Channel.class,
|
||||
com.rometools.rome.feed.rss.Cloud.class, com.rometools.rome.feed.rss.Content.class,
|
||||
com.rometools.rome.feed.rss.Description.class, com.rometools.rome.feed.rss.Enclosure.class,
|
||||
com.rometools.rome.feed.rss.Guid.class, com.rometools.rome.feed.rss.Image.class, com.rometools.rome.feed.rss.Item.class,
|
||||
com.rometools.rome.feed.rss.Source.class, com.rometools.rome.feed.rss.TextInput.class,
|
||||
com.rometools.rome.feed.synd.SyndLinkImpl.class, com.rometools.rome.feed.synd.SyndPersonImpl.class,
|
||||
com.rometools.modules.activitystreams.types.Article.class,
|
||||
com.rometools.modules.activitystreams.types.Audio.class,
|
||||
com.rometools.modules.activitystreams.types.Bookmark.class,
|
||||
com.rometools.modules.activitystreams.types.Comment.class,
|
||||
com.rometools.modules.activitystreams.types.Event.class,
|
||||
com.rometools.modules.activitystreams.types.File.class,
|
||||
com.rometools.modules.activitystreams.types.Folder.class,
|
||||
com.rometools.modules.activitystreams.types.List.class,
|
||||
com.rometools.modules.activitystreams.types.Note.class,
|
||||
com.rometools.modules.activitystreams.types.Person.class,
|
||||
com.rometools.modules.activitystreams.types.Photo.class,
|
||||
com.rometools.modules.activitystreams.types.PhotoAlbum.class,
|
||||
com.rometools.modules.activitystreams.types.Place.class,
|
||||
com.rometools.modules.activitystreams.types.Playlist.class,
|
||||
com.rometools.modules.activitystreams.types.Product.class,
|
||||
com.rometools.modules.activitystreams.types.Review.class,
|
||||
com.rometools.modules.activitystreams.types.Service.class,
|
||||
com.rometools.modules.activitystreams.types.Song.class,
|
||||
com.rometools.modules.activitystreams.types.Status.class,
|
||||
com.rometools.modules.base.types.DateTimeRange.class,
|
||||
com.rometools.modules.base.types.FloatUnit.class,
|
||||
com.rometools.modules.base.types.GenderEnumeration.class,
|
||||
com.rometools.modules.base.types.IntUnit.class,
|
||||
com.rometools.modules.base.types.PriceTypeEnumeration.class,
|
||||
com.rometools.modules.base.types.ShippingType.class,
|
||||
com.rometools.modules.base.types.ShortDate.class,
|
||||
com.rometools.modules.base.types.Size.class,
|
||||
com.rometools.modules.base.types.YearType.class,
|
||||
com.rometools.modules.content.ContentItem.class,
|
||||
com.rometools.modules.georss.GeoRSSPoint.class,
|
||||
com.rometools.modules.georss.geometries.Envelope.class,
|
||||
com.rometools.modules.georss.geometries.LineString.class,
|
||||
com.rometools.modules.georss.geometries.LinearRing.class,
|
||||
com.rometools.modules.georss.geometries.Point.class,
|
||||
com.rometools.modules.georss.geometries.Polygon.class,
|
||||
com.rometools.modules.georss.geometries.Position.class,
|
||||
com.rometools.modules.georss.geometries.PositionList.class,
|
||||
com.rometools.modules.mediarss.types.MediaGroup.class,
|
||||
com.rometools.modules.mediarss.types.Metadata.class,
|
||||
com.rometools.modules.mediarss.types.Thumbnail.class,
|
||||
com.rometools.modules.opensearch.entity.OSQuery.class,
|
||||
com.rometools.modules.photocast.types.PhotoDate.class,
|
||||
com.rometools.modules.sle.types.DateValue.class,
|
||||
com.rometools.modules.sle.types.Group.class,
|
||||
com.rometools.modules.sle.types.NumberValue.class,
|
||||
com.rometools.modules.sle.types.Sort.class,
|
||||
com.rometools.modules.sle.types.StringValue.class,
|
||||
com.rometools.modules.yahooweather.types.Astronomy.class,
|
||||
com.rometools.modules.yahooweather.types.Atmosphere.class,
|
||||
com.rometools.modules.yahooweather.types.Condition.class,
|
||||
com.rometools.modules.yahooweather.types.Forecast.class,
|
||||
com.rometools.modules.yahooweather.types.Location.class,
|
||||
com.rometools.modules.yahooweather.types.Units.class,
|
||||
com.rometools.modules.yahooweather.types.Wind.class,
|
||||
com.rometools.opml.feed.opml.Attribute.class,
|
||||
com.rometools.opml.feed.opml.Opml.class,
|
||||
com.rometools.opml.feed.opml.Outline.class,
|
||||
com.rometools.rome.feed.atom.Category.class,
|
||||
com.rometools.rome.feed.atom.Content.class,
|
||||
com.rometools.rome.feed.atom.Entry.class,
|
||||
com.rometools.rome.feed.atom.Feed.class,
|
||||
com.rometools.rome.feed.atom.Generator.class,
|
||||
com.rometools.rome.feed.atom.Link.class,
|
||||
com.rometools.rome.feed.atom.Person.class,
|
||||
com.rometools.rome.feed.rss.Category.class,
|
||||
com.rometools.rome.feed.rss.Channel.class,
|
||||
com.rometools.rome.feed.rss.Cloud.class,
|
||||
com.rometools.rome.feed.rss.Content.class,
|
||||
com.rometools.rome.feed.rss.Description.class,
|
||||
com.rometools.rome.feed.rss.Enclosure.class,
|
||||
com.rometools.rome.feed.rss.Guid.class,
|
||||
com.rometools.rome.feed.rss.Image.class,
|
||||
com.rometools.rome.feed.rss.Item.class,
|
||||
com.rometools.rome.feed.rss.Source.class,
|
||||
com.rometools.rome.feed.rss.TextInput.class,
|
||||
com.rometools.rome.feed.synd.SyndLinkImpl.class,
|
||||
com.rometools.rome.feed.synd.SyndPersonImpl.class,
|
||||
java.util.ArrayList.class,
|
||||
|
||||
// rome modules
|
||||
com.rometools.modules.sse.modules.Conflict.class, com.rometools.modules.sse.modules.Conflicts.class,
|
||||
com.rometools.modules.cc.CreativeCommonsImpl.class, com.rometools.modules.feedpress.modules.FeedpressModuleImpl.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleImpl.class, com.rometools.modules.sse.modules.Sharing.class,
|
||||
com.rometools.modules.georss.SimpleModuleImpl.class, com.rometools.modules.atom.modules.AtomLinkModuleImpl.class,
|
||||
com.rometools.modules.itunes.EntryInformationImpl.class, com.rometools.modules.sse.modules.Update.class,
|
||||
com.rometools.modules.photocast.PhotocastModuleImpl.class, com.rometools.modules.itunes.FeedInformationImpl.class,
|
||||
com.rometools.modules.yahooweather.YWeatherModuleImpl.class, com.rometools.modules.feedburner.FeedBurnerImpl.class,
|
||||
com.rometools.modules.sse.modules.Related.class, com.rometools.modules.fyyd.modules.FyydModuleImpl.class,
|
||||
com.rometools.modules.psc.modules.PodloveSimpleChapterModuleImpl.class, com.rometools.modules.thr.ThreadingModuleImpl.class,
|
||||
com.rometools.modules.sse.modules.Sync.class, com.rometools.modules.sle.SimpleListExtensionImpl.class,
|
||||
com.rometools.modules.slash.SlashImpl.class, com.rometools.modules.sse.modules.History.class,
|
||||
com.rometools.modules.georss.GMLModuleImpl.class, com.rometools.modules.base.CustomTagsImpl.class,
|
||||
com.rometools.modules.base.GoogleBaseImpl.class, com.rometools.modules.sle.SleEntryImpl.class,
|
||||
com.rometools.modules.mediarss.MediaEntryModuleImpl.class, com.rometools.modules.content.ContentModuleImpl.class,
|
||||
com.rometools.modules.georss.W3CGeoModuleImpl.class, com.rometools.rome.feed.module.DCModuleImpl.class,
|
||||
com.rometools.modules.mediarss.MediaModuleImpl.class, com.rometools.rome.feed.module.SyModuleImpl.class,
|
||||
com.rometools.modules.sse.modules.Conflict.class,
|
||||
com.rometools.modules.sse.modules.Conflicts.class,
|
||||
com.rometools.modules.cc.CreativeCommonsImpl.class,
|
||||
com.rometools.modules.feedpress.modules.FeedpressModuleImpl.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleImpl.class,
|
||||
com.rometools.modules.sse.modules.Sharing.class,
|
||||
com.rometools.modules.georss.SimpleModuleImpl.class,
|
||||
com.rometools.modules.atom.modules.AtomLinkModuleImpl.class,
|
||||
com.rometools.modules.itunes.EntryInformationImpl.class,
|
||||
com.rometools.modules.sse.modules.Update.class,
|
||||
com.rometools.modules.photocast.PhotocastModuleImpl.class,
|
||||
com.rometools.modules.itunes.FeedInformationImpl.class,
|
||||
com.rometools.modules.yahooweather.YWeatherModuleImpl.class,
|
||||
com.rometools.modules.feedburner.FeedBurnerImpl.class,
|
||||
com.rometools.modules.sse.modules.Related.class,
|
||||
com.rometools.modules.fyyd.modules.FyydModuleImpl.class,
|
||||
com.rometools.modules.psc.modules.PodloveSimpleChapterModuleImpl.class,
|
||||
com.rometools.modules.thr.ThreadingModuleImpl.class,
|
||||
com.rometools.modules.sse.modules.Sync.class,
|
||||
com.rometools.modules.sle.SimpleListExtensionImpl.class,
|
||||
com.rometools.modules.slash.SlashImpl.class,
|
||||
com.rometools.modules.sse.modules.History.class,
|
||||
com.rometools.modules.georss.GMLModuleImpl.class,
|
||||
com.rometools.modules.base.CustomTagsImpl.class,
|
||||
com.rometools.modules.base.GoogleBaseImpl.class,
|
||||
com.rometools.modules.sle.SleEntryImpl.class,
|
||||
com.rometools.modules.mediarss.MediaEntryModuleImpl.class,
|
||||
com.rometools.modules.content.ContentModuleImpl.class,
|
||||
com.rometools.modules.georss.W3CGeoModuleImpl.class,
|
||||
com.rometools.rome.feed.module.DCModuleImpl.class,
|
||||
com.rometools.modules.mediarss.MediaModuleImpl.class,
|
||||
com.rometools.rome.feed.module.SyModuleImpl.class,
|
||||
|
||||
// extracted from all 3 rome.properties files of rome library
|
||||
com.rometools.rome.io.impl.RSS090Parser.class, com.rometools.rome.io.impl.RSS091NetscapeParser.class,
|
||||
com.rometools.rome.io.impl.RSS091UserlandParser.class, com.rometools.rome.io.impl.RSS092Parser.class,
|
||||
com.rometools.rome.io.impl.RSS093Parser.class, com.rometools.rome.io.impl.RSS094Parser.class,
|
||||
com.rometools.rome.io.impl.RSS10Parser.class, com.rometools.rome.io.impl.RSS20wNSParser.class,
|
||||
com.rometools.rome.io.impl.RSS20Parser.class, com.rometools.rome.io.impl.Atom10Parser.class,
|
||||
com.rometools.rome.io.impl.RSS090Parser.class,
|
||||
com.rometools.rome.io.impl.RSS091NetscapeParser.class,
|
||||
com.rometools.rome.io.impl.RSS091UserlandParser.class,
|
||||
com.rometools.rome.io.impl.RSS092Parser.class,
|
||||
com.rometools.rome.io.impl.RSS093Parser.class,
|
||||
com.rometools.rome.io.impl.RSS094Parser.class,
|
||||
com.rometools.rome.io.impl.RSS10Parser.class,
|
||||
com.rometools.rome.io.impl.RSS20wNSParser.class,
|
||||
com.rometools.rome.io.impl.RSS20Parser.class,
|
||||
com.rometools.rome.io.impl.Atom10Parser.class,
|
||||
com.rometools.rome.io.impl.Atom03Parser.class,
|
||||
|
||||
com.rometools.rome.io.impl.SyModuleParser.class, com.rometools.rome.io.impl.DCModuleParser.class,
|
||||
|
||||
com.rometools.rome.io.impl.RSS090Generator.class, com.rometools.rome.io.impl.RSS091NetscapeGenerator.class,
|
||||
com.rometools.rome.io.impl.RSS091UserlandGenerator.class, com.rometools.rome.io.impl.RSS092Generator.class,
|
||||
com.rometools.rome.io.impl.RSS093Generator.class, com.rometools.rome.io.impl.RSS094Generator.class,
|
||||
com.rometools.rome.io.impl.RSS10Generator.class, com.rometools.rome.io.impl.RSS20Generator.class,
|
||||
com.rometools.rome.io.impl.Atom10Generator.class, com.rometools.rome.io.impl.Atom03Generator.class,
|
||||
|
||||
com.rometools.rome.feed.synd.impl.ConverterForAtom10.class, com.rometools.rome.feed.synd.impl.ConverterForAtom03.class,
|
||||
com.rometools.rome.io.impl.SyModuleParser.class,
|
||||
com.rometools.rome.io.impl.DCModuleParser.class,
|
||||
com.rometools.rome.io.impl.RSS090Generator.class,
|
||||
com.rometools.rome.io.impl.RSS091NetscapeGenerator.class,
|
||||
com.rometools.rome.io.impl.RSS091UserlandGenerator.class,
|
||||
com.rometools.rome.io.impl.RSS092Generator.class,
|
||||
com.rometools.rome.io.impl.RSS093Generator.class,
|
||||
com.rometools.rome.io.impl.RSS094Generator.class,
|
||||
com.rometools.rome.io.impl.RSS10Generator.class,
|
||||
com.rometools.rome.io.impl.RSS20Generator.class,
|
||||
com.rometools.rome.io.impl.Atom10Generator.class,
|
||||
com.rometools.rome.io.impl.Atom03Generator.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForAtom10.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForAtom03.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS090.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS091Netscape.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS091Userland.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS092.class, com.rometools.rome.feed.synd.impl.ConverterForRSS093.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS094.class, com.rometools.rome.feed.synd.impl.ConverterForRSS10.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS092.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS093.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS094.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS10.class,
|
||||
com.rometools.rome.feed.synd.impl.ConverterForRSS20.class,
|
||||
|
||||
com.rometools.modules.mediarss.io.RSS20YahooParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class, com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class, com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class, com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class, com.rometools.modules.atom.io.AtomModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.atom.io.AtomModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParserOldNamespace.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class, com.rometools.modules.sle.io.ModuleParser.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleParser.class, com.rometools.modules.feedpress.io.FeedpressParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
com.rometools.modules.sle.io.ModuleParser.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleParser.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressParser.class,
|
||||
com.rometools.modules.fyyd.io.FyydParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class, com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class, com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class, com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class, com.rometools.modules.atom.io.AtomModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.atom.io.AtomModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParserOldNamespace.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class, com.rometools.modules.sle.io.ModuleParser.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleParser.class, com.rometools.modules.feedpress.io.FeedpressParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
com.rometools.modules.sle.io.ModuleParser.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleParser.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressParser.class,
|
||||
com.rometools.modules.fyyd.io.FyydParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS1.class, com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class, com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class, com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS1.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class, com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class, com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressParser.class, com.rometools.modules.fyyd.io.FyydParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class, com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class, com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.atom.io.AtomModuleParser.class, com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class, com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class, com.rometools.modules.itunes.io.ITunesParserOldNamespace.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class, com.rometools.modules.sle.io.ItemParser.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressParser.class,
|
||||
com.rometools.modules.fyyd.io.FyydParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.atom.io.AtomModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.itunes.io.ITunesParserOldNamespace.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
com.rometools.modules.sle.io.ItemParser.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleParser.class,
|
||||
com.rometools.modules.psc.io.PodloveSimpleChapterParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS1.class, com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class, com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS1.class,
|
||||
com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class,
|
||||
com.rometools.modules.content.io.ContentModuleParser.class,
|
||||
com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class, com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class, com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class, com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class,
|
||||
com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class, com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class, com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class, com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class, com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.cc.io.ModuleParserRSS2.class,
|
||||
com.rometools.modules.base.io.GoogleBaseParser.class,
|
||||
com.rometools.modules.base.io.CustomTagParser.class,
|
||||
com.rometools.modules.slash.io.SlashModuleParser.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleParser.class,
|
||||
com.rometools.modules.georss.SimpleParser.class,
|
||||
com.rometools.modules.georss.W3CGeoParser.class,
|
||||
com.rometools.modules.photocast.io.Parser.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
com.rometools.modules.mediarss.io.AlternateMediaModuleParser.class,
|
||||
com.rometools.modules.thr.io.ThreadingModuleParser.class, com.rometools.modules.psc.io.PodloveSimpleChapterParser.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.itunes.io.ITunesGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class, com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class, com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class, com.rometools.modules.atom.io.AtomModuleGenerator.class,
|
||||
com.rometools.modules.sle.io.ModuleGenerator.class, com.rometools.modules.yahooweather.io.WeatherModuleGenerator.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressGenerator.class, com.rometools.modules.fyyd.io.FyydGenerator.class,
|
||||
|
||||
com.rometools.modules.thr.io.ThreadingModuleParser.class,
|
||||
com.rometools.modules.psc.io.PodloveSimpleChapterParser.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class, com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class, com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class, com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class, com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressGenerator.class, com.rometools.modules.fyyd.io.FyydGenerator.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.base.io.GoogleBaseGenerator.class,
|
||||
com.rometools.modules.base.io.CustomTagGenerator.class, com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.slash.io.SlashModuleGenerator.class, com.rometools.modules.itunes.io.ITunesGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class, com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class, com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class, com.rometools.modules.atom.io.AtomModuleGenerator.class,
|
||||
com.rometools.modules.itunes.io.ITunesGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.atom.io.AtomModuleGenerator.class,
|
||||
com.rometools.modules.sle.io.ModuleGenerator.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleGenerator.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressGenerator.class,
|
||||
com.rometools.modules.fyyd.io.FyydGenerator.class,
|
||||
com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.feedpress.io.FeedpressGenerator.class,
|
||||
com.rometools.modules.fyyd.io.FyydGenerator.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.base.io.GoogleBaseGenerator.class,
|
||||
com.rometools.modules.base.io.CustomTagGenerator.class,
|
||||
com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.slash.io.SlashModuleGenerator.class,
|
||||
com.rometools.modules.itunes.io.ITunesGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.atom.io.AtomModuleGenerator.class,
|
||||
com.rometools.modules.yahooweather.io.WeatherModuleGenerator.class,
|
||||
com.rometools.modules.psc.io.PodloveSimpleChapterGenerator.class,
|
||||
|
||||
com.rometools.modules.base.io.GoogleBaseGenerator.class, com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.base.io.GoogleBaseGenerator.class,
|
||||
com.rometools.modules.content.io.ContentModuleGenerator.class,
|
||||
com.rometools.modules.slash.io.SlashModuleGenerator.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.base.io.GoogleBaseGenerator.class,
|
||||
com.rometools.modules.base.io.CustomTagGenerator.class, com.rometools.modules.slash.io.SlashModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class, com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class, com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.base.io.GoogleBaseGenerator.class,
|
||||
com.rometools.modules.base.io.CustomTagGenerator.class,
|
||||
com.rometools.modules.slash.io.SlashModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class, com.rometools.modules.base.io.CustomTagGenerator.class,
|
||||
com.rometools.modules.cc.io.CCModuleGenerator.class,
|
||||
com.rometools.modules.base.io.CustomTagGenerator.class,
|
||||
com.rometools.modules.slash.io.SlashModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class, com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class, com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class, com.rometools.modules.thr.io.ThreadingModuleGenerator.class,
|
||||
com.rometools.modules.opensearch.impl.OpenSearchModuleGenerator.class,
|
||||
com.rometools.modules.georss.SimpleGenerator.class,
|
||||
com.rometools.modules.georss.W3CGeoGenerator.class,
|
||||
com.rometools.modules.photocast.io.Generator.class,
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
com.rometools.modules.thr.io.ThreadingModuleGenerator.class,
|
||||
com.rometools.modules.psc.io.PodloveSimpleChapterGenerator.class,
|
||||
|
||||
com.rometools.modules.mediarss.io.MediaModuleParser.class,
|
||||
|
||||
com.rometools.modules.mediarss.io.MediaModuleGenerator.class,
|
||||
|
||||
com.rometools.opml.io.impl.OPML10Generator.class, com.rometools.opml.io.impl.OPML20Generator.class,
|
||||
|
||||
com.rometools.opml.io.impl.OPML10Parser.class, com.rometools.opml.io.impl.OPML20Parser.class,
|
||||
|
||||
com.rometools.opml.feed.synd.impl.ConverterForOPML10.class, com.rometools.opml.feed.synd.impl.ConverterForOPML20.class, })
|
||||
|
||||
public class NativeImageClasses {
|
||||
}
|
||||
com.rometools.opml.io.impl.OPML10Generator.class,
|
||||
com.rometools.opml.io.impl.OPML20Generator.class,
|
||||
com.rometools.opml.io.impl.OPML10Parser.class,
|
||||
com.rometools.opml.io.impl.OPML20Parser.class,
|
||||
com.rometools.opml.feed.synd.impl.ConverterForOPML10.class,
|
||||
com.rometools.opml.feed.synd.impl.ConverterForOPML20.class,
|
||||
})
|
||||
public class NativeImageClasses {}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.google.common.hash.HashFunction;
|
||||
import com.google.common.hash.Hashing;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@UtilityClass
|
||||
@SuppressWarnings("deprecation")
|
||||
public class Digests {
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.SequencedMap;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedVersion;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import inet.ipaddr.IPAddress;
|
||||
import inet.ipaddr.IPAddressNetwork;
|
||||
import inet.ipaddr.IPAddressString;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import nl.altindag.ssl.SSLFactory;
|
||||
import nl.altindag.ssl.apache5.util.Apache5SslUtils;
|
||||
|
||||
import org.apache.hc.client5.http.DnsResolver;
|
||||
import org.apache.hc.client5.http.SystemDefaultDnsResolver;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
@@ -35,32 +39,43 @@ import org.apache.hc.core5.util.TimeValue;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.brotli.dec.BrotliInputStream;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedVersion;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import nl.altindag.ssl.SSLFactory;
|
||||
import nl.altindag.ssl.apache5.util.Apache5SslUtils;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.SequencedMap;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
@Singleton
|
||||
@RequiredArgsConstructor
|
||||
public class HttpClientFactory {
|
||||
|
||||
private static final DnsResolver DNS_RESOLVER = SystemDefaultDnsResolver.INSTANCE;
|
||||
private static final IPAddress CGNAT_RANGE = new IPAddressString("100.64.0.0/10").getAddress();
|
||||
|
||||
private final CommaFeedConfiguration config;
|
||||
private final CommaFeedVersion version;
|
||||
|
||||
public CloseableHttpClient newClient(int poolSize) {
|
||||
PoolingHttpClientConnectionManager connectionManager = newConnectionManager(config, poolSize);
|
||||
String userAgent = config.httpClient()
|
||||
PoolingHttpClientConnectionManager connectionManager =
|
||||
newConnectionManager(config, poolSize);
|
||||
String userAgent =
|
||||
config.httpClient()
|
||||
.userAgent()
|
||||
.orElseGet(() -> String.format("CommaFeed/%s (https://github.com/Athou/commafeed)", version.getVersion()));
|
||||
.orElseGet(
|
||||
() ->
|
||||
String.format(
|
||||
"CommaFeed/%s (https://github.com/Athou/commafeed)",
|
||||
version.getVersion()));
|
||||
return newClient(config, connectionManager, userAgent);
|
||||
}
|
||||
|
||||
private CloseableHttpClient newClient(CommaFeedConfiguration config, HttpClientConnectionManager connectionManager, String userAgent) {
|
||||
private CloseableHttpClient newClient(
|
||||
CommaFeedConfiguration config,
|
||||
HttpClientConnectionManager connectionManager,
|
||||
String userAgent) {
|
||||
List<Header> headers = new ArrayList<>();
|
||||
headers.add(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, "en"));
|
||||
headers.add(new BasicHeader(HttpHeaders.PRAGMA, "No-cache"));
|
||||
@@ -71,11 +86,13 @@ public class HttpClientFactory {
|
||||
contentDecoderMap.put(ContentCoding.DEFLATE.token(), DeflateInputStream::new);
|
||||
contentDecoderMap.put(ContentCoding.BROTLI.token(), BrotliInputStream::new);
|
||||
|
||||
RedirectStrategy redirectStrategy = config.httpClient().blockLocalAddresses()
|
||||
RedirectStrategy redirectStrategy =
|
||||
config.httpClient().blockLocalAddresses()
|
||||
? new BlockLocalAddressesRedirectStrategy(DNS_RESOLVER)
|
||||
: new DefaultRedirectStrategy();
|
||||
|
||||
return HttpClientBuilder.create()
|
||||
.disableConnectionState()
|
||||
.useSystemProperties()
|
||||
.disableAutomaticRetries()
|
||||
.disableCookieManagement()
|
||||
@@ -83,35 +100,45 @@ public class HttpClientFactory {
|
||||
.setDefaultHeaders(headers)
|
||||
.setConnectionManager(connectionManager)
|
||||
.evictExpiredConnections()
|
||||
.evictIdleConnections(TimeValue.of(config.httpClient().idleConnectionsEvictionInterval()))
|
||||
.evictIdleConnections(
|
||||
TimeValue.of(config.httpClient().idleConnectionsEvictionInterval()))
|
||||
.setContentDecoderRegistry(new LinkedHashMap<>(contentDecoderMap))
|
||||
.setRedirectStrategy(redirectStrategy)
|
||||
.build();
|
||||
}
|
||||
|
||||
private PoolingHttpClientConnectionManager newConnectionManager(CommaFeedConfiguration config, int poolSize) {
|
||||
SSLFactory sslFactory = SSLFactory.builder().withUnsafeTrustMaterial().withUnsafeHostnameVerifier().build();
|
||||
DnsResolver dnsResolver = config.httpClient().blockLocalAddresses() ? new BlockLocalAddressesDnsResolver(DNS_RESOLVER)
|
||||
private PoolingHttpClientConnectionManager newConnectionManager(
|
||||
CommaFeedConfiguration config, int poolSize) {
|
||||
SSLFactory sslFactory =
|
||||
SSLFactory.builder().withUnsafeTrustMaterial().withUnsafeHostnameVerifier().build();
|
||||
DnsResolver dnsResolver =
|
||||
config.httpClient().blockLocalAddresses()
|
||||
? new BlockLocalAddressesDnsResolver(DNS_RESOLVER)
|
||||
: DNS_RESOLVER;
|
||||
|
||||
return PoolingHttpClientConnectionManagerBuilder.create()
|
||||
.setTlsSocketStrategy(Apache5SslUtils.toTlsSocketStrategy(sslFactory))
|
||||
.setDefaultConnectionConfig(ConnectionConfig.custom()
|
||||
.setDefaultConnectionConfig(
|
||||
ConnectionConfig.custom()
|
||||
.setConnectTimeout(Timeout.of(config.httpClient().connectTimeout()))
|
||||
.setSocketTimeout(Timeout.of(config.httpClient().socketTimeout()))
|
||||
.setTimeToLive(Timeout.of(config.httpClient().connectionTimeToLive()))
|
||||
.setTimeToLive(
|
||||
Timeout.of(config.httpClient().connectionTimeToLive()))
|
||||
.build())
|
||||
.setDefaultTlsConfig(
|
||||
TlsConfig.custom()
|
||||
.setHandshakeTimeout(
|
||||
Timeout.of(config.httpClient().sslHandshakeTimeout()))
|
||||
.build())
|
||||
.setDefaultTlsConfig(TlsConfig.custom().setHandshakeTimeout(Timeout.of(config.httpClient().sslHandshakeTimeout())).build())
|
||||
.setMaxConnPerRoute(poolSize)
|
||||
.setMaxConnTotal(poolSize)
|
||||
.setDnsResolver(dnsResolver)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
private static boolean isLocalAddress(InetAddress address) {
|
||||
return address.isSiteLocalAddress() || address.isAnyLocalAddress() || address.isLinkLocalAddress() || address.isLoopbackAddress()
|
||||
|| address.isMulticastAddress();
|
||||
IPAddress ip = new IPAddressNetwork.IPAddressGenerator().from(address);
|
||||
return ip.isLocal() || ip.isLoopback() || ip.isMulticast() || CGNAT_RANGE.contains(ip);
|
||||
}
|
||||
|
||||
private record BlockLocalAddressesDnsResolver(DnsResolver delegate) implements DnsResolver {
|
||||
@@ -120,7 +147,8 @@ public class HttpClientFactory {
|
||||
InetAddress[] addresses = delegate.resolve(host);
|
||||
for (InetAddress addr : addresses) {
|
||||
if (isLocalAddress(addr)) {
|
||||
throw new UnknownHostException("Access to local address blocked: " + addr.getHostAddress());
|
||||
throw new UnknownHostException(
|
||||
"Access to local address blocked: " + addr.getHostAddress());
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
@@ -138,7 +166,8 @@ public class HttpClientFactory {
|
||||
private final DnsResolver delegate;
|
||||
|
||||
@Override
|
||||
public URI getLocationURI(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException {
|
||||
public URI getLocationURI(HttpRequest request, HttpResponse response, HttpContext context)
|
||||
throws HttpException {
|
||||
URI redirectUri = super.getLocationURI(request, response, context);
|
||||
|
||||
String host = redirectUri.getHost();
|
||||
@@ -155,12 +184,12 @@ public class HttpClientFactory {
|
||||
|
||||
for (InetAddress addr : addresses) {
|
||||
if (isLocalAddress(addr)) {
|
||||
throw new HttpException("Access to local address blocked: " + addr.getHostAddress());
|
||||
throw new HttpException(
|
||||
"Access to local address blocked: " + addr.getHostAddress());
|
||||
}
|
||||
}
|
||||
|
||||
return redirectUri;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.InstantSource;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedConfiguration.HttpClientCache;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.ws.rs.core.CacheControl;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Lombok;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
@@ -27,25 +34,16 @@ import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.jboss.resteasy.reactive.common.headers.CacheControlDelegate;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedConfiguration.HttpClientCache;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.InstantSource;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Lombok;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Smart HTTP getter: handles gzip, ssl, last modified and etag headers
|
||||
*/
|
||||
/** Smart HTTP getter: handles gzip, ssl, last modified and etag headers */
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class HttpGetter {
|
||||
@@ -54,24 +52,42 @@ public class HttpGetter {
|
||||
private final CloseableHttpClient client;
|
||||
private final Cache<HttpRequest, HttpResponse> cache;
|
||||
|
||||
public HttpGetter(CommaFeedConfiguration config, InstantSource instantSource, HttpClientFactory httpClientFactory,
|
||||
public HttpGetter(
|
||||
CommaFeedConfiguration config,
|
||||
InstantSource instantSource,
|
||||
HttpClientFactory httpClientFactory,
|
||||
MetricRegistry metrics) {
|
||||
this.config = config;
|
||||
this.instantSource = instantSource;
|
||||
this.client = httpClientFactory.newClient(config.feedRefresh().httpThreads());
|
||||
this.cache = newCache(config);
|
||||
|
||||
metrics.registerGauge(MetricRegistry.name(getClass(), "cache", "size"), () -> cache == null ? 0 : cache.size());
|
||||
metrics.registerGauge(MetricRegistry.name(getClass(), "cache", "memoryUsage"),
|
||||
() -> cache == null ? 0 : cache.asMap().values().stream().mapToInt(e -> ArrayUtils.getLength(e.content)).sum());
|
||||
metrics.registerGauge(
|
||||
MetricRegistry.name(getClass(), "cache", "size"),
|
||||
() -> cache == null ? 0 : cache.size());
|
||||
metrics.registerGauge(
|
||||
MetricRegistry.name(getClass(), "cache", "memoryUsage"),
|
||||
() ->
|
||||
cache == null
|
||||
? 0
|
||||
: cache.asMap().values().stream()
|
||||
.mapToInt(e -> ArrayUtils.getLength(e.content))
|
||||
.sum());
|
||||
}
|
||||
|
||||
public HttpResult get(String url) throws IOException, NotModifiedException, TooManyRequestsException, SchemeNotAllowedException {
|
||||
public HttpResult get(String url)
|
||||
throws IOException,
|
||||
NotModifiedException,
|
||||
TooManyRequestsException,
|
||||
SchemeNotAllowedException {
|
||||
return get(HttpRequest.builder(url).build());
|
||||
}
|
||||
|
||||
public HttpResult get(HttpRequest request)
|
||||
throws IOException, NotModifiedException, TooManyRequestsException, SchemeNotAllowedException {
|
||||
throws IOException,
|
||||
NotModifiedException,
|
||||
TooManyRequestsException,
|
||||
SchemeNotAllowedException {
|
||||
URI uri = URI.create(request.getUrl());
|
||||
ensureHttpScheme(uri.getScheme());
|
||||
|
||||
@@ -91,7 +107,8 @@ public class HttpGetter {
|
||||
}
|
||||
|
||||
int code = response.code();
|
||||
if (code == HttpStatus.SC_TOO_MANY_REQUESTS || code == HttpStatus.SC_SERVICE_UNAVAILABLE && response.retryAfter() != null) {
|
||||
if (code == HttpStatus.SC_TOO_MANY_REQUESTS
|
||||
|| code == HttpStatus.SC_SERVICE_UNAVAILABLE && response.retryAfter() != null) {
|
||||
throw new TooManyRequestsException(response.retryAfter());
|
||||
}
|
||||
|
||||
@@ -106,12 +123,18 @@ public class HttpGetter {
|
||||
String lastModifiedHeader = response.lastModifiedHeader();
|
||||
String eTagHeader = response.eTagHeader();
|
||||
|
||||
Duration validFor = Optional.ofNullable(response.cacheControl())
|
||||
Duration validFor =
|
||||
Optional.ofNullable(response.cacheControl())
|
||||
.filter(cc -> cc.getMaxAge() >= 0)
|
||||
.map(cc -> Duration.ofSeconds(cc.getMaxAge()))
|
||||
.orElse(Duration.ZERO);
|
||||
|
||||
return new HttpResult(response.content(), response.contentType(), lastModifiedHeader, eTagHeader, response.urlAfterRedirect(),
|
||||
return new HttpResult(
|
||||
response.content(),
|
||||
response.contentType(),
|
||||
lastModifiedHeader,
|
||||
eTagHeader,
|
||||
response.urlAfterRedirect(),
|
||||
validFor);
|
||||
}
|
||||
|
||||
@@ -125,7 +148,8 @@ public class HttpGetter {
|
||||
log.debug("fetching {}", request.getUrl());
|
||||
|
||||
HttpClientContext context = HttpClientContext.create();
|
||||
context.setRequestConfig(RequestConfig.custom()
|
||||
context.setRequestConfig(
|
||||
RequestConfig.custom()
|
||||
.setResponseTimeout(Timeout.of(config.httpClient().responseTimeout()))
|
||||
// causes issues with some feeds
|
||||
// see https://github.com/Athou/commafeed/issues/1572
|
||||
@@ -133,39 +157,62 @@ public class HttpGetter {
|
||||
.setProtocolUpgradeEnabled(false)
|
||||
.build());
|
||||
|
||||
return client.execute(request.toClassicHttpRequest(), context, resp -> {
|
||||
byte[] content = resp.getEntity() == null ? null
|
||||
: toByteArray(resp.getEntity(), config.httpClient().maxResponseSize().asLongValue());
|
||||
return client.execute(
|
||||
request.toClassicHttpRequest(),
|
||||
context,
|
||||
resp -> {
|
||||
byte[] content =
|
||||
resp.getEntity() == null
|
||||
? null
|
||||
: toByteArray(
|
||||
resp.getEntity(),
|
||||
config.httpClient().maxResponseSize().asLongValue());
|
||||
int code = resp.getCode();
|
||||
String lastModifiedHeader = Optional.ofNullable(resp.getFirstHeader(HttpHeaders.LAST_MODIFIED))
|
||||
String lastModifiedHeader =
|
||||
Optional.ofNullable(resp.getFirstHeader(HttpHeaders.LAST_MODIFIED))
|
||||
.map(NameValuePair::getValue)
|
||||
.map(StringUtils::trimToNull)
|
||||
.orElse(null);
|
||||
String eTagHeader = Optional.ofNullable(resp.getFirstHeader(HttpHeaders.ETAG))
|
||||
String eTagHeader =
|
||||
Optional.ofNullable(resp.getFirstHeader(HttpHeaders.ETAG))
|
||||
.map(NameValuePair::getValue)
|
||||
.map(StringUtils::trimToNull)
|
||||
.orElse(null);
|
||||
|
||||
CacheControl cacheControl = Optional.ofNullable(resp.getFirstHeader(HttpHeaders.CACHE_CONTROL))
|
||||
CacheControl cacheControl =
|
||||
Optional.ofNullable(resp.getFirstHeader(HttpHeaders.CACHE_CONTROL))
|
||||
.map(NameValuePair::getValue)
|
||||
.map(StringUtils::trimToNull)
|
||||
.map(HttpGetter::toCacheControl)
|
||||
.orElse(null);
|
||||
|
||||
Instant retryAfter = Optional.ofNullable(resp.getFirstHeader(HttpHeaders.RETRY_AFTER))
|
||||
Instant retryAfter =
|
||||
Optional.ofNullable(resp.getFirstHeader(HttpHeaders.RETRY_AFTER))
|
||||
.map(NameValuePair::getValue)
|
||||
.map(StringUtils::trimToNull)
|
||||
.map(this::toInstant)
|
||||
.orElse(null);
|
||||
|
||||
String contentType = Optional.ofNullable(resp.getEntity()).map(HttpEntity::getContentType).orElse(null);
|
||||
String urlAfterRedirect = Optional.ofNullable(context.getRedirectLocations())
|
||||
String contentType =
|
||||
Optional.ofNullable(resp.getEntity())
|
||||
.map(HttpEntity::getContentType)
|
||||
.orElse(null);
|
||||
String urlAfterRedirect =
|
||||
Optional.ofNullable(context.getRedirectLocations())
|
||||
.map(RedirectLocations::getAll)
|
||||
.map(l -> Iterables.getLast(l, null))
|
||||
.map(URI::toString)
|
||||
.orElse(request.getUrl());
|
||||
|
||||
return new HttpResponse(code, lastModifiedHeader, eTagHeader, cacheControl, retryAfter, content, contentType, urlAfterRedirect);
|
||||
return new HttpResponse(
|
||||
code,
|
||||
lastModifiedHeader,
|
||||
eTagHeader,
|
||||
cacheControl,
|
||||
retryAfter,
|
||||
content,
|
||||
contentType,
|
||||
urlAfterRedirect);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -193,7 +240,8 @@ public class HttpGetter {
|
||||
private static byte[] toByteArray(HttpEntity entity, long maxBytes) throws IOException {
|
||||
if (entity.getContentLength() > maxBytes) {
|
||||
throw new IOException(
|
||||
"Response size (%s bytes) exceeds the maximum allowed size (%s bytes)".formatted(entity.getContentLength(), maxBytes));
|
||||
"Response size (%s bytes) exceeds the maximum allowed size (%s bytes)"
|
||||
.formatted(entity.getContentLength(), maxBytes));
|
||||
}
|
||||
|
||||
try (InputStream input = entity.getContent()) {
|
||||
@@ -203,7 +251,9 @@ public class HttpGetter {
|
||||
|
||||
byte[] bytes = ByteStreams.limit(input, maxBytes + 1).readAllBytes();
|
||||
if (bytes.length > maxBytes) {
|
||||
throw new IOException("Response size exceeds the maximum allowed size (%s bytes)".formatted(maxBytes));
|
||||
throw new IOException(
|
||||
"Response size exceeds the maximum allowed size (%s bytes)"
|
||||
.formatted(maxBytes));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
@@ -216,7 +266,9 @@ public class HttpGetter {
|
||||
}
|
||||
|
||||
return CacheBuilder.newBuilder()
|
||||
.weigher((HttpRequest key, HttpResponse value) -> value.content() != null ? value.content().length : 0)
|
||||
.weigher(
|
||||
(HttpRequest key, HttpResponse value) ->
|
||||
value.content() != null ? value.content().length : 0)
|
||||
.maximumWeight(cacheConfig.maximumMemorySize().asLongValue())
|
||||
.expireAfterWrite(cacheConfig.expiration())
|
||||
.build();
|
||||
@@ -234,21 +286,18 @@ public class HttpGetter {
|
||||
public static class NotModifiedException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* if the value of this header changed, this is its new value
|
||||
*/
|
||||
/** if the value of this header changed, this is its new value */
|
||||
private final String newLastModifiedHeader;
|
||||
|
||||
/**
|
||||
* if the value of this header changed, this is its new value
|
||||
*/
|
||||
/** if the value of this header changed, this is its new value */
|
||||
private final String newEtagHeader;
|
||||
|
||||
public NotModifiedException(String message) {
|
||||
this(message, null, null);
|
||||
}
|
||||
|
||||
public NotModifiedException(String message, String newLastModifiedHeader, String newEtagHeader) {
|
||||
public NotModifiedException(
|
||||
String message, String newLastModifiedHeader, String newEtagHeader) {
|
||||
super(message);
|
||||
this.newLastModifiedHeader = newLastModifiedHeader;
|
||||
this.newEtagHeader = newEtagHeader;
|
||||
@@ -299,12 +348,21 @@ public class HttpGetter {
|
||||
}
|
||||
}
|
||||
|
||||
private record HttpResponse(int code, String lastModifiedHeader, String eTagHeader, CacheControl cacheControl, Instant retryAfter,
|
||||
byte[] content, String contentType, String urlAfterRedirect) {
|
||||
}
|
||||
|
||||
public record HttpResult(byte[] content, String contentType, String lastModifiedSince, String eTag, String urlAfterRedirect,
|
||||
Duration validFor) {
|
||||
}
|
||||
private record HttpResponse(
|
||||
int code,
|
||||
String lastModifiedHeader,
|
||||
String eTagHeader,
|
||||
CacheControl cacheControl,
|
||||
Instant retryAfter,
|
||||
byte[] content,
|
||||
String contentType,
|
||||
String urlAfterRedirect) {}
|
||||
|
||||
public record HttpResult(
|
||||
byte[] content,
|
||||
String contentType,
|
||||
String lastModifiedSince,
|
||||
String eTag,
|
||||
String urlAfterRedirect,
|
||||
Duration validFor) {}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,59 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.netpreserve.urlcanon.Canonicalizer;
|
||||
import org.netpreserve.urlcanon.ParsedUrl;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.net.URI;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@UtilityClass
|
||||
@Slf4j
|
||||
public class Urls {
|
||||
|
||||
private static final String ESCAPED_QUESTION_MARK = Pattern.quote("?");
|
||||
private static final Pattern QUESTION_MARK = Pattern.compile(Pattern.quote("?"));
|
||||
|
||||
public static boolean isHttp(String url) {
|
||||
return url.startsWith("http://");
|
||||
if (url == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return url.toLowerCase(Locale.ROOT).startsWith("http://");
|
||||
}
|
||||
|
||||
public static boolean isHttps(String url) {
|
||||
return url.startsWith("https://");
|
||||
if (url == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return url.toLowerCase(Locale.ROOT).startsWith("https://");
|
||||
}
|
||||
|
||||
public static boolean isAbsolute(String url) {
|
||||
return isHttp(url) || isHttps(url);
|
||||
}
|
||||
|
||||
/** remove malicious 'javascript: 'URLs * */
|
||||
public static String sanitize(String url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isHttp(url) && !isHttps(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param relativeUrl
|
||||
* the url of the entry
|
||||
* @param feedLink
|
||||
* the url of the feed as described in the feed
|
||||
* @param feedUrl
|
||||
* the url of the feed that we used to fetch the feed
|
||||
* @param relativeUrl the url of the entry
|
||||
* @param feedLink the url of the feed as described in the feed
|
||||
* @param feedUrl the url of the feed that we used to fetch the feed
|
||||
* @return an absolute url pointing to the entry
|
||||
*/
|
||||
public static String toAbsolute(String relativeUrl, String feedLink, String feedUrl) {
|
||||
@@ -47,7 +65,11 @@ public class Urls {
|
||||
try {
|
||||
return URI.create(baseUrl).resolve(relativeUrl).toString();
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.debug("Unable to create absolute url from relative url: {} base: {}", relativeUrl, baseUrl, e);
|
||||
log.debug(
|
||||
"Unable to create absolute url from relative url: {} base: {}",
|
||||
relativeUrl,
|
||||
baseUrl,
|
||||
e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +86,8 @@ public class Urls {
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the url. The resulting url is not meant to be fetched but rather used as a mean to identify a feed and avoid duplicates
|
||||
* Normalize the url. The resulting url is not meant to be fetched but rather used as a mean to
|
||||
* identify a feed and avoid duplicates
|
||||
*/
|
||||
public static String normalize(String url) {
|
||||
if (url == null) {
|
||||
@@ -95,9 +118,9 @@ public class Urls {
|
||||
normalized = normalized.replace("feedproxy.google.com", "feeds.feedburner.com");
|
||||
|
||||
// feedburner feeds have a special treatment
|
||||
if (normalized.split(ESCAPED_QUESTION_MARK)[0].contains("feedburner.com")) {
|
||||
if (QUESTION_MARK.split(normalized)[0].contains("feedburner.com")) {
|
||||
normalized = normalized.replace("feeds2.feedburner.com", "feeds.feedburner.com");
|
||||
normalized = normalized.split(ESCAPED_QUESTION_MARK)[0];
|
||||
normalized = QUESTION_MARK.split(normalized)[0];
|
||||
normalized = Strings.CS.removeEnd(normalized, "/");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.QFeedCategory;
|
||||
import com.commafeed.backend.model.QUser;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Singleton
|
||||
public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
|
||||
@@ -22,11 +22,17 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
}
|
||||
|
||||
public List<FeedCategory> findAll(User user) {
|
||||
return query().selectFrom(CATEGORY).where(CATEGORY.user.eq(user)).join(CATEGORY.user, QUser.user).fetchJoin().fetch();
|
||||
return query().selectFrom(CATEGORY)
|
||||
.where(CATEGORY.user.eq(user))
|
||||
.join(CATEGORY.user, QUser.user)
|
||||
.fetchJoin()
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public FeedCategory findById(User user, Long id) {
|
||||
return query().selectFrom(CATEGORY).where(CATEGORY.user.eq(user), CATEGORY.id.eq(id)).fetchOne();
|
||||
return query().selectFrom(CATEGORY)
|
||||
.where(CATEGORY.user.eq(user), CATEGORY.id.eq(id))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
public FeedCategory findByName(User user, String name, FeedCategory parent) {
|
||||
@@ -36,7 +42,9 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
} else {
|
||||
parentPredicate = CATEGORY.parent.eq(parent);
|
||||
}
|
||||
return query().selectFrom(CATEGORY).where(CATEGORY.user.eq(user), CATEGORY.name.eq(name), parentPredicate).fetchOne();
|
||||
return query().selectFrom(CATEGORY)
|
||||
.where(CATEGORY.user.eq(user), CATEGORY.name.eq(name), parentPredicate)
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
public List<FeedCategory> findByParent(User user, FeedCategory parent) {
|
||||
@@ -67,5 +75,4 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
}
|
||||
return isChild;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.apache.commons.lang3.Strings;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.QFeed;
|
||||
import com.commafeed.backend.model.QFeedSubscription;
|
||||
import com.querydsl.jpa.JPAExpressions;
|
||||
import com.querydsl.jpa.impl.JPAQuery;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.apache.commons.lang3.Strings;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class FeedDAO extends GenericDAO<Feed> {
|
||||
|
||||
@@ -29,12 +29,16 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
|
||||
public List<Feed> findNextUpdatable(int count, Instant lastLoginThreshold) {
|
||||
JPAQuery<Feed> query = query().selectFrom(FEED)
|
||||
JPAQuery<Feed> query =
|
||||
query().selectFrom(FEED)
|
||||
.distinct()
|
||||
// join on subscriptions to only refresh feeds that have subscribers
|
||||
.join(SUBSCRIPTION)
|
||||
.on(SUBSCRIPTION.feed.eq(FEED))
|
||||
.where(FEED.disabledUntil.isNull().or(FEED.disabledUntil.lt(Instant.now())));
|
||||
.where(
|
||||
FEED.disabledUntil
|
||||
.isNull()
|
||||
.or(FEED.disabledUntil.lt(Instant.now())));
|
||||
|
||||
if (lastLoginThreshold != null) {
|
||||
query.join(SUBSCRIPTION.user).where(SUBSCRIPTION.user.lastLogin.gt(lastLoginThreshold));
|
||||
@@ -48,7 +52,8 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
|
||||
public Feed findByUrl(String normalizedUrl, String normalizedUrlHash) {
|
||||
return query().selectFrom(FEED)
|
||||
return query()
|
||||
.selectFrom(FEED)
|
||||
.where(FEED.normalizedUrlHash.eq(normalizedUrlHash))
|
||||
.fetch()
|
||||
.stream()
|
||||
@@ -59,6 +64,9 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
|
||||
public List<Feed> findWithoutSubscriptions(int max) {
|
||||
QFeedSubscription sub = QFeedSubscription.feedSubscription;
|
||||
return query().selectFrom(FEED).where(JPAExpressions.selectOne().from(sub).where(sub.feed.eq(FEED)).notExists()).limit(max).fetch();
|
||||
return query().selectFrom(FEED)
|
||||
.where(JPAExpressions.selectOne().from(sub).where(sub.feed.eq(FEED)).notExists())
|
||||
.limit(max)
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.commafeed.backend.model.QFeedEntry;
|
||||
import com.commafeed.backend.model.QFeedEntryContent;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||
|
||||
@@ -20,11 +20,15 @@ public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||
}
|
||||
|
||||
public List<FeedEntryContent> findExisting(String contentHash, String titleHash) {
|
||||
return query().select(CONTENT).from(CONTENT).where(CONTENT.contentHash.eq(contentHash), CONTENT.titleHash.eq(titleHash)).fetch();
|
||||
return query().select(CONTENT)
|
||||
.from(CONTENT)
|
||||
.where(CONTENT.contentHash.eq(contentHash), CONTENT.titleHash.eq(titleHash))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
public long deleteWithoutEntries(int max) {
|
||||
List<Long> ids = query().select(CONTENT.id)
|
||||
List<Long> ids =
|
||||
query().select(CONTENT.id)
|
||||
.from(CONTENT)
|
||||
.leftJoin(ENTRY)
|
||||
.on(ENTRY.content.id.eq(CONTENT.id))
|
||||
|
||||
@@ -1,32 +1,59 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.QFeedEntry;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.querydsl.core.Tuple;
|
||||
import com.querydsl.core.types.dsl.NumberExpression;
|
||||
import com.querydsl.jpa.impl.JPAQuery;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Singleton
|
||||
public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
|
||||
private static final QFeedEntry ENTRY = QFeedEntry.feedEntry;
|
||||
private static final int IN_CLAUSE_BATCH_SIZE = 1000;
|
||||
|
||||
public FeedEntryDAO(EntityManager entityManager) {
|
||||
super(entityManager, FeedEntry.class);
|
||||
}
|
||||
|
||||
public FeedEntry findExisting(String guidHash, Feed feed) {
|
||||
return query().select(ENTRY).from(ENTRY).where(ENTRY.guidHash.eq(guidHash), ENTRY.feed.eq(feed)).limit(1).fetchOne();
|
||||
return query().select(ENTRY)
|
||||
.from(ENTRY)
|
||||
.where(ENTRY.guidHash.eq(guidHash), ENTRY.feed.eq(feed))
|
||||
.limit(1)
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
public List<FeedCapacity> findFeedsExceedingCapacity(long maxCapacity, long max, boolean keepStarredEntries) {
|
||||
public Set<String> findExistingGuidHashes(Set<String> guidHashes, Feed feed) {
|
||||
if (guidHashes.isEmpty()) {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
Set<String> result = new HashSet<>();
|
||||
for (List<String> batch :
|
||||
Lists.partition(new ArrayList<>(guidHashes), IN_CLAUSE_BATCH_SIZE)) {
|
||||
result.addAll(
|
||||
query().select(ENTRY.guidHash)
|
||||
.from(ENTRY)
|
||||
.where(ENTRY.feed.eq(feed), ENTRY.guidHash.in(batch))
|
||||
.fetch());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<FeedCapacity> findFeedsExceedingCapacity(
|
||||
long maxCapacity, long max, boolean keepStarredEntries) {
|
||||
NumberExpression<Long> count = ENTRY.id.count();
|
||||
JPAQuery<Tuple> query = query().select(ENTRY.feed.id, count).from(ENTRY);
|
||||
|
||||
@@ -34,25 +61,21 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
query.where(Predicates.isNotStarred(ENTRY));
|
||||
}
|
||||
|
||||
return query.groupBy(ENTRY.feed)
|
||||
.having(count.gt(maxCapacity))
|
||||
.limit(max)
|
||||
.fetch()
|
||||
.stream()
|
||||
return query.groupBy(ENTRY.feed).having(count.gt(maxCapacity)).limit(max).fetch().stream()
|
||||
.map(t -> new FeedCapacity(t.get(ENTRY.feed.id), t.get(count)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
public int delete(Long feedId, long max) {
|
||||
List<FeedEntry> list = query().selectFrom(ENTRY).where(ENTRY.feed.id.eq(feedId)).limit(max).fetch();
|
||||
List<FeedEntry> list =
|
||||
query().selectFrom(ENTRY).where(ENTRY.feed.id.eq(feedId)).limit(max).fetch();
|
||||
return delete(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete entries older than a certain date
|
||||
*/
|
||||
/** Delete entries older than a certain date */
|
||||
public int deleteEntriesOlderThan(Instant olderThan, long max, boolean keepStarredEntries) {
|
||||
JPAQuery<FeedEntry> query = query().selectFrom(ENTRY)
|
||||
JPAQuery<FeedEntry> query =
|
||||
query().selectFrom(ENTRY)
|
||||
.where(ENTRY.published.lt(olderThan))
|
||||
.orderBy(ENTRY.published.asc())
|
||||
.limit(max);
|
||||
@@ -64,11 +87,13 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
return delete(query.fetch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the oldest entries of a feed
|
||||
*/
|
||||
/** Delete the oldest entries of a feed */
|
||||
public int deleteOldEntries(Long feedId, long max, boolean keepStarredEntries) {
|
||||
JPAQuery<FeedEntry> query = query().selectFrom(ENTRY).where(ENTRY.feed.id.eq(feedId)).orderBy(ENTRY.published.asc()).limit(max);
|
||||
JPAQuery<FeedEntry> query =
|
||||
query().selectFrom(ENTRY)
|
||||
.where(ENTRY.feed.id.eq(feedId))
|
||||
.orderBy(ENTRY.published.asc())
|
||||
.limit(max);
|
||||
|
||||
if (keepStarredEntries) {
|
||||
query.where(Predicates.isNotStarred(ENTRY));
|
||||
@@ -77,6 +102,5 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
return delete(query.fetch());
|
||||
}
|
||||
|
||||
public record FeedCapacity(Long id, Long capacity) {
|
||||
}
|
||||
public record FeedCapacity(Long id, Long capacity) {}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.feed.FeedEntryKeyword;
|
||||
import com.commafeed.backend.feed.FeedEntryKeyword.Mode;
|
||||
@@ -33,6 +22,17 @@ import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.NumberExpression;
|
||||
import com.querydsl.jpa.impl.JPAQuery;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
@@ -46,25 +46,33 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
private final FeedEntryTagDAO feedEntryTagDAO;
|
||||
private final CommaFeedConfiguration config;
|
||||
|
||||
public FeedEntryStatusDAO(EntityManager entityManager, FeedEntryTagDAO feedEntryTagDAO, CommaFeedConfiguration config) {
|
||||
public FeedEntryStatusDAO(
|
||||
EntityManager entityManager,
|
||||
FeedEntryTagDAO feedEntryTagDAO,
|
||||
CommaFeedConfiguration config) {
|
||||
super(entityManager, FeedEntryStatus.class);
|
||||
this.feedEntryTagDAO = feedEntryTagDAO;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public FeedEntryStatus getStatus(User user, FeedSubscription sub, FeedEntry entry) {
|
||||
List<FeedEntryStatus> statuses = query().selectFrom(STATUS).where(STATUS.entry.eq(entry), STATUS.subscription.eq(sub)).fetch();
|
||||
List<FeedEntryStatus> statuses =
|
||||
query().selectFrom(STATUS)
|
||||
.where(STATUS.entry.eq(entry), STATUS.subscription.eq(sub))
|
||||
.fetch();
|
||||
FeedEntryStatus status = statuses.stream().findFirst().orElse(null);
|
||||
return handleStatus(user, status, sub, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an artificial "unread" status if status is null
|
||||
*/
|
||||
private FeedEntryStatus handleStatus(User user, FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
|
||||
/** creates an artificial "unread" status if status is null */
|
||||
private FeedEntryStatus handleStatus(
|
||||
User user, FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
|
||||
if (status == null) {
|
||||
Instant statusesInstantThreshold = config.database().cleanup().statusesInstantThreshold();
|
||||
boolean read = statusesInstantThreshold != null && entry.getPublished().isBefore(statusesInstantThreshold);
|
||||
Instant statusesInstantThreshold =
|
||||
config.database().cleanup().statusesInstantThreshold();
|
||||
boolean read =
|
||||
statusesInstantThreshold != null
|
||||
&& entry.getPublished().isBefore(statusesInstantThreshold);
|
||||
status = new FeedEntryStatus(user, sub, entry);
|
||||
status.setRead(read);
|
||||
status.setMarkable(!read);
|
||||
@@ -75,20 +83,32 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
private void fetchTags(User user, List<FeedEntryStatus> statuses) {
|
||||
Map<Long, List<FeedEntryTag>> tagsByEntryIds = feedEntryTagDAO.findByEntries(user,
|
||||
statuses.stream().map(FeedEntryStatus::getEntry).toList());
|
||||
Map<Long, List<FeedEntryTag>> tagsByEntryIds =
|
||||
feedEntryTagDAO.findByEntries(
|
||||
user, statuses.stream().map(FeedEntryStatus::getEntry).toList());
|
||||
for (FeedEntryStatus status : statuses) {
|
||||
List<FeedEntryTag> tags = tagsByEntryIds.get(status.getEntry().getId());
|
||||
status.setTags(tags == null ? List.of() : tags);
|
||||
}
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> findStarred(User user, Instant newerThan, int offset, int limit, ReadingOrder order,
|
||||
public List<FeedEntryStatus> findStarred(
|
||||
User user,
|
||||
List<FeedEntryKeyword> keywords,
|
||||
Instant newerThan,
|
||||
int offset,
|
||||
int limit,
|
||||
ReadingOrder order,
|
||||
boolean includeContent) {
|
||||
JPAQuery<FeedEntryStatus> query = query().selectFrom(STATUS).where(STATUS.user.eq(user), STATUS.starred.isTrue());
|
||||
if (includeContent) {
|
||||
JPAQuery<FeedEntryStatus> query =
|
||||
query().selectFrom(STATUS).where(STATUS.user.eq(user), STATUS.starred.isTrue());
|
||||
if (includeContent || CollectionUtils.isNotEmpty(keywords)) {
|
||||
query.join(STATUS.entry).fetchJoin();
|
||||
query.join(STATUS.entry.content).fetchJoin();
|
||||
query.join(STATUS.entry.content, CONTENT).fetchJoin();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(keywords)) {
|
||||
applyKeywordsFilter(query, keywords);
|
||||
}
|
||||
|
||||
if (newerThan != null) {
|
||||
@@ -120,10 +140,21 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return statuses;
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> findBySubscriptions(User user, List<FeedSubscription> subs, boolean unreadOnly,
|
||||
List<FeedEntryKeyword> keywords, Instant newerThan, int offset, int limit, ReadingOrder order, boolean includeContent,
|
||||
String tag, Long minEntryId, Long maxEntryId) {
|
||||
Map<Long, List<FeedSubscription>> subsByFeedId = subs.stream().collect(Collectors.groupingBy(s -> s.getFeed().getId()));
|
||||
public List<FeedEntryStatus> findBySubscriptions(
|
||||
User user,
|
||||
List<FeedSubscription> subs,
|
||||
boolean unreadOnly,
|
||||
List<FeedEntryKeyword> keywords,
|
||||
Instant newerThan,
|
||||
int offset,
|
||||
int limit,
|
||||
ReadingOrder order,
|
||||
boolean includeContent,
|
||||
String tag,
|
||||
Long minEntryId,
|
||||
Long maxEntryId) {
|
||||
Map<Long, List<FeedSubscription>> subsByFeedId =
|
||||
subs.stream().collect(Collectors.groupingBy(s -> s.getFeed().getId()));
|
||||
|
||||
JPAQuery<Tuple> query = query().select(ENTRY, STATUS).from(ENTRY);
|
||||
query.leftJoin(ENTRY.statuses, STATUS).on(STATUS.subscription.in(subs));
|
||||
@@ -132,16 +163,9 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
if (includeContent || CollectionUtils.isNotEmpty(keywords)) {
|
||||
query.join(ENTRY.content, CONTENT).fetchJoin();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(keywords)) {
|
||||
for (FeedEntryKeyword keyword : keywords) {
|
||||
BooleanBuilder or = new BooleanBuilder();
|
||||
or.or(CONTENT.content.containsIgnoreCase(keyword.keyword()));
|
||||
or.or(CONTENT.title.containsIgnoreCase(keyword.keyword()));
|
||||
if (keyword.mode() == Mode.EXCLUDE) {
|
||||
or.not();
|
||||
}
|
||||
query.where(or);
|
||||
}
|
||||
applyKeywordsFilter(query, keywords);
|
||||
}
|
||||
|
||||
if (unreadOnly && tag == null) {
|
||||
@@ -202,8 +226,21 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return statuses;
|
||||
}
|
||||
|
||||
private void applyKeywordsFilter(JPAQuery<?> query, List<FeedEntryKeyword> keywords) {
|
||||
for (FeedEntryKeyword keyword : keywords) {
|
||||
BooleanBuilder or = new BooleanBuilder();
|
||||
or.or(CONTENT.content.containsIgnoreCase(keyword.keyword()));
|
||||
or.or(CONTENT.title.containsIgnoreCase(keyword.keyword()));
|
||||
if (keyword.mode() == Mode.EXCLUDE) {
|
||||
or.not();
|
||||
}
|
||||
query.where(or);
|
||||
}
|
||||
}
|
||||
|
||||
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
||||
JPAQuery<Tuple> query = query().select(ENTRY.count(), ENTRY.published.max())
|
||||
JPAQuery<Tuple> query =
|
||||
query().select(ENTRY.count(), ENTRY.published.max())
|
||||
.from(ENTRY)
|
||||
.leftJoin(ENTRY.statuses, STATUS)
|
||||
.on(STATUS.subscription.eq(sub))
|
||||
@@ -230,7 +267,8 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
public long deleteOldStatuses(Instant olderThan, int limit) {
|
||||
List<Long> ids = query().select(STATUS.id)
|
||||
List<Long> ids =
|
||||
query().select(STATUS.id)
|
||||
.from(STATUS)
|
||||
.where(STATUS.entryInserted.lt(olderThan), STATUS.starred.isFalse())
|
||||
.limit(limit)
|
||||
@@ -245,13 +283,15 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
where.and(SUBSCRIPTION.autoMarkAsReadAfterDays.isNotNull());
|
||||
where.and(SUBSCRIPTION.autoMarkAsReadAfterDays.gt(0));
|
||||
|
||||
NumberExpression<Integer> daysDiff = Expressions.numberTemplate(Integer.class, "TIMESTAMPDIFF(DAY, {0}, {1})", ENTRY.published,
|
||||
now);
|
||||
NumberExpression<Integer> daysDiff =
|
||||
Expressions.numberTemplate(
|
||||
Integer.class, "TIMESTAMPDIFF(DAY, {0}, {1})", ENTRY.published, now);
|
||||
where.and(daysDiff.goe(SUBSCRIPTION.autoMarkAsReadAfterDays));
|
||||
|
||||
where.and(buildUnreadPredicate());
|
||||
|
||||
List<Tuple> tuples = query().select(ENTRY, STATUS, SUBSCRIPTION)
|
||||
List<Tuple> tuples =
|
||||
query().select(ENTRY, STATUS, SUBSCRIPTION)
|
||||
.from(ENTRY)
|
||||
.join(ENTRY.feed, FEED)
|
||||
.join(SUBSCRIPTION)
|
||||
@@ -265,7 +305,8 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
long updated = 0;
|
||||
|
||||
// Update existing statuses
|
||||
List<Long> statusIdsToUpdate = tuples.stream()
|
||||
List<Long> statusIdsToUpdate =
|
||||
tuples.stream()
|
||||
.map(t -> t.get(STATUS))
|
||||
.filter(s -> s != null && s.getId() != null)
|
||||
.map(FeedEntryStatus::getId)
|
||||
@@ -273,7 +314,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
.toList();
|
||||
|
||||
if (!statusIdsToUpdate.isEmpty()) {
|
||||
updated += updateQuery(STATUS).where(STATUS.id.in(statusIdsToUpdate)).set(STATUS.read, true).execute();
|
||||
updated +=
|
||||
updateQuery(STATUS)
|
||||
.where(STATUS.id.in(statusIdsToUpdate))
|
||||
.set(STATUS.read, true)
|
||||
.execute();
|
||||
}
|
||||
|
||||
// Insert new statuses for entries without existing status
|
||||
@@ -291,5 +336,4 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryTag;
|
||||
import com.commafeed.backend.model.QFeedEntryTag;
|
||||
import com.commafeed.backend.model.User;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class FeedEntryTagDAO extends GenericDAO<FeedEntryTag> {
|
||||
|
||||
@@ -30,7 +30,8 @@ public class FeedEntryTagDAO extends GenericDAO<FeedEntryTag> {
|
||||
}
|
||||
|
||||
public Map<Long, List<FeedEntryTag>> findByEntries(User user, List<FeedEntry> entries) {
|
||||
return query().selectFrom(TAG)
|
||||
return query()
|
||||
.selectFrom(TAG)
|
||||
.where(TAG.user.eq(user), TAG.entry.in(entries))
|
||||
.fetch()
|
||||
.stream()
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import com.commafeed.backend.model.AbstractModel;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
import com.commafeed.backend.model.QFeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.querydsl.jpa.JPQLQuery;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
@@ -15,14 +19,10 @@ import org.hibernate.event.spi.PostCommitInsertEventListener;
|
||||
import org.hibernate.event.spi.PostInsertEvent;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import com.commafeed.backend.model.AbstractModel;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
import com.commafeed.backend.model.QFeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.querydsl.jpa.JPQLQuery;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
@@ -37,12 +37,14 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public void onPostCommitInsert(Consumer<FeedSubscription> consumer) {
|
||||
entityManager.unwrap(SharedSessionContractImplementor.class)
|
||||
entityManager
|
||||
.unwrap(SharedSessionContractImplementor.class)
|
||||
.getFactory()
|
||||
.getServiceRegistry()
|
||||
.getService(EventListenerRegistry.class)
|
||||
.getEventListenerGroup(EventType.POST_COMMIT_INSERT)
|
||||
.appendListener(new PostCommitInsertEventListener() {
|
||||
.appendListener(
|
||||
new PostCommitInsertEventListener() {
|
||||
@Override
|
||||
public void onPostInsert(PostInsertEvent event) {
|
||||
if (event.getEntity() instanceof FeedSubscription s) {
|
||||
@@ -63,7 +65,8 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public FeedSubscription findById(User user, Long id) {
|
||||
List<FeedSubscription> subs = query().selectFrom(SUBSCRIPTION)
|
||||
List<FeedSubscription> subs =
|
||||
query().selectFrom(SUBSCRIPTION)
|
||||
.where(SUBSCRIPTION.user.eq(user), SUBSCRIPTION.id.eq(id))
|
||||
.leftJoin(SUBSCRIPTION.feed)
|
||||
.fetchJoin()
|
||||
@@ -79,7 +82,8 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public FeedSubscription findByFeed(User user, Feed feed) {
|
||||
List<FeedSubscription> subs = query().selectFrom(SUBSCRIPTION)
|
||||
List<FeedSubscription> subs =
|
||||
query().selectFrom(SUBSCRIPTION)
|
||||
.where(SUBSCRIPTION.user.eq(user), SUBSCRIPTION.feed.eq(feed))
|
||||
.fetch();
|
||||
FeedSubscription sub = subs.stream().findFirst().orElse(null);
|
||||
@@ -87,7 +91,8 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findAll(User user) {
|
||||
List<FeedSubscription> subs = query().selectFrom(SUBSCRIPTION)
|
||||
List<FeedSubscription> subs =
|
||||
query().selectFrom(SUBSCRIPTION)
|
||||
.where(SUBSCRIPTION.user.eq(user))
|
||||
.leftJoin(SUBSCRIPTION.feed)
|
||||
.fetchJoin()
|
||||
@@ -98,11 +103,15 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public Long count(User user) {
|
||||
return query().select(SUBSCRIPTION.count()).from(SUBSCRIPTION).where(SUBSCRIPTION.user.eq(user)).fetchOne();
|
||||
return query().select(SUBSCRIPTION.count())
|
||||
.from(SUBSCRIPTION)
|
||||
.where(SUBSCRIPTION.user.eq(user))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
||||
JPQLQuery<FeedSubscription> query = query().selectFrom(SUBSCRIPTION).where(SUBSCRIPTION.user.eq(user));
|
||||
JPQLQuery<FeedSubscription> query =
|
||||
query().selectFrom(SUBSCRIPTION).where(SUBSCRIPTION.user.eq(user));
|
||||
if (category == null) {
|
||||
query.where(SUBSCRIPTION.category.isNull());
|
||||
} else {
|
||||
@@ -112,8 +121,14 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findByCategories(User user, List<FeedCategory> categories) {
|
||||
Set<Long> categoryIds = categories.stream().map(AbstractModel::getId).collect(Collectors.toSet());
|
||||
return findAll(user).stream().filter(s -> s.getCategory() != null && categoryIds.contains(s.getCategory().getId())).toList();
|
||||
Set<Long> categoryIds =
|
||||
categories.stream().map(AbstractModel::getId).collect(Collectors.toSet());
|
||||
return findAll(user).stream()
|
||||
.filter(
|
||||
s ->
|
||||
s.getCategory() != null
|
||||
&& categoryIds.contains(s.getCategory().getId()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private List<FeedSubscription> initRelations(List<FeedSubscription> list) {
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.jpa.SpecHints;
|
||||
|
||||
import com.commafeed.backend.model.AbstractModel;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.jpa.impl.JPADeleteClause;
|
||||
@@ -14,8 +7,15 @@ import com.querydsl.jpa.impl.JPAQuery;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import com.querydsl.jpa.impl.JPAUpdateClause;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.hibernate.jpa.SpecHints;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class GenericDAO<T extends AbstractModel> {
|
||||
|
||||
@@ -62,5 +62,4 @@ public abstract class GenericDAO<T extends AbstractModel> {
|
||||
query.setHint(SpecHints.HINT_SPEC_QUERY_TIMEOUT, Math.toIntExact(timeout.toMillis()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ public class Predicates {
|
||||
private static final QFeedEntryStatus STATUS = QFeedEntryStatus.feedEntryStatus;
|
||||
|
||||
public static BooleanExpression isNotStarred(QFeedEntry entry) {
|
||||
return JPAExpressions.selectOne().from(STATUS).where(STATUS.entry.eq(entry).and(STATUS.starred.isTrue())).notExists();
|
||||
return JPAExpressions.selectOne()
|
||||
.from(STATUS)
|
||||
.where(STATUS.entry.eq(entry).and(STATUS.starred.isTrue()))
|
||||
.notExists();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import io.quarkus.narayana.jta.QuarkusTransaction;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import io.quarkus.narayana.jta.QuarkusTransaction;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@Singleton
|
||||
public class UnitOfWork {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.QUser;
|
||||
import com.commafeed.backend.model.User;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
@Singleton
|
||||
public class UserDAO extends GenericDAO<User> {
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.QUserRole;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Singleton
|
||||
public class UserRoleDAO extends GenericDAO<UserRole> {
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.commafeed.backend.dao;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import com.commafeed.backend.model.QUserSettings;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
@Singleton
|
||||
public class UserSettingsDAO extends GenericDAO<UserSettings> {
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractFaviconFetcher {
|
||||
|
||||
private static final List<String> ICON_MIMETYPE_BLACKLIST = Arrays.asList("application/xml", "text/html");
|
||||
private static final long MIN_ICON_LENGTH = 100;
|
||||
private static final long MAX_ICON_LENGTH = 100000;
|
||||
|
||||
public abstract Favicon fetch(Feed feed);
|
||||
|
||||
protected boolean isValidIconResponse(byte[] content, String contentType) {
|
||||
if (content == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long length = content.length;
|
||||
|
||||
if (StringUtils.isNotBlank(contentType)) {
|
||||
contentType = contentType.split(";")[0];
|
||||
}
|
||||
|
||||
if (ICON_MIMETYPE_BLACKLIST.contains(contentType)) {
|
||||
log.debug("Content-Type {} is blacklisted", contentType);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length < MIN_ICON_LENGTH) {
|
||||
log.debug("Length {} below MIN_ICON_LENGTH {}", length, MIN_ICON_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length > MAX_ICON_LENGTH) {
|
||||
log.debug("Length {} greater than MAX_ICON_LENGTH {}", length, MAX_ICON_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.Urls;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Inspired/Ported from https://github.com/potatolondon/getfavicon
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Singleton
|
||||
@Priority(Integer.MIN_VALUE)
|
||||
public class DefaultFaviconFetcher extends AbstractFaviconFetcher {
|
||||
|
||||
private final HttpGetter getter;
|
||||
|
||||
@Override
|
||||
public Favicon fetch(Feed feed) {
|
||||
Favicon icon = fetch(feed.getLink());
|
||||
if (icon == null) {
|
||||
icon = fetch(feed.getUrl());
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
private Favicon fetch(String url) {
|
||||
if (url == null) {
|
||||
log.debug("url is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
int doubleSlash = url.indexOf("//");
|
||||
if (doubleSlash == -1) {
|
||||
doubleSlash = 0;
|
||||
} else {
|
||||
doubleSlash += 2;
|
||||
}
|
||||
int firstSlash = url.indexOf('/', doubleSlash);
|
||||
if (firstSlash != -1) {
|
||||
url = url.substring(0, firstSlash);
|
||||
}
|
||||
|
||||
Favicon icon = getIconAtRoot(url);
|
||||
|
||||
if (icon == null) {
|
||||
icon = getIconInPage(url);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private Favicon getIconAtRoot(String url) {
|
||||
byte[] bytes = null;
|
||||
String contentType = null;
|
||||
|
||||
try {
|
||||
url = Urls.removeTrailingSlash(url) + "/favicon.ico";
|
||||
log.debug("getting root icon at {}", url);
|
||||
HttpResult result = getter.get(url);
|
||||
bytes = result.content();
|
||||
contentType = result.contentType();
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve iconAtRoot for url {}: ", url, e);
|
||||
}
|
||||
|
||||
if (!isValidIconResponse(bytes, contentType)) {
|
||||
return null;
|
||||
}
|
||||
return new Favicon(bytes, contentType);
|
||||
}
|
||||
|
||||
private Favicon getIconInPage(String url) {
|
||||
|
||||
Document doc;
|
||||
try {
|
||||
HttpResult result = getter.get(url);
|
||||
doc = Jsoup.parse(new String(result.content()), url);
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve page to find icon", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
Elements icons = doc.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
||||
|
||||
if (icons.isEmpty()) {
|
||||
log.debug("No icon found in page {}", url);
|
||||
return null;
|
||||
}
|
||||
|
||||
String href = icons.getFirst().attr("abs:href");
|
||||
if (StringUtils.isBlank(href)) {
|
||||
log.debug("No icon found in page");
|
||||
return null;
|
||||
}
|
||||
|
||||
log.debug("Found unconfirmed iconInPage at {}", href);
|
||||
|
||||
byte[] bytes;
|
||||
String contentType;
|
||||
try {
|
||||
HttpResult result = getter.get(href);
|
||||
bytes = result.content();
|
||||
contentType = result.contentType();
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve icon found in page {}", href, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isValidIconResponse(bytes, contentType)) {
|
||||
log.debug("Invalid icon found for {}", href);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Favicon(bytes, contentType);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,33 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.apache.hc.core5.http.NameValuePair;
|
||||
import org.apache.hc.core5.net.URIBuilder;
|
||||
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.hc.core5.http.NameValuePair;
|
||||
import org.apache.hc.core5.net.URIBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Singleton
|
||||
public class FacebookFaviconFetcher extends AbstractFaviconFetcher {
|
||||
@Priority(3)
|
||||
public class FacebookFaviconFetcher implements FaviconFetcher {
|
||||
|
||||
private final HttpGetter getter;
|
||||
|
||||
@Override
|
||||
public Favicon fetch(Feed feed) {
|
||||
String url = feed.getUrl();
|
||||
|
||||
if (!url.toLowerCase().contains("www.facebook.com")) {
|
||||
return null;
|
||||
}
|
||||
@@ -36,25 +37,19 @@ public class FacebookFaviconFetcher extends AbstractFaviconFetcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
String iconUrl = String.format("https://graph.facebook.com/%s/picture?type=square&height=16", userName);
|
||||
|
||||
byte[] bytes = null;
|
||||
String contentType = null;
|
||||
String iconUrl =
|
||||
String.format(
|
||||
"https://graph.facebook.com/%s/picture?type=square&height=16", userName);
|
||||
|
||||
try {
|
||||
log.debug("Getting Facebook user's icon, {}", url);
|
||||
|
||||
HttpResult iconResult = getter.get(iconUrl);
|
||||
bytes = iconResult.content();
|
||||
contentType = iconResult.contentType();
|
||||
return new Favicon(iconResult.content(), iconResult.contentType());
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve Facebook icon", e);
|
||||
}
|
||||
|
||||
if (!isValidIconResponse(bytes, contentType)) {
|
||||
return null;
|
||||
}
|
||||
return new Favicon(bytes, contentType);
|
||||
}
|
||||
|
||||
private String extractUserName(String url) {
|
||||
@@ -67,7 +62,10 @@ public class FacebookFaviconFetcher extends AbstractFaviconFetcher {
|
||||
}
|
||||
|
||||
List<NameValuePair> params = new URIBuilder(uri).getQueryParams();
|
||||
return params.stream().filter(p -> "id".equals(p.getName())).map(NameValuePair::getValue).findFirst().orElse(null);
|
||||
return params.stream()
|
||||
.filter(p -> "id".equals(p.getName()))
|
||||
.map(NameValuePair::getValue)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ public record Favicon(byte[] icon, MediaType mediaType) {
|
||||
try {
|
||||
return MediaType.valueOf(contentType);
|
||||
} catch (Exception e) {
|
||||
log.debug("invalid content type '{}' received, returning default value", contentType, e);
|
||||
log.debug(
|
||||
"invalid content type '{}' received, returning default value", contentType, e);
|
||||
return DEFAULT_MEDIA_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
public interface FaviconFetcher {
|
||||
|
||||
Favicon fetch(Feed feed);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/** Fetch favicon from the url declared in the feed. */
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Singleton
|
||||
@Priority(2)
|
||||
public class FeedFaviconFetcher implements FaviconFetcher {
|
||||
|
||||
private final HttpGetter getter;
|
||||
|
||||
@Override
|
||||
public Favicon fetch(Feed feed) {
|
||||
String url = feed.getIconUrl();
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
HttpResult result = getter.get(url);
|
||||
return new Favicon(result.content(), result.contentType());
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve icon declared in the feed {}", url, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.commafeed.backend.favicon;
|
||||
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
/** Extracts favicon url from html page. */
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Singleton
|
||||
@Priority(1)
|
||||
public class HtmlFaviconFetcher implements FaviconFetcher {
|
||||
|
||||
private final HttpGetter getter;
|
||||
|
||||
@Override
|
||||
public Favicon fetch(Feed feed) {
|
||||
String url = feed.getLink();
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Document doc;
|
||||
try {
|
||||
HttpResult result = getter.get(url);
|
||||
doc = Jsoup.parse(new String(result.content()), url);
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve page to find icon", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
Elements icons = doc.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
||||
if (icons.isEmpty()) {
|
||||
log.debug("No icon found in page {}", url);
|
||||
return null;
|
||||
}
|
||||
|
||||
String href = icons.getFirst().attr("abs:href");
|
||||
if (StringUtils.isBlank(href)) {
|
||||
log.debug("No icon found in page");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
HttpResult result = getter.get(href);
|
||||
return new Favicon(result.content(), result.contentType());
|
||||
} catch (Exception e) {
|
||||
log.debug("Failed to retrieve icon found in page {}", href, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user