mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-10 02:53:05 +03:00
Compare commits
837 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3e563385c | ||
|
|
5e45403cb1 | ||
|
|
23de7e517e | ||
|
|
be23f4eb0d | ||
|
|
38c08c4fad | ||
|
|
1b4ab5e777 | ||
|
|
293e0f5faf | ||
|
|
13ae2266de | ||
|
|
6870e3496c | ||
|
|
ea88bdf2f3 | ||
|
|
a6f04ffb7c | ||
|
|
db266d75d6 | ||
|
|
f47d2c1f1a | ||
|
|
8bee67f1f8 | ||
|
|
cf11a2dc1e | ||
|
|
e2434d38c5 | ||
|
|
9e61a6fd72 | ||
|
|
d292fde9e2 | ||
|
|
25321d7f80 | ||
|
|
9c6454ec46 | ||
|
|
09c377fb6c | ||
|
|
97dc02b163 | ||
|
|
aa08d3f2bf | ||
|
|
2354cd45d4 | ||
|
|
c8ca0c72e1 | ||
|
|
3089e9e40a | ||
|
|
954950dc14 | ||
|
|
f6f4cdf9e7 | ||
|
|
3a9b48a2aa | ||
|
|
5769d5ca91 | ||
|
|
03271c43a7 | ||
|
|
bb30d26ffb | ||
|
|
e9ee0ef1f5 | ||
|
|
3aefbf8cf6 | ||
|
|
469bf9d514 | ||
|
|
a165883999 | ||
|
|
74d2c2addf | ||
|
|
096e1b2970 | ||
|
|
b0f44f1d5a | ||
|
|
584be05e93 | ||
|
|
3592c629e7 | ||
|
|
f99e0407fd | ||
|
|
fe9c6fb8ae | ||
|
|
54a6a33c01 | ||
|
|
0130580151 | ||
|
|
aa4dd04b99 | ||
|
|
c08d1d5b7f | ||
|
|
312ff4f3d8 | ||
|
|
c6629aebf8 | ||
|
|
016a7e5542 | ||
|
|
61861b1904 | ||
|
|
3ceb8337e7 | ||
|
|
87c8feed4a | ||
|
|
fd411cda18 | ||
|
|
abd6649e5d | ||
|
|
6f3d9688cf | ||
|
|
f9ad453317 | ||
|
|
bd78a36db8 | ||
|
|
5cc49d25c4 | ||
|
|
88fb668cc5 | ||
|
|
5b696124fc | ||
|
|
31382b232d | ||
|
|
48f9b96029 | ||
|
|
b3da2ff8f4 | ||
|
|
1b13273d61 | ||
|
|
2e615b003d | ||
|
|
b2c8c0d361 | ||
|
|
0caed5b410 | ||
|
|
07b38b825a | ||
|
|
df8edaa083 | ||
|
|
cbd4e070bf | ||
|
|
4cc9811447 | ||
|
|
df06a37395 | ||
|
|
12effd4e62 | ||
|
|
6813db06d7 | ||
|
|
8b4fa42e49 | ||
|
|
4251cbc277 | ||
|
|
5ac895bef6 | ||
|
|
666db81a09 | ||
|
|
fe05aa8cf1 | ||
|
|
143d70d264 | ||
|
|
bcb2a3d5e9 | ||
|
|
0bc142de9a | ||
|
|
5ad6613b9e | ||
|
|
7c22a99e05 | ||
|
|
3bc367da3b | ||
|
|
822d407584 | ||
|
|
8653722088 | ||
|
|
577fb2c6fe | ||
|
|
4242a10dbe | ||
|
|
162021def9 | ||
|
|
4492eb0e66 | ||
|
|
27ad11039c | ||
|
|
aba905fa26 | ||
|
|
7f878b8209 | ||
|
|
82c4c6fffa | ||
|
|
05cea509f2 | ||
|
|
1341ead608 | ||
|
|
aaf20592bb | ||
|
|
bfc6ee616c | ||
|
|
6a9a9546fd | ||
|
|
b988b989d5 | ||
|
|
62755c7312 | ||
|
|
76ac1e6143 | ||
|
|
b5d89a67e8 | ||
|
|
eb56475651 | ||
|
|
fe168135ae | ||
|
|
18a621ec25 | ||
|
|
3edd6ab767 | ||
|
|
e0d78f9731 | ||
|
|
b496f979f0 | ||
|
|
9604088e3c | ||
|
|
368edeb8ad | ||
|
|
973eaf5caf | ||
|
|
abcd6cd10d | ||
|
|
ee54231715 | ||
|
|
4314b451d9 | ||
|
|
4317702559 | ||
|
|
f36e73e748 | ||
|
|
7cc3f9506e | ||
|
|
9ef7ccfc12 | ||
|
|
77420739e6 | ||
|
|
0ef72683bb | ||
|
|
6773223da4 | ||
|
|
8ca4963ff3 | ||
|
|
2ed802424a | ||
|
|
992d56e565 | ||
|
|
d10406fd75 | ||
|
|
c8c58d6aac | ||
|
|
a55e6b7fbc | ||
|
|
d255900957 | ||
|
|
f52f5290b2 | ||
|
|
e5f5f7c384 | ||
|
|
2ccb8b7380 | ||
|
|
b973c91781 | ||
|
|
7f38b19238 | ||
|
|
b7093b0d40 | ||
|
|
e67dd3fc0e | ||
|
|
bc9594aeed | ||
|
|
8499be23cc | ||
|
|
75bbd30296 | ||
|
|
38d0b004ba | ||
|
|
30be00adb2 | ||
|
|
0ffddacf11 | ||
|
|
dafd186410 | ||
|
|
00ca4abbe1 | ||
|
|
cb8f01065a | ||
|
|
3c639c2e80 | ||
|
|
0539fdc5e3 | ||
|
|
a0204ada2f | ||
|
|
8a456bf895 | ||
|
|
aed00733f8 | ||
|
|
9ec85a0f18 | ||
|
|
5d5afe10e8 | ||
|
|
c108e5c485 | ||
|
|
e21592f473 | ||
|
|
4dcae54035 | ||
|
|
39747ee80b | ||
|
|
bcc818f397 | ||
|
|
b162e9290b | ||
|
|
62606e46b5 | ||
|
|
56cf1a581c | ||
|
|
c97c2217a5 | ||
|
|
4502024468 | ||
|
|
1346ebc134 | ||
|
|
c3e889cd41 | ||
|
|
d944f415f3 | ||
|
|
38f80edc80 | ||
|
|
092e9e29f1 | ||
|
|
78638c72fb | ||
|
|
9ff7575c85 | ||
|
|
41fb696ef6 | ||
|
|
e615b56a70 | ||
|
|
e005c32151 | ||
|
|
7ab7f69916 | ||
|
|
2c0520b540 | ||
|
|
b8ccf7fa70 | ||
|
|
d4bde14a01 | ||
|
|
93db8990d9 | ||
|
|
03aa37731b | ||
|
|
9c4bf48b4e | ||
|
|
5bfb7b5d11 | ||
|
|
ffa1c370fd | ||
|
|
0a982e2bfd | ||
|
|
7a2427bf07 | ||
|
|
569a41fc2a | ||
|
|
97d2f778f8 | ||
|
|
901573473d | ||
|
|
8c8972f0b5 | ||
|
|
0f9a8d8ee1 | ||
|
|
5a5da33f44 | ||
|
|
2351eeba56 | ||
|
|
41ac5f8d76 | ||
|
|
93b40b04cb | ||
|
|
b92fc7ea9d | ||
|
|
d3e7f53d93 | ||
|
|
2a6f7c1a40 | ||
|
|
523e0c927e | ||
|
|
66bfb2b4f8 | ||
|
|
7df938674e | ||
|
|
195142861c | ||
|
|
ffbfd46dea | ||
|
|
3d43b834de | ||
|
|
77c6fd5ab2 | ||
|
|
6a5f22fc2f | ||
|
|
118c583bff | ||
|
|
2f602deb5a | ||
|
|
1e94511f79 | ||
|
|
b0e6c357f7 | ||
|
|
af92b4370f | ||
|
|
cefcbcb2ac | ||
|
|
5913db991b | ||
|
|
edc15c8e92 | ||
|
|
de8bb15c78 | ||
|
|
6395f4889d | ||
|
|
7d178aad0b | ||
|
|
3c64e1d33f | ||
|
|
a529edaad1 | ||
|
|
acbe4082a8 | ||
|
|
ac55682260 | ||
|
|
90a00e1293 | ||
|
|
6b646e24ea | ||
|
|
62712aa12c | ||
|
|
0ff7f28753 | ||
|
|
6deebb4498 | ||
|
|
751e12e5b5 | ||
|
|
074d9aa5d5 | ||
|
|
fdb3f3c7b7 | ||
|
|
23590bb962 | ||
|
|
624800a1c7 | ||
|
|
e6ceab46a4 | ||
|
|
81aca67745 | ||
|
|
dd462f8072 | ||
|
|
d2c2dcd53c | ||
|
|
f38e715d01 | ||
|
|
7c3c0aa940 | ||
|
|
c67b78bc68 | ||
|
|
7d2a498f68 | ||
|
|
c14b530692 | ||
|
|
987dbe98c8 | ||
|
|
3da081ba86 | ||
|
|
43861f0ce1 | ||
|
|
34323ae811 | ||
|
|
9bbb3b6164 | ||
|
|
0003a55c1d | ||
|
|
98ea585a0f | ||
|
|
d93eb9a87e | ||
|
|
36d934f4c0 | ||
|
|
0d85af019c | ||
|
|
54f663b0f3 | ||
|
|
ae1dd5b1fc | ||
|
|
57b17b174f | ||
|
|
cfb19fa9fc | ||
|
|
32c4d50912 | ||
|
|
40c5dc92c0 | ||
|
|
dbba4ef4f6 | ||
|
|
a75163a49f | ||
|
|
a1b84d2dea | ||
|
|
97ba12b8ef | ||
|
|
c6de7225b9 | ||
|
|
b4f71859d9 | ||
|
|
84b20afe1f | ||
|
|
e10b986ea0 | ||
|
|
7631956451 | ||
|
|
c7bb2fe137 | ||
|
|
5ceedced1c | ||
|
|
fc247dab92 | ||
|
|
c56dbc1c44 | ||
|
|
675a8a9ec9 | ||
|
|
df00909b85 | ||
|
|
5d4f71eb9a | ||
|
|
d0567fc8c6 | ||
|
|
ced2d21f7b | ||
|
|
5a8a19e07b | ||
|
|
57452d65ef | ||
|
|
d250f7bd95 | ||
|
|
435e50fd9a | ||
|
|
bafbc2372c | ||
|
|
2b492ed8cd | ||
|
|
cc2f91b331 | ||
|
|
9afaa6ae4d | ||
|
|
5929a04bea | ||
|
|
ccfd8fa66c | ||
|
|
2798759216 | ||
|
|
c9c0b91d56 | ||
|
|
48b2941cfe | ||
|
|
1451cbc39e | ||
|
|
cd95eabcc6 | ||
|
|
d7b753ae3a | ||
|
|
1f5ce4e4a2 | ||
|
|
3757102919 | ||
|
|
843f55fedc | ||
|
|
a83333e475 | ||
|
|
aecd294fd7 | ||
|
|
f8e5908fd6 | ||
|
|
12a88fe042 | ||
|
|
46dbc53092 | ||
|
|
8bd46d35fe | ||
|
|
a3cc39ddd8 | ||
|
|
e1076bab9c | ||
|
|
994266a54f | ||
|
|
de07c146c9 | ||
|
|
08ed0a9a5d | ||
|
|
737a1b8a37 | ||
|
|
3b2e4e27eb | ||
|
|
95f91e0263 | ||
|
|
e68755a6c1 | ||
|
|
6995e747c2 | ||
|
|
31b8651117 | ||
|
|
972174b1e4 | ||
|
|
fa9b87ca0a | ||
|
|
7fad6b753e | ||
|
|
dbf91be3a6 | ||
|
|
ae82a4eee0 | ||
|
|
c0f212b459 | ||
|
|
46508880c7 | ||
|
|
2d024327b8 | ||
|
|
9effdc7df6 | ||
|
|
eaca25d456 | ||
|
|
8c46c22c64 | ||
|
|
b08b81cf7c | ||
|
|
b5a1811784 | ||
|
|
93ef62f239 | ||
|
|
5f86bb6dcd | ||
|
|
8518769e6b | ||
|
|
e69e097e19 | ||
|
|
7207749044 | ||
|
|
1c7d90c3dc | ||
|
|
1082f20c20 | ||
|
|
af4b810c5e | ||
|
|
97a02f5803 | ||
|
|
277830855d | ||
|
|
eca5abe4bb | ||
|
|
4185558f5e | ||
|
|
9644e894f0 | ||
|
|
9c76a2e91b | ||
|
|
b97f958770 | ||
|
|
8fbdee23b5 | ||
|
|
f04beeb222 | ||
|
|
e61ae70aa6 | ||
|
|
d7be6a5ab0 | ||
|
|
84bbe86fd2 | ||
|
|
d61ed2d9a6 | ||
|
|
298fe97ab2 | ||
|
|
95200ad225 | ||
|
|
d352d883d3 | ||
|
|
6c8ca30f7f | ||
|
|
8c3f3c503b | ||
|
|
639d75bd83 | ||
|
|
48e7c6c904 | ||
|
|
c887c79160 | ||
|
|
1dca643fb1 | ||
|
|
f96d8e025a | ||
|
|
c0e0f176a8 | ||
|
|
6281cd707d | ||
|
|
d447207489 | ||
|
|
ed572467aa | ||
|
|
3e46650957 | ||
|
|
85a8ef3513 | ||
|
|
70dcfd325b | ||
|
|
9f249e3eed | ||
|
|
5ef7ab540a | ||
|
|
a640baeea7 | ||
|
|
29d5344ba7 | ||
|
|
e31c6d3934 | ||
|
|
ca4bd57b8d | ||
|
|
fd73b0cac0 | ||
|
|
cb83dc2664 | ||
|
|
2fd9418af0 | ||
|
|
1ca2c4b4e1 | ||
|
|
bdb2d81687 | ||
|
|
fa638388b4 | ||
|
|
73fe6fc4b6 | ||
|
|
7da787609b | ||
|
|
7691b11f33 | ||
|
|
549c01c736 | ||
|
|
e211445034 | ||
|
|
dea69e800f | ||
|
|
80bdfd1d98 | ||
|
|
f090071db2 | ||
|
|
d5d85d121a | ||
|
|
bfec336549 | ||
|
|
bf25284b93 | ||
|
|
6eec6c9957 | ||
|
|
207261a2cf | ||
|
|
c9e800af64 | ||
|
|
854e1e7a4f | ||
|
|
5ec573d92a | ||
|
|
7c628e9e4f | ||
|
|
e06af011d6 | ||
|
|
28562804f7 | ||
|
|
567adb8caa | ||
|
|
98e5f56066 | ||
|
|
e0d7b30a5e | ||
|
|
853b2fa17c | ||
|
|
4c23f38076 | ||
|
|
4344b951a6 | ||
|
|
00fb955103 | ||
|
|
0b7dc7ff64 | ||
|
|
e1f72b1f27 | ||
|
|
e59eac6a07 | ||
|
|
f737fad43a | ||
|
|
065ec7ec0b | ||
|
|
ffecdfc18c | ||
|
|
3b2875a5a8 | ||
|
|
a21ecda78f | ||
|
|
fa7335156a | ||
|
|
b79fead73d | ||
|
|
39c91bd6ca | ||
|
|
21ee835551 | ||
|
|
0216ef80f8 | ||
|
|
8e98c62122 | ||
|
|
4363cbd88b | ||
|
|
b94bcee867 | ||
|
|
f7846d0141 | ||
|
|
b824d8b84b | ||
|
|
7d9e315593 | ||
|
|
08e9eaa954 | ||
|
|
487dbf3e85 | ||
|
|
808cd6f06a | ||
|
|
447dd3aed7 | ||
|
|
2321866302 | ||
|
|
26489c4908 | ||
|
|
a3ebbabf95 | ||
|
|
058a3dcc6a | ||
|
|
1f819d3382 | ||
|
|
f7227c6ca1 | ||
|
|
a4953263bd | ||
|
|
3873c7fda0 | ||
|
|
845ebc5e62 | ||
|
|
a5ae5600ce | ||
|
|
eacc8c7d35 | ||
|
|
0bf7babcbe | ||
|
|
82ad4b9235 | ||
|
|
e221c1d25d | ||
|
|
a90316b4d9 | ||
|
|
09f4477510 | ||
|
|
c680dbb53e | ||
|
|
4549337335 | ||
|
|
c831af2fe2 | ||
|
|
21f1813d82 | ||
|
|
7ee9c9b7a0 | ||
|
|
0675b06bea | ||
|
|
22d8528d90 | ||
|
|
d5fdb9c3a7 | ||
|
|
00eb6c0d6f | ||
|
|
9a8298a84d | ||
|
|
2aa9cf4007 | ||
|
|
7ea91dfcc4 | ||
|
|
84f9e94268 | ||
|
|
bbf3a2138b | ||
|
|
8941c059f6 | ||
|
|
0d8669fbe8 | ||
|
|
51433528a1 | ||
|
|
a82527dcdf | ||
|
|
95f41b6a73 | ||
|
|
919b8ef9e2 | ||
|
|
b34cbc2f16 | ||
|
|
894933848a | ||
|
|
b39ff1dd42 | ||
|
|
f2e749548c | ||
|
|
0a0de6708e | ||
|
|
623f9f6d8a | ||
|
|
3788ccd447 | ||
|
|
bb12d8240f | ||
|
|
c171b6def2 | ||
|
|
8f28c3a0fb | ||
|
|
31dccaca0f | ||
|
|
daf8d649f2 | ||
|
|
d4eeafe53f | ||
|
|
0a1a109b2e | ||
|
|
f7ab17d24d | ||
|
|
3984b828e8 | ||
|
|
5d0c5fd40d | ||
|
|
57f95bdc32 | ||
|
|
63b90ab45c | ||
|
|
2b3ebb0751 | ||
|
|
d3f0346f04 | ||
|
|
eeb8c59ff2 | ||
|
|
48b5602144 | ||
|
|
fd5d8bebb9 | ||
|
|
ff72acd194 | ||
|
|
5f122e7f79 | ||
|
|
0132ad05ab | ||
|
|
79c4469ac7 | ||
|
|
5c5b326b1a | ||
|
|
56a98a3bb0 | ||
|
|
1d658a5a4d | ||
|
|
939e02ccee | ||
|
|
507f89b8ed | ||
|
|
ac9322370b | ||
|
|
172feab084 | ||
|
|
095d4d4d15 | ||
|
|
162ea38a95 | ||
|
|
dea7be5e8a | ||
|
|
797b426ae7 | ||
|
|
3de51cd9f8 | ||
|
|
5fda3f482a | ||
|
|
4f746c40d7 | ||
|
|
6bff5f6df8 | ||
|
|
001cad22db | ||
|
|
a37324cbee | ||
|
|
a4a9a181f5 | ||
|
|
7610947248 | ||
|
|
8bc1419699 | ||
|
|
a968e31179 | ||
|
|
6fd79fb015 | ||
|
|
59446a8dd2 | ||
|
|
00088c2954 | ||
|
|
975ad25162 | ||
|
|
19dca018b2 | ||
|
|
24f355a779 | ||
|
|
d5cf0ad2c8 | ||
|
|
1dc0a1de6c | ||
|
|
46fde9aa04 | ||
|
|
a8ac58fd5b | ||
|
|
99bba29715 | ||
|
|
f308a01e59 | ||
|
|
406320cb98 | ||
|
|
1e7aca8a3d | ||
|
|
26fcb78ae3 | ||
|
|
2b0082bf15 | ||
|
|
4239de1ee7 | ||
|
|
59c18a7454 | ||
|
|
855215673a | ||
|
|
cb7714a32e | ||
|
|
992eed5ef7 | ||
|
|
efee37a632 | ||
|
|
5262439300 | ||
|
|
ce7cbc1f64 | ||
|
|
8851ace543 | ||
|
|
d6051d9d7e | ||
|
|
c207404089 | ||
|
|
e851bb869b | ||
|
|
fd5df98616 | ||
|
|
b026772764 | ||
|
|
ecd2dab0a2 | ||
|
|
9acc93853e | ||
|
|
24910348a1 | ||
|
|
d5eb8fc121 | ||
|
|
7ad432be23 | ||
|
|
0381c5a288 | ||
|
|
78929418cc | ||
|
|
b28d22545a | ||
|
|
78ed8f660c | ||
|
|
2e338f74ec | ||
|
|
12bcd1a528 | ||
|
|
92903f0d4a | ||
|
|
c8f157444c | ||
|
|
ed9d27bb3a | ||
|
|
f840d9b60f | ||
|
|
a16d3d4887 | ||
|
|
e4101128e0 | ||
|
|
042d3e3f93 | ||
|
|
0340eccb52 | ||
|
|
68bfabbaba | ||
|
|
19dc0872a9 | ||
|
|
f1f97186ba | ||
|
|
f353afe926 | ||
|
|
9653cf46fb | ||
|
|
9528b2d391 | ||
|
|
f68038f2cf | ||
|
|
fc1bee30a6 | ||
|
|
3262f8dc2a | ||
|
|
c666f9d050 | ||
|
|
5e840c1db6 | ||
|
|
90dcd9f267 | ||
|
|
3213537277 | ||
|
|
1eb2b6ec61 | ||
|
|
eb45a36af0 | ||
|
|
a17c1a7c3a | ||
|
|
518c166a39 | ||
|
|
2dee5b8d04 | ||
|
|
1f32f95b9c | ||
|
|
016dc9d86c | ||
|
|
c050abf3e8 | ||
|
|
170358c3c4 | ||
|
|
40c9688cef | ||
|
|
7435fa8446 | ||
|
|
834b26934b | ||
|
|
2fb5984869 | ||
|
|
cab9fa1ae6 | ||
|
|
f62af90ae3 | ||
|
|
0d0900269f | ||
|
|
072938289c | ||
|
|
8933574ce9 | ||
|
|
86835dd3c6 | ||
|
|
86c4c9471b | ||
|
|
fa018ec6a9 | ||
|
|
ddd7b2b8af | ||
|
|
5ef76a5e31 | ||
|
|
c93ce48e67 | ||
|
|
ac7a09d6c5 | ||
|
|
2d3ecf8bf8 | ||
|
|
5562d3db4c | ||
|
|
170000e04a | ||
|
|
e35e52b2f4 | ||
|
|
f1b4eee8b5 | ||
|
|
60c45d6273 | ||
|
|
6225b92da0 | ||
|
|
64b6805ec3 | ||
|
|
a9800e8ff0 | ||
|
|
c46a50ace9 | ||
|
|
79e9fe112c | ||
|
|
970386bd9a | ||
|
|
e063fcb036 | ||
|
|
ea7e834ae1 | ||
|
|
bd3645cbb0 | ||
|
|
e2ca6e92e4 | ||
|
|
9eab2bfe41 | ||
|
|
6734450d40 | ||
|
|
ac114b27a9 | ||
|
|
17d7f5f88e | ||
|
|
ff51e679dc | ||
|
|
d37c5d8921 | ||
|
|
81e38e772b | ||
|
|
a13dc9b91c | ||
|
|
99bae981da | ||
|
|
9c96ce5f6e | ||
|
|
034c13c48f | ||
|
|
7d438a748f | ||
|
|
91f5f0bfc4 | ||
|
|
0736ca7b5a | ||
|
|
970c95959a | ||
|
|
529d24ec30 | ||
|
|
b0f2135762 | ||
|
|
1c106e8323 | ||
|
|
bfe7d1ee3a | ||
|
|
b337371a0c | ||
|
|
a1b9f90d7d | ||
|
|
4fbed419d0 | ||
|
|
92dcf0c13b | ||
|
|
ae5a7d7962 | ||
|
|
bac765aaaa | ||
|
|
c1596180bf | ||
|
|
e7ad883fe9 | ||
|
|
cb0e8df4a4 | ||
|
|
9792fb117c | ||
|
|
3d14898b35 | ||
|
|
da07197c88 | ||
|
|
9b7da736ed | ||
|
|
9a6f4372f8 | ||
|
|
1a790b30ed | ||
|
|
ea1f6e7870 | ||
|
|
92a12ea33b | ||
|
|
845001249a | ||
|
|
56d5ba6d06 | ||
|
|
873cd02bde | ||
|
|
4265220ccd | ||
|
|
12d5298420 | ||
|
|
f39a17de14 | ||
|
|
12ed1d6429 | ||
|
|
7b17b5b488 | ||
|
|
0cf8b376ac | ||
|
|
8c76900470 | ||
|
|
9e21ecceea | ||
|
|
69e0ed42ea | ||
|
|
31aa44d23d | ||
|
|
5ce64eb0f8 | ||
|
|
99854fd07a | ||
|
|
8caefc2a55 | ||
|
|
f0c8273b63 | ||
|
|
24d0c6a54a | ||
|
|
55a25d7a42 | ||
|
|
ae49d04088 | ||
|
|
6a1dd69358 | ||
|
|
dc2eca9f2c | ||
|
|
f38ca3a392 | ||
|
|
ec2fa95bf3 | ||
|
|
7b40c6fef1 | ||
|
|
cca4c516f1 | ||
|
|
b4e32a5ede | ||
|
|
4015ac78cd | ||
|
|
0c1c41aeaf | ||
|
|
78e8eae5ad | ||
|
|
cd5fb84136 | ||
|
|
bb0c234984 | ||
|
|
18dd6b2875 | ||
|
|
f67e327b29 | ||
|
|
3646e9e050 | ||
|
|
926470829d | ||
|
|
357799b508 | ||
|
|
02678253b9 | ||
|
|
aeb0aded91 | ||
|
|
c554321495 | ||
|
|
a705e56acc | ||
|
|
4a06b6d13b | ||
|
|
4a5e2828df | ||
|
|
0f9178f1de | ||
|
|
675cd01d60 | ||
|
|
fcb85ebb98 | ||
|
|
5975a0c5c8 | ||
|
|
953bd5f210 | ||
|
|
727f176542 | ||
|
|
dc4271505b | ||
|
|
3f764e2407 | ||
|
|
f812ac838e | ||
|
|
7e84a8964e | ||
|
|
4ef806b14e | ||
|
|
1f6e0ebf81 | ||
|
|
3738f87278 | ||
|
|
e2c4e52f39 | ||
|
|
741a01db3b | ||
|
|
726026f0ae | ||
|
|
c7f87c0d69 | ||
|
|
4fa3c30df2 | ||
|
|
0d0a2b4d58 | ||
|
|
c1032967c2 | ||
|
|
4035f6aa21 | ||
|
|
dc2db22c3d | ||
|
|
2599babe31 | ||
|
|
8424ff5b61 | ||
|
|
b123f7ffcd | ||
|
|
9563e4f85e | ||
|
|
c4b7c91f3a | ||
|
|
1a94976752 | ||
|
|
407dc9272c | ||
|
|
5d4880c497 | ||
|
|
c0364fc766 | ||
|
|
76abff2fba | ||
|
|
a7d28045cb | ||
|
|
885df54cca | ||
|
|
93e66746f9 | ||
|
|
1f8dcea494 | ||
|
|
bbe2891ec5 | ||
|
|
de291fd7de | ||
|
|
01f88e4de5 | ||
|
|
b3bb031fca | ||
|
|
24d6532cf1 | ||
|
|
f3e39e87d7 | ||
|
|
4d5428ea90 | ||
|
|
c175371557 | ||
|
|
fc14c08bcc | ||
|
|
30b4ddeddf | ||
|
|
876ae44b8a | ||
|
|
39ae56db0a | ||
|
|
35bc6866d5 | ||
|
|
654dd2b704 | ||
|
|
2faa8c141f | ||
|
|
ac0064110b | ||
|
|
2af1ae5d8a | ||
|
|
833a1da355 | ||
|
|
e6dab2fa11 | ||
|
|
5c828df567 | ||
|
|
c7e0be3c3b | ||
|
|
e7145acd56 | ||
|
|
debd9eb8ce | ||
|
|
c3091b75a3 | ||
|
|
4430706915 | ||
|
|
487ebd3ca8 | ||
|
|
45400ac301 | ||
|
|
cbb99b6e6e | ||
|
|
063fabd344 | ||
|
|
cb9c848918 | ||
|
|
b8898e2338 | ||
|
|
41e92b34ad | ||
|
|
109112ba93 | ||
|
|
c975d50cdc | ||
|
|
575584b68f | ||
|
|
113d00f840 | ||
|
|
1567031046 | ||
|
|
98842b9357 | ||
|
|
8037382e8f | ||
|
|
70e85cb6c4 | ||
|
|
624ad9cb98 | ||
|
|
69ae006f37 | ||
|
|
d4f0b03982 | ||
|
|
d257c3c1bb | ||
|
|
03c23e15b3 | ||
|
|
00de8316ca | ||
|
|
e37e88f92f | ||
|
|
40820e3b41 | ||
|
|
c0f5fe9bd3 | ||
|
|
cbaafbc132 | ||
|
|
1f2c73b40a | ||
|
|
01946c6ef5 | ||
|
|
4ded042dde | ||
|
|
424ca49c26 | ||
|
|
a2eb4c5e60 | ||
|
|
0c159cd8b6 | ||
|
|
7336427ce6 | ||
|
|
8b938e2696 | ||
|
|
a7b2b92f2b | ||
|
|
5fe7d7f0bf | ||
|
|
e109e54949 | ||
|
|
8139179780 | ||
|
|
9a1a588857 | ||
|
|
b063dfd2e3 | ||
|
|
29a293f9e7 | ||
|
|
77c3ddc7ca | ||
|
|
9b978578ce | ||
|
|
4385430f05 | ||
|
|
4e2b30b193 | ||
|
|
7604c4b0f1 | ||
|
|
cb3691dd0d | ||
|
|
45fc7342f5 | ||
|
|
0cc5cc796d | ||
|
|
860c7da6e8 | ||
|
|
d35021db92 | ||
|
|
5df171b3f9 | ||
|
|
d318010c67 | ||
|
|
37b2d3aa2c | ||
|
|
279e91bb3d | ||
|
|
e619e19242 | ||
|
|
01c352d2e8 | ||
|
|
23d0537fb3 | ||
|
|
d622fc9281 | ||
|
|
435023a8f9 | ||
|
|
0173f7642b | ||
|
|
60fb3d5c06 | ||
|
|
fe07b4bbc5 | ||
|
|
69d4886697 | ||
|
|
610e56baaf | ||
|
|
5ac518b02a | ||
|
|
3564b00fc0 | ||
|
|
a118498f79 | ||
|
|
e5ecdcf8c9 | ||
|
|
1e0c7f05e6 | ||
|
|
bd255b3553 | ||
|
|
f568aed520 | ||
|
|
27ecf175d8 | ||
|
|
11a454c0fc | ||
|
|
8dd91ce9f8 | ||
|
|
92e5f946c1 | ||
|
|
fd250e4fe1 | ||
|
|
1ec130757d | ||
|
|
ce3e287892 | ||
|
|
13ed3329e0 | ||
|
|
25c23af865 | ||
|
|
4b7c41ee0f | ||
|
|
717b726329 | ||
|
|
04022f85af | ||
|
|
deb36eeeda | ||
|
|
95b81ff54a | ||
|
|
6076462ff5 | ||
|
|
5967d26228 | ||
|
|
bf654bde60 |
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "8.0.4",
|
||||
"version": "8.0.11",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
|
||||
162
.github/ISSUE_TEMPLATE/issue report.yml
vendored
162
.github/ISSUE_TEMPLATE/issue report.yml
vendored
@@ -1,58 +1,131 @@
|
||||
name: Issue Report
|
||||
description: File an issue report
|
||||
title: "[Issue]: "
|
||||
labels: [bug, triage]
|
||||
body:
|
||||
- type: markdown
|
||||
id: introduction
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report an issue. Before submitting a report, please do the following:
|
||||
1. Please head to our forum or chat rooms and troubleshoot with volunteers if you haven't already. Links can be found here: https://jellyfin.org/contact/
|
||||
2. Please search the bug tracker for similar issues. If you do find one, please comment there instead of opening a new bug report.
|
||||
3. If you decide to open a new report, please provide as much detail as possible.
|
||||
4. Please **ONLY** report **ONE** issue per report. If you are experiencing multiple issues, please open multiple reports.
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
### Thank you for taking the time to report an issue!
|
||||
Please keep in mind that Jellyfin is a [free and open-source](https://jellyfin.org/docs/general/about) project, made up entirely and exclusively of **volunteers** who donate their free time to the project.
|
||||
- type: checkboxes
|
||||
id: before-posting
|
||||
attributes:
|
||||
label: Please describe your bug
|
||||
description: Also tell us, what did you expect to happen?
|
||||
label: "This issue respects the following points:"
|
||||
description: All conditions are **required**. Failure to comply with any of these conditions may cause your issue to be closed without comment.
|
||||
options:
|
||||
- label: This is a **bug**, not a question or a configuration issue; Please visit our forum or chat rooms first to troubleshoot with volunteers, before creating a report. The links can be found [here](https://jellyfin.org/contact/).
|
||||
required: true
|
||||
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
|
||||
required: true
|
||||
- label: I'm using an up to date version of Jellyfin Server stable, unstable or master; We generally do not support previous older versions. If possible, please update to the latest version before opening an issue.
|
||||
required: true
|
||||
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
|
||||
required: true
|
||||
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
|
||||
required: true
|
||||
- type: markdown
|
||||
id: preliminary-information
|
||||
attributes:
|
||||
value: |
|
||||
### General preliminary information
|
||||
|
||||
Please keep the following in mind when creating this issue:
|
||||
|
||||
1. Fill in as much of the template as possible. When you are unsure about the relevancy of a section, do include the information requested in that section. Only leave out information in sections when you are completely sure about it not being relevant.
|
||||
2. Provide as much detail as possible. Do not assume other people to know what is going on.
|
||||
3. Keep everything readable and structured. Nobody enjoys reading poorly written reports that are difficult to understand.
|
||||
4. Keep an eye on your report as long as it is open, your involvement might be requested at a later moment.
|
||||
5. Keep the title short and descriptive. The title is not the place to write down a full description of the issue.
|
||||
6. When deciding to leave out information in a field, leave it blank and empty. Avoid writing things such as `n/a` for empty fields.
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Description of the bug
|
||||
description: Please provide a detailed description on the bug you encountered, in a readable and comprehensible way.
|
||||
placeholder: |
|
||||
The more information that you are able to provide, the better. Did you do anything before this happened? Did you upgrade or change anything? Any screenshots or logs you can provide will be helpful.
|
||||
If you are using an old release of Jellyfin, please also explain why.
|
||||
After upgrading to version x.y.z of Jellyfin, the "login disclaimer" is showing incorrect text. It appears to me that it is appending the server name to the end of the login disclaimer, and showing that to a user. It might be a regression from pull request x. I have tried rebooting my host as well as my container multiple times. I tested this functionality on different clients, and it happens to all the tested clients (client x, y, z), that support the login disclaimer functionality. This makes me believe it is a server side issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro-steps
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
label: Reproduction steps
|
||||
description: Reproduction steps should be complete and self-contained. Anyone can reproduce this issue by following these steps. Furthermore, the steps should be clear and easy to follow.
|
||||
placeholder: |
|
||||
1. In this environment...
|
||||
2. With this config...
|
||||
3. Run '...'
|
||||
4. See error...
|
||||
1. Sign in on the Jellyfin web client, with an admin account, using a browser of your choice.
|
||||
2. Navigate to the dashboard.
|
||||
3. Select "general".
|
||||
4. Change the login disclaimer to something like "I am a cool disclaimer!"
|
||||
5. Save the settings.
|
||||
6. Sign out.
|
||||
7. Make sure you are on the sign in screen. Otherwise, navigate to the sign in screen manually.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: What is the current _bug_ behavior?
|
||||
description: Write down the incorrect behavior that currently happens after following the reproduction steps.
|
||||
placeholder: |
|
||||
The login disclaimer on the sign in screen has the server name appended to the text. The text shown is: "I am a cool disclaimer!jellyfinserver".
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: What is the expected _correct_ behavior?
|
||||
description: Write down the correct expected behavior that is supposed to happen after following the reproduction steps.
|
||||
placeholder: |
|
||||
The login disclaimer on the sign in screen should only show the configured text. The text that should be shown is: "I am a cool disclaimer!".
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Jellyfin Version
|
||||
description: What version of Jellyfin are you running?
|
||||
label: Jellyfin Server version
|
||||
description: What version of Jellyfin are you using?
|
||||
options:
|
||||
- 10.8.13
|
||||
- 10.8.12
|
||||
- 10.8.11 or older (please specify)
|
||||
- Unstable (master branch)
|
||||
- 10.9.11+
|
||||
- Master
|
||||
- Unstable
|
||||
- Older*
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version-other
|
||||
id: version-master
|
||||
attributes:
|
||||
label: "if other:"
|
||||
placeholder: Other
|
||||
label: "Specify commit id"
|
||||
description: Fill in this field in case the option 'master' is selected. Provide the commit id it was built on.
|
||||
placeholder: |
|
||||
610e56baafc3011e1bfa043bdabb567bda0c2ab0
|
||||
- type: input
|
||||
id: version-unstable
|
||||
attributes:
|
||||
label: "Specify unstable release number"
|
||||
description: Fill in this field in case the option 'unstable' is selected. Provide the unstable release number.
|
||||
placeholder: |
|
||||
2024050906
|
||||
- type: input
|
||||
id: version-older
|
||||
attributes:
|
||||
label: "Specify version number"
|
||||
description: Fill in this field in case the option 'older' is selected. Provide the version number.
|
||||
placeholder: |
|
||||
x.y.z
|
||||
- type: input
|
||||
id: build-version
|
||||
attributes:
|
||||
label: "Specify the build version"
|
||||
description: Please provide the build version that is shown in the dashboard.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment-information
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Accurately fill in as much environment details as possible. If a certain environment field is not shown in the template below, but you consider useful information, please include it.
|
||||
Examples:
|
||||
- **OS**: [e.g. Debian 11, Windows 10]
|
||||
- **Linux Kernel**: [e.g. none, 5.15, 6.1, etc.]
|
||||
@@ -87,21 +160,22 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
id: general-information-logs
|
||||
attributes:
|
||||
value: |
|
||||
When providing logs, please keep the following things in mind.
|
||||
1. **DO NOT** use external paste services.
|
||||
When providing logs, please keep the following things in mind:
|
||||
1. **DO NOT** use external paste services. If logs are too large to paste into the field, upload them as text files.
|
||||
2. Please provide complete logs.
|
||||
- For server logs, include everything you think is important plus *10 lines before and after*
|
||||
- For server logs, ensure to capture all relevant information, encompassing both the events leading up to and following the occurrence of the issue. Typically, providing 10 *lines preceding and succeeding* the problem should be adequate.
|
||||
- For ffmpeg logs, please provide the entire file unmodified.
|
||||
3. Please do not run logs through any translation program. Especially beware if your browser translates pages by default.
|
||||
3. Please do not run logs through any translation program. We exclusively accept raw, untranslated logs. Particularly exercise caution if your browser automatically translates pages by default.
|
||||
- Do not forget to censor out personal information such as public IP addresses.
|
||||
4. Please do not include logs as screenshots, with the only exception being client logs in browsers.
|
||||
- type: textarea
|
||||
id: logs
|
||||
id: jellyfin-logs
|
||||
attributes:
|
||||
label: Jellyfin logs
|
||||
description: Please copy and paste any relevant log output. This can be found in Dashboard > Logs.
|
||||
placeholder: For playback issues, browser/client and FFmpeg logs may be more useful.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
@@ -109,24 +183,20 @@ body:
|
||||
id: ffmpeg-logs
|
||||
attributes:
|
||||
label: FFmpeg logs
|
||||
description: Please copy and paste recent FFmpeg log output. This can be found in Dashboard > Logs > FFmpeg*.log.
|
||||
placeholder: This field is mandatory for debugging hardware transcoding issues. It's important to include the specific codec details. If no FFmpeg logs appear, the file was Direct Played and did not use FFmpeg.
|
||||
description: Relevant FFmpeg log output. This can be found in Dashboard > Logs > FFmpeg*.log. This field is considered mandatory for transcoding related issues. It's also important to include the specific codec details.
|
||||
render: shell
|
||||
- type: textarea
|
||||
id: browserlogs
|
||||
id: browser-logs
|
||||
attributes:
|
||||
label: Please attach any browser or client logs here
|
||||
placeholder: Access browser logs by using the F12 to bring up the console. Screenshots are typically easier to read than raw logs. For clients such as Android or iOS, please see our documentation.
|
||||
label: Client / Browser logs
|
||||
description: Access browser logs by using the F12 to bring up the console. Screenshots are typically easier to read than raw logs. For clients such as Android or iOS, please see our documentation.
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Please attach any screenshots here
|
||||
placeholder: Images can be pasted directly into the textbox and will be hosted by github.
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
label: Relevant screenshots or videos
|
||||
description: Attach relevant screenshots or videos related to this report.
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct)
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
label: Additional information
|
||||
description: Any additional information that might be useful to this issue.
|
||||
|
||||
10
.github/workflows/ci-codeql-analysis.yml
vendored
10
.github/workflows/ci-codeql-analysis.yml
vendored
@@ -20,18 +20,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-extended
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
uses: github/codeql-action/autobuild@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3
|
||||
uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||
|
||||
149
.github/workflows/ci-compat.yml
vendored
Normal file
149
.github/workflows/ci-compat.yml
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
name: ABI Compatibility
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
abi-head:
|
||||
name: ABI - HEAD
|
||||
runs-on: ubuntu-latest
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: abi-head
|
||||
retention-days: 14
|
||||
if-no-files-found: error
|
||||
path: out/
|
||||
|
||||
abi-base:
|
||||
name: ABI - BASE
|
||||
if: ${{ github.base_ref != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout common ancestor
|
||||
env:
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
run: |
|
||||
git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
|
||||
git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
|
||||
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||
git checkout --progress --force $ANCESTOR_REF
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: abi-base
|
||||
retention-days: 14
|
||||
if-no-files-found: error
|
||||
path: out/
|
||||
|
||||
abi-diff:
|
||||
permissions:
|
||||
pull-requests: write # to create or update comment (peter-evans/create-or-update-comment)
|
||||
|
||||
name: ABI - Difference
|
||||
if: ${{ github.event_name == 'pull_request_target' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- abi-head
|
||||
- abi-base
|
||||
|
||||
steps:
|
||||
- name: Download abi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: abi-head
|
||||
path: abi-head
|
||||
|
||||
- name: Download abi-base
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: abi-base
|
||||
path: abi-base
|
||||
|
||||
- name: Setup ApiCompat
|
||||
run: |
|
||||
dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool
|
||||
|
||||
- name: Run ApiCompat
|
||||
id: diff
|
||||
run: |
|
||||
{
|
||||
echo 'body<<EOF'
|
||||
for file in Jellyfin.Data.dll MediaBrowser.Common.dll MediaBrowser.Controller.dll MediaBrowser.Model.dll Emby.Naming.dll Jellyfin.Extensions.dll; do
|
||||
COMPAT_OUTPUT="$( { apicompat --left ./abi-base/${file} --right ./abi-head/${file}; } 2>&1 )"
|
||||
if [ "APICompat ran successfully without finding any breaking changes." != "${COMPAT_OUTPUT}" ]; then
|
||||
printf "\n${file}\n${COMPAT_OUTPUT}\n"
|
||||
fi
|
||||
done
|
||||
echo EOF
|
||||
} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Find difference comment
|
||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
direction: last
|
||||
body-includes: abi-diff-workflow-comment
|
||||
|
||||
- name: Reply or edit difference comment (changed)
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
if: ${{ steps.diff.outputs.body != '' }}
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
body: |
|
||||
<!--abi-diff-workflow-comment-->
|
||||
<details>
|
||||
<summary>ABI Difference</summary>
|
||||
|
||||
```
|
||||
${{ steps.diff.outputs.body }}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- name: Reply or edit difference comment (unchanged)
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
if: ${{ steps.diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
body: |
|
||||
<!--abi-diff-workflow-comment-->
|
||||
<details>
|
||||
<summary>ABI Difference</summary>
|
||||
|
||||
No changes to the ABI found. See history of this comment for previous changes.
|
||||
|
||||
</details>
|
||||
124
.github/workflows/ci-openapi.yml
vendored
124
.github/workflows/ci-openapi.yml
vendored
@@ -3,6 +3,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request_target:
|
||||
|
||||
permissions: {}
|
||||
@@ -14,18 +16,18 @@ jobs:
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: openapi-head
|
||||
retention-days: 14
|
||||
@@ -39,7 +41,7 @@ jobs:
|
||||
permissions: read-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
@@ -53,13 +55,13 @@ jobs:
|
||||
ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
|
||||
git checkout --progress --force $ANCESTOR_REF
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: openapi-base
|
||||
retention-days: 14
|
||||
@@ -78,12 +80,12 @@ jobs:
|
||||
- openapi-base
|
||||
steps:
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
- name: Download openapi-base
|
||||
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: openapi-base
|
||||
path: openapi-base
|
||||
@@ -99,11 +101,24 @@ jobs:
|
||||
- id: read-diff
|
||||
name: Read openapi-diff output
|
||||
run: |
|
||||
# Read and fix markdown
|
||||
body=$(cat openapi-changes.md)
|
||||
body="${body//'%'/'%25'}"
|
||||
body="${body//$'\n'/'%0A'}"
|
||||
body="${body//$'\r'/'%0D'}"
|
||||
echo ::set-output name=body::$body
|
||||
# Write to workflow summary
|
||||
echo "$body" >> $GITHUB_STEP_SUMMARY
|
||||
# Set ApiChanged var
|
||||
if [ "$body" != '' ]; then
|
||||
echo "ApiChanged=1" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "ApiChanged=0" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
# Add header/footer for diff comment
|
||||
echo '<!--openapi-diff-workflow-comment-->' > openapi-changes-reply.md
|
||||
echo "<details>" >> openapi-changes-reply.md
|
||||
echo "<summary>Changes in OpenAPI specification found. Expand to see details.</summary>" >> openapi-changes-reply.md
|
||||
echo "" >> openapi-changes-reply.md
|
||||
echo "$body" >> openapi-changes-reply.md
|
||||
echo "" >> openapi-changes-reply.md
|
||||
echo "</details>" >> openapi-changes-reply.md
|
||||
- name: Find difference comment
|
||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
|
||||
id: find-comment
|
||||
@@ -113,22 +128,15 @@ jobs:
|
||||
body-includes: openapi-diff-workflow-comment
|
||||
- name: Reply or edit difference comment (changed)
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
if: ${{ steps.read-diff.outputs.body != '' }}
|
||||
if: ${{ steps.read-diff.outputs.ApiChanged == '1' }}
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
body: |
|
||||
<!--openapi-diff-workflow-comment-->
|
||||
<details>
|
||||
<summary>Changes in OpenAPI specification found. Expand to see details.</summary>
|
||||
|
||||
${{ steps.read-diff.outputs.body }}
|
||||
|
||||
</details>
|
||||
body-path: openapi-changes-reply.md
|
||||
- name: Edit difference comment (unchanged)
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
|
||||
if: ${{ steps.read-diff.outputs.ApiChanged == '0' && steps.find-comment.outputs.comment-id != '' }}
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
@@ -138,11 +146,9 @@ jobs:
|
||||
|
||||
No changes to OpenAPI specification found. See history of this comment for previous changes.
|
||||
|
||||
publish:
|
||||
publish-unstable:
|
||||
name: OpenAPI - Publish Unstable Spec
|
||||
if: |
|
||||
github.event_name != 'pull_request_target' &&
|
||||
contains(github.repository_owner, 'jellyfin')
|
||||
if: ${{ github.event_name != 'pull_request_target' && !startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- openapi-head
|
||||
@@ -152,7 +158,7 @@ jobs:
|
||||
run: |-
|
||||
echo "JELLYFIN_VERSION=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
@@ -166,7 +172,7 @@ jobs:
|
||||
strip_components: 1
|
||||
target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||
- name: Move openapi.json (unstable) into place
|
||||
uses: appleboy/ssh-action@029f5b4aeeeb58fdfe1410a5d17f967dacf36262 # v1.0.3
|
||||
uses: appleboy/ssh-action@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
|
||||
with:
|
||||
host: "${{ secrets.REPO_HOST }}"
|
||||
username: "${{ secrets.REPO_USER }}"
|
||||
@@ -201,3 +207,65 @@ jobs:
|
||||
sudo ln -s unstable/${LAST_SPEC} ${TGT_DIR}/jellyfin-openapi-unstable_previous.json
|
||||
fi
|
||||
) 200>/run/workflows/openapi-unstable.lock
|
||||
|
||||
publish-stable:
|
||||
name: OpenAPI - Publish Stable Spec
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- openapi-head
|
||||
steps:
|
||||
- name: Set version number
|
||||
id: version
|
||||
run: |-
|
||||
echo "JELLYFIN_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
- name: Upload openapi.json (stable) to repository server
|
||||
uses: appleboy/scp-action@917f8b81dfc1ccd331fef9e2d61bdc6c8be94634 # v0.1.7
|
||||
with:
|
||||
host: "${{ secrets.REPO_HOST }}"
|
||||
username: "${{ secrets.REPO_USER }}"
|
||||
key: "${{ secrets.REPO_KEY }}"
|
||||
source: openapi-head/openapi.json
|
||||
strip_components: 1
|
||||
target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||
- name: Move openapi.json (stable) into place
|
||||
uses: appleboy/ssh-action@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
|
||||
with:
|
||||
host: "${{ secrets.REPO_HOST }}"
|
||||
username: "${{ secrets.REPO_USER }}"
|
||||
key: "${{ secrets.REPO_KEY }}"
|
||||
debug: false
|
||||
script_stop: false
|
||||
script: |
|
||||
if ! test -d /run/workflows; then
|
||||
sudo mkdir -p /run/workflows
|
||||
sudo chown ${{ secrets.REPO_USER }} /run/workflows
|
||||
fi
|
||||
(
|
||||
flock -x -w 300 200 || exit 1
|
||||
TGT_DIR="/srv/repository/main/openapi"
|
||||
LAST_SPEC="$( ls -lt ${TGT_DIR}/stable/ | grep 'jellyfin-openapi' | head -1 | awk '{ print $NF }' )"
|
||||
# If new and previous spec don't differ (diff retcode 0), remove incoming and finish
|
||||
if diff /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/stable/${LAST_SPEC} &>/dev/null; then
|
||||
rm -r /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}
|
||||
exit 0
|
||||
fi
|
||||
# Move new spec into place
|
||||
sudo mv /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json
|
||||
# Delete previous jellyfin-openapi-stable_previous.json
|
||||
sudo rm ${TGT_DIR}/jellyfin-openapi-stable_previous.json
|
||||
# Move current jellyfin-openapi-stable.json symlink to jellyfin-openapi-stable_previous.json
|
||||
sudo mv ${TGT_DIR}/jellyfin-openapi-stable.json ${TGT_DIR}/jellyfin-openapi-stable_previous.json
|
||||
# Create new jellyfin-openapi-stable.json symlink
|
||||
sudo ln -s stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json ${TGT_DIR}/jellyfin-openapi-stable.json
|
||||
# Check that the previous openapi stable spec link is correct
|
||||
if [[ "$( readlink ${TGT_DIR}/jellyfin-openapi-stable_previous.json )" != "stable/${LAST_SPEC}" ]]; then
|
||||
sudo rm ${TGT_DIR}/jellyfin-openapi-stable_previous.json
|
||||
sudo ln -s stable/${LAST_SPEC} ${TGT_DIR}/jellyfin-openapi-stable_previous.json
|
||||
fi
|
||||
) 200>/run/workflows/openapi-stable.lock
|
||||
|
||||
6
.github/workflows/ci-tests.yml
vendored
6
.github/workflows/ci-tests.yml
vendored
@@ -19,9 +19,9 @@ jobs:
|
||||
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
- uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
|
||||
with:
|
||||
dotnet-version: ${{ env.SDK_VERSION }}
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
--verbosity minimal
|
||||
|
||||
- name: Merge code coverage results
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@2a2d60ea1c7e811f54684179af6ac1ae8c1ce69a # 5.2.5
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@62f9e70ab348d56eee76d446b4db903a85ab0ea8 # v5.3.11
|
||||
with:
|
||||
reports: "**/coverage.cobertura.xml"
|
||||
targetdir: "merged/"
|
||||
|
||||
8
.github/workflows/commands.yml
vendored
8
.github/workflows/commands.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
reactions: '+1'
|
||||
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
reactions: eyes
|
||||
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
@@ -128,11 +128,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: pull in script
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
repository: jellyfin/jellyfin-triage-script
|
||||
- name: install python
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
|
||||
4
.github/workflows/issue-template-check.yml
vendored
4
.github/workflows/issue-template-check.yml
vendored
@@ -10,11 +10,11 @@ jobs:
|
||||
issues: write
|
||||
steps:
|
||||
- name: pull in script
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
repository: jellyfin/jellyfin-triage-script
|
||||
- name: install python
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: 'pip'
|
||||
|
||||
2
.github/workflows/pull-request-conflict.yml
vendored
2
.github/workflows/pull-request-conflict.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
if: ${{ github.repository == 'jellyfin/jellyfin' }}
|
||||
steps:
|
||||
- name: Apply label
|
||||
uses: eps1lon/actions-label-merge-conflict@e62d7a53ff8be8b97684bffb6cfbbf3fc1115e2e # v3.0.0
|
||||
uses: eps1lon/actions-label-merge-conflict@1b1b1fcde06a9b3d089f3464c96417961dde1168 # v3.0.2
|
||||
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request_target'}}
|
||||
with:
|
||||
dirtyLabel: 'merge conflict'
|
||||
|
||||
4
.github/workflows/release-bump-version.yaml
vendored
4
.github/workflows/release-bump-version.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
yq-version: v4.9.8
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ env.TAG_BRANCH }}
|
||||
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
NEXT_VERSION: ${{ github.event.inputs.NEXT_VERSION }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ env.TAG_BRANCH }}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
- [joshuaboniface](https://github.com/joshuaboniface)
|
||||
- [JustAMan](https://github.com/JustAMan)
|
||||
- [justinfenn](https://github.com/justinfenn)
|
||||
- [JPVenson](https://github.com/JPVenson)
|
||||
- [KerryRJ](https://github.com/KerryRJ)
|
||||
- [Larvitar](https://github.com/Larvitar)
|
||||
- [LeoVerto](https://github.com/LeoVerto)
|
||||
@@ -183,6 +184,16 @@
|
||||
- [btopherjohnson](https://github.com/btopherjohnson)
|
||||
- [GeorgeH005](https://github.com/GeorgeH005)
|
||||
- [Vedant](https://github.com/viktory36/)
|
||||
- [NotSaifA](https://github.com/NotSaifA)
|
||||
- [HonestlyWhoKnows](https://github.com/honestlywhoknows)
|
||||
- [TheMelmacian](https://github.com/TheMelmacian)
|
||||
- [ItsAllAboutTheCode](https://github.com/ItsAllAboutTheCode)
|
||||
- [pret0rian8](https://github.com/pret0rian)
|
||||
- [jaina heartles](https://github.com/heartles)
|
||||
- [oxixes](https://github.com/oxixes)
|
||||
- [elfalem](https://github.com/elfalem)
|
||||
- [benedikt257](https://github.com/benedikt257)
|
||||
- [revam](https://github.com/revam)
|
||||
|
||||
# Emby Contributors
|
||||
|
||||
@@ -255,3 +266,4 @@
|
||||
- [JPUC1143](https://github.com/Jpuc1143/)
|
||||
- [0x25CBFC4F](https://github.com/0x25CBFC4F)
|
||||
- [Robert Lützner](https://github.com/rluetzner)
|
||||
- [Nathan McCrina](https://github.com/nfmccrina)
|
||||
|
||||
@@ -4,52 +4,50 @@
|
||||
</PropertyGroup>
|
||||
<!-- Run "dotnet list package (dash,dash)outdated" to see the latest versions of each package.-->
|
||||
<ItemGroup Label="Package Dependencies">
|
||||
<PackageVersion Include="AsyncKeyedLock" Version="6.4.2" />
|
||||
<PackageVersion Include="AsyncKeyedLock" Version="7.0.2" />
|
||||
<PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
|
||||
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
|
||||
<PackageVersion Include="AutoFixture" Version="4.18.1" />
|
||||
<PackageVersion Include="BDInfo" Version="0.8.0" />
|
||||
<PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.3.2" />
|
||||
<PackageVersion Include="BlurHashSharp" Version="1.3.2" />
|
||||
<PackageVersion Include="BlurHashSharp.SkiaSharp" Version="1.3.3" />
|
||||
<PackageVersion Include="BlurHashSharp" Version="1.3.3" />
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageVersion Include="Diacritics" Version="3.3.29" />
|
||||
<PackageVersion Include="DiscUtils.Udf" Version="0.16.13" />
|
||||
<PackageVersion Include="DotNet.Glob" Version="3.1.3" />
|
||||
<PackageVersion Include="EFCoreSecondLevelCacheInterceptor" Version="4.4.3" />
|
||||
<PackageVersion Include="FsCheck.Xunit" Version="2.16.6" />
|
||||
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.2" />
|
||||
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.3" />
|
||||
<PackageVersion Include="ICU4N.Transliterator" Version="60.1.0-alpha.356" />
|
||||
<PackageVersion Include="IDisposableAnalyzers" Version="4.0.7" />
|
||||
<PackageVersion Include="IDisposableAnalyzers" Version="4.0.8" />
|
||||
<PackageVersion Include="Jellyfin.XmlTv" Version="10.8.0" />
|
||||
<PackageVersion Include="libse" Version="4.0.5" />
|
||||
<PackageVersion Include="LrcParser" Version="2023.524.0" />
|
||||
<PackageVersion Include="libse" Version="4.0.8" />
|
||||
<PackageVersion Include="LrcParser" Version="2024.0728.2" />
|
||||
<PackageVersion Include="MetaBrainz.MusicBrainz" Version="6.1.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.HttpOverrides" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="8.0.4" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageVersion Include="MimeTypes" Version="2.4.0" />
|
||||
<PackageVersion Include="Mono.Nat" Version="3.0.4" />
|
||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||
@@ -57,36 +55,37 @@
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageVersion Include="PlaylistsNET" Version="1.4.1" />
|
||||
<PackageVersion Include="prometheus-net.AspNetCore" Version="8.2.1" />
|
||||
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.0" />
|
||||
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.1" />
|
||||
<PackageVersion Include="prometheus-net" Version="8.2.1" />
|
||||
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||
<PackageVersion Include="Serilog.Enrichers.Thread" Version="3.1.0" />
|
||||
<PackageVersion Include="Serilog.Settings.Configuration" Version="8.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.Async" Version="1.5.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageVersion Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
||||
<PackageVersion Include="Serilog.Settings.Configuration" Version="8.0.4" />
|
||||
<PackageVersion Include="Serilog.Sinks.Async" Version="2.1.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.Graylog" Version="3.1.1" />
|
||||
<PackageVersion Include="SerilogAnalyzer" Version="0.15.0" />
|
||||
<PackageVersion Include="SharpFuzz" Version="2.1.1" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.8" />
|
||||
<PackageVersion Include="SkiaSharp.HarfBuzz" Version="2.88.8" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageVersion Include="SkiaSharp.HarfBuzz" Version="2.88.9" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<PackageVersion Include="Svg.Skia" Version="1.0.0.18" />
|
||||
<PackageVersion Include="Svg.Skia" Version="2.0.0.1" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.5.0" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||
<PackageVersion Include="System.Globalization" Version="4.3.0" />
|
||||
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.3" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="8.0.1" />
|
||||
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="6.8.0" />
|
||||
<PackageVersion Include="TMDbLib" Version="2.2.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.8" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
|
||||
<PackageVersion Include="xunit" Version="2.7.1" />
|
||||
<PackageVersion Include="xunit" Version="2.9.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -36,7 +36,7 @@
|
||||
<PropertyGroup>
|
||||
<Authors>Jellyfin Contributors</Authors>
|
||||
<PackageId>Jellyfin.Naming</PackageId>
|
||||
<VersionPrefix>10.9.0</VersionPrefix>
|
||||
<VersionPrefix>10.10.3</VersionPrefix>
|
||||
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Emby.Naming.ExternalFiles
|
||||
pathInfo.Language = culture.ThreeLetterISOLanguageName;
|
||||
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else if (_namingOptions.MediaHearingImpairedFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))
|
||||
else if (_namingOptions.MediaHearingImpairedFlags.Any(s => currentSliceWithoutSeparator.Equals(s, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
pathInfo.IsHearingImpaired = true;
|
||||
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Emby.Naming.TV
|
||||
"stagione"
|
||||
};
|
||||
|
||||
private static readonly char[] _splitChars = ['.', '_', ' ', '-'];
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse season number from path.
|
||||
/// </summary>
|
||||
@@ -83,14 +85,9 @@ namespace Emby.Naming.TV
|
||||
}
|
||||
}
|
||||
|
||||
if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase))
|
||||
if (TryGetSeasonNumberFromPart(filename, out int seasonNumber))
|
||||
{
|
||||
var testFilename = filename.AsSpan().Slice(1);
|
||||
|
||||
if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
|
||||
{
|
||||
return (val, true);
|
||||
}
|
||||
return (seasonNumber, true);
|
||||
}
|
||||
|
||||
// Look for one of the season folder names
|
||||
@@ -108,10 +105,10 @@ namespace Emby.Naming.TV
|
||||
}
|
||||
}
|
||||
|
||||
var parts = filename.Split(new[] { '.', '_', ' ', '-' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var parts = filename.Split(_splitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (TryGetSeasonNumberFromPart(part, out int seasonNumber))
|
||||
if (TryGetSeasonNumberFromPart(part, out seasonNumber))
|
||||
{
|
||||
return (seasonNumber, true);
|
||||
}
|
||||
|
||||
44
Emby.Naming/TV/TvParserHelpers.cs
Normal file
44
Emby.Naming/TV/TvParserHelpers.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace Emby.Naming.TV;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for TV metadata parsing.
|
||||
/// </summary>
|
||||
public static class TvParserHelpers
|
||||
{
|
||||
private static readonly string[] _continuingState = ["Pilot", "Returning Series", "Returning"];
|
||||
private static readonly string[] _endedState = ["Cancelled", "Canceled"];
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse a string into <see cref="SeriesStatus"/>.
|
||||
/// </summary>
|
||||
/// <param name="status">The status string.</param>
|
||||
/// <param name="enumValue">The <see cref="SeriesStatus"/>.</param>
|
||||
/// <returns>Returns true if parsing was successful.</returns>
|
||||
public static bool TryParseSeriesStatus(string status, out SeriesStatus? enumValue)
|
||||
{
|
||||
if (Enum.TryParse(status, true, out SeriesStatus seriesStatus))
|
||||
{
|
||||
enumValue = seriesStatus;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_continuingState.Contains(status, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
enumValue = SeriesStatus.Continuing;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_endedState.Contains(status, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
enumValue = SeriesStatus.Ended;
|
||||
return true;
|
||||
}
|
||||
|
||||
enumValue = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Emby.Naming.Video;
|
||||
|
||||
@@ -141,7 +141,9 @@ namespace Emby.Naming.Video
|
||||
{
|
||||
if (group.Key)
|
||||
{
|
||||
videos.InsertRange(0, group.OrderByDescending(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||
videos.InsertRange(0, group
|
||||
.OrderByDescending(x => ResolutionRegex().Match(x.Files[0].FileNameWithoutExtension.ToString()).Value, new AlphanumericComparator())
|
||||
.ThenBy(x => x.Files[0].FileNameWithoutExtension.ToString(), new AlphanumericComparator()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ public class PhotoProvider : ICustomMetadataProvider<Photo>, IForcedProvider, IH
|
||||
private readonly ILogger<PhotoProvider> _logger;
|
||||
private readonly IImageProcessor _imageProcessor;
|
||||
|
||||
// These are causing taglib to hang
|
||||
// Other extensions might cause taglib to hang
|
||||
private readonly string[] _includeExtensions = [".jpg", ".jpeg", ".png", ".tiff", ".cr2", ".webp", ".avif"];
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -104,6 +104,6 @@ namespace Emby.Server.Implementations.AppBase
|
||||
/// Gets the folder path to the temp directory within the cache folder.
|
||||
/// </summary>
|
||||
/// <value>The temp directory.</value>
|
||||
public string TempDirectory => Path.Combine(CachePath, "temp");
|
||||
public string TempDirectory => Path.Join(Path.GetTempPath(), "jellyfin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ using Jellyfin.MediaEncoding.Hls.Playlist;
|
||||
using Jellyfin.Networking.Manager;
|
||||
using Jellyfin.Networking.Udp;
|
||||
using Jellyfin.Server.Implementations;
|
||||
using Jellyfin.Server.Implementations.MediaSegments;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Events;
|
||||
@@ -401,7 +402,12 @@ namespace Emby.Server.Implementations
|
||||
ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
|
||||
ConfigurationManager.NamedConfigurationUpdated += OnConfigurationUpdated;
|
||||
|
||||
Resolve<IMediaEncoder>().SetFFmpegPath();
|
||||
var ffmpegValid = Resolve<IMediaEncoder>().SetFFmpegPath();
|
||||
|
||||
if (!ffmpegValid)
|
||||
{
|
||||
throw new FfmpegException("Failed to find valid ffmpeg");
|
||||
}
|
||||
|
||||
Logger.LogInformation("ServerId: {ServerId}", SystemId);
|
||||
Logger.LogInformation("Core startup complete");
|
||||
@@ -422,7 +428,7 @@ namespace Emby.Server.Implementations
|
||||
// Initialize runtime stat collection
|
||||
if (ConfigurationManager.Configuration.EnableMetrics)
|
||||
{
|
||||
DotNetRuntimeStatsBuilder.Default().StartCollecting();
|
||||
_disposableParts.Add(DotNetRuntimeStatsBuilder.Default().StartCollecting());
|
||||
}
|
||||
|
||||
var networkConfiguration = ConfigurationManager.GetNetworkConfiguration();
|
||||
@@ -552,6 +558,8 @@ namespace Emby.Server.Implementations
|
||||
serviceCollection.AddScoped<DynamicHlsHelper>();
|
||||
serviceCollection.AddScoped<IClientEventLogger, ClientEventLogger>();
|
||||
serviceCollection.AddSingleton<IDirectoryService, DirectoryService>();
|
||||
|
||||
serviceCollection.AddSingleton<IMediaSegmentManager, MediaSegmentManager>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -635,6 +643,7 @@ namespace Emby.Server.Implementations
|
||||
UserView.TVSeriesManager = Resolve<ITVSeriesManager>();
|
||||
UserView.CollectionManager = Resolve<ICollectionManager>();
|
||||
BaseItem.MediaSourceManager = Resolve<IMediaSourceManager>();
|
||||
BaseItem.MediaSegmentManager = Resolve<IMediaSegmentManager>();
|
||||
CollectionFolder.XmlSerializer = _xmlSerializer;
|
||||
CollectionFolder.ApplicationHost = this;
|
||||
}
|
||||
@@ -664,7 +673,8 @@ namespace Emby.Server.Implementations
|
||||
GetExports<IMetadataService>(),
|
||||
GetExports<IMetadataProvider>(),
|
||||
GetExports<IMetadataSaver>(),
|
||||
GetExports<IExternalId>());
|
||||
GetExports<IExternalId>(),
|
||||
GetExports<IExternalUrlProvider>());
|
||||
|
||||
Resolve<IMediaSourceManager>().AddParts(GetExports<IMediaSourceProvider>());
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ namespace Emby.Server.Implementations
|
||||
{ DefaultRedirectKey, "web/" },
|
||||
{ FfmpegProbeSizeKey, "1G" },
|
||||
{ FfmpegAnalyzeDurationKey, "200M" },
|
||||
{ PlaylistsAllowDuplicatesKey, bool.FalseString },
|
||||
{ BindToUnixSocketKey, bool.FalseString },
|
||||
{ SqliteCacheSizeKey, "20000" }
|
||||
{ SqliteCacheSizeKey, "20000" },
|
||||
{ FfmpegSkipValidationKey, bool.FalseString },
|
||||
{ FfmpegImgExtractPerfTradeoffKey, bool.FalseString },
|
||||
{ DetectNetworkChangeKey, bool.TrueString }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Jellyfin.Extensions;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -13,6 +14,8 @@ namespace Emby.Server.Implementations.Data
|
||||
public abstract class BaseSqliteRepository : IDisposable
|
||||
{
|
||||
private bool _disposed = false;
|
||||
private SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
|
||||
private SqliteConnection _writeConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
|
||||
@@ -28,17 +31,6 @@ namespace Emby.Server.Implementations.Data
|
||||
/// </summary>
|
||||
protected string DbFilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of write connections to create.
|
||||
/// </summary>
|
||||
/// <value>Path to the DB file.</value>
|
||||
protected int WriteConnectionsCount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of read connections to create.
|
||||
/// </summary>
|
||||
protected int ReadConnectionsCount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// </summary>
|
||||
@@ -64,7 +56,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
/// <summary>
|
||||
/// Gets the journal size limit. <see href="https://www.sqlite.org/pragma.html#pragma_journal_size_limit" />.
|
||||
/// The default (-1) is overriden to prevent unconstrained WAL size, as reported by users.
|
||||
/// The default (-1) is overridden to prevent unconstrained WAL size, as reported by users.
|
||||
/// </summary>
|
||||
/// <value>The journal size limit.</value>
|
||||
protected virtual int? JournalSizeLimit => 134_217_728; // 128MiB
|
||||
@@ -98,9 +90,55 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
}
|
||||
|
||||
protected SqliteConnection GetConnection()
|
||||
protected ManagedConnection GetConnection(bool readOnly = false)
|
||||
{
|
||||
var connection = new SqliteConnection($"Filename={DbFilePath}");
|
||||
if (!readOnly)
|
||||
{
|
||||
_writeLock.Wait();
|
||||
if (_writeConnection is not null)
|
||||
{
|
||||
return new ManagedConnection(_writeConnection, _writeLock);
|
||||
}
|
||||
|
||||
var writeConnection = new SqliteConnection($"Filename={DbFilePath};Pooling=False");
|
||||
writeConnection.Open();
|
||||
|
||||
if (CacheSize.HasValue)
|
||||
{
|
||||
writeConnection.Execute("PRAGMA cache_size=" + CacheSize.Value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(LockingMode))
|
||||
{
|
||||
writeConnection.Execute("PRAGMA locking_mode=" + LockingMode);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(JournalMode))
|
||||
{
|
||||
writeConnection.Execute("PRAGMA journal_mode=" + JournalMode);
|
||||
}
|
||||
|
||||
if (JournalSizeLimit.HasValue)
|
||||
{
|
||||
writeConnection.Execute("PRAGMA journal_size_limit=" + JournalSizeLimit.Value);
|
||||
}
|
||||
|
||||
if (Synchronous.HasValue)
|
||||
{
|
||||
writeConnection.Execute("PRAGMA synchronous=" + (int)Synchronous.Value);
|
||||
}
|
||||
|
||||
if (PageSize.HasValue)
|
||||
{
|
||||
writeConnection.Execute("PRAGMA page_size=" + PageSize.Value);
|
||||
}
|
||||
|
||||
writeConnection.Execute("PRAGMA temp_store=" + (int)TempStore);
|
||||
|
||||
return new ManagedConnection(_writeConnection = writeConnection, _writeLock);
|
||||
}
|
||||
|
||||
var connection = new SqliteConnection($"Filename={DbFilePath};Mode=ReadOnly");
|
||||
connection.Open();
|
||||
|
||||
if (CacheSize.HasValue)
|
||||
@@ -135,17 +173,17 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
connection.Execute("PRAGMA temp_store=" + (int)TempStore);
|
||||
|
||||
return connection;
|
||||
return new ManagedConnection(connection, null);
|
||||
}
|
||||
|
||||
public SqliteCommand PrepareStatement(SqliteConnection connection, string sql)
|
||||
public SqliteCommand PrepareStatement(ManagedConnection connection, string sql)
|
||||
{
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = sql;
|
||||
return command;
|
||||
}
|
||||
|
||||
protected bool TableExists(SqliteConnection connection, string name)
|
||||
protected bool TableExists(ManagedConnection connection, string name)
|
||||
{
|
||||
using var statement = PrepareStatement(connection, "select DISTINCT tbl_name from sqlite_master");
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
@@ -159,7 +197,7 @@ namespace Emby.Server.Implementations.Data
|
||||
return false;
|
||||
}
|
||||
|
||||
protected List<string> GetColumnNames(SqliteConnection connection, string table)
|
||||
protected List<string> GetColumnNames(ManagedConnection connection, string table)
|
||||
{
|
||||
var columnNames = new List<string>();
|
||||
|
||||
@@ -174,7 +212,7 @@ namespace Emby.Server.Implementations.Data
|
||||
return columnNames;
|
||||
}
|
||||
|
||||
protected void AddColumn(SqliteConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
|
||||
protected void AddColumn(ManagedConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
|
||||
{
|
||||
if (existingColumnNames.Contains(columnName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -207,6 +245,24 @@ namespace Emby.Server.Implementations.Data
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispose)
|
||||
{
|
||||
_writeLock.Wait();
|
||||
try
|
||||
{
|
||||
_writeConnection.Dispose();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_writeLock.Release();
|
||||
}
|
||||
|
||||
_writeLock.Dispose();
|
||||
}
|
||||
|
||||
_writeConnection = null;
|
||||
_writeLock = null;
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
62
Emby.Server.Implementations/Data/ManagedConnection.cs
Normal file
62
Emby.Server.Implementations/Data/ManagedConnection.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace Emby.Server.Implementations.Data;
|
||||
|
||||
public sealed class ManagedConnection : IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim? _writeLock;
|
||||
|
||||
private SqliteConnection _db;
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
public ManagedConnection(SqliteConnection db, SemaphoreSlim? writeLock)
|
||||
{
|
||||
_db = db;
|
||||
_writeLock = writeLock;
|
||||
}
|
||||
|
||||
public SqliteTransaction BeginTransaction()
|
||||
=> _db.BeginTransaction();
|
||||
|
||||
public SqliteCommand CreateCommand()
|
||||
=> _db.CreateCommand();
|
||||
|
||||
public void Execute(string commandText)
|
||||
=> _db.Execute(commandText);
|
||||
|
||||
public SqliteCommand PrepareStatement(string sql)
|
||||
=> _db.PrepareStatement(sql);
|
||||
|
||||
public IEnumerable<SqliteDataReader> Query(string commandText)
|
||||
=> _db.Query(commandText);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_writeLock is null)
|
||||
{
|
||||
// Read connections are managed with an internal pool
|
||||
_db.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write lock is managed by BaseSqliteRepository
|
||||
// Don't dispose here
|
||||
_writeLock.Release();
|
||||
}
|
||||
|
||||
_db = null!;
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -183,7 +181,8 @@ namespace Emby.Server.Implementations.Data
|
||||
"ElPresentFlag",
|
||||
"BlPresentFlag",
|
||||
"DvBlSignalCompatibilityId",
|
||||
"IsHearingImpaired"
|
||||
"IsHearingImpaired",
|
||||
"Rotation"
|
||||
};
|
||||
|
||||
private static readonly string _mediaStreamSaveColumnsInsertQuery =
|
||||
@@ -327,7 +326,6 @@ namespace Emby.Server.Implementations.Data
|
||||
DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
|
||||
|
||||
CacheSize = configuration.GetSqliteCacheSize();
|
||||
ReadConnectionsCount = Environment.ProcessorCount * 2;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -344,7 +342,7 @@ namespace Emby.Server.Implementations.Data
|
||||
base.Initialize();
|
||||
|
||||
const string CreateMediaStreamsTableCommand
|
||||
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, DvVersionMajor INT NULL, DvVersionMinor INT NULL, DvProfile INT NULL, DvLevel INT NULL, RpuPresentFlag INT NULL, ElPresentFlag INT NULL, BlPresentFlag INT NULL, DvBlSignalCompatibilityId INT NULL, IsHearingImpaired BIT NULL, PRIMARY KEY (ItemId, StreamIndex))";
|
||||
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, DvVersionMajor INT NULL, DvVersionMinor INT NULL, DvProfile INT NULL, DvLevel INT NULL, RpuPresentFlag INT NULL, ElPresentFlag INT NULL, BlPresentFlag INT NULL, DvBlSignalCompatibilityId INT NULL, IsHearingImpaired BIT NULL, Rotation INT NULL, PRIMARY KEY (ItemId, StreamIndex))";
|
||||
|
||||
const string CreateMediaAttachmentsTableCommand
|
||||
= "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
|
||||
@@ -539,12 +537,15 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
AddColumn(connection, "MediaStreams", "IsHearingImpaired", "BIT", existingColumnNames);
|
||||
|
||||
AddColumn(connection, "MediaStreams", "Rotation", "INT", existingColumnNames);
|
||||
|
||||
connection.Execute(string.Join(';', postQueries));
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveImages(BaseItem item)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
@@ -601,7 +602,7 @@ namespace Emby.Server.Implementations.Data
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private void SaveItemsInTransaction(SqliteConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
||||
private void SaveItemsInTransaction(ManagedConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
||||
{
|
||||
using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText))
|
||||
using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId"))
|
||||
@@ -1047,9 +1048,10 @@ namespace Emby.Server.Implementations.Data
|
||||
foreach (var part in value.SpanSplit('|'))
|
||||
{
|
||||
var providerDelimiterIndex = part.IndexOf('=');
|
||||
if (providerDelimiterIndex != -1 && providerDelimiterIndex == part.LastIndexOf('='))
|
||||
// Don't let empty values through
|
||||
if (providerDelimiterIndex != -1 && part.Length != providerDelimiterIndex + 1)
|
||||
{
|
||||
item.SetProviderId(part.Slice(0, providerDelimiterIndex).ToString(), part.Slice(providerDelimiterIndex + 1).ToString());
|
||||
item.SetProviderId(part[..providerDelimiterIndex].ToString(), part[(providerDelimiterIndex + 1)..].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1261,7 +1263,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, _retrieveItemColumnsSelectQuery))
|
||||
{
|
||||
statement.TryBind("@guid", id);
|
||||
@@ -1298,16 +1300,15 @@ namespace Emby.Server.Implementations.Data
|
||||
&& type != typeof(Book)
|
||||
&& type != typeof(LiveTvProgram)
|
||||
&& type != typeof(AudioBook)
|
||||
&& type != typeof(Audio)
|
||||
&& type != typeof(MusicAlbum);
|
||||
}
|
||||
|
||||
private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query)
|
||||
{
|
||||
return GetItem(reader, query, HasProgramAttributes(query), HasEpisodeAttributes(query), HasServiceName(query), HasStartDate(query), HasTrailerTypes(query), HasArtistFields(query), HasSeriesFields(query));
|
||||
return GetItem(reader, query, HasProgramAttributes(query), HasEpisodeAttributes(query), HasServiceName(query), HasStartDate(query), HasTrailerTypes(query), HasArtistFields(query), HasSeriesFields(query), false);
|
||||
}
|
||||
|
||||
private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields)
|
||||
private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields, bool skipDeserialization)
|
||||
{
|
||||
var typeString = reader.GetString(0);
|
||||
|
||||
@@ -1320,7 +1321,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
BaseItem item = null;
|
||||
|
||||
if (TypeRequiresDeserialization(type))
|
||||
if (TypeRequiresDeserialization(type) && !skipDeserialization)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1888,7 +1889,7 @@ namespace Emby.Server.Implementations.Data
|
||||
CheckDisposed();
|
||||
|
||||
var chapters = new List<ChapterInfo>();
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"))
|
||||
{
|
||||
statement.TryBind("@ItemId", item.Id);
|
||||
@@ -1907,7 +1908,7 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"))
|
||||
{
|
||||
statement.TryBind("@ItemId", item.Id);
|
||||
@@ -1981,7 +1982,7 @@ namespace Emby.Server.Implementations.Data
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private void InsertChapters(Guid idBlob, IReadOnlyList<ChapterInfo> chapters, SqliteConnection db)
|
||||
private void InsertChapters(Guid idBlob, IReadOnlyList<ChapterInfo> chapters, ManagedConnection db)
|
||||
{
|
||||
var startIndex = 0;
|
||||
var limit = 100;
|
||||
@@ -2323,7 +2324,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
columns.Add(builder.ToString());
|
||||
|
||||
query.ExcludeItemIds = [..query.ExcludeItemIds, item.Id, ..item.ExtraIds];
|
||||
query.ExcludeItemIds = [.. query.ExcludeItemIds, item.Id, .. item.ExtraIds];
|
||||
query.ExcludeProviderIds = item.ProviderIds;
|
||||
}
|
||||
|
||||
@@ -2338,9 +2339,6 @@ namespace Emby.Server.Implementations.Data
|
||||
if (query.SearchTerm.Length > 1)
|
||||
{
|
||||
builder.Append("+ ((CleanName like @SearchTermContains or (OriginalTitle not null and OriginalTitle like @SearchTermContains)) * 10)");
|
||||
builder.Append("+ (SELECT COUNT(1) * 1 from ItemValues where ItemId=Guid and CleanValue like @SearchTermContains)");
|
||||
builder.Append("+ (SELECT COUNT(1) * 2 from ItemValues where ItemId=Guid and CleanValue like @SearchTermStartsWith)");
|
||||
builder.Append("+ (SELECT COUNT(1) * 10 from ItemValues where ItemId=Guid and CleanValue like @SearchTermEquals)");
|
||||
}
|
||||
|
||||
builder.Append(") as SearchScore");
|
||||
@@ -2371,11 +2369,6 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
statement.TryBind("@SearchTermContains", "%" + searchTerm + "%");
|
||||
}
|
||||
|
||||
if (commandText.Contains("@SearchTermEquals", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
statement.TryBind("@SearchTermEquals", searchTerm);
|
||||
}
|
||||
}
|
||||
|
||||
private void BindSimilarParams(InternalItemsQuery query, SqliteCommand statement)
|
||||
@@ -2441,6 +2434,7 @@ namespace Emby.Server.Implementations.Data
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int GetCount(InternalItemsQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -2470,7 +2464,7 @@ namespace Emby.Server.Implementations.Data
|
||||
var commandText = commandTextBuilder.ToString();
|
||||
|
||||
using (new QueryTimeLogger(Logger, commandText))
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText))
|
||||
{
|
||||
if (EnableJoinUserData(query))
|
||||
@@ -2488,6 +2482,7 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<BaseItem> GetItemList(InternalItemsQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -2538,7 +2533,7 @@ namespace Emby.Server.Implementations.Data
|
||||
var commandText = commandTextBuilder.ToString();
|
||||
var items = new List<BaseItem>();
|
||||
using (new QueryTimeLogger(Logger, commandText))
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText))
|
||||
{
|
||||
if (EnableJoinUserData(query))
|
||||
@@ -2562,7 +2557,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
{
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields);
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, query.SkipDeserialization);
|
||||
if (item is not null)
|
||||
{
|
||||
items.Add(item);
|
||||
@@ -2641,6 +2636,7 @@ namespace Emby.Server.Implementations.Data
|
||||
items.Add(newItem);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -2746,7 +2742,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
var list = new List<BaseItem>();
|
||||
var result = new QueryResult<BaseItem>();
|
||||
using var connection = GetConnection();
|
||||
using var connection = GetConnection(true);
|
||||
using var transaction = connection.BeginTransaction();
|
||||
if (!isReturningZeroItems)
|
||||
{
|
||||
@@ -2774,7 +2770,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
{
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields);
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, false);
|
||||
if (item is not null)
|
||||
{
|
||||
list.Add(item);
|
||||
@@ -2831,7 +2827,7 @@ namespace Emby.Server.Implementations.Data
|
||||
prepend.Add((ItemSortBy.Random, SortOrder.Ascending));
|
||||
}
|
||||
|
||||
orderBy = query.OrderBy = [..prepend, ..orderBy];
|
||||
orderBy = query.OrderBy = [.. prepend, .. orderBy];
|
||||
}
|
||||
else if (orderBy.Count == 0)
|
||||
{
|
||||
@@ -2885,6 +2881,7 @@ namespace Emby.Server.Implementations.Data
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<Guid> GetItemIdsList(InternalItemsQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -2928,7 +2925,7 @@ namespace Emby.Server.Implementations.Data
|
||||
var commandText = commandTextBuilder.ToString();
|
||||
var list = new List<Guid>();
|
||||
using (new QueryTimeLogger(Logger, commandText))
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText))
|
||||
{
|
||||
if (EnableJoinUserData(query))
|
||||
@@ -4201,6 +4198,15 @@ namespace Emby.Server.Implementations.Data
|
||||
OR (select CleanValue from ItemValues where ItemId=ParentId and Type=6 and CleanValue in ({includedTags})) is not null)
|
||||
""");
|
||||
}
|
||||
|
||||
// A playlist should be accessible to its owner regardless of allowed tags.
|
||||
else if (includeTypes.Length == 1 && includeTypes.FirstOrDefault() is BaseItemKind.Playlist)
|
||||
{
|
||||
whereClauses.Add($"""
|
||||
((select CleanValue from ItemValues where ItemId=Guid and Type=6 and CleanValue in ({includedTags})) is not null
|
||||
OR data like @PlaylistOwnerUserId)
|
||||
""");
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("((select CleanValue from ItemValues where ItemId=Guid and Type=6 and cleanvalue in (" + includedTags + ")) is not null)");
|
||||
@@ -4212,6 +4218,11 @@ namespace Emby.Server.Implementations.Data
|
||||
{
|
||||
statement.TryBind(paramName + index, GetCleanValue(query.IncludeInheritedTags[index]));
|
||||
}
|
||||
|
||||
if (query.User is not null)
|
||||
{
|
||||
statement.TryBind("@PlaylistOwnerUserId", $"""%"OwnerUserId":"{query.User.Id.ToString("N")}"%""");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4429,6 +4440,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|| query.IncludeItemTypes.Contains(BaseItemKind.Season);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void UpdateInheritedValues()
|
||||
{
|
||||
const string Statements = """
|
||||
@@ -4445,6 +4457,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DeleteItem(Guid id)
|
||||
{
|
||||
if (id.IsEmpty())
|
||||
@@ -4477,7 +4490,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private void ExecuteWithSingleParam(SqliteConnection db, string query, Guid value)
|
||||
private void ExecuteWithSingleParam(ManagedConnection db, string query, Guid value)
|
||||
{
|
||||
using (var statement = PrepareStatement(db, query))
|
||||
{
|
||||
@@ -4487,6 +4500,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<string> GetPeopleNames(InternalPeopleQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -4510,7 +4524,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
}
|
||||
|
||||
var list = new List<string>();
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText.ToString()))
|
||||
{
|
||||
// Run this again to bind the params
|
||||
@@ -4525,6 +4539,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<PersonInfo> GetPeople(InternalPeopleQuery query)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
@@ -4548,7 +4563,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
||||
}
|
||||
|
||||
var list = new List<PersonInfo>();
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText.ToString()))
|
||||
{
|
||||
// Run this again to bind the params
|
||||
@@ -4633,7 +4648,7 @@ AND Type = @InternalPersonType)");
|
||||
return whereClauses;
|
||||
}
|
||||
|
||||
private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, SqliteConnection db, SqliteCommand deleteAncestorsStatement)
|
||||
private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, ManagedConnection db, SqliteCommand deleteAncestorsStatement)
|
||||
{
|
||||
if (itemId.IsEmpty())
|
||||
{
|
||||
@@ -4684,46 +4699,55 @@ AND Type = @InternalPersonType)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query)
|
||||
{
|
||||
return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<string> GetStudioNames()
|
||||
{
|
||||
return GetItemValueNames(new[] { 3 }, Array.Empty<string>(), Array.Empty<string>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<string> GetAllArtistNames()
|
||||
{
|
||||
return GetItemValueNames(new[] { 0, 1 }, Array.Empty<string>(), Array.Empty<string>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<string> GetMusicGenreNames()
|
||||
{
|
||||
return GetItemValueNames(
|
||||
@@ -4738,6 +4762,7 @@ AND Type = @InternalPersonType)");
|
||||
Array.Empty<string>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<string> GetGenreNames()
|
||||
{
|
||||
return GetItemValueNames(
|
||||
@@ -4788,7 +4813,7 @@ AND Type = @InternalPersonType)");
|
||||
|
||||
var list = new List<string>();
|
||||
using (new QueryTimeLogger(Logger, commandText))
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, commandText))
|
||||
{
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
@@ -4988,8 +5013,8 @@ AND Type = @InternalPersonType)");
|
||||
var list = new List<(BaseItem, ItemCounts)>();
|
||||
var result = new QueryResult<(BaseItem, ItemCounts)>();
|
||||
using (new QueryTimeLogger(Logger, commandText))
|
||||
using (var connection = GetConnection())
|
||||
using (var transaction = connection.BeginTransaction(deferred: true))
|
||||
using (var connection = GetConnection(true))
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
{
|
||||
if (!isReturningZeroItems)
|
||||
{
|
||||
@@ -5021,7 +5046,7 @@ AND Type = @InternalPersonType)");
|
||||
|
||||
foreach (var row in statement.ExecuteQuery())
|
||||
{
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields);
|
||||
var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields, false);
|
||||
if (item is not null)
|
||||
{
|
||||
var countStartColumn = columns.Count - 1;
|
||||
@@ -5144,12 +5169,12 @@ AND Type = @InternalPersonType)");
|
||||
list.AddRange(inheritedTags.Select(i => (6, i)));
|
||||
|
||||
// Remove all invalid values.
|
||||
list.RemoveAll(i => string.IsNullOrEmpty(i.Item2));
|
||||
list.RemoveAll(i => string.IsNullOrWhiteSpace(i.Item2));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
||||
private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, ManagedConnection db)
|
||||
{
|
||||
if (itemId.IsEmpty())
|
||||
{
|
||||
@@ -5168,7 +5193,7 @@ AND Type = @InternalPersonType)");
|
||||
InsertItemValues(itemId, values, db);
|
||||
}
|
||||
|
||||
private void InsertItemValues(Guid id, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
||||
private void InsertItemValues(Guid id, List<(int MagicNumber, string Value)> values, ManagedConnection db)
|
||||
{
|
||||
const int Limit = 100;
|
||||
var startIndex = 0;
|
||||
@@ -5202,12 +5227,6 @@ AND Type = @InternalPersonType)");
|
||||
|
||||
var itemValue = currentValueInfo.Value;
|
||||
|
||||
// Don't save if invalid
|
||||
if (string.IsNullOrWhiteSpace(itemValue))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
statement.TryBind("@Type" + index, currentValueInfo.MagicNumber);
|
||||
statement.TryBind("@Value" + index, itemValue);
|
||||
statement.TryBind("@CleanValue" + index, GetCleanValue(itemValue));
|
||||
@@ -5221,6 +5240,7 @@ AND Type = @InternalPersonType)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void UpdatePeople(Guid itemId, List<PersonInfo> people)
|
||||
{
|
||||
if (itemId.IsEmpty())
|
||||
@@ -5228,24 +5248,25 @@ AND Type = @InternalPersonType)");
|
||||
throw new ArgumentNullException(nameof(itemId));
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(people);
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
using var connection = GetConnection();
|
||||
using var transaction = connection.BeginTransaction();
|
||||
// First delete chapters
|
||||
// Delete all existing people first
|
||||
using var command = connection.CreateCommand();
|
||||
command.CommandText = "delete from People where ItemId=@ItemId";
|
||||
command.TryBind("@ItemId", itemId);
|
||||
command.ExecuteNonQuery();
|
||||
|
||||
InsertPeople(itemId, people, connection);
|
||||
if (people is not null)
|
||||
{
|
||||
InsertPeople(itemId, people, connection);
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private void InsertPeople(Guid id, List<PersonInfo> people, SqliteConnection db)
|
||||
private void InsertPeople(Guid id, List<PersonInfo> people, ManagedConnection db)
|
||||
{
|
||||
const int Limit = 100;
|
||||
var startIndex = 0;
|
||||
@@ -5321,6 +5342,7 @@ AND Type = @InternalPersonType)");
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<MediaStream> GetMediaStreams(MediaStreamQuery query)
|
||||
{
|
||||
CheckDisposed();
|
||||
@@ -5341,7 +5363,7 @@ AND Type = @InternalPersonType)");
|
||||
|
||||
cmdText += " order by StreamIndex ASC";
|
||||
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
{
|
||||
var list = new List<MediaStream>();
|
||||
|
||||
@@ -5369,6 +5391,7 @@ AND Type = @InternalPersonType)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
@@ -5394,7 +5417,7 @@ AND Type = @InternalPersonType)");
|
||||
transaction.Commit();
|
||||
}
|
||||
|
||||
private void InsertMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, SqliteConnection db)
|
||||
private void InsertMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, ManagedConnection db)
|
||||
{
|
||||
const int Limit = 10;
|
||||
var startIndex = 0;
|
||||
@@ -5489,6 +5512,8 @@ AND Type = @InternalPersonType)");
|
||||
statement.TryBind("@DvBlSignalCompatibilityId" + index, stream.DvBlSignalCompatibilityId);
|
||||
|
||||
statement.TryBind("@IsHearingImpaired" + index, stream.IsHearingImpaired);
|
||||
|
||||
statement.TryBind("@Rotation" + index, stream.Rotation);
|
||||
}
|
||||
|
||||
statement.ExecuteNonQuery();
|
||||
@@ -5700,18 +5725,28 @@ AND Type = @InternalPersonType)");
|
||||
|
||||
item.IsHearingImpaired = reader.TryGetBoolean(43, out var result) && result;
|
||||
|
||||
if (item.Type == MediaStreamType.Subtitle)
|
||||
if (reader.TryGetInt32(44, out var rotation))
|
||||
{
|
||||
item.Rotation = rotation;
|
||||
}
|
||||
|
||||
if (item.Type is MediaStreamType.Audio or MediaStreamType.Subtitle)
|
||||
{
|
||||
item.LocalizedUndefined = _localization.GetLocalizedString("Undefined");
|
||||
item.LocalizedDefault = _localization.GetLocalizedString("Default");
|
||||
item.LocalizedForced = _localization.GetLocalizedString("Forced");
|
||||
item.LocalizedExternal = _localization.GetLocalizedString("External");
|
||||
item.LocalizedHearingImpaired = _localization.GetLocalizedString("HearingImpaired");
|
||||
|
||||
if (item.Type is MediaStreamType.Subtitle)
|
||||
{
|
||||
item.LocalizedUndefined = _localization.GetLocalizedString("Undefined");
|
||||
item.LocalizedForced = _localization.GetLocalizedString("Forced");
|
||||
item.LocalizedHearingImpaired = _localization.GetLocalizedString("HearingImpaired");
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
|
||||
{
|
||||
CheckDisposed();
|
||||
@@ -5728,7 +5763,7 @@ AND Type = @InternalPersonType)");
|
||||
cmdText += " order by AttachmentIndex ASC";
|
||||
|
||||
var list = new List<MediaAttachment>();
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
using (var statement = PrepareStatement(connection, cmdText))
|
||||
{
|
||||
statement.TryBind("@ItemId", query.ItemId);
|
||||
@@ -5747,6 +5782,7 @@ AND Type = @InternalPersonType)");
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveMediaAttachments(
|
||||
Guid id,
|
||||
IReadOnlyList<MediaAttachment> attachments,
|
||||
@@ -5778,7 +5814,7 @@ AND Type = @InternalPersonType)");
|
||||
private void InsertMediaAttachments(
|
||||
Guid id,
|
||||
IReadOnlyList<MediaAttachment> attachments,
|
||||
SqliteConnection db,
|
||||
ManagedConnection db,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
const int InsertAtOnce = 10;
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
}
|
||||
|
||||
private void ImportUserIds(SqliteConnection db, IEnumerable<User> users)
|
||||
private void ImportUserIds(ManagedConnection db, IEnumerable<User> users)
|
||||
{
|
||||
var userIdsWithUserData = GetAllUserIdsWithUserData(db);
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
}
|
||||
|
||||
private List<Guid> GetAllUserIdsWithUserData(SqliteConnection db)
|
||||
private List<Guid> GetAllUserIdsWithUserData(ManagedConnection db)
|
||||
{
|
||||
var list = new List<Guid>();
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.Data
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveUserData(SqliteConnection db, long internalUserId, string key, UserItemData userData)
|
||||
private static void SaveUserData(ManagedConnection db, long internalUserId, string key, UserItemData userData)
|
||||
{
|
||||
using (var statement = db.PrepareStatement("replace into UserDatas (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"))
|
||||
{
|
||||
@@ -267,7 +267,7 @@ namespace Emby.Server.Implementations.Data
|
||||
|
||||
ArgumentException.ThrowIfNullOrEmpty(key);
|
||||
|
||||
using (var connection = GetConnection())
|
||||
using (var connection = GetConnection(true))
|
||||
{
|
||||
using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from UserDatas where key =@Key and userId=@UserId"))
|
||||
{
|
||||
@@ -333,10 +333,10 @@ namespace Emby.Server.Implementations.Data
|
||||
/// <returns>The user item data.</returns>
|
||||
private UserItemData ReadRow(SqliteDataReader reader)
|
||||
{
|
||||
var userData = new UserItemData();
|
||||
|
||||
userData.Key = reader[0].ToString();
|
||||
// userData.UserId = reader[1].ReadGuidFromBlob();
|
||||
var userData = new UserItemData
|
||||
{
|
||||
Key = reader.GetString(0)
|
||||
};
|
||||
|
||||
if (reader.TryGetDouble(2, out var rating))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
@@ -83,12 +81,12 @@ namespace Emby.Server.Implementations.Dto
|
||||
private ILiveTvManager LivetvManager => _livetvManagerFactory.Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
|
||||
public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var accessibleItems = user is null ? items : items.Where(x => x.IsVisible(user)).ToList();
|
||||
var returnItems = new BaseItemDto[accessibleItems.Count];
|
||||
List<(BaseItem, BaseItemDto)> programTuples = null;
|
||||
List<(BaseItemDto, LiveTvChannel)> channelTuples = null;
|
||||
List<(BaseItem, BaseItemDto)>? programTuples = null;
|
||||
List<(BaseItemDto, LiveTvChannel)>? channelTuples = null;
|
||||
|
||||
for (int index = 0; index < accessibleItems.Count; index++)
|
||||
{
|
||||
@@ -137,7 +135,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return returnItems;
|
||||
}
|
||||
|
||||
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
|
||||
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var dto = GetBaseItemDtoInternal(item, options, user, owner);
|
||||
if (item is LiveTvChannel tvChannel)
|
||||
@@ -167,7 +165,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return dto;
|
||||
}
|
||||
|
||||
private static IList<BaseItem> GetTaggedItems(IItemByName byName, User user, DtoOptions options)
|
||||
private static IList<BaseItem> GetTaggedItems(IItemByName byName, User? user, DtoOptions options)
|
||||
{
|
||||
return byName.GetTaggedItems(
|
||||
new InternalItemsQuery(user)
|
||||
@@ -177,7 +175,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
});
|
||||
}
|
||||
|
||||
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
|
||||
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null)
|
||||
{
|
||||
var dto = new BaseItemDto
|
||||
{
|
||||
@@ -292,7 +290,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
|
||||
var path = mediaSource.Path;
|
||||
string fileExtensionContainer = null;
|
||||
string? fileExtensionContainer = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
@@ -316,7 +314,8 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null)
|
||||
/// <inheritdoc />
|
||||
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem>? taggedItems, User? user = null)
|
||||
{
|
||||
var dto = GetBaseItemDtoInternal(item, options, user);
|
||||
|
||||
@@ -486,10 +485,10 @@ namespace Emby.Server.Implementations.Dto
|
||||
return images
|
||||
.Select(p => GetImageCacheTag(item, p))
|
||||
.Where(i => i is not null)
|
||||
.ToArray();
|
||||
.ToArray()!; // null values got filtered out
|
||||
}
|
||||
|
||||
private string GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
||||
private string? GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -508,7 +507,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
/// <param name="dto">The dto.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="user">The requesting user.</param>
|
||||
private void AttachPeople(BaseItemDto dto, BaseItem item, User user = null)
|
||||
private void AttachPeople(BaseItemDto dto, BaseItem item, User? user = null)
|
||||
{
|
||||
// Ordering by person type to ensure actors and artists are at the front.
|
||||
// This is taking advantage of the fact that they both begin with A
|
||||
@@ -552,7 +551,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
|
||||
var list = new List<BaseItemPerson>();
|
||||
|
||||
var dictionary = people.Select(p => p.Name)
|
||||
Dictionary<string, Person> dictionary = people.Select(p => p.Name)
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase).Select(c =>
|
||||
{
|
||||
try
|
||||
@@ -565,9 +564,9 @@ namespace Emby.Server.Implementations.Dto
|
||||
return null;
|
||||
}
|
||||
}).Where(i => i is not null)
|
||||
.Where(i => user is null || i.IsVisible(user))
|
||||
.DistinctBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
||||
.Where(i => user is null || i!.IsVisible(user))
|
||||
.DistinctBy(x => x!.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.ToDictionary(i => i!.Name, StringComparer.OrdinalIgnoreCase)!; // null values got filtered out
|
||||
|
||||
for (var i = 0; i < people.Count; i++)
|
||||
{
|
||||
@@ -580,7 +579,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
Type = person.Type
|
||||
};
|
||||
|
||||
if (dictionary.TryGetValue(person.Name, out Person entity))
|
||||
if (dictionary.TryGetValue(person.Name, out Person? entity))
|
||||
{
|
||||
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
|
||||
baseItemPerson.Id = entity.Id;
|
||||
@@ -650,7 +649,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return _libraryManager.GetGenreId(name);
|
||||
}
|
||||
|
||||
private string GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ImageType imageType, int imageIndex = 0)
|
||||
private string? GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ImageType imageType, int imageIndex = 0)
|
||||
{
|
||||
var image = item.GetImageInfo(imageType, imageIndex);
|
||||
if (image is not null)
|
||||
@@ -661,9 +660,14 @@ namespace Emby.Server.Implementations.Dto
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ItemImageInfo image)
|
||||
private string? GetTagAndFillBlurhash(BaseItemDto dto, BaseItem item, ItemImageInfo image)
|
||||
{
|
||||
var tag = GetImageCacheTag(item, image);
|
||||
if (tag is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(image.BlurHash))
|
||||
{
|
||||
dto.ImageBlurHashes ??= new Dictionary<ImageType, Dictionary<string, string>>();
|
||||
@@ -716,7 +720,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, DtoOptions options)
|
||||
private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options)
|
||||
{
|
||||
if (options.ContainsField(ItemFields.DateCreated))
|
||||
{
|
||||
@@ -1097,7 +1101,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
BaseItem[] allExtras = null;
|
||||
BaseItem[]? allExtras = null;
|
||||
|
||||
if (options.ContainsField(ItemFields.SpecialFeatureCount))
|
||||
{
|
||||
@@ -1134,7 +1138,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
dto.SeasonId = episode.SeasonId;
|
||||
dto.SeriesId = episode.SeriesId;
|
||||
|
||||
Series episodeSeries = null;
|
||||
Series? episodeSeries = null;
|
||||
|
||||
// this block will add the series poster for episodes without a poster
|
||||
// TODO maybe remove the if statement entirely
|
||||
@@ -1162,8 +1166,10 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
|
||||
// Add SeriesInfo
|
||||
if (item is Series series)
|
||||
Series? series;
|
||||
if (item is Series tmp)
|
||||
{
|
||||
series = tmp;
|
||||
dto.AirDays = series.AirDays;
|
||||
dto.AirTime = series.AirTime;
|
||||
dto.Status = series.Status?.ToString();
|
||||
@@ -1264,7 +1270,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
private BaseItem GetImageDisplayParent(BaseItem currentItem, BaseItem originalItem)
|
||||
private BaseItem? GetImageDisplayParent(BaseItem currentItem, BaseItem originalItem)
|
||||
{
|
||||
if (currentItem is MusicAlbum musicAlbum)
|
||||
{
|
||||
@@ -1285,7 +1291,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return parent;
|
||||
}
|
||||
|
||||
private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
|
||||
private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem? owner)
|
||||
{
|
||||
if (!item.SupportsInheritedParentImages)
|
||||
{
|
||||
@@ -1305,7 +1311,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
return;
|
||||
}
|
||||
|
||||
BaseItem parent = null;
|
||||
BaseItem? parent = null;
|
||||
var isFirst = true;
|
||||
|
||||
var imageTags = dto.ImageTags;
|
||||
@@ -1378,7 +1384,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
private string GetMappedPath(BaseItem item, BaseItem ownerItem)
|
||||
private string GetMappedPath(BaseItem item, BaseItem? ownerItem)
|
||||
{
|
||||
var path = item.Path;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -134,17 +133,18 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
|
||||
private UserDataChangeInfo GetUserDataChangeInfo(Guid userId, List<BaseItem> changedItems)
|
||||
{
|
||||
var user = _userManager.GetUserById(userId);
|
||||
var user = _userManager.GetUserById(userId)
|
||||
?? throw new ArgumentException("Invalid user ID", nameof(userId));
|
||||
|
||||
return new UserDataChangeInfo
|
||||
{
|
||||
UserId = userId.ToString("N", CultureInfo.InvariantCulture),
|
||||
UserId = userId,
|
||||
UserDataList = changedItems
|
||||
.DistinctBy(x => x.Id)
|
||||
.Select(i =>
|
||||
{
|
||||
var dto = _userDataManager.GetUserDataDto(i, user);
|
||||
dto.ItemId = i.Id.ToString("N", CultureInfo.InvariantCulture);
|
||||
dto.ItemId = i.Id;
|
||||
return dto;
|
||||
})
|
||||
.ToArray()
|
||||
|
||||
@@ -314,6 +314,12 @@ namespace Emby.Server.Implementations.IO
|
||||
var ex = e.GetException();
|
||||
var dw = (FileSystemWatcher)sender;
|
||||
|
||||
if (ex is UnauthorizedAccessException unauthorizedAccessException)
|
||||
{
|
||||
_logger.LogError(unauthorizedAccessException, "Permission error for Directory watcher: {Path}", dw.Path);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path);
|
||||
|
||||
DisposeWatcher(dw, true);
|
||||
|
||||
@@ -80,12 +80,14 @@ namespace Emby.Server.Implementations.IO
|
||||
public virtual string MakeAbsolutePath(string folderPath, string filePath)
|
||||
{
|
||||
// path is actually a stream
|
||||
if (string.IsNullOrWhiteSpace(filePath) || filePath.Contains("://", StringComparison.Ordinal))
|
||||
if (string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
return filePath;
|
||||
}
|
||||
|
||||
if (filePath.Length > 3 && filePath[1] == ':' && filePath[2] == '/')
|
||||
var isAbsolutePath = Path.IsPathRooted(filePath) && (!OperatingSystem.IsWindows() || filePath[0] != '\\');
|
||||
|
||||
if (isAbsolutePath)
|
||||
{
|
||||
// absolute local path
|
||||
return filePath;
|
||||
@@ -97,17 +99,10 @@ namespace Emby.Server.Implementations.IO
|
||||
return filePath;
|
||||
}
|
||||
|
||||
var firstChar = filePath[0];
|
||||
if (firstChar == '/')
|
||||
{
|
||||
// for this we don't really know
|
||||
return filePath;
|
||||
}
|
||||
|
||||
var filePathSpan = filePath.AsSpan();
|
||||
|
||||
// relative path
|
||||
if (firstChar == '\\')
|
||||
// relative path on windows
|
||||
if (filePath[0] == '\\')
|
||||
{
|
||||
filePathSpan = filePathSpan.Slice(1);
|
||||
}
|
||||
@@ -154,6 +149,26 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void MoveDirectory(string source, string destination)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Move(source, destination);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// Cross device move requires a copy
|
||||
Directory.CreateDirectory(destination);
|
||||
foreach (string file in Directory.GetFiles(source))
|
||||
{
|
||||
File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), true);
|
||||
}
|
||||
|
||||
Directory.Delete(source, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path.
|
||||
/// </summary>
|
||||
@@ -332,11 +347,7 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation time UTC.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime GetCreationTimeUtc(string path)
|
||||
{
|
||||
return GetCreationTimeUtc(GetFileSystemInfo(path));
|
||||
@@ -373,11 +384,7 @@ namespace Emby.Server.Implementations.IO
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last write time UTC.
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>DateTime.</returns>
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime GetLastWriteTimeUtc(string path)
|
||||
{
|
||||
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
|
||||
@@ -394,7 +401,7 @@ namespace Emby.Server.Implementations.IO
|
||||
var info = new FileInfo(path);
|
||||
|
||||
if (info.Exists &&
|
||||
((info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) != isHidden)
|
||||
(info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden != isHidden)
|
||||
{
|
||||
if (isHidden)
|
||||
{
|
||||
@@ -422,8 +429,8 @@ namespace Emby.Server.Implementations.IO
|
||||
return;
|
||||
}
|
||||
|
||||
if (((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) == readOnly
|
||||
&& ((info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) == isHidden)
|
||||
if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly == readOnly
|
||||
&& (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden == isHidden)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -451,11 +458,7 @@ namespace Emby.Server.Implementations.IO
|
||||
File.SetAttributes(path, attributes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swaps the files.
|
||||
/// </summary>
|
||||
/// <param name="file1">The file1.</param>
|
||||
/// <param name="file2">The file2.</param>
|
||||
/// <inheritdoc />
|
||||
public virtual void SwapFiles(string file1, string file2)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(file1);
|
||||
@@ -471,7 +474,7 @@ namespace Emby.Server.Implementations.IO
|
||||
File.Copy(file1, temp1, true);
|
||||
|
||||
File.Copy(file2, file1, true);
|
||||
File.Copy(temp1, file2, true);
|
||||
File.Move(temp1, file2, true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -11,7 +11,6 @@ using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace Emby.Server.Implementations.Images
|
||||
{
|
||||
@@ -33,12 +32,12 @@ namespace Emby.Server.Implementations.Images
|
||||
Parent = item,
|
||||
Recursive = true,
|
||||
DtoOptions = new DtoOptions(true),
|
||||
ImageTypes = new ImageType[] { ImageType.Primary },
|
||||
OrderBy = new (ItemSortBy, SortOrder)[]
|
||||
{
|
||||
ImageTypes = [ImageType.Primary],
|
||||
OrderBy =
|
||||
[
|
||||
(ItemSortBy.IsFolder, SortOrder.Ascending),
|
||||
(ItemSortBy.SortName, SortOrder.Ascending)
|
||||
},
|
||||
],
|
||||
Limit = 1
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
@@ -15,5 +18,13 @@ namespace Emby.Server.Implementations.Images
|
||||
: base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<BaseItem> GetItemsWithImages(BaseItem item)
|
||||
{
|
||||
var items = base.GetItemsWithImages(item);
|
||||
|
||||
// Ignore any folders because they can have generated collages
|
||||
return items.Where(i => i is not Folder).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ namespace Emby.Server.Implementations.Library
|
||||
"**/lost+found/**",
|
||||
"**/lost+found",
|
||||
|
||||
// Trickplay files
|
||||
"**/*.trickplay",
|
||||
"**/*.trickplay/**",
|
||||
|
||||
// WMC temp recording directories that will constantly be written to
|
||||
"**/TempRec/**",
|
||||
"**/TempRec",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable CA5394
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -16,6 +17,7 @@ using Emby.Server.Implementations.Library.Resolvers;
|
||||
using Emby.Server.Implementations.Library.Validators;
|
||||
using Emby.Server.Implementations.Playlists;
|
||||
using Emby.Server.Implementations.ScheduledTasks.Tasks;
|
||||
using Emby.Server.Implementations.Sorting;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using Jellyfin.Extensions;
|
||||
@@ -667,7 +669,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (parent is not null)
|
||||
{
|
||||
var multiItemResolvers = resolvers is null ? MultiItemResolvers : resolvers.OfType<IMultiItemResolver>().ToArray();
|
||||
var multiItemResolvers = resolvers is null ? MultiItemResolvers : resolvers.OfType<IMultiItemResolver>();
|
||||
|
||||
foreach (var resolver in multiItemResolvers)
|
||||
{
|
||||
@@ -1029,7 +1031,7 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ValidateTopLibraryFolders(CancellationToken cancellationToken, bool removeRoot = false)
|
||||
public async Task ValidateTopLibraryFolders(CancellationToken cancellationToken, bool removeRoot = false)
|
||||
{
|
||||
await RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -1528,7 +1530,7 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
var userViews = UserViewManager.GetUserViews(new UserViewQuery
|
||||
{
|
||||
UserId = user.Id,
|
||||
User = user,
|
||||
IncludeHidden = true,
|
||||
IncludeExternalContent = allowExternalContent
|
||||
});
|
||||
@@ -1710,13 +1712,19 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User? user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder)
|
||||
{
|
||||
var isFirst = true;
|
||||
|
||||
IOrderedEnumerable<BaseItem>? orderedItems = null;
|
||||
|
||||
foreach (var orderBy in sortBy.Select(o => GetComparer(o, user)).Where(c => c is not null))
|
||||
{
|
||||
if (isFirst)
|
||||
if (orderBy is RandomComparer)
|
||||
{
|
||||
var randomItems = items.ToArray();
|
||||
Random.Shared.Shuffle(randomItems);
|
||||
items = randomItems;
|
||||
// Items are no longer ordered at this point, so set orderedItems back to null
|
||||
orderedItems = null;
|
||||
}
|
||||
else if (orderedItems is null)
|
||||
{
|
||||
orderedItems = sortOrder == SortOrder.Descending
|
||||
? items.OrderByDescending(i => i, orderBy)
|
||||
@@ -1728,8 +1736,6 @@ namespace Emby.Server.Implementations.Library
|
||||
? orderedItems!.ThenByDescending(i => i, orderBy)
|
||||
: orderedItems!.ThenBy(i => i, orderBy); // orderedItems is set during the first iteration
|
||||
}
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
return orderedItems ?? items;
|
||||
@@ -1738,8 +1744,6 @@ namespace Emby.Server.Implementations.Library
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User? user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy)
|
||||
{
|
||||
var isFirst = true;
|
||||
|
||||
IOrderedEnumerable<BaseItem>? orderedItems = null;
|
||||
|
||||
foreach (var (name, sortOrder) in orderBy)
|
||||
@@ -1750,7 +1754,15 @@ namespace Emby.Server.Implementations.Library
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isFirst)
|
||||
if (comparer is RandomComparer)
|
||||
{
|
||||
var randomItems = items.ToArray();
|
||||
Random.Shared.Shuffle(randomItems);
|
||||
items = randomItems;
|
||||
// Items are no longer ordered at this point, so set orderedItems back to null
|
||||
orderedItems = null;
|
||||
}
|
||||
else if (orderedItems is null)
|
||||
{
|
||||
orderedItems = sortOrder == SortOrder.Descending
|
||||
? items.OrderByDescending(i => i, comparer)
|
||||
@@ -1762,8 +1774,6 @@ namespace Emby.Server.Implementations.Library
|
||||
? orderedItems!.ThenByDescending(i => i, comparer)
|
||||
: orderedItems!.ThenBy(i => i, comparer); // orderedItems is set during the first iteration
|
||||
}
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
return orderedItems ?? items;
|
||||
@@ -1884,7 +1894,7 @@ namespace Emby.Server.Implementations.Library
|
||||
try
|
||||
{
|
||||
var index = item.GetImageIndex(img);
|
||||
image = await ConvertImageToLocal(item, img, index, removeOnFailure: true).ConfigureAwait(false);
|
||||
image = await ConvertImageToLocal(item, img, index, true).ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
@@ -2715,33 +2725,9 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem)
|
||||
{
|
||||
string? newPath;
|
||||
if (ownerItem is not null)
|
||||
{
|
||||
var libraryOptions = GetLibraryOptions(ownerItem);
|
||||
if (libraryOptions is not null)
|
||||
{
|
||||
foreach (var pathInfo in libraryOptions.PathInfos)
|
||||
{
|
||||
if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out newPath))
|
||||
{
|
||||
return newPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var metadataPath = _configurationManager.Configuration.MetadataPath;
|
||||
var metadataNetworkPath = _configurationManager.Configuration.MetadataNetworkPath;
|
||||
|
||||
if (path.TryReplaceSubPath(metadataPath, metadataNetworkPath, out newPath))
|
||||
{
|
||||
return newPath;
|
||||
}
|
||||
|
||||
foreach (var map in _configurationManager.Configuration.PathSubstitutions)
|
||||
{
|
||||
if (path.TryReplaceSubPath(map.From, map.To, out newPath))
|
||||
if (path.TryReplaceSubPath(map.From, map.To, out var newPath))
|
||||
{
|
||||
return newPath;
|
||||
}
|
||||
@@ -2812,8 +2798,10 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
|
||||
_itemRepository.UpdatePeople(item.Id, people);
|
||||
|
||||
await SavePeopleMetadataAsync(people, cancellationToken).ConfigureAwait(false);
|
||||
if (people is not null)
|
||||
{
|
||||
await SavePeopleMetadataAsync(people, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ItemImageInfo> ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex, bool removeOnFailure)
|
||||
@@ -3058,15 +3046,6 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions);
|
||||
|
||||
foreach (var originalPathInfo in libraryOptions.PathInfos)
|
||||
{
|
||||
if (string.Equals(mediaPath.Path, originalPathInfo.Path, StringComparison.Ordinal))
|
||||
{
|
||||
originalPathInfo.NetworkPath = mediaPath.NetworkPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace Emby.Server.Implementations.Library
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stream.IsPgsSubtitleStream)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -374,7 +379,8 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
|
||||
{
|
||||
if (userData.SubtitleStreamIndex.HasValue
|
||||
if (userData is not null
|
||||
&& userData.SubtitleStreamIndex.HasValue
|
||||
&& user.RememberSubtitleSelections
|
||||
&& user.SubtitleMode != SubtitlePlaybackMode.None
|
||||
&& allowRememberingSelection)
|
||||
@@ -406,7 +412,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
|
||||
{
|
||||
if (userData.AudioStreamIndex.HasValue && user.RememberAudioSelections && allowRememberingSelection)
|
||||
if (userData is not null && userData.AudioStreamIndex.HasValue && user.RememberAudioSelections && allowRememberingSelection)
|
||||
{
|
||||
var index = userData.AudioStreamIndex.Value;
|
||||
// Make sure the saved index is still valid
|
||||
@@ -429,7 +435,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
if (mediaType == MediaType.Video)
|
||||
{
|
||||
var userData = item is null ? new UserItemData() : _userDataManager.GetUserData(user, item);
|
||||
var userData = item is null ? null : _userDataManager.GetUserData(user, item);
|
||||
|
||||
var allowRememberingSelection = item is null || item.EnableRememberingTrackSelections;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Library
|
||||
item.GetParents().Any(i => i.IsLocked);
|
||||
|
||||
// Make sure DateCreated and DateModified have values
|
||||
var fileInfo = directoryService.GetFile(item.Path);
|
||||
var fileInfo = directoryService.GetFileSystemEntry(item.Path);
|
||||
if (fileInfo is null)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Emby.Naming.Audio;
|
||||
using Emby.Naming.Common;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
@@ -85,6 +86,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
|
||||
var albumResolver = new MusicAlbumResolver(_logger, _namingOptions, _directoryService);
|
||||
var albumParser = new AlbumParser(_namingOptions);
|
||||
|
||||
var directories = args.FileSystemChildren.Where(i => i.IsDirectory);
|
||||
|
||||
@@ -100,6 +102,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
}
|
||||
|
||||
// If the folder is a multi-disc folder, then it is not an artist folder
|
||||
if (albumParser.IsMultiPart(fileSystemInfo.FullName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we contain a music album assume we are an artist folder
|
||||
if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, _directoryService))
|
||||
{
|
||||
|
||||
@@ -68,11 +68,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
var justName = Path.GetFileName(item.Path.AsSpan());
|
||||
|
||||
var id = justName.GetAttributeValue("tmdbid");
|
||||
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Tmdb, id);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Tmdb, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,22 +373,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
// Check for TMDb id
|
||||
var tmdbid = justName.GetAttributeValue("tmdbid");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tmdbid))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Tmdb, tmdbid);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Tmdb, tmdbid);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(item.Path))
|
||||
{
|
||||
// Check for IMDb id - we use full media path, as we can assume that this will match in any use case (whether id in parent dir or in file name)
|
||||
var imdbid = item.Path.AsSpan().GetAttributeValue("imdbid");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(imdbid))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Imdb, imdbid);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Imdb, imdbid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
||||
{
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
// It's a boxset if the path is a directory with [playlist] in its name
|
||||
// It's a playlist if the path is a directory with [playlist] in its name
|
||||
var filename = Path.GetFileName(Path.TrimEndingDirectorySeparator(args.Path));
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
{
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
IndexNumber = seasonParserResult.SeasonNumber,
|
||||
SeriesId = series.Id,
|
||||
SeriesName = series.Name
|
||||
SeriesName = series.Name,
|
||||
Path = seasonParserResult.IsSeasonFolder ? path : null
|
||||
};
|
||||
|
||||
if (!season.IndexNumber.HasValue || !seasonParserResult.IsSeasonFolder)
|
||||
@@ -78,27 +79,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
}
|
||||
}
|
||||
|
||||
if (season.IndexNumber.HasValue)
|
||||
if (season.IndexNumber.HasValue && string.IsNullOrEmpty(season.Name))
|
||||
{
|
||||
var seasonNumber = season.IndexNumber.Value;
|
||||
if (string.IsNullOrEmpty(season.Name))
|
||||
{
|
||||
var seasonNames = series.SeasonNames;
|
||||
if (seasonNames.TryGetValue(seasonNumber, out var seasonName))
|
||||
{
|
||||
season.Name = seasonName;
|
||||
}
|
||||
else
|
||||
{
|
||||
season.Name = seasonNumber == 0 ?
|
||||
args.LibraryOptions.SeasonZeroDisplayName :
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
_localization.GetLocalizedString("NameSeasonNumber"),
|
||||
seasonNumber,
|
||||
args.LibraryOptions.PreferredMetadataLanguage);
|
||||
}
|
||||
}
|
||||
season.Name = seasonNumber == 0 ?
|
||||
args.LibraryOptions.SeasonZeroDisplayName :
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
_localization.GetLocalizedString("NameSeasonNumber"),
|
||||
seasonNumber,
|
||||
args.LibraryOptions.PreferredMetadataLanguage);
|
||||
}
|
||||
|
||||
return season;
|
||||
|
||||
@@ -186,46 +186,25 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
||||
var justName = Path.GetFileName(path.AsSpan());
|
||||
|
||||
var imdbId = justName.GetAttributeValue("imdbid");
|
||||
if (!string.IsNullOrEmpty(imdbId))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Imdb, imdbId);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Imdb, imdbId);
|
||||
|
||||
var tvdbId = justName.GetAttributeValue("tvdbid");
|
||||
if (!string.IsNullOrEmpty(tvdbId))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Tvdb, tvdbId);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Tvdb, tvdbId);
|
||||
|
||||
var tvmazeId = justName.GetAttributeValue("tvmazeid");
|
||||
if (!string.IsNullOrEmpty(tvmazeId))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.TvMaze, tvmazeId);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.TvMaze, tvmazeId);
|
||||
|
||||
var tmdbId = justName.GetAttributeValue("tmdbid");
|
||||
if (!string.IsNullOrEmpty(tmdbId))
|
||||
{
|
||||
item.SetProviderId(MetadataProvider.Tmdb, tmdbId);
|
||||
}
|
||||
item.TrySetProviderId(MetadataProvider.Tmdb, tmdbId);
|
||||
|
||||
var anidbId = justName.GetAttributeValue("anidbid");
|
||||
if (!string.IsNullOrEmpty(anidbId))
|
||||
{
|
||||
item.SetProviderId("AniDB", anidbId);
|
||||
}
|
||||
item.TrySetProviderId("AniDB", anidbId);
|
||||
|
||||
var aniListId = justName.GetAttributeValue("anilistid");
|
||||
if (!string.IsNullOrEmpty(aniListId))
|
||||
{
|
||||
item.SetProviderId("AniList", aniListId);
|
||||
}
|
||||
item.TrySetProviderId("AniList", aniListId);
|
||||
|
||||
var aniSearchId = justName.GetAttributeValue("anisearchid");
|
||||
if (!string.IsNullOrEmpty(aniSearchId))
|
||||
{
|
||||
item.SetProviderId("AniSearch", aniSearchId);
|
||||
}
|
||||
item.TrySetProviderId("AniSearch", aniSearchId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Jellyfin.Data.Entities;
|
||||
@@ -32,6 +29,12 @@ namespace Emby.Server.Implementations.Library
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IUserDataRepository _repository;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDataManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||
/// <param name="repository">Instance of the <see cref="IUserDataRepository"/> interface.</param>
|
||||
public UserDataManager(
|
||||
IServerConfigurationManager config,
|
||||
IUserManager userManager,
|
||||
@@ -42,15 +45,10 @@ namespace Emby.Server.Implementations.Library
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public event EventHandler<UserDataSaveEventArgs> UserDataSaved;
|
||||
|
||||
public void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = _userManager.GetUserById(userId);
|
||||
|
||||
SaveUserData(user, item, userData, reason, cancellationToken);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<UserDataSaveEventArgs>? UserDataSaved;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(userData);
|
||||
@@ -81,6 +79,7 @@ namespace Emby.Server.Implementations.Library
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveUserData(User user, BaseItem item, UpdateUserItemDataDto userDataDto, UserDataSaveReason reason)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
@@ -128,39 +127,7 @@ namespace Emby.Server.Implementations.Library
|
||||
SaveUserData(user, item, userData, reason, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the provided user data for the given user. Batch operation. Does not fire any events or update the cache.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="userData">The user item data.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = _userManager.GetUserById(userId);
|
||||
|
||||
_repository.SaveAllUserData(user.InternalId, userData, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all user data for the given user.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <returns>A <see cref="List{UserItemData}"/> containing all of the user's item data.</returns>
|
||||
public List<UserItemData> GetAllUserData(Guid userId)
|
||||
{
|
||||
var user = _userManager.GetUserById(userId);
|
||||
|
||||
return _repository.GetAllUserData(user.InternalId);
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys)
|
||||
{
|
||||
var user = _userManager.GetUserById(userId);
|
||||
|
||||
return GetUserData(user, itemId, keys);
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(User user, Guid itemId, List<string> keys)
|
||||
private UserItemData GetUserData(User user, Guid itemId, List<string> keys)
|
||||
{
|
||||
var userId = user.InternalId;
|
||||
|
||||
@@ -186,7 +153,7 @@ namespace Emby.Server.Implementations.Library
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new UnreachableException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -198,27 +165,18 @@ namespace Emby.Server.Implementations.Library
|
||||
return internalUserId.ToString(CultureInfo.InvariantCulture) + "-" + itemId.ToString("N", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public UserItemData GetUserData(User user, BaseItem item)
|
||||
{
|
||||
return GetUserData(user, item.Id, item.GetUserDataKeys());
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(Guid userId, BaseItem item)
|
||||
{
|
||||
return GetUserData(userId, item.Id, item.GetUserDataKeys());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public UserItemDataDto GetUserDataDto(BaseItem item, User user)
|
||||
{
|
||||
var userData = GetUserData(user, item);
|
||||
var dto = GetUserItemDataDto(userData);
|
||||
|
||||
item.FillUserDataDtoValues(dto, userData, null, user, new DtoOptions());
|
||||
return dto;
|
||||
}
|
||||
=> GetUserDataDto(item, null, user, new DtoOptions());
|
||||
|
||||
/// <inheritdoc />
|
||||
public UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions options)
|
||||
public UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto? itemDto, User user, DtoOptions options)
|
||||
{
|
||||
var userData = GetUserData(user, item);
|
||||
var dto = GetUserItemDataDto(userData);
|
||||
|
||||
@@ -16,7 +16,6 @@ using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.Library;
|
||||
using MediaBrowser.Model.Querying;
|
||||
@@ -27,17 +26,15 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly IChannelManager _channelManager;
|
||||
private readonly ILiveTvManager _liveTvManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IServerConfigurationManager config)
|
||||
public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IServerConfigurationManager config)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_localizationManager = localizationManager;
|
||||
_userManager = userManager;
|
||||
_channelManager = channelManager;
|
||||
_liveTvManager = liveTvManager;
|
||||
_config = config;
|
||||
@@ -45,11 +42,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public Folder[] GetUserViews(UserViewQuery query)
|
||||
{
|
||||
var user = _userManager.GetUserById(query.UserId);
|
||||
if (user is null)
|
||||
{
|
||||
throw new ArgumentException("User id specified in the query does not exist.", nameof(query));
|
||||
}
|
||||
var user = query.User;
|
||||
|
||||
var folders = _libraryManager.GetUserRootFolder()
|
||||
.GetChildren(user, true)
|
||||
@@ -125,14 +118,14 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
var channelResult = _channelManager.GetChannelsInternalAsync(new ChannelQuery
|
||||
{
|
||||
UserId = query.UserId
|
||||
UserId = user.Id
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
var channels = channelResult.Items;
|
||||
|
||||
list.AddRange(channels);
|
||||
|
||||
if (_liveTvManager.GetEnabledUsers().Select(i => i.Id).Contains(query.UserId))
|
||||
if (_liveTvManager.GetEnabledUsers().Select(i => i.Id).Contains(user.Id))
|
||||
{
|
||||
list.Add(_liveTvManager.GetInternalLiveTvFolder(CancellationToken.None));
|
||||
}
|
||||
@@ -207,9 +200,7 @@ namespace Emby.Server.Implementations.Library
|
||||
|
||||
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request, DtoOptions options)
|
||||
{
|
||||
var user = _userManager.GetUserById(request.UserId);
|
||||
|
||||
var libraryItems = GetItemsForLatestItems(user, request, options);
|
||||
var libraryItems = GetItemsForLatestItems(request.User, request, options);
|
||||
|
||||
var list = new List<Tuple<BaseItem, List<BaseItem>>>();
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
{}
|
||||
{
|
||||
"Albums": "аальбомқәа"
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
"Favorites": "Gunstelinge",
|
||||
"HeaderFavoriteShows": "Gunsteling Vertonings",
|
||||
"ValueSpecialEpisodeName": "Spesiale - {0}",
|
||||
"HeaderAlbumArtists": "Kunstenaars se Album",
|
||||
"HeaderAlbumArtists": "Album kunstenaars",
|
||||
"Books": "Boeke",
|
||||
"HeaderNextUp": "Volgende",
|
||||
"Movies": "Flieks",
|
||||
"Shows": "Televisie Reekse",
|
||||
"HeaderContinueWatching": "Kyk Verder",
|
||||
"HeaderContinueWatching": "Hou aan kyk",
|
||||
"HeaderFavoriteEpisodes": "Gunsteling Episodes",
|
||||
"Photos": "Foto's",
|
||||
"Playlists": "Snitlyste",
|
||||
@@ -19,7 +19,7 @@
|
||||
"Sync": "Sinkroniseer",
|
||||
"HeaderFavoriteSongs": "Gunsteling Liedjies",
|
||||
"Songs": "Liedjies",
|
||||
"DeviceOnlineWithName": "{0} is gekoppel",
|
||||
"DeviceOnlineWithName": "{0} is aanlyn",
|
||||
"DeviceOfflineWithName": "{0} is ontkoppel",
|
||||
"Collections": "Versamelings",
|
||||
"Inherit": "Ontvang",
|
||||
@@ -61,7 +61,7 @@
|
||||
"NotificationOptionPluginInstalled": "Inprop module geïnstalleer",
|
||||
"NotificationOptionPluginError": "Inprop module het misluk",
|
||||
"NotificationOptionNewLibraryContent": "Nuwe inhoud bygevoeg",
|
||||
"NotificationOptionInstallationFailed": "Installering het misluk",
|
||||
"NotificationOptionInstallationFailed": "Installasie mislukking",
|
||||
"NotificationOptionCameraImageUploaded": "Kamera foto is opgelaai",
|
||||
"NotificationOptionAudioPlaybackStopped": "Oudio terugspeel het gestop",
|
||||
"NotificationOptionAudioPlayback": "Oudio terugspeel het begin",
|
||||
@@ -86,9 +86,9 @@
|
||||
"HomeVideos": "Tuis Videos",
|
||||
"HeaderRecordingGroups": "Groep Opnames",
|
||||
"Genres": "Genres",
|
||||
"FailedLoginAttemptWithUserName": "Mislukte aansluiting van {0}",
|
||||
"FailedLoginAttemptWithUserName": "Mislukte aanmeldpoging van {0}",
|
||||
"ChapterNameValue": "Hoofstuk {0}",
|
||||
"CameraImageUploadedFrom": "'n Nuwe kamera photo opgelaai van {0}",
|
||||
"CameraImageUploadedFrom": "'n Nuwe kamera foto is opgelaai vanaf {0}",
|
||||
"AuthenticationSucceededWithUserName": "{0} suksesvol geverifieer",
|
||||
"Albums": "Albums",
|
||||
"TasksChannelsCategory": "Internet kanale",
|
||||
@@ -114,8 +114,8 @@
|
||||
"TaskRefreshChapterImagesDescription": "Maak kleinkiekeis (fotos) vir films wat hoofstukke het.",
|
||||
"TaskRefreshChapterImages": "Verkry Hoofstuk Beelde",
|
||||
"Undefined": "Ongedefineerd",
|
||||
"Forced": "Geforseer",
|
||||
"Default": "Oorspronklik",
|
||||
"Forced": "Geforseerd",
|
||||
"Default": "Standaard",
|
||||
"TaskCleanActivityLogDescription": "Verwyder aktiwiteitsaantekeninge ouer as die opgestelde ouderdom.",
|
||||
"TaskCleanActivityLog": "Maak Aktiwiteitsaantekeninge Skoon",
|
||||
"TaskOptimizeDatabaseDescription": "Komprimeer databasis en verkort vrye ruimte. As hierdie taak uitgevoer word nadat die media versameling geskandeer is of ander veranderings aangebring is wat databasisaanpassings impliseer, kan dit die prestasie verbeter.",
|
||||
@@ -125,5 +125,9 @@
|
||||
"External": "Ekstern",
|
||||
"HearingImpaired": "gehoorgestremd",
|
||||
"TaskRefreshTrickplayImages": "Genereer Fopspeel Beelde",
|
||||
"TaskRefreshTrickplayImagesDescription": "Skep fopspeel voorskou vir videos in aangeskakelde media versameling."
|
||||
"TaskRefreshTrickplayImagesDescription": "Skep fopspeel voorskou vir videos in aangeskakelde media versameling.",
|
||||
"TaskAudioNormalizationDescription": "Skandeer lêers vir oudio-normaliseringsdata.",
|
||||
"TaskAudioNormalization": "Odio Normalisering",
|
||||
"TaskCleanCollectionsAndPlaylists": "Maak versamelings en snitlyste skoon",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Verwyder items uit versamelings en snitlyste wat nie meer bestaan nie."
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"Albums": "البومات",
|
||||
"Albums": "ألبومات",
|
||||
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
|
||||
"Application": "تطبيق",
|
||||
"Artists": "الفنانين",
|
||||
"Artists": "الفنانون",
|
||||
"AuthenticationSucceededWithUserName": "نجحت عملية التوثيق بـ {0}",
|
||||
"Books": "الكتب",
|
||||
"CameraImageUploadedFrom": "رُفعت صورة الكاميرا الجديدة من {0}",
|
||||
"Channels": "القنوات",
|
||||
"ChapterNameValue": "الفصل {0}",
|
||||
"Collections": "التجميعات",
|
||||
"Collections": "المجموعات",
|
||||
"DeviceOfflineWithName": "قُطِع الاتصال ب{0}",
|
||||
"DeviceOnlineWithName": "{0} متصل",
|
||||
"FailedLoginAttemptWithUserName": "محاولة تسجيل الدخول فشلت من {0}",
|
||||
"FailedLoginAttemptWithUserName": "محاولة تسجيل الدخول فاشلة من {0}",
|
||||
"Favorites": "المفضلة",
|
||||
"Folders": "المجلدات",
|
||||
"Genres": "التصنيفات",
|
||||
@@ -130,5 +130,6 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "حذف المجموعات وقوائم التشغيل",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "حذف عناصر من المجموعات وقوائم التشغيل التي لم تعد موجودة.",
|
||||
"TaskAudioNormalization": "تطبيع الصوت",
|
||||
"TaskAudioNormalizationDescription": "مسح الملفات لتطبيع بيانات الصوت."
|
||||
"TaskAudioNormalizationDescription": "مسح الملفات لتطبيع بيانات الصوت.",
|
||||
"TaskDownloadMissingLyrics": "تنزيل عبارات القصيدة"
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"UserDownloadingItemWithValues": "{0} спампоўваецца {1}",
|
||||
"TaskOptimizeDatabase": "Аптымізаваць базу дадзеных",
|
||||
"Artists": "Выканаўцы",
|
||||
"UserOfflineFromDevice": "{0} адключыўся ад {1}",
|
||||
"UserOfflineFromDevice": "{0} адлучыўся ад {1}",
|
||||
"UserPolicyUpdatedWithName": "Палітыка карыстальніка абноўлена для {0}",
|
||||
"TaskCleanActivityLogDescription": "Выдаляе старэйшыя за зададзены ўзрост запісы ў журнале актыўнасці.",
|
||||
"TaskRefreshChapterImagesDescription": "Стварае мініяцюры для відэа, якія маюць раздзелы.",
|
||||
@@ -66,7 +66,7 @@
|
||||
"AppDeviceValues": "Прыкладанне: {0}, Прылада: {1}",
|
||||
"Books": "Кнігі",
|
||||
"CameraImageUploadedFrom": "Новая выява камеры была загружана з {0}",
|
||||
"DeviceOfflineWithName": "{0} адключыўся",
|
||||
"DeviceOfflineWithName": "{0} адлучыўся",
|
||||
"DeviceOnlineWithName": "{0} падлучаны",
|
||||
"Forced": "Прымусова",
|
||||
"HeaderRecordingGroups": "Групы запісаў",
|
||||
@@ -127,5 +127,13 @@
|
||||
"TaskRefreshTrickplayImages": "Стварыце выявы Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Стварае прагляд відэаролікаў для Trickplay у падключаных бібліятэках.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ачысціце калекцыі і спісы прайгравання",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Выдаляе элементы з калекцый і спісаў прайгравання, якія больш не існуюць."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Выдаляе элементы з калекцый і спісаў прайгравання, якія больш не існуюць.",
|
||||
"TaskAudioNormalizationDescription": "Сканіруе файлы на прадмет нармалізацыі гуку.",
|
||||
"TaskAudioNormalization": "Нармалізацыя гуку",
|
||||
"TaskExtractMediaSegmentsDescription": "Выдае або атрымлівае медыясегменты з убудоў з падтрымкай MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Перамяшчае існуючыя файлы trickplay у адпаведнасці з наладамі бібліятэкі.",
|
||||
"TaskDownloadMissingLyrics": "Спампаваць зніклыя тэксты песень",
|
||||
"TaskDownloadMissingLyricsDescription": "Спампоўвае тэксты для песень",
|
||||
"TaskExtractMediaSegments": "Сканіраванне медыя-сегмента",
|
||||
"TaskMoveTrickplayImages": "Перанесці месцазнаходжанне выявы Trickplay"
|
||||
}
|
||||
|
||||
@@ -126,5 +126,11 @@
|
||||
"External": "Външен",
|
||||
"HearingImpaired": "Увреден слух",
|
||||
"TaskRefreshTrickplayImages": "Генерирай изображение",
|
||||
"TaskRefreshTrickplayImagesDescription": "Създава прегледи на Trickplay за видеа в активирани библиотеки."
|
||||
"TaskRefreshTrickplayImagesDescription": "Създава прегледи на Trickplay за видеа в активирани библиотеки.",
|
||||
"TaskDownloadMissingLyrics": "Свали липсващи текстове",
|
||||
"TaskDownloadMissingLyricsDescription": "Свали текстове за песни",
|
||||
"TaskCleanCollectionsAndPlaylists": "Изчисти колекциите и плейлистовете",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Премахни несъществуващи файлове в колекциите и плейлистите.",
|
||||
"TaskAudioNormalization": "Нормализиране на звука",
|
||||
"TaskAudioNormalizationDescription": "Сканирай файловете за нормализация на звука."
|
||||
}
|
||||
|
||||
@@ -130,5 +130,7 @@
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Esborra elements de col·leccions i llistes de reproducció que ja no existeixen.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Neteja col·leccions i llistes de reproducció",
|
||||
"TaskAudioNormalization": "Normalització d'Àudio",
|
||||
"TaskAudioNormalizationDescription": "Escaneja arxius per dades de normalització d'àudio."
|
||||
"TaskAudioNormalizationDescription": "Escaneja arxius per dades de normalització d'àudio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Baixar lletres de les cançons",
|
||||
"TaskDownloadMissingLyrics": "Baixar lletres que falten"
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"HeaderFavoriteEpisodes": "Oblíbené epizody",
|
||||
"HeaderFavoriteShows": "Oblíbené seriály",
|
||||
"HeaderFavoriteSongs": "Oblíbená hudba",
|
||||
"HeaderLiveTV": "Živý přenos",
|
||||
"HeaderLiveTV": "TV vysílání",
|
||||
"HeaderNextUp": "Další díly",
|
||||
"HeaderRecordingGroups": "Skupiny nahrávek",
|
||||
"HomeVideos": "Domácí videa",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Pročistit kolekce a seznamy přehrávání",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Odstraní neexistující položky z kolekcí a seznamů přehrávání.",
|
||||
"TaskAudioNormalization": "Normalizace zvuku",
|
||||
"TaskAudioNormalizationDescription": "Skenovat soubory za účelem normalizace zvuku."
|
||||
"TaskAudioNormalizationDescription": "Skenovat soubory za účelem normalizace zvuku.",
|
||||
"TaskDownloadMissingLyrics": "Stáhnout chybějící texty k písni",
|
||||
"TaskDownloadMissingLyricsDescription": "Stáhne texty k písni",
|
||||
"TaskExtractMediaSegments": "Skenování segmentů médií",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrahuje či získá segmenty médií pomocí zásuvných modulů MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Přesunout úložiště obrázků Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Přesune existující soubory Trickplay podle nastavení knihovny."
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"Genres": "Genrer",
|
||||
"HeaderAlbumArtists": "Albumkunstnere",
|
||||
"HeaderContinueWatching": "Fortsæt afspilning",
|
||||
"HeaderFavoriteAlbums": "Favoritalbummer",
|
||||
"HeaderFavoriteAlbums": "Favoritalbum",
|
||||
"HeaderFavoriteArtists": "Favoritkunstnere",
|
||||
"HeaderFavoriteEpisodes": "Yndlingsafsnit",
|
||||
"HeaderFavoriteShows": "Yndlingsserier",
|
||||
@@ -87,21 +87,21 @@
|
||||
"UserOnlineFromDevice": "{0} er online fra {1}",
|
||||
"UserPasswordChangedWithName": "Adgangskode er ændret for brugeren {0}",
|
||||
"UserPolicyUpdatedWithName": "Brugerpolitikken er blevet opdateret for {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}",
|
||||
"UserStartedPlayingItemWithValues": "{0} afspiller {1} på {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek",
|
||||
"ValueSpecialEpisodeName": "Special - {0}",
|
||||
"VersionNumber": "Version {0}",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Søger på internettet efter manglende undertekster baseret på metadata-konfigurationen.",
|
||||
"TaskDownloadMissingSubtitles": "Hent manglende undertekster",
|
||||
"TaskUpdatePluginsDescription": "Henter og installerer opdateringer for plugins, som er indstillet til at blive opdateret automatisk.",
|
||||
"TaskDownloadMissingSubtitles": "Hentede medie mangler undertekster",
|
||||
"TaskUpdatePluginsDescription": "Henter og installerer opdateringer for plugins, som er konfigurerede til at blive opdateret automatisk.",
|
||||
"TaskUpdatePlugins": "Opdater Plugins",
|
||||
"TaskCleanLogsDescription": "Sletter log-filer som er mere end {0} dage gamle.",
|
||||
"TaskCleanLogs": "Ryd Log-mappe",
|
||||
"TaskRefreshLibraryDescription": "Scanner dit mediebibliotek for nye filer og opdateret metadata.",
|
||||
"TaskRefreshLibrary": "Scan Mediebibliotek",
|
||||
"TaskCleanCacheDescription": "Sletter cache-filer som systemet ikke længere bruger.",
|
||||
"TaskCleanCache": "Ryd Cache-mappe",
|
||||
"TaskCleanCache": "Ryd cache-mappe",
|
||||
"TasksChannelsCategory": "Internetkanaler",
|
||||
"TasksApplicationCategory": "Applikation",
|
||||
"TasksLibraryCategory": "Bibliotek",
|
||||
@@ -128,5 +128,13 @@
|
||||
"TaskRefreshTrickplayImages": "Generér Trickplay Billeder",
|
||||
"TaskRefreshTrickplayImagesDescription": "Laver trickplay forhåndsvisninger for videoer i aktiverede biblioteker.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ryd op i samlinger og afspilningslister",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner enheder fra samlinger og afspilningslister der ikke eksisterer længere."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra samlinger og afspilningslister der ikke eksisterer længere.",
|
||||
"TaskAudioNormalizationDescription": "Skanner filer for data vedrørende audio-normalisering.",
|
||||
"TaskAudioNormalization": "Audio-normalisering",
|
||||
"TaskDownloadMissingLyricsDescription": "Hentede sange mangler sangtekster",
|
||||
"TaskDownloadMissingLyrics": "Hentede medie mangler sangtekster",
|
||||
"TaskExtractMediaSegments": "Scan mediesegment",
|
||||
"TaskMoveTrickplayImages": "Migrer billedelokation for Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Flyt eksisterende trickplay-filer jævnfør biblioteksindstillilnger.",
|
||||
"TaskExtractMediaSegmentsDescription": "Ekstraherer eller henter mediesegmenter fra plugins som understøtter MediaSegment."
|
||||
}
|
||||
|
||||
@@ -126,9 +126,15 @@
|
||||
"External": "Extern",
|
||||
"HearingImpaired": "Hörgeschädigt",
|
||||
"TaskRefreshTrickplayImages": "Trickplay-Bilder generieren",
|
||||
"TaskRefreshTrickplayImagesDescription": "Erstellt eine Trickplay-Vorschau für Videos in aktivierten Bibliotheken.",
|
||||
"TaskRefreshTrickplayImagesDescription": "Erstellt ein Trickplay-Vorschauen für Videos in aktivierten Bibliotheken.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Sammlungen und Playlisten aufräumen",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Lösche nicht mehr vorhandene Einträge aus den Sammlungen und Playlisten.",
|
||||
"TaskAudioNormalization": "Audio Normalisierung",
|
||||
"TaskAudioNormalizationDescription": "Durchsucht Dateien nach Audionormalisierungsdaten."
|
||||
"TaskAudioNormalizationDescription": "Durchsucht Dateien nach Audionormalisierungsdaten.",
|
||||
"TaskDownloadMissingLyricsDescription": "Lädt Songtexte herunter",
|
||||
"TaskDownloadMissingLyrics": "Fehlende Songtexte herunterladen",
|
||||
"TaskExtractMediaSegments": "Scanne Mediensegmente",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrahiert oder empfängt Mediensegmente von Plugins die Mediensegmente nutzen.",
|
||||
"TaskMoveTrickplayImages": "Verzeichnis für Trickplay-Bilder migrieren",
|
||||
"TaskMoveTrickplayImagesDescription": "Trickplay-Bilder werden entsprechend der Bibliothekseinstellungen verschoben."
|
||||
}
|
||||
|
||||
@@ -126,5 +126,9 @@
|
||||
"External": "Εξωτερικό",
|
||||
"HearingImpaired": "Με προβλήματα ακοής",
|
||||
"TaskRefreshTrickplayImages": "Δημιουργήστε εικόνες Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Δημιουργεί προεπισκοπήσεις trickplay για βίντεο σε ενεργοποιημένες βιβλιοθήκες."
|
||||
"TaskRefreshTrickplayImagesDescription": "Δημιουργεί προεπισκοπήσεις trickplay για βίντεο σε ενεργοποιημένες βιβλιοθήκες.",
|
||||
"TaskAudioNormalization": "Ομοιομορφία ήχου",
|
||||
"TaskAudioNormalizationDescription": "Ανίχνευση αρχείων για δεδομένα ομοιομορφίας ήχου.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Καθαρισμός συλλογών και λιστών αναπαραγωγής",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Αφαιρούνται στοιχεία από τις συλλογές και τις λίστες αναπαραγωγής που δεν υπάρχουν πλέον."
|
||||
}
|
||||
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Clean up collections and playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist.",
|
||||
"TaskAudioNormalization": "Audio Normalisation",
|
||||
"TaskAudioNormalizationDescription": "Scans files for audio normalisation data."
|
||||
"TaskAudioNormalizationDescription": "Scans files for audio normalisation data.",
|
||||
"TaskDownloadMissingLyrics": "Download missing lyrics",
|
||||
"TaskDownloadMissingLyricsDescription": "Downloads lyrics for songs",
|
||||
"TaskExtractMediaSegments": "Media Segment Scan",
|
||||
"TaskExtractMediaSegmentsDescription": "Extracts or obtains media segments from MediaSegment enabled plugins.",
|
||||
"TaskMoveTrickplayImages": "Migrate Trickplay Image Location",
|
||||
"TaskMoveTrickplayImagesDescription": "Moves existing trickplay files according to the library settings."
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"DeviceOfflineWithName": "{0} has disconnected",
|
||||
"DeviceOnlineWithName": "{0} is connected",
|
||||
"External": "External",
|
||||
"FailedLoginAttemptWithUserName": "Failed login try from {0}",
|
||||
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
|
||||
"Favorites": "Favorites",
|
||||
"Folders": "Folders",
|
||||
"Forced": "Forced",
|
||||
@@ -122,6 +122,8 @@
|
||||
"TaskCleanTranscodeDescription": "Deletes transcode files more than one day old.",
|
||||
"TaskRefreshChannels": "Refresh Channels",
|
||||
"TaskRefreshChannelsDescription": "Refreshes internet channel information.",
|
||||
"TaskDownloadMissingLyrics": "Download missing lyrics",
|
||||
"TaskDownloadMissingLyricsDescription": "Downloads lyrics for songs",
|
||||
"TaskDownloadMissingSubtitles": "Download missing subtitles",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Searches the internet for missing subtitles based on metadata configuration.",
|
||||
"TaskOptimizeDatabase": "Optimize database",
|
||||
@@ -129,5 +131,9 @@
|
||||
"TaskKeyframeExtractor": "Keyframe Extractor",
|
||||
"TaskKeyframeExtractorDescription": "Extracts keyframes from video files to create more precise HLS playlists. This task may run for a long time.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Clean up collections and playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist.",
|
||||
"TaskExtractMediaSegments": "Media Segment Scan",
|
||||
"TaskExtractMediaSegmentsDescription": "Extracts or obtains media segments from MediaSegment enabled plugins.",
|
||||
"TaskMoveTrickplayImages": "Migrate Trickplay Image Location",
|
||||
"TaskMoveTrickplayImagesDescription": "Moves existing trickplay files according to the library settings."
|
||||
}
|
||||
|
||||
1
Emby.Server.Implementations/Localization/Core/enm.json
Normal file
1
Emby.Server.Implementations/Localization/Core/enm.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -124,5 +124,17 @@
|
||||
"External": "Externo",
|
||||
"TaskKeyframeExtractorDescription": "Extrae Fotogramas Clave de los archivos de vídeo para crear Listas de Reprodución HLS más precisas. Esta tarea puede durar mucho tiempo.",
|
||||
"TaskKeyframeExtractor": "Extractor de Fotogramas Clave",
|
||||
"HearingImpaired": "Discapacidad Auditiva"
|
||||
"HearingImpaired": "Discapacidad Auditiva",
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea vistas previas de reproducción engañosa para videos en bibliotecas habilitadas.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanea archivos en busca de datos de normalización de audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimina elementos de colecciones y listas de reproducción que ya no existen.",
|
||||
"TaskDownloadMissingLyrics": "Descargar letra faltante",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones",
|
||||
"TaskExtractMediaSegments": "Escanear Segmentos de Media",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrae u obtiene segmentos de medio de plugins habilitados para MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Mueve archivos existentes de trickplay de acuerdo a la configuración de la biblioteca.",
|
||||
"TaskMoveTrickplayImages": "Migrar Ubicación de Imagen de Trickplay"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Colecciones",
|
||||
"DeviceOfflineWithName": "{0} se ha desconectado",
|
||||
"DeviceOnlineWithName": "{0} está conectado",
|
||||
"FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión desde {0}",
|
||||
"FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}",
|
||||
"Favorites": "Favoritos",
|
||||
"Folders": "Carpetas",
|
||||
"Genres": "Géneros",
|
||||
@@ -124,5 +124,17 @@
|
||||
"TaskKeyframeExtractorDescription": "Extrae los cuadros clave de los archivos de vídeo para crear listas HLS más precisas. Esta tarea puede tardar un buen rato.",
|
||||
"TaskKeyframeExtractor": "Extractor de Cuadros Clave",
|
||||
"External": "Externo",
|
||||
"HearingImpaired": "Discapacidad Auditiva"
|
||||
"HearingImpaired": "Discapacidad Auditiva",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea previsualizaciones para la barra de reproducción en las bibliotecas habilitadas.",
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de la barra de reproducción",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Analiza los archivos para normalizar el audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpieza de colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Quita elementos que ya no existen de colecciones y listas de reproducción.",
|
||||
"TaskDownloadMissingLyrics": "descargar letras que faltan",
|
||||
"TaskDownloadMissingLyricsDescription": "Descargar letras de canciones",
|
||||
"TaskExtractMediaSegments": "Escaneo de segmentos de medios",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrae u obtiene segmentos de medios de plugins habilitados para MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migrar la ubicación de la imagen de Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Mueve archivos de trickplay existentes según la configuración de la biblioteca."
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Colecciones",
|
||||
"DeviceOfflineWithName": "{0} se ha desconectado",
|
||||
"DeviceOnlineWithName": "{0} está conectado",
|
||||
"FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión desde {0}",
|
||||
"FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}",
|
||||
"Favorites": "Favoritos",
|
||||
"Folders": "Carpetas",
|
||||
"Genres": "Géneros",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimina elementos de colecciones y listas de reproducción que ya no existen.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanear archivos para obtener datos de normalización."
|
||||
"TaskAudioNormalizationDescription": "Escanear archivos para obtener datos de normalización.",
|
||||
"TaskDownloadMissingLyricsDescription": "Descargar letras para las canciones",
|
||||
"TaskDownloadMissingLyrics": "Descargar letras faltantes",
|
||||
"TaskMoveTrickplayImagesDescription": "Mueve archivos de trickplay existentes según la configuración de la biblioteca.",
|
||||
"TaskExtractMediaSegments": "Escaneo de segmentos de medios",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrae u obtiene segmentos de medios de plugins habilitados para MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migrar la ubicación de la imagen de Trickplay"
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"CameraImageUploadedFrom": "Una nueva imagen de cámara ha sido subida desde {0}",
|
||||
"AuthenticationSucceededWithUserName": "{0} autenticado con éxito",
|
||||
"Application": "Aplicación",
|
||||
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
|
||||
"AppDeviceValues": "Aplicación: {0}, Dispositivo: {1}",
|
||||
"TaskCleanActivityLogDescription": "Elimina las entradas del registro de actividad anteriores al periodo configurado.",
|
||||
"TaskCleanActivityLog": "Limpiar registro de actividades",
|
||||
"Undefined": "Sin definir",
|
||||
@@ -125,5 +125,11 @@
|
||||
"TaskKeyframeExtractor": "Extractor de Fotogramas Clave",
|
||||
"HearingImpaired": "Discapacidad auditiva",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea previsualizaciones para la barra de reproducción en las bibliotecas habilitadas.",
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de la barra de reproducción"
|
||||
"TaskRefreshTrickplayImages": "Generar imágenes de la barra de reproducción",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Quita elementos que ya no existen de colecciones y listas de reproducción.",
|
||||
"TaskAudioNormalizationDescription": "Analiza los archivos para normalizar el audio.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpieza de colecciones y listas de reproducción",
|
||||
"TaskDownloadMissingLyrics": "Descargar letra faltante",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones"
|
||||
}
|
||||
|
||||
@@ -12,14 +12,118 @@
|
||||
"Application": "Aplicación",
|
||||
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
|
||||
"HeaderContinueWatching": "Continuar Viendo",
|
||||
"HeaderAlbumArtists": "Artistas del Álbum",
|
||||
"HeaderAlbumArtists": "Artistas del álbum",
|
||||
"Genres": "Géneros",
|
||||
"Folders": "Carpetas",
|
||||
"Favorites": "Favoritos",
|
||||
"FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido de {0}",
|
||||
"FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido desde {0}",
|
||||
"HeaderFavoriteSongs": "Canciones Favoritas",
|
||||
"HeaderFavoriteEpisodes": "Episodios Favoritos",
|
||||
"HeaderFavoriteArtists": "Artistas Favoritos",
|
||||
"External": "Externo",
|
||||
"Default": "Predeterminado"
|
||||
"Default": "Predeterminado",
|
||||
"Movies": "Películas",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "La sección {0} de la configuración ha sido actualizada",
|
||||
"MixedContent": "Contenido mixto",
|
||||
"Music": "Música",
|
||||
"NotificationOptionCameraImageUploaded": "Imagen de la cámara subida",
|
||||
"NotificationOptionServerRestartRequired": "Se necesita reiniciar el servidor",
|
||||
"NotificationOptionVideoPlayback": "Reproducción de video iniciada",
|
||||
"Sync": "Sincronizar",
|
||||
"Shows": "Series",
|
||||
"UserDownloadingItemWithValues": "{0} está descargando {1}",
|
||||
"UserOfflineFromDevice": "{0} se ha desconectado desde {1}",
|
||||
"UserOnlineFromDevice": "{0} está en línea desde {1}",
|
||||
"TasksChannelsCategory": "Canales de Internet",
|
||||
"TaskRefreshChannelsDescription": "Actualiza la información de canales de Internet.",
|
||||
"TaskDownloadMissingSubtitles": "Descargar subtítulos faltantes",
|
||||
"TaskOptimizeDatabaseDescription": "Compacta la base de datos y libera espacio. Ejecutar esta tarea después de escanear la biblioteca o hacer otros cambios que impliquen modificaciones en la base de datos puede mejorar el rendimiento.",
|
||||
"TaskKeyframeExtractorDescription": "Extrae Fotogramas Clave de los archivos de vídeo para crear Listas de Reproducción HLS más precisas. Esta tarea puede durar mucho tiempo.",
|
||||
"TaskAudioNormalization": "Normalización de audio",
|
||||
"TaskAudioNormalizationDescription": "Escanear archivos para la normalización de data.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remover elementos de colecciones y listas de reproducción que no existen.",
|
||||
"TvShows": "Series de TV",
|
||||
"UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}",
|
||||
"TaskRefreshChannels": "Actualizar canales",
|
||||
"Photos": "Fotos",
|
||||
"HeaderFavoriteShows": "Programas favoritos",
|
||||
"TaskCleanActivityLog": "Limpiar registro de actividades",
|
||||
"UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}",
|
||||
"System": "Sistema",
|
||||
"User": "Usuario",
|
||||
"Forced": "Forzado",
|
||||
"PluginInstalledWithName": "{0} ha sido instalado",
|
||||
"HeaderFavoriteAlbums": "Álbumes favoritos",
|
||||
"TaskUpdatePlugins": "Actualizar Plugins",
|
||||
"Latest": "Recientes",
|
||||
"UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}",
|
||||
"Songs": "Canciones",
|
||||
"NotificationOptionPluginError": "Falla de plugin",
|
||||
"ScheduledTaskStartedWithName": "{0} iniciado",
|
||||
"TasksApplicationCategory": "Aplicación",
|
||||
"UserDeletedWithName": "El usuario {0} ha sido eliminado",
|
||||
"TaskRefreshChapterImages": "Extraer imágenes de los capítulos",
|
||||
"TaskUpdatePluginsDescription": "Descarga e instala actualizaciones para plugins que están configurados para actualizarse automáticamente.",
|
||||
"TaskRefreshPeopleDescription": "Actualiza metadatos de actores y directores en tu biblioteca de medios.",
|
||||
"NotificationOptionUserLockedOut": "Usuario bloqueado",
|
||||
"TaskCleanTranscodeDescription": "Elimina archivos transcodificados que tengan más de un día.",
|
||||
"TaskCleanTranscode": "Limpiar el directorio de transcodificaciones",
|
||||
"NotificationOptionPluginUpdateInstalled": "Actualización de plugin instalada",
|
||||
"NotificationOptionAudioPlaybackStopped": "Reproducción de audio detenida",
|
||||
"TasksLibraryCategory": "Biblioteca",
|
||||
"NotificationOptionPluginInstalled": "Plugin instalado",
|
||||
"UserPolicyUpdatedWithName": "La política de usuario ha sido actualizada para {0}",
|
||||
"VersionNumber": "Versión {0}",
|
||||
"HeaderNextUp": "A continuación",
|
||||
"ValueHasBeenAddedToLibrary": "{0} se ha añadido a tu biblioteca",
|
||||
"LabelIpAddressValue": "Dirección IP: {0}",
|
||||
"NameSeasonNumber": "Temporada {0}",
|
||||
"NotificationOptionNewLibraryContent": "Nuevo contenido agregado",
|
||||
"Plugin": "Plugin",
|
||||
"NotificationOptionAudioPlayback": "Reproducción de audio iniciada",
|
||||
"NotificationOptionTaskFailed": "Falló la tarea programada",
|
||||
"LabelRunningTimeValue": "Tiempo en ejecución: {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Falló la descarga de subtítulos desde {0} para {1}",
|
||||
"TaskRefreshLibrary": "Escanear biblioteca de medios",
|
||||
"ServerNameNeedsToBeRestarted": "{0} debe ser reiniciado",
|
||||
"TasksMaintenanceCategory": "Mantenimiento",
|
||||
"ProviderValue": "Proveedor: {0}",
|
||||
"UserCreatedWithName": "El usuario {0} ha sido creado",
|
||||
"PluginUninstalledWithName": "{0} ha sido desinstalado",
|
||||
"ValueSpecialEpisodeName": "Especial - {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} falló",
|
||||
"TaskCleanLogs": "Limpiar directorio de registros",
|
||||
"NameInstallFailed": "Falló la instalación de {0}",
|
||||
"UserLockedOutWithName": "El usuario {0} ha sido bloqueado",
|
||||
"TaskRefreshLibraryDescription": "Escanea tu biblioteca de medios para encontrar archivos nuevos y actualizar los metadatos.",
|
||||
"StartupEmbyServerIsLoading": "El servidor Jellyfin está cargando. Por favor, intente de nuevo en un momento.",
|
||||
"Playlists": "Listas de reproducción",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Busca subtítulos faltantes en Internet basándose en la configuración de metadatos.",
|
||||
"MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor",
|
||||
"TaskRefreshPeople": "Actualizar personas",
|
||||
"NotificationOptionVideoPlaybackStopped": "Reproducción de video detenida",
|
||||
"HeaderLiveTV": "TV en vivo",
|
||||
"NameSeasonUnknown": "Temporada desconocida",
|
||||
"NotificationOptionInstallationFailed": "Fallo de instalación",
|
||||
"NotificationOptionPluginUninstalled": "Plugin desinstalado",
|
||||
"TaskCleanCache": "Limpiar directorio caché",
|
||||
"TaskRefreshChapterImagesDescription": "Crea miniaturas para videos que tienen capítulos.",
|
||||
"Inherit": "Heredar",
|
||||
"HeaderRecordingGroups": "Grupos de grabación",
|
||||
"ItemAddedWithName": "{0} fue agregado a la biblioteca",
|
||||
"TaskOptimizeDatabase": "Optimizar base de datos",
|
||||
"TaskKeyframeExtractor": "Extractor de Fotogramas Clave",
|
||||
"HearingImpaired": "Discapacidad auditiva",
|
||||
"HomeVideos": "Videos caseros",
|
||||
"ItemRemovedWithName": "{0} fue removido de la biblioteca",
|
||||
"MessageApplicationUpdated": "El servidor Jellyfin ha sido actualizado",
|
||||
"MessageApplicationUpdatedTo": "El servidor Jellyfin ha sido actualizado a {0}",
|
||||
"MusicVideos": "Videos musicales",
|
||||
"NewVersionIsAvailable": "Una nueva versión de Jellyfin está disponible para descargar.",
|
||||
"PluginUpdatedWithName": "{0} ha sido actualizado",
|
||||
"Undefined": "Sin definir",
|
||||
"TaskCleanActivityLogDescription": "Elimina las entradas del registro de actividad anteriores al periodo configurado.",
|
||||
"TaskCleanCacheDescription": "Elimina archivos caché que ya no son necesarios para el sistema.",
|
||||
"TaskCleanLogsDescription": "Elimina archivos de registro con más de {0} días de antigüedad."
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
"Forced": "Sunnitud",
|
||||
"Folders": "Kaustad",
|
||||
"Favorites": "Lemmikud",
|
||||
"FailedLoginAttemptWithUserName": "{0} - sisselogimine nurjus",
|
||||
"FailedLoginAttemptWithUserName": "Sisselogimine nurjus aadressilt {0}",
|
||||
"DeviceOnlineWithName": "{0} on ühendatud",
|
||||
"DeviceOfflineWithName": "{0} katkestas ühenduse",
|
||||
"Default": "Vaikimisi",
|
||||
@@ -125,5 +125,15 @@
|
||||
"TaskKeyframeExtractorDescription": "Eraldab videofailidest võtmekaadreid, et luua täpsemaid HLS-i esitusloendeid. See ülesanne võib kesta pikka aega.",
|
||||
"TaskKeyframeExtractor": "Võtmekaadri ekstraktor",
|
||||
"TaskRefreshTrickplayImages": "Loo eelvaate pildid",
|
||||
"TaskRefreshTrickplayImagesDescription": "Loob eelvaated videotele, kus lubatud."
|
||||
"TaskRefreshTrickplayImagesDescription": "Loob eelvaated videotele, kus lubatud.",
|
||||
"TaskAudioNormalization": "Heli Normaliseerimine",
|
||||
"TaskAudioNormalizationDescription": "Skaneerib faile heli normaliseerimise andmete jaoks.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Eemaldab kogumikest ja esitusloenditest asjad, mida enam ei eksisteeri.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Puhasta kogumikud ja esitusloendid",
|
||||
"TaskDownloadMissingLyrics": "Lae alla puuduolev lüürika",
|
||||
"TaskDownloadMissingLyricsDescription": "Lae lauludele alla lüürika",
|
||||
"TaskMoveTrickplayImagesDescription": "Liigutab trickplay pildid meediakogu sätete kohaselt.",
|
||||
"TaskExtractMediaSegments": "Meediasegmentide skaneerimine",
|
||||
"TaskExtractMediaSegmentsDescription": "Eraldab või võtab meediasegmendid MediaSegment'i lubavatest pluginatest.",
|
||||
"TaskMoveTrickplayImages": "Migreeri trickplay piltide asukoht"
|
||||
}
|
||||
|
||||
@@ -128,5 +128,13 @@
|
||||
"TaskRefreshTrickplayImages": "تولید تصاویر Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "تولید پیشنمایش های trickplay برای ویدیو های فعال شده در کتابخانه.",
|
||||
"TaskCleanCollectionsAndPlaylists": "پاکسازی مجموعه ها و لیست پخش",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "موارد را از مجموعه ها و لیست پخش هایی که دیگر وجود ندارند حذف میکند."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "موارد را از مجموعه ها و لیست پخش هایی که دیگر وجود ندارند حذف میکند.",
|
||||
"TaskAudioNormalizationDescription": "بررسی فایل برای دادههای نرمال کردن صدا.",
|
||||
"TaskDownloadMissingLyrics": "دانلود متنهای ناموجود",
|
||||
"TaskDownloadMissingLyricsDescription": "دانلود متن شعرها",
|
||||
"TaskAudioNormalization": "نرمال کردن صدا",
|
||||
"TaskExtractMediaSegments": "بررسی بخش محتوا",
|
||||
"TaskExtractMediaSegmentsDescription": "بخشهای محتوا را از افزونههای مربوط استخراح میکند.",
|
||||
"TaskMoveTrickplayImages": "جابهجایی عکسهای Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "دادههای Trickplay را با توجه به تنظیمات کتابخانه جابهجا میکند."
|
||||
}
|
||||
|
||||
@@ -127,5 +127,8 @@
|
||||
"TaskRefreshTrickplayImages": "Luo Trickplay-kuvat",
|
||||
"TaskRefreshTrickplayImagesDescription": "Luo Trickplay-esikatselut käytössä olevien kirjastojen videoista.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Poistaa kohteet kokoelmista ja soittolistoista joita ei ole enää olemassa.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Puhdista kokoelmat ja soittolistat"
|
||||
"TaskCleanCollectionsAndPlaylists": "Puhdista kokoelmat ja soittolistat",
|
||||
"TaskAudioNormalization": "Äänenvoimakkuuden normalisointi",
|
||||
"TaskAudioNormalizationDescription": "Etsii tiedostoista äänenvoimakkuuden normalisointitietoja.",
|
||||
"TaskDownloadMissingLyrics": "Lataa puuttuva lyriikka"
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"HeaderFavoriteSongs": "Mga Paboritong Kanta",
|
||||
"HeaderFavoriteShows": "Mga Paboritong Pelikula",
|
||||
"HeaderFavoriteEpisodes": "Mga Paboritong Episode",
|
||||
"HeaderFavoriteEpisodes": "Mga Paboritong Yugto",
|
||||
"HeaderFavoriteArtists": "Mga Paboritong Artista",
|
||||
"HeaderFavoriteAlbums": "Mga Paboritong Album",
|
||||
"HeaderContinueWatching": "Magpatuloy sa Panonood",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Collections",
|
||||
"DeviceOfflineWithName": "{0} s'est déconnecté",
|
||||
"DeviceOnlineWithName": "{0} est connecté",
|
||||
"FailedLoginAttemptWithUserName": "Tentative de connexion échoué par {0}",
|
||||
"FailedLoginAttemptWithUserName": "Tentative de connexion échouée par {0}",
|
||||
"Favorites": "Favoris",
|
||||
"Folders": "Dossiers",
|
||||
"Genres": "Genres",
|
||||
@@ -39,7 +39,7 @@
|
||||
"MixedContent": "Contenu mixte",
|
||||
"Movies": "Films",
|
||||
"Music": "Musique",
|
||||
"MusicVideos": "Vidéos musicales",
|
||||
"MusicVideos": "Vidéoclips",
|
||||
"NameInstallFailed": "échec d'installation de {0}",
|
||||
"NameSeasonNumber": "Saison {0}",
|
||||
"NameSeasonUnknown": "Saison Inconnue",
|
||||
@@ -128,5 +128,12 @@
|
||||
"TaskRefreshTrickplayImages": "Générer des images Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crée des aperçus Trickplay pour les vidéos dans les médiathèques activées.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Nettoyer les collections et les listes de lecture",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Supprimer les liens inexistants des collections et des listes de lecture"
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Supprime les éléments des collections et des listes de lecture qui n'existent plus.",
|
||||
"TaskAudioNormalization": "Normalisation audio",
|
||||
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio.",
|
||||
"TaskExtractMediaSegments": "Analyse des segments de média",
|
||||
"TaskDownloadMissingLyricsDescription": "Téléchargement des paroles des chansons",
|
||||
"TaskMoveTrickplayImagesDescription": "Déplace les fichiers trickplay existants en fonction des paramètres de la bibliothèque.",
|
||||
"TaskDownloadMissingLyrics": "Télécharger les paroles des chansons manquantes",
|
||||
"TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"Albums": "Albums",
|
||||
"AppDeviceValues": "Application : {0}, Appareil : {1}",
|
||||
"AppDeviceValues": "Application : {0}, Appareil : {1}",
|
||||
"Application": "Application",
|
||||
"Artists": "Artistes",
|
||||
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
|
||||
@@ -15,7 +15,7 @@
|
||||
"Favorites": "Favoris",
|
||||
"Folders": "Dossiers",
|
||||
"Genres": "Genres",
|
||||
"HeaderAlbumArtists": "Artistes de l'album",
|
||||
"HeaderAlbumArtists": "Artistes d'albums",
|
||||
"HeaderContinueWatching": "Continuer de regarder",
|
||||
"HeaderFavoriteAlbums": "Albums favoris",
|
||||
"HeaderFavoriteArtists": "Artistes préférés",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Nettoyer les collections et les listes de lecture",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Supprime les éléments des collections et des listes de lecture qui n'existent plus.",
|
||||
"TaskAudioNormalization": "Normalisation audio",
|
||||
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio."
|
||||
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Téléchargement des paroles des chansons",
|
||||
"TaskDownloadMissingLyrics": "Télécharger les paroles des chansons manquantes",
|
||||
"TaskExtractMediaSegments": "Analyse des segments de média",
|
||||
"TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrait ou obtient des segments de média à partir des plugins compatibles avec MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Déplace les fichiers trickplay existants en fonction des paramètres de la bibliothèque."
|
||||
}
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
{
|
||||
"Albums": "Albaim"
|
||||
"Albums": "Albaim",
|
||||
"Artists": "Ealaíontóir",
|
||||
"AuthenticationSucceededWithUserName": "{0} fíordheimhnithe",
|
||||
"Books": "leabhair",
|
||||
"CameraImageUploadedFrom": "Tá íomhá ceamara nua uaslódáilte ó {0}",
|
||||
"Channels": "Cainéil",
|
||||
"ChapterNameValue": "Caibidil {0}",
|
||||
"Collections": "Bailiúcháin",
|
||||
"Default": "Mainneachtain",
|
||||
"DeviceOfflineWithName": "scoireadh {0}",
|
||||
"DeviceOnlineWithName": "{0} ceangailte",
|
||||
"External": "Forimeallach",
|
||||
"FailedLoginAttemptWithUserName": "Iarracht ar theip ar fhíordheimhniú ó {0}",
|
||||
"Favorites": "Ceanáin"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Albums": "Álbumes",
|
||||
"Collections": "Colecións",
|
||||
"ChapterNameValue": "Capítulos {0}",
|
||||
"Collections": "Coleccións",
|
||||
"ChapterNameValue": "Capítulo {0}",
|
||||
"Channels": "Canles",
|
||||
"CameraImageUploadedFrom": "Cargouse unha nova imaxe da cámara desde {0}",
|
||||
"Books": "Libros",
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"NotificationOptionUserLockedOut": "משתמש ננעל",
|
||||
"NotificationOptionVideoPlayback": "ניגון וידאו החל",
|
||||
"NotificationOptionVideoPlaybackStopped": "ניגון וידאו הופסק",
|
||||
"Photos": "תמונות",
|
||||
"Photos": "צילומים",
|
||||
"Playlists": "רשימות נגינה",
|
||||
"Plugin": "תוסף",
|
||||
"PluginInstalledWithName": "{0} הותקן",
|
||||
@@ -126,5 +126,15 @@
|
||||
"External": "חיצוני",
|
||||
"HearingImpaired": "לקוי שמיעה",
|
||||
"TaskRefreshTrickplayImages": "יצירת תמונות המחשה",
|
||||
"TaskRefreshTrickplayImagesDescription": "יוצר תמונות המחשה לסרטונים שפעילים בספריות."
|
||||
"TaskRefreshTrickplayImagesDescription": "יוצר תמונות המחשה לסרטונים שפעילים בספריות.",
|
||||
"TaskAudioNormalization": "נרמול שמע",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "מנקה פריטים לא קיימים מאוספים ורשימות השמעה.",
|
||||
"TaskAudioNormalizationDescription": "מחפש קבצי נורמליזציה של שמע.",
|
||||
"TaskCleanCollectionsAndPlaylists": "מנקה אוספים ורשימות השמעה",
|
||||
"TaskDownloadMissingLyrics": "הורדת מילים חסרות",
|
||||
"TaskDownloadMissingLyricsDescription": "הורדת מילים לשירים",
|
||||
"TaskMoveTrickplayImages": "מעביר את מיקום תמונות Trickplay",
|
||||
"TaskExtractMediaSegments": "סריקת מדיה",
|
||||
"TaskExtractMediaSegmentsDescription": "מחלץ חלקי מדיה מתוספים המאפשרים זאת.",
|
||||
"TaskMoveTrickplayImagesDescription": "מזיז קבצי trickplay קיימים בהתאם להגדרות הספרייה."
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"Forced": "बलपूर्वक",
|
||||
"Folders": "फ़ोल्डर",
|
||||
"Favorites": "पसंदीदा",
|
||||
"FailedLoginAttemptWithUserName": "{0} से लॉगिन असफल हुआ",
|
||||
"FailedLoginAttemptWithUserName": "{0} से संप्रवेश असफल हुआ",
|
||||
"DeviceOnlineWithName": "{0} कनेक्ट हो गया है",
|
||||
"DeviceOfflineWithName": "{0} डिस्कनेक्ट हो गया है",
|
||||
"Default": "प्राथमिक",
|
||||
@@ -125,5 +125,7 @@
|
||||
"TaskDownloadMissingSubtitlesDescription": "मेटाडेटा कॉन्फ़िगरेशन के आधार पर लापता उपशीर्षक के लिए इंटरनेट खोजता है।",
|
||||
"TaskKeyframeExtractorDescription": "अधिक सटीक एचएलएस प्लेलिस्ट बनाने के लिए वीडियो फ़ाइलों से मुख्य-फ़्रेम निकालता है। यह कार्य लंबे समय तक चल सकता है।",
|
||||
"TaskRefreshTrickplayImages": "ट्रिकप्लै चित्रों को सृजन करे",
|
||||
"TaskRefreshTrickplayImagesDescription": "नियत संग्रहों में चलचित्रों का ट्रीकप्लै दर्शनों को सृजन करे."
|
||||
"TaskRefreshTrickplayImagesDescription": "नियत संग्रहों में चलचित्रों का ट्रीकप्लै दर्शनों को सृजन करे.",
|
||||
"TaskAudioNormalization": "श्रव्य सामान्यीकरण",
|
||||
"TaskAudioNormalizationDescription": "श्रव्य सामान्यीकरण के लिए फाइलें अन्वेषण करें"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Kolekcije",
|
||||
"DeviceOfflineWithName": "{0} je prekinuo vezu",
|
||||
"DeviceOnlineWithName": "{0} je povezan",
|
||||
"FailedLoginAttemptWithUserName": "Neuspjeli pokušaj prijave od {0}",
|
||||
"FailedLoginAttemptWithUserName": "Neuspješan pokušaj prijave od {0}",
|
||||
"Favorites": "Favoriti",
|
||||
"Folders": "Mape",
|
||||
"Genres": "Žanrovi",
|
||||
@@ -126,5 +126,15 @@
|
||||
"TaskOptimizeDatabaseDescription": "Sažima bazu podataka i uklanja prazan prostor. Pokretanje ovog zadatka, može poboljšati performanse nakon provođenja indeksiranja biblioteke ili provođenja drugih promjena koje utječu na bazu podataka.",
|
||||
"HearingImpaired": "Oštećen sluh",
|
||||
"TaskRefreshTrickplayImages": "Generiraj Trickplay Slike",
|
||||
"TaskRefreshTrickplayImagesDescription": "Kreira trickplay pretpreglede za videe u omogućenim knjižnicama."
|
||||
"TaskRefreshTrickplayImagesDescription": "Kreira trickplay pretpreglede za videe u omogućenim knjižnicama.",
|
||||
"TaskAudioNormalization": "Normalizacija zvuka",
|
||||
"TaskAudioNormalizationDescription": "Skenira datoteke u potrazi za podacima o normalizaciji zvuka.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Uklanja stavke iz zbirki i popisa za reprodukciju koje više ne postoje.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Očisti zbirke i popise za reprodukciju",
|
||||
"TaskExtractMediaSegments": "Skeniranje dijelova medija",
|
||||
"TaskDownloadMissingLyrics": "Preuzmi tekstove koji nedostaju",
|
||||
"TaskDownloadMissingLyricsDescription": "Preuzmi tekstove pjesama",
|
||||
"TaskExtractMediaSegmentsDescription": "Izvlači ili pribavlja dijelove medija iz omogućenih media pluginova.",
|
||||
"TaskMoveTrickplayImages": "Preseli lokaciju Trickplay slika",
|
||||
"TaskMoveTrickplayImagesDescription": "Preseli lokaciju Trickplay slika prema postavkama zbirke."
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"Albums": "Albumok",
|
||||
"AppDeviceValues": "Program: {0}, Eszköz: {1}",
|
||||
"AppDeviceValues": "Program: {0}, eszköz: {1}",
|
||||
"Application": "Alkalmazás",
|
||||
"Artists": "Előadók",
|
||||
"AuthenticationSucceededWithUserName": "{0} sikeresen hitelesítve",
|
||||
"Books": "Könyvek",
|
||||
"CameraImageUploadedFrom": "Új kamerakép lett feltöltve innen: {0}",
|
||||
"Channels": "Csatornák",
|
||||
"ChapterNameValue": "Jelenet {0}",
|
||||
"ChapterNameValue": "{0}. jelenet",
|
||||
"Collections": "Gyűjtemények",
|
||||
"DeviceOfflineWithName": "{0} kijelentkezett",
|
||||
"DeviceOnlineWithName": "{0} belépett",
|
||||
@@ -15,31 +15,31 @@
|
||||
"Favorites": "Kedvencek",
|
||||
"Folders": "Könyvtárak",
|
||||
"Genres": "Műfajok",
|
||||
"HeaderAlbumArtists": "Album előadók",
|
||||
"HeaderAlbumArtists": "Albumelőadók",
|
||||
"HeaderContinueWatching": "Megtekintés folytatása",
|
||||
"HeaderFavoriteAlbums": "Kedvenc Albumok",
|
||||
"HeaderFavoriteAlbums": "Kedvenc albumok",
|
||||
"HeaderFavoriteArtists": "Kedvenc előadók",
|
||||
"HeaderFavoriteEpisodes": "Kedvenc epizódok",
|
||||
"HeaderFavoriteShows": "Kedvenc sorozatok",
|
||||
"HeaderFavoriteSongs": "Kedvenc dalok",
|
||||
"HeaderFavoriteSongs": "Kedvenc számok",
|
||||
"HeaderLiveTV": "Élő TV",
|
||||
"HeaderNextUp": "Következik",
|
||||
"HeaderRecordingGroups": "Felvételi csoportok",
|
||||
"HomeVideos": "Otthoni videók",
|
||||
"Inherit": "Örökölt",
|
||||
"ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
|
||||
"ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
|
||||
"Inherit": "Öröklés",
|
||||
"ItemAddedWithName": "{0} hozzáadva a médiatárhoz",
|
||||
"ItemRemovedWithName": "{0} eltávolítva a médiatárból",
|
||||
"LabelIpAddressValue": "IP-cím: {0}",
|
||||
"LabelRunningTimeValue": "Lejátszási idő: {0}",
|
||||
"Latest": "Legújabb",
|
||||
"MessageApplicationUpdated": "A Jellyfin kiszolgáló frissítve lett",
|
||||
"MessageApplicationUpdatedTo": "A Jellyfin kiszolgáló frissítve lett a következőre: {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "A kiszolgálókonfigurációs rész frissítve lett: {0}",
|
||||
"MessageServerConfigurationUpdated": "Kiszolgálókonfiguráció frissítve lett",
|
||||
"MessageServerConfigurationUpdated": "A kiszolgálókonfiguráció frissítve lett",
|
||||
"MixedContent": "Vegyes tartalom",
|
||||
"Movies": "Filmek",
|
||||
"Music": "Zenék",
|
||||
"MusicVideos": "Zenei videóklippek",
|
||||
"MusicVideos": "Zenei videóklipek",
|
||||
"NameInstallFailed": "{0} sikertelen telepítés",
|
||||
"NameSeasonNumber": "{0}. évad",
|
||||
"NameSeasonUnknown": "Ismeretlen évad",
|
||||
@@ -56,7 +56,7 @@
|
||||
"NotificationOptionPluginUninstalled": "Bővítmény eltávolítva",
|
||||
"NotificationOptionPluginUpdateInstalled": "Bővítményfrissítés telepítve",
|
||||
"NotificationOptionServerRestartRequired": "A kiszolgáló újraindítása szükséges",
|
||||
"NotificationOptionTaskFailed": "Ütemezett feladat hiba",
|
||||
"NotificationOptionTaskFailed": "Hiba az ütemezett feladatban",
|
||||
"NotificationOptionUserLockedOut": "Felhasználó tiltva",
|
||||
"NotificationOptionVideoPlayback": "Videólejátszás elkezdve",
|
||||
"NotificationOptionVideoPlaybackStopped": "Videólejátszás leállítva",
|
||||
@@ -107,7 +107,7 @@
|
||||
"TaskCleanCache": "Gyorsítótár könyvtárának ürítése",
|
||||
"TasksChannelsCategory": "Internetes csatornák",
|
||||
"TasksApplicationCategory": "Alkalmazás",
|
||||
"TasksLibraryCategory": "Könyvtár",
|
||||
"TasksLibraryCategory": "Médiatár",
|
||||
"TasksMaintenanceCategory": "Karbantartás",
|
||||
"TaskDownloadMissingSubtitlesDescription": "A metaadat-konfiguráció alapján ellenőrzi és letölti a hiányzó feliratokat az internetről.",
|
||||
"TaskDownloadMissingSubtitles": "Hiányzó feliratok letöltése",
|
||||
@@ -119,16 +119,22 @@
|
||||
"Undefined": "Meghatározatlan",
|
||||
"Forced": "Kényszerített",
|
||||
"Default": "Alapértelmezett",
|
||||
"TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a könyvtár beolvasása után, vagy egyéb, adatbázis-módosítást igénylő változtatások végrehajtása javíthatja a teljesítményt.",
|
||||
"TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a médiatár beolvasása, vagy egyéb adatbázis-módosítást igénylő változtatás végrehajtása után, javíthatja a teljesítményt.",
|
||||
"TaskOptimizeDatabase": "Adatbázis optimalizálása",
|
||||
"TaskKeyframeExtractor": "Kulcsképkockák kibontása",
|
||||
"TaskKeyframeExtractorDescription": "Kibontja a kulcsképkockákat a videófájlokból, hogy pontosabb HLS lejátszási listákat hozzon létre. Ez a feladat hosszú ideig tarthat.",
|
||||
"External": "Külső",
|
||||
"HearingImpaired": "Hallássérült",
|
||||
"TaskRefreshTrickplayImages": "Trickplay képek generálása",
|
||||
"TaskRefreshTrickplayImages": "Trickplay képek előállítása",
|
||||
"TaskRefreshTrickplayImagesDescription": "Trickplay előnézetet készít az engedélyezett könyvtárakban lévő videókhoz.",
|
||||
"TaskAudioNormalization": "Hangerő Normalizáció",
|
||||
"TaskAudioNormalization": "Hangerő-normalizálás",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Nem létező elemek törlése a gyűjteményekből és lejátszási listákról.",
|
||||
"TaskAudioNormalizationDescription": "Hangerő normalizációs adatok keresése.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Gyűjtemények és lejátszási listák optimalizálása"
|
||||
"TaskAudioNormalizationDescription": "Hangerő-normalizálási adatok keresése.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Gyűjtemények és lejátszási listák optimalizálása",
|
||||
"TaskExtractMediaSegments": "Médiaszegmens felismerése",
|
||||
"TaskDownloadMissingLyrics": "Hiányzó szöveg letöltése",
|
||||
"TaskDownloadMissingLyricsDescription": "Zenék szövegének letöltése",
|
||||
"TaskMoveTrickplayImages": "Trickplay képek helyének átköltöztetése",
|
||||
"TaskMoveTrickplayImagesDescription": "A médiatár-beállításoknak megfelelően áthelyezi a meglévő trickplay fájlokat.",
|
||||
"TaskExtractMediaSegmentsDescription": "Kinyeri vagy megszerzi a médiaszegmenseket a MediaSegment támogatással rendelkező bővítményekből."
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"Movies": "Film",
|
||||
"MessageServerConfigurationUpdated": "Konfigurasi server telah diperbarui",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Bagian konfigurasi server {0} telah diperbarui",
|
||||
"FailedLoginAttemptWithUserName": "Gagal melakukan login dari {0}",
|
||||
"FailedLoginAttemptWithUserName": "Gagal upaya login dari {0}",
|
||||
"CameraImageUploadedFrom": "Sebuah gambar kamera baru telah diunggah dari {0}",
|
||||
"DeviceOfflineWithName": "{0} telah terputus",
|
||||
"DeviceOnlineWithName": "{0} telah terhubung",
|
||||
@@ -125,5 +125,9 @@
|
||||
"External": "Luar",
|
||||
"HearingImpaired": "Gangguan Pendengaran",
|
||||
"TaskRefreshTrickplayImages": "Hasilkan Gambar Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Buat pratinjau trickplay untuk video di perpustakaan yang diaktifkan."
|
||||
"TaskRefreshTrickplayImagesDescription": "Buat pratinjau trickplay untuk video di perpustakaan yang diaktifkan.",
|
||||
"TaskAudioNormalizationDescription": "Pindai file untuk data normalisasi audio.",
|
||||
"TaskAudioNormalization": "Normalisasi Audio",
|
||||
"TaskCleanCollectionsAndPlaylists": "Bersihkan koleksi dan daftar putar",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Menghapus item dari koleksi dan daftar putar yang sudah tidak ada."
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"Genres": "Stefnur",
|
||||
"Folders": "Möppur",
|
||||
"Favorites": "Uppáhalds",
|
||||
"FailedLoginAttemptWithUserName": "{0} reyndi að auðkenna sig",
|
||||
"FailedLoginAttemptWithUserName": "{0} mistókst að auðkenna sig",
|
||||
"DeviceOnlineWithName": "{0} hefur tengst",
|
||||
"DeviceOfflineWithName": "{0} hefur aftengst",
|
||||
"Collections": "Söfn",
|
||||
@@ -123,5 +123,13 @@
|
||||
"TaskRefreshChapterImages": "Plokka kafla-myndir",
|
||||
"TaskCleanActivityLogDescription": "Eyðir virkniskráningarfærslum sem hafa náð settum hámarksaldri.",
|
||||
"Forced": "Þvingað",
|
||||
"External": "Útvær"
|
||||
"External": "Útvær",
|
||||
"TaskRefreshTrickplayImagesDescription": "Býr til hraðspilunarmyndir fyrir myndbönd í virkum söfnum.",
|
||||
"TaskRefreshTrickplayImages": "Búa til hraðspilunarmyndir",
|
||||
"TaskAudioNormalization": "Hljóðstöðlun",
|
||||
"TaskAudioNormalizationDescription": "Leitar að hljóðstöðlunargögnum í skrám.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Hreinsa söfn og spilunarlista",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjarlægir hluti úr söfnum og spilalistum sem eru ekki lengur til.",
|
||||
"TaskDownloadMissingLyricsDescription": "Sækja söngtexta fyrir lög",
|
||||
"TaskDownloadMissingLyrics": "Sækja söngtexta sem vantar"
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@
|
||||
"NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata",
|
||||
"NotificationOptionInstallationFailed": "Installazione fallita",
|
||||
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
|
||||
"NotificationOptionPluginError": "Errore del Plug-in",
|
||||
"NotificationOptionPluginInstalled": "Plug-in installato",
|
||||
"NotificationOptionPluginUninstalled": "Plug-in disinstallato",
|
||||
"NotificationOptionPluginUpdateInstalled": "Aggiornamento del plug-in installato",
|
||||
"NotificationOptionPluginError": "Errore del plugin",
|
||||
"NotificationOptionPluginInstalled": "Plugin installato",
|
||||
"NotificationOptionPluginUninstalled": "Plugin disinstallato",
|
||||
"NotificationOptionPluginUpdateInstalled": "Aggiornamento plugin installato",
|
||||
"NotificationOptionServerRestartRequired": "Riavvio del server necessario",
|
||||
"NotificationOptionTaskFailed": "Operazione pianificata fallita",
|
||||
"NotificationOptionUserLockedOut": "Utente bloccato",
|
||||
@@ -68,10 +68,10 @@
|
||||
"PluginUpdatedWithName": "{0} è stato aggiornato",
|
||||
"ProviderValue": "Provider: {0}",
|
||||
"ScheduledTaskFailedWithName": "{0} fallito",
|
||||
"ScheduledTaskStartedWithName": "{0} avviati",
|
||||
"ScheduledTaskStartedWithName": "{0} avviato",
|
||||
"ServerNameNeedsToBeRestarted": "{0} deve essere riavviato",
|
||||
"Shows": "Serie TV",
|
||||
"Songs": "Canzoni",
|
||||
"Songs": "Brani",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin server si sta avviando. Per favore riprova più tardi.",
|
||||
"SubtitleDownloadFailureForItem": "Impossibile scaricare i sottotitoli per {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "Impossibile scaricare i sottotitoli da {0} per {1}",
|
||||
@@ -83,52 +83,56 @@
|
||||
"UserDeletedWithName": "L'utente {0} è stato rimosso",
|
||||
"UserDownloadingItemWithValues": "{0} sta scaricando {1}",
|
||||
"UserLockedOutWithName": "L'utente {0} è stato bloccato",
|
||||
"UserOfflineFromDevice": "{0} si è disconnesso su {1}",
|
||||
"UserOfflineFromDevice": "{0} si è disconnesso da {1}",
|
||||
"UserOnlineFromDevice": "{0} è online su {1}",
|
||||
"UserPasswordChangedWithName": "La password è stata cambiata per l'utente {0}",
|
||||
"UserPolicyUpdatedWithName": "La policy dell'utente è stata aggiornata per {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} ha avviato la riproduzione di \"{1}\" su {2}",
|
||||
"UserStartedPlayingItemWithValues": "{0} ha avviato la riproduzione di {1} su {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} ha interrotto la riproduzione di {1} su {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} è stato aggiunto alla tua libreria multimediale",
|
||||
"ValueSpecialEpisodeName": "Speciale - {0}",
|
||||
"VersionNumber": "Versione {0}",
|
||||
"TaskRefreshChannelsDescription": "Aggiorna le informazioni dei canali Internet.",
|
||||
"TaskRefreshChannelsDescription": "Aggiorna le informazioni dei canali internet.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Cerca su internet i sottotitoli mancanti basandosi sulle configurazioni dei metadati.",
|
||||
"TaskDownloadMissingSubtitles": "Scarica i sottotitoli mancanti",
|
||||
"TaskRefreshChannels": "Aggiorna i canali",
|
||||
"TaskCleanTranscodeDescription": "Cancella i file di transcode più vecchi di un giorno.",
|
||||
"TaskCleanTranscode": "Svuota la cartella del transcoding",
|
||||
"TaskUpdatePluginsDescription": "Scarica e installa gli aggiornamenti per i plugin che sono stati configurati per essere aggiornati contemporaneamente.",
|
||||
"TaskUpdatePlugins": "Aggiorna i Plugin",
|
||||
"TaskRefreshPeopleDescription": "Aggiorna i metadati per gli attori e registi nella tua libreria multimediale.",
|
||||
"TaskRefreshPeople": "Aggiornamento Persone",
|
||||
"TaskRefreshChannels": "Aggiorna canali",
|
||||
"TaskCleanTranscodeDescription": "Cancella i file di transcodifica più vecchi di un giorno.",
|
||||
"TaskCleanTranscode": "Svuota la cartella della transcodifica",
|
||||
"TaskUpdatePluginsDescription": "Scarica e installa gli aggiornamenti per i plugin configurati per l'aggiornamento automatico.",
|
||||
"TaskUpdatePlugins": "Aggiorna i plugin",
|
||||
"TaskRefreshPeopleDescription": "Aggiorna i metadati degli attori e registi nella tua libreria.",
|
||||
"TaskRefreshPeople": "Aggiorna Persone",
|
||||
"TaskCleanLogsDescription": "Rimuovi i file di log più vecchi di {0} giorni.",
|
||||
"TaskCleanLogs": "Pulisci la cartella dei log",
|
||||
"TaskRefreshLibraryDescription": "Analizza la tua libreria multimediale per nuovi file e rinnova i metadati.",
|
||||
"TaskRefreshLibrary": "Scan Librerie",
|
||||
"TaskRefreshChapterImagesDescription": "Crea le thumbnail per i video che hanno capitoli.",
|
||||
"TaskRefreshLibraryDescription": "Scansiona la libreria alla ricerca di nuovi file e aggiorna i metadati.",
|
||||
"TaskRefreshLibrary": "Scansione della libreria",
|
||||
"TaskRefreshChapterImagesDescription": "Crea le miniature per i video che hanno capitoli.",
|
||||
"TaskRefreshChapterImages": "Estrai immagini capitolo",
|
||||
"TaskCleanCacheDescription": "Cancella i file di cache non più necessari al sistema.",
|
||||
"TaskCleanCache": "Pulisci la directory della cache",
|
||||
"TaskCleanCache": "Pulisci la cartella della cache",
|
||||
"TasksChannelsCategory": "Canali su Internet",
|
||||
"TasksApplicationCategory": "Applicazione",
|
||||
"TasksLibraryCategory": "Libreria",
|
||||
"TasksMaintenanceCategory": "Manutenzione",
|
||||
"TaskCleanActivityLog": "Attività di Registro Completate",
|
||||
"TaskCleanActivityLogDescription": "Elimina gli inserimenti nel registro delle attività più vecchie dell’età configurata.",
|
||||
"TaskCleanActivityLogDescription": "Elimina le voci del registro delle attività più vecchie dell’età configurata.",
|
||||
"Undefined": "Non Definito",
|
||||
"Forced": "Forzato",
|
||||
"Default": "Predefinito",
|
||||
"TaskOptimizeDatabaseDescription": "Compatta Database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altri cambiamenti inerenti il database potrebbe aumentarne la performance.",
|
||||
"TaskOptimizeDatabase": "Ottimizza Database",
|
||||
"TaskOptimizeDatabaseDescription": "Compatta database e tronca spazi liberi. Eseguire questa azione dopo la scansione o dopo aver fatto altre modifiche inerenti il database potrebbe aumentarne le prestazioni.",
|
||||
"TaskOptimizeDatabase": "Ottimizza database",
|
||||
"TaskKeyframeExtractor": "Estrattore di Keyframe",
|
||||
"TaskKeyframeExtractorDescription": "Estrae i keyframe dai video per creare migliori playlist HLS. Questa procedura potrebbe richiedere molto tempo.",
|
||||
"External": "Esterno",
|
||||
"HearingImpaired": "con problemi di udito",
|
||||
"HearingImpaired": "Non Udenti",
|
||||
"TaskRefreshTrickplayImages": "Genera immagini Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Crea anteprime trickplay per i video nelle librerie abilitate.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Ripulire le raccolte e le playlist",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Rimuove gli elementi dalle raccolte e dalle playlist che non esistono più.",
|
||||
"TaskAudioNormalization": "Normalizzazione Audio",
|
||||
"TaskAudioNormalizationDescription": "Scansione files per normalizzazione audio."
|
||||
"TaskCleanCollectionsAndPlaylists": "Ripulire le collezioni e le playlist",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Rimuove gli elementi dalle collezioni e dalle playlist che non esistono più.",
|
||||
"TaskAudioNormalization": "Normalizzazione dell'audio",
|
||||
"TaskAudioNormalizationDescription": "Scansiona i file alla ricerca dei dati per la normalizzazione dell'audio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Scarica testi per le canzoni",
|
||||
"TaskDownloadMissingLyrics": "Scarica testi mancanti",
|
||||
"TaskMoveTrickplayImages": "Sposta le immagini Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Sposta le immagini Trickplay esistenti secondo la configurazione della libreria."
|
||||
}
|
||||
|
||||
@@ -129,5 +129,10 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "コレクションとプレイリストをクリーンアップ",
|
||||
"TaskAudioNormalization": "音声の正規化",
|
||||
"TaskAudioNormalizationDescription": "音声の正規化データのためにファイルをスキャンします。",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "在しなくなったコレクションやプレイリストからアイテムを削除します。"
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "在しなくなったコレクションやプレイリストからアイテムを削除します。",
|
||||
"TaskDownloadMissingLyricsDescription": "歌詞をダウンロード",
|
||||
"TaskExtractMediaSegments": "メディアセグメントを読み取る",
|
||||
"TaskMoveTrickplayImages": "Trickplayの画像を移動",
|
||||
"TaskMoveTrickplayImagesDescription": "ライブラリ設定によりTrickplayのファイルを移動。",
|
||||
"TaskDownloadMissingLyrics": "記録されていない歌詞をダウンロード"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,133 @@
|
||||
{
|
||||
"Albums": "Albums"
|
||||
"Albums": "អាលប៊ុម",
|
||||
"MessageApplicationUpdatedTo": "ម៉ាស៊ីនមេនៃJellyfinត្រូវបានអាប់ដេតទៅកាន់ {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "ការកំណត់ម៉ាស៊ីនមេ ផ្នែក {0} ត្រូវបានអាប់ដេត",
|
||||
"MessageServerConfigurationUpdated": "ការកំណត់ម៉ាស៊ីនមេត្រូវបានអាប់ដេត",
|
||||
"AppDeviceValues": "កម្មវិធី: {0}, ឧបករណ៍: {1}",
|
||||
"MixedContent": "មាតិកាចម្រុះ",
|
||||
"UserLockedOutWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានផ្អាក",
|
||||
"Application": "កម្មវិធី",
|
||||
"Artists": "សិល្បករ",
|
||||
"AuthenticationSucceededWithUserName": "{0} បានផ្ទៀងផ្ទាត់ដោយជោគជ័យ",
|
||||
"Books": "សៀវភៅ",
|
||||
"NameSeasonNumber": "រដូវកាលទី {0}",
|
||||
"NotificationOptionPluginInstalled": "Plugin បានដំឡើងរួច",
|
||||
"CameraImageUploadedFrom": "រូបភាពកាមេរ៉ាថ្មីត្រូវបានបង្ហោះពី {0}",
|
||||
"Channels": "ប៉ុស្ត៍",
|
||||
"ChapterNameValue": "ជំពូក {0}",
|
||||
"Collections": "បណ្តុំ",
|
||||
"External": "ខាងក្រៅ",
|
||||
"Default": "លំនាំដើម",
|
||||
"NotificationOptionInstallationFailed": "ការដំឡើងមិនបានសម្រេច",
|
||||
"DeviceOfflineWithName": "{0} បានផ្តាច់",
|
||||
"Folders": "ថតឯកសារ",
|
||||
"DeviceOnlineWithName": "{0} បានភ្ចាប់",
|
||||
"HearingImpaired": "ខ្សោយការស្តាប់",
|
||||
"HomeVideos": "វីឌីអូថតខ្លួនឯង",
|
||||
"Favorites": "ចំណូលចិត្ត",
|
||||
"HeaderFavoriteEpisodes": "ភាគដែលចូលចិត្ត",
|
||||
"Forced": "បង្ខំ",
|
||||
"Genres": "ប្រភេទ",
|
||||
"HeaderFavoriteArtists": "សិល្បករដែលចូលចិត្ត",
|
||||
"NotificationOptionApplicationUpdateAvailable": "កម្មវិធី យើងអាចអាប់ដេតបាន",
|
||||
"NotificationOptionApplicationUpdateInstalled": "កម្មវិធី ដែលបានដំឡើងរួច",
|
||||
"NotificationOptionAudioPlaybackStopped": "ការចាក់សម្លេងបានផ្អាក",
|
||||
"HeaderContinueWatching": "បន្តមើល",
|
||||
"HeaderFavoriteAlbums": "អាល់ប៊ុមដែលចូលចិត្ត",
|
||||
"HeaderFavoriteShows": "រឿងភាគដែលចូលចិត្ត",
|
||||
"NewVersionIsAvailable": "មានជំនាន់ថ្មី ម៉ាស៊ីនមេJellyfin អាចទាញយកបាន.",
|
||||
"HeaderAlbumArtists": "សិល្បករអាល់ប៊ុម",
|
||||
"NotificationOptionCameraImageUploaded": "រូបភាពពីកាំមេរ៉ាបានអាប់ឡូតរួច",
|
||||
"HeaderFavoriteSongs": "ចម្រៀងដែលចូលចិត្ត",
|
||||
"HeaderNextUp": "បន្ទាប់",
|
||||
"HeaderLiveTV": "ទូរទស្សន៍ផ្សាយផ្ទាល់",
|
||||
"Movies": "រឿង",
|
||||
"HeaderRecordingGroups": "ក្រុមនៃការថត",
|
||||
"Music": "តន្ត្រី",
|
||||
"Inherit": "មរតក",
|
||||
"MusicVideos": "វីដេអូតន្ត្រី",
|
||||
"NameInstallFailed": "{0} ការដំឡើងបានបរាជ័យ",
|
||||
"NotificationOptionNewLibraryContent": "មាតិកាថ្មីៗត្រូវបានបន្ថែម",
|
||||
"ItemAddedWithName": "{0} ត្រូវបានបន្ថែមទៅបណ្ណាល័យ",
|
||||
"NameSeasonUnknown": "រដូវកាលមិនច្បាស់លាស់",
|
||||
"ItemRemovedWithName": "{0} ត្រូវបានដកចេញពីបណ្ណាល័យ",
|
||||
"LabelIpAddressValue": "លេខ IP: {0}",
|
||||
"LabelRunningTimeValue": "ពេលវេលាកំពុងដំណើរការ: {0}",
|
||||
"Latest": "ចុងក្រោយ",
|
||||
"NotificationOptionAudioPlayback": "ការចាក់សំឡេងបានចាប់ផ្ដើម",
|
||||
"NotificationOptionPluginError": "Plugin មិនដំណើរការ",
|
||||
"NotificationOptionPluginUninstalled": "Plugin បានលុបចេញរួច",
|
||||
"MessageApplicationUpdated": "ម៉ាស៊ីនមេនៃJellyfinត្រូវបានអាប់ដេត",
|
||||
"NotificationOptionPluginUpdateInstalled": "Plugin អាប់ដេតបានដំឡើងរួច",
|
||||
"NotificationOptionUserLockedOut": "អ្នកប្រើប្រាស់ត្រូវបានជាប់គាំង",
|
||||
"NotificationOptionServerRestartRequired": "តម្រូវឱ្យចាប់ផ្ដើមម៉ាស៊ីនមេឡើងវិញ",
|
||||
"Photos": "រូបថត",
|
||||
"Playlists": "បញ្ជីចាក់",
|
||||
"Plugin": "Plugin",
|
||||
"PluginInstalledWithName": "{0} ត្រូវបានដំឡើង",
|
||||
"NotificationOptionTaskFailed": "កិច្ចការដែលបានគ្រោងទុកបានបរាជ័យ",
|
||||
"PluginUpdatedWithName": "{0} ត្រូវបានអាប់ដេត",
|
||||
"NotificationOptionVideoPlayback": "ការចាក់វីដេអូបានចាប់ផ្តើម",
|
||||
"Songs": "ចម្រៀង",
|
||||
"ScheduledTaskStartedWithName": "{0} បានចាប់ផ្តើម",
|
||||
"NotificationOptionVideoPlaybackStopped": "ការចាក់វីដេអូបានបញ្ឈប់",
|
||||
"PluginUninstalledWithName": "{0} ត្រូវបានលុបចេញ",
|
||||
"Shows": "រឿងភាគ",
|
||||
"ProviderValue": "អ្នកផ្តល់សេវា: {0}",
|
||||
"SubtitleDownloadFailureFromForItem": "សាប់ថាយថលបានបរាជ័យក្នុងការទាញយកពី {0} នៃ {1}",
|
||||
"Sync": "ធ្វើអោយដំណាលគ្នា",
|
||||
"System": "ប្រព័ន្ធ",
|
||||
"TvShows": "កម្មវិធីទូរទស្សន៍",
|
||||
"ScheduledTaskFailedWithName": "{0} បានបរាជ័យ",
|
||||
"Undefined": "មិនបានកំណត់",
|
||||
"User": "អ្នកប្រើប្រាស់",
|
||||
"UserCreatedWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានបង្កើតឡើង",
|
||||
"ServerNameNeedsToBeRestarted": "{0} ចាំបាច់ត្រូវចាប់ផ្តើមឡើងវិញ",
|
||||
"StartupEmbyServerIsLoading": "ម៉ាស៊ីនមេJellyfin កំពុងដំណើរការ. សូមព្យាយាមម្តងទៀតក្នុងពេលឆាប់ៗនេះ.",
|
||||
"UserDeletedWithName": "អ្នកប្រើប្រាស់ {0} ត្រូវបានលុបចេញ",
|
||||
"UserOnlineFromDevice": "{0} បានឃើញអនឡានពី {1}",
|
||||
"UserDownloadingItemWithValues": "{0} កំពុងទាញយក {1}",
|
||||
"UserOfflineFromDevice": "{0} បានផ្តាច់ចេញពី {1}",
|
||||
"UserStartedPlayingItemWithValues": "{0} កំពុងចាក់ {1} នៅលើ {2}",
|
||||
"TaskRefreshChapterImagesDescription": "បង្កើតរូបភាពតូចៗសម្រាប់វីដេអូដែលមានតាមជំពូក.",
|
||||
"VersionNumber": "កំណែ {0}",
|
||||
"TasksMaintenanceCategory": "តំហែរទាំ",
|
||||
"TasksLibraryCategory": "បណ្ណាល័យ",
|
||||
"TasksApplicationCategory": "កម្មវិធី",
|
||||
"TaskCleanActivityLog": "សម្អាតកំណត់ហេតុសកម្មភាព",
|
||||
"UserPasswordChangedWithName": "ពាក្យសម្ងាត់ត្រូវបានផ្លាស់ប្តូរសម្រាប់អ្នកប្រើប្រាស់ {0}",
|
||||
"TaskCleanCache": "សម្អាតបញ្ជីឃ្លាំងសម្ងាត់",
|
||||
"TaskRefreshChapterImages": "ដកស្រង់រូបភាពតាមជំពូក",
|
||||
"UserPolicyUpdatedWithName": "គោលការណ៍អ្នកប្រើប្រាស់ត្រូវបានធ្វើបច្ចុប្បន្នភាពសម្រាប់ {0}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} បានបញ្ចប់ការចាក់ {1} នៅលើ {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} ត្រូវបានបញ្ចូលទៅក្នុងបណ្ណាល័យរឿងរបស់អ្នក",
|
||||
"ValueSpecialEpisodeName": "ពិសេស - {0}",
|
||||
"TasksChannelsCategory": "ប៉ុស្តតាមអ៊ីនធឺណិត",
|
||||
"TaskAudioNormalization": "ធ្វើឱ្យមានតន្ត្រីមានសម្លេងស្មើគ្នា",
|
||||
"TaskCleanActivityLogDescription": "លុបកំណត់ហេតុសកម្មភាពចាស់ជាងអាយុដែលបានកំណត់រចនាសម្ព័ន្ធ.",
|
||||
"TaskCleanCacheDescription": "លុបឯកសារឃ្លាំងសម្ងាត់លែងត្រូវការដោយប្រព័ន្ធ.",
|
||||
"TaskRefreshLibraryDescription": "ស្កេនបណ្ណាល័យរឿងរបស់អ្នក សម្រាប់ឯកសារថ្មីៗ និងmetadata ឡើងវិញ.",
|
||||
"TaskCleanLogsDescription": "លុបឯកសារកំណត់ហេតុដែលមានអាយុកាលលើសពី {0} ថ្ងៃ.",
|
||||
"TaskRefreshPeopleDescription": "ធ្វើបច្ចុប្បន្នភាព metadata សម្រាប់តួសម្តែង និងអ្នកដឹកនាំនៅក្នុងបណ្ណាល័យរឿងរបស់អ្នក.",
|
||||
"TaskOptimizeDatabaseDescription": "បង្រួម Database និង Truncate free space. ដំណើរការកិច្ចការនេះ បន្ទាប់ពីការស្កេនបណ្ណាល័យ ឬធ្វើការផ្លាស់ប្តូរផ្សេងទៀត ដែលបញ្ជាក់ថា ការកែប្រែ Database អាចធ្វើឱ្យដំណើរការប្រសើរឡើង.",
|
||||
"TaskRefreshTrickplayImages": "បង្កើតបណ្តុំរូបភាពតាម Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "បង្កើត trickplay previews សម្រាប់វីដេអូក្នុងបណ្ណាល័យដែលបានបង្ហាញ.",
|
||||
"TaskKeyframeExtractorDescription": "ស្រង់យកFrame គន្លឹះៗពីវីដេអូ ដើម្បីបង្កើតបញ្ជីចាក់ HLS ច្បាស់លាស់ជាងមុន. កិច្ចការនេះអាចនឹងដំណើរការយូរ.",
|
||||
"FailedLoginAttemptWithUserName": "បរាជ័យក្នុងការព្យាយាមចូលពី {0}",
|
||||
"TaskCleanTranscode": "សម្អាតថតឯកសារ Transcode",
|
||||
"TaskRefreshChannelsDescription": "Refreshes ព័ត៌មានបណ្តាញអ៊ីនធឺណិត.",
|
||||
"TaskDownloadMissingSubtitles": "ទាញយកសាប់ថាយថលដែលបាត់",
|
||||
"TaskRefreshChannels": "Refresh ឆានែល",
|
||||
"TaskKeyframeExtractor": "ការញែក Keyframe",
|
||||
"TaskAudioNormalizationDescription": "ស្កែនឯកសារសម្រាប់ធ្វើឱ្យមានតន្ត្រីមានសម្លេងស្មើគ្នា.",
|
||||
"TaskRefreshLibrary": "ស្កេនបណ្ណាល័យរឿង",
|
||||
"TaskCleanLogs": "សម្អាត Log Directory",
|
||||
"TaskRefreshPeople": "Refresh អ្នកប្រើប្រាស់",
|
||||
"TaskUpdatePlugins": "ធ្វើបច្ចុប្បន្នភាព Plugins",
|
||||
"TaskUpdatePluginsDescription": "ទាញយក និងដំឡើងបច្ចុប្បន្នភាពសម្រាប់Plugins ដែលត្រូវបាន Config ដើម្បីធ្វើបច្ចុប្បន្នភាពដោយស្វ័យប្រវត្តិ.",
|
||||
"TaskCleanTranscodeDescription": "លុបឯកសារ Transcode ដែលលើសពីមួយថ្ងៃ.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "ស្វែងរកតាមអ៊ីនធឺណិត សម្រាប់សាប់ថាយថល ដែលបាត់ដោយផ្អែកលើ metadata.",
|
||||
"TaskOptimizeDatabase": "ធ្វើឱ្យ Database ប្រសើរឡើង",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "លុបរបស់របរចេញពីបណ្តុំ និងបញ្ជីចាក់ដែលលែងមាន.",
|
||||
"TaskCleanCollectionsAndPlaylists": "សម្អាតបណ្តុំ និងបញ្ជីចាក់"
|
||||
}
|
||||
|
||||
@@ -125,5 +125,10 @@
|
||||
"TaskKeyframeExtractor": "키프레임 추출",
|
||||
"External": "외부",
|
||||
"HearingImpaired": "청각 장애",
|
||||
"TaskCleanCollectionsAndPlaylists": "컬렉션과 재생목록 정리"
|
||||
"TaskCleanCollectionsAndPlaylists": "컬렉션과 재생목록 정리",
|
||||
"TaskAudioNormalization": "오디오의 볼륨 수준을 일정하게 조정",
|
||||
"TaskAudioNormalizationDescription": "오디오의 볼륨 수준을 일정하게 조정하기 위해 파일을 스캔합니다.",
|
||||
"TaskRefreshTrickplayImages": "비디오 탐색용 미리보기 썸네일 생성",
|
||||
"TaskRefreshTrickplayImagesDescription": "활성화된 라이브러리에서 비디오의 트릭플레이 미리보기를 생성합니다.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "더 이상 존재하지 않는 컬렉션 및 재생 목록에서 항목을 제거합니다."
|
||||
}
|
||||
|
||||
139
Emby.Server.Implementations/Localization/Core/kw.json
Normal file
139
Emby.Server.Implementations/Localization/Core/kw.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"Collections": "Kuntellow",
|
||||
"DeviceOfflineWithName": "{0} re anjunyas",
|
||||
"External": "A-ves",
|
||||
"Folders": "Plegellow",
|
||||
"HeaderFavoriteAlbums": "Albomow Drudh",
|
||||
"HeaderFavoriteArtists": "Artydhyon Drudh",
|
||||
"HeaderFavoriteEpisodes": "Towlennow Drudh",
|
||||
"HeaderFavoriteSongs": "Kanow Drudh",
|
||||
"HeaderRecordingGroups": "Bagasow Rekordya",
|
||||
"HearingImpaired": "Klewans Aperys",
|
||||
"HomeVideos": "Gwydhyow Tre",
|
||||
"Inherit": "Herya",
|
||||
"LabelRunningTimeValue": "Prys ow ponya: {0}",
|
||||
"Latest": "Diwettha",
|
||||
"MessageApplicationUpdated": "Servell Jellyfin re beu nowedhys",
|
||||
"MessageApplicationUpdatedTo": "Servell Jellyfin re beu nowedhys dhe {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Rann dewisyans servell {0} re beu nowedhys",
|
||||
"MixedContent": "Dalgh kemmyskys",
|
||||
"Movies": "Fylmow",
|
||||
"MusicVideos": "Gwydhyow Ilow",
|
||||
"NameSeasonUnknown": "Seson Anwodhvedhys",
|
||||
"NotificationOptionAudioPlayback": "Seneans dallethys",
|
||||
"NotificationOptionAudioPlaybackStopped": "Seneans hedhys",
|
||||
"NotificationOptionPluginError": "Defowt ystynnans",
|
||||
"NotificationOptionPluginUninstalled": "Ystynnans anynstallys",
|
||||
"NotificationOptionPluginUpdateInstalled": "Nowedheans ystynnans ynstallys",
|
||||
"Application": "Gweythres",
|
||||
"Favorites": "Moyha Kerys",
|
||||
"Forced": "Konstrynys",
|
||||
"Albums": "Albomow",
|
||||
"Books": "Lyvrow",
|
||||
"Channels": "Kanolyow",
|
||||
"AppDeviceValues": "App: {0}, Devis: {1}",
|
||||
"Artists": "Artyhdyon",
|
||||
"HeaderAlbumArtists": "Albom artydhyon",
|
||||
"HeaderNextUp": "Nessa",
|
||||
"CameraImageUploadedFrom": "Skeusen kamera nowydh re beu ughkargys a-dhyworth {0}",
|
||||
"ChapterNameValue": "Chaptra {0}",
|
||||
"FailedLoginAttemptWithUserName": "Assay omgelm fyllys a-dhyworth {0}",
|
||||
"AuthenticationSucceededWithUserName": "{0} omgelmys yn sewen",
|
||||
"Default": "Defowt",
|
||||
"DeviceOnlineWithName": "{0} yw junys",
|
||||
"ItemRemovedWithName": "{0} a veu dileys a-dhyworth an lyverva",
|
||||
"LabelIpAddressValue": "Trigva PK: {)}",
|
||||
"Music": "Ilow",
|
||||
"HeaderContinueWatching": "Pesya Ow Kweles",
|
||||
"NameSeasonNumber": "Seson {0}",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Nowedheans gweythres ynstallys",
|
||||
"NotificationOptionCameraImageUploaded": "Skeusen kamera ughkargys",
|
||||
"HeaderFavoriteShows": "Diskwedhyansow Drudh",
|
||||
"HeaderLiveTV": "PW Yn Fyw",
|
||||
"MessageServerConfigurationUpdated": "Dewisyans servell re beu nowedhys",
|
||||
"ItemAddedWithName": "{0} a veu keworrys dhe'n lyverva",
|
||||
"NameInstallFailed": "{0} ynstallyans fyllys",
|
||||
"NotificationOptionNewLibraryContent": "Dalgh nowydh keworrys",
|
||||
"NewVersionIsAvailable": "Yma versyon nowydh a Servell Jellyfin neb yw kavadow rag iskarga.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Nowedheans gweythres kavadow",
|
||||
"NotificationOptionInstallationFailed": "Defowt ynstallyans",
|
||||
"Genres": "Eghennow",
|
||||
"NotificationOptionPluginInstalled": "Ystynnans ynstallys",
|
||||
"NotificationOptionServerRestartRequired": "Dastalleth servell yw res",
|
||||
"StartupEmbyServerIsLoading": "Yma Servell Jellyfin ow kargya. Assay arta yn berr mar pleg.",
|
||||
"SubtitleDownloadFailureFromForItem": "Istitlow a fyllis iskarga a-dhyworth {0] rag {1}",
|
||||
"System": "Kevreyth",
|
||||
"User": "Devnydhyer",
|
||||
"UserDeletedWithName": "Devnydhyer {0} re beu dileys",
|
||||
"UserLockedOutWithName": "Devnydhyer {0} re beu alhwedhys yn-mes",
|
||||
"UserStoppedPlayingItemWithValues": "{0} re worfennas gwari {1} war {2}",
|
||||
"UserOfflineFromDevice": "{0} re anjunyas a-dhyworth {1}",
|
||||
"UserOnlineFromDevice": "{0} yw warlinen a-dhyworth {1}",
|
||||
"NotificationOptionUserLockedOut": "Devnydhyer yw alhwedhys yn-mes",
|
||||
"Photos": "Skeusennow",
|
||||
"Playlists": "Rolyow-gwari",
|
||||
"Plugin": "Ystynnans",
|
||||
"PluginInstalledWithName": "{0} a veu ynstallys",
|
||||
"UserPolicyUpdatedWithName": "Polici devnydhyer re beu nowedhys rag {0}",
|
||||
"PluginUpdatedWithName": "{0} a veu nowedhys",
|
||||
"ScheduledTaskFailedWithName": "{0} a fyllis",
|
||||
"Songs": "Kanow",
|
||||
"Sync": "Kesseni",
|
||||
"TvShows": "Towlennow PW",
|
||||
"Undefined": "Anstyrys",
|
||||
"UserCreatedWithName": "Devnydhyer {0} re beu gwruthys",
|
||||
"UserDownloadingItemWithValues": "Yma {0} owth iskarga {1}",
|
||||
"UserPasswordChangedWithName": "Ger-tremena re beu chanjys rag devnydhyer {0}",
|
||||
"UserStartedPlayingItemWithValues": "Yma {0} ow kwari {1} war {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} re beu keworrys dhe'th lyverva media",
|
||||
"VersionNumber": "Versyon {0}",
|
||||
"TasksLibraryCategory": "Lyverva",
|
||||
"TaskCleanActivityLog": "Glanhe Kovlyver Gwrians",
|
||||
"TaskRefreshPeople": "Disegha Tus",
|
||||
"TaskRefreshLibrary": "Arhwilas Lyverva Media",
|
||||
"TaskCleanTranscodeDescription": "Y hwra dilea restrennow treylya neg a veu gwrys kyns nans yw dydh.",
|
||||
"NotificationOptionVideoPlaybackStopped": "Gwareans gwydhyow yw hedhys",
|
||||
"NotificationOptionVideoPlayback": "Gwareans gwydhyow yw dallethys",
|
||||
"PluginUninstalledWithName": "{0} a veu anynstallys",
|
||||
"NotificationOptionTaskFailed": "Defowt oberen towlennys",
|
||||
"ProviderValue": "Provier: {0}",
|
||||
"ScheduledTaskStartedWithName": "{0} a dhallathas",
|
||||
"ServerNameNeedsToBeRestarted": "Yma edhom dhe {0} a vos dastallathys",
|
||||
"ValueSpecialEpisodeName": "Arbennik - {0}",
|
||||
"TasksMaintenanceCategory": "Mentons",
|
||||
"TasksApplicationCategory": "Gweythres",
|
||||
"TasksChannelsCategory": "Kanolyow Kesrosweyth",
|
||||
"TaskCleanLogs": "Glanhe Kevarwodhyador Kovlyver",
|
||||
"TaskAudioNormalization": "Normalheans Klewans",
|
||||
"TaskRefreshChannels": "Disegha Kanolyow",
|
||||
"TaskCleanTranscode": "Glanhe Kevarwodhyador Treylya",
|
||||
"TaskUpdatePlugins": "Nowedhi Ystynansow",
|
||||
"Shows": "Diskwedhyansow",
|
||||
"TaskCleanCache": "Glanhe Kevarwodhyador Gwithva",
|
||||
"TaskCleanActivityLogDescription": "Y hwra dilea lin kovlyver gwrians kottha ages an bloodh dewisys.",
|
||||
"TaskCleanCacheDescription": "Y hwra dilea restrennow gwithva nag yw res rag an kevreyth.",
|
||||
"TaskRefreshPeopleDescription": "Y hwra nowedhi metadata rag gwarioryon ha kevarwodhoryon yn dha lyverva media.",
|
||||
"TaskRefreshChapterImages": "Kuntel Imajys Chaptra",
|
||||
"TaskRefreshChapterImagesDescription": "Y hwra ewines meus rag gwydhyowyow gans chaptraow.",
|
||||
"TaskRefreshTrickplayImagesDescription": "Y hwra kynwelyow trickplay rag gwydhyowyow yn lyvervaow gallosegys.",
|
||||
"TaskRefreshTrickplayImages": "Dinythi Imajys Trickplay",
|
||||
"TaskCleanLogsDescription": "Y hwra dilea restrennow kovlyver a veu gwrys kyns nans yw {0} dydh.",
|
||||
"TaskDownloadMissingLyrics": "Iskarga geryow kellys",
|
||||
"TaskUpdatePluginsDescription": "Y hwra iskarga hag ynstallya nowedheansow rag ystynansow neb yw dewisys dhe nowedhi yn awtomatek.",
|
||||
"TaskDownloadMissingSubtitles": "Iskarga istitlow kellys",
|
||||
"TaskRefreshChannelsDescription": "Y hwra disegha kedhlow kanolyow kesrosweyth.",
|
||||
"TaskDownloadMissingLyricsDescription": "Y hwra iskarga geryow rag kanow",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Y hwra hwilas an kesrosweyth rag istitlow kellys a-dhywoth dewisyans metadata.",
|
||||
"TaskOptimizeDatabase": "Gwellhe selvanylyon",
|
||||
"TaskOptimizeDatabaseDescription": "Y hwra kesstrotha ha berrhe efander rydh. Martesen y hwra gwellhe gwryth mar kwre'ta an oberen ma wosa ty dhe arhwilas an lyverva, po neb chanj aral neb a brof chanjyansow selvanylyon.",
|
||||
"TaskAudioNormalizationDescription": "Y hwra arhwilas restrennow rag manylyon normalheans klewans.",
|
||||
"TaskRefreshLibraryDescription": "Y hwra arhwilas dha lyverva media rag restrennow nowydh ha disegha metamanylyon.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Glanhe kuntellow ha rolyow-gwari",
|
||||
"TaskKeyframeExtractor": "Estennell Framalhwedh",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Y hwra dilea taklow a-dhyworth kuntellow ha rolyow-gwari na vos na moy.",
|
||||
"TaskKeyframeExtractorDescription": "Y hwra kuntel framyowalhwedh a-dhyworth restrennow gwydhyowyow rag gul rolyow-gwari HLS moy poran. Martesen y hwra an oberen ma ow ponya rag termyn hir.",
|
||||
"TaskExtractMediaSegments": "Arhwilas Rann Media",
|
||||
"TaskExtractMediaSegmentsDescription": "Kavos rannow media a-dhyworth ystynansow gallosegys MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Divroa Tyller Imach TrickPlay",
|
||||
"TaskMoveTrickplayImagesDescription": "Y hwra movya restrennow a-lemmyn trickplay herwydh settyansow lyverva."
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Kolekcijos",
|
||||
"DeviceOfflineWithName": "{0} buvo atjungtas",
|
||||
"DeviceOnlineWithName": "{0} prisijungęs",
|
||||
"FailedLoginAttemptWithUserName": "Nesėkmingas prisijungimas iš {0}",
|
||||
"FailedLoginAttemptWithUserName": "Nesėkmingas {0} bandymas prisijungti",
|
||||
"Favorites": "Mėgstami",
|
||||
"Folders": "Katalogai",
|
||||
"Genres": "Žanrai",
|
||||
@@ -127,6 +127,14 @@
|
||||
"HearingImpaired": "Su klausos sutrikimais",
|
||||
"TaskRefreshTrickplayImages": "Generuoti Trickplay atvaizdus",
|
||||
"TaskRefreshTrickplayImagesDescription": "Sukuria trickplay peržiūras vaizdo įrašams įgalintose bibliotekose.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Sutvarko duomenis jūsų kolekcijose ir grojaraščiuose.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Pašalina nebeegzistuojančius elementus iš kolekcijų ir grojaraščių."
|
||||
"TaskCleanCollectionsAndPlaylists": "Sutvarko duomenis jūsų kolekcijose ir grojaraščiuose",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Pašalina nebeegzistuojančius elementus iš kolekcijų ir grojaraščių.",
|
||||
"TaskAudioNormalization": "Garso Normalizavimas",
|
||||
"TaskAudioNormalizationDescription": "Skenuoti garso normalizavimo informacijos failuose.",
|
||||
"TaskExtractMediaSegments": "Medijos Segmentų Nuskaitymas",
|
||||
"TaskDownloadMissingLyrics": "Parsisiųsti trūkstamus dainų tekstus",
|
||||
"TaskExtractMediaSegmentsDescription": "Ištraukia arba gauna medijos segmentus iš MediaSegment ijungtų papildinių.",
|
||||
"TaskMoveTrickplayImages": "Migruoti Trickplay Vaizdų Vietą",
|
||||
"TaskMoveTrickplayImagesDescription": "Perkelia egzisuojančius trickplay failus pagal bibliotekos nustatymus.",
|
||||
"TaskDownloadMissingLyricsDescription": "Parsisiųsti dainų žodžius"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"Inherit": "Pārmantot",
|
||||
"AppDeviceValues": "Lietotne: {0}, Ierīce: {1}",
|
||||
"VersionNumber": "Versija {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} ir ticis pievienots jūsu multvides bibliotēkai",
|
||||
"ValueHasBeenAddedToLibrary": "{0} tika pievienots jūsu multvides bibliotēkai",
|
||||
"UserStoppedPlayingItemWithValues": "{0} ir beidzis atskaņot {1} uz {2}",
|
||||
"UserStartedPlayingItemWithValues": "{0} atskaņo {1} uz {2}",
|
||||
"UserPasswordChangedWithName": "Lietotāja {0} parole tika nomainīta",
|
||||
@@ -95,7 +95,7 @@
|
||||
"TaskRefreshChapterImages": "Izvilkt nodaļu attēlus",
|
||||
"TasksApplicationCategory": "Lietotne",
|
||||
"TasksLibraryCategory": "Bibliotēka",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Internetā meklē trūkstošus subtitrus balstoties uz metadatu uzstādījumiem.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Meklē internetā trūkstošos subtitrus, pamatojoties uz metadatu konfigurāciju.",
|
||||
"TaskDownloadMissingSubtitles": "Lejupielādēt trūkstošos subtitrus",
|
||||
"TaskRefreshChannelsDescription": "Atjauno interneta kanālu informāciju.",
|
||||
"TaskRefreshChannels": "Atjaunot kanālus",
|
||||
@@ -105,8 +105,8 @@
|
||||
"TaskUpdatePlugins": "Atjaunot paplašinājumus",
|
||||
"TaskRefreshPeopleDescription": "Atjauno metadatus aktieriem un direktoriem jūsu multivides bibliotēkā.",
|
||||
"TaskRefreshPeople": "Atjaunot cilvēkus",
|
||||
"TaskCleanLogsDescription": "Nodzēš logdatnes, kas ir senākas par {0} dienām.",
|
||||
"TaskCleanLogs": "Iztīrīt logdatņu mapi",
|
||||
"TaskCleanLogsDescription": "Nodzēš žurnāla ierakstus, kas ir senāki par {0} dienām.",
|
||||
"TaskCleanLogs": "Iztīrīt žurnālu mapi",
|
||||
"TaskRefreshLibraryDescription": "Skenē jūsu multivides bibliotēku, lai atrastu jaunas datnes, un atsvaidzina metadatus.",
|
||||
"TaskRefreshLibrary": "Skenēt multivides bibliotēku",
|
||||
"TaskRefreshChapterImagesDescription": "Izveido sīktēlus priekš video ar sadaļām.",
|
||||
@@ -125,5 +125,9 @@
|
||||
"TaskKeyframeExtractor": "Atslēgkadru ekstraktors",
|
||||
"TaskKeyframeExtractorDescription": "Ekstraktē atslēgkadrus no video failiem lai izveidotu precīzākus HLS atskaņošanas sarakstus. Šis process var būt ilgs.",
|
||||
"TaskRefreshTrickplayImages": "Ģenerēt partīšanas attēlus",
|
||||
"TaskRefreshTrickplayImagesDescription": "Izveido priekšskatījumus videoklipu pārtīšanai iespējotajās bibliotēkās."
|
||||
"TaskRefreshTrickplayImagesDescription": "Izveido priekšskatījumus videoklipu pārtīšanai iespējotajās bibliotēkās.",
|
||||
"TaskAudioNormalization": "Audio normalizācija",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Noņem vairs neeksistējošus vienumus no kolekcijām un atskaņošanas sarakstiem.",
|
||||
"TaskAudioNormalizationDescription": "Skanē failus priekš audio normālizācijas informācijas.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Notīrīt kolekcijas un atskaņošanas sarakstus"
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"Genres": "Жанрови",
|
||||
"Folders": "Папки",
|
||||
"Favorites": "Омилени",
|
||||
"FailedLoginAttemptWithUserName": "Неуспешно поврзување од {0}",
|
||||
"FailedLoginAttemptWithUserName": "Неуспешен обид за најавување од {0}",
|
||||
"DeviceOnlineWithName": "{0} е приклучен",
|
||||
"DeviceOfflineWithName": "{0} се исклучи",
|
||||
"Collections": "Колекции",
|
||||
@@ -123,5 +123,13 @@
|
||||
"TaskCleanActivityLogDescription": "Избришува логови на активности постари од определеното време.",
|
||||
"TaskCleanActivityLog": "Избриши Лог на Активности",
|
||||
"External": "Надворешен",
|
||||
"HearingImpaired": "Оштетен слух"
|
||||
"HearingImpaired": "Оштетен слух",
|
||||
"TaskCleanCollectionsAndPlaylists": "Исчисти ги колекциите и плејлистите",
|
||||
"TaskAudioNormalizationDescription": "Скенирање датотеки за податоци за нормализација на звукот.",
|
||||
"TaskDownloadMissingLyrics": "Преземи стихови кои недостасуваат",
|
||||
"TaskDownloadMissingLyricsDescription": "Преземи стихови/текстови за песни",
|
||||
"TaskRefreshTrickplayImages": "Генерирај слики за прегледување (Trickplay)",
|
||||
"TaskAudioNormalization": "Нормализација на звукот",
|
||||
"TaskRefreshTrickplayImagesDescription": "Креира трикплеј прегледи за видеа во овозможените библиотеки.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат."
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"ChapterNameValue": "അധ്യായം {0}",
|
||||
"DeviceOfflineWithName": "{0} വിച്ഛേദിച്ചു",
|
||||
"DeviceOnlineWithName": "{0} ബന്ധിപ്പിച്ചു",
|
||||
"FailedLoginAttemptWithUserName": "{0} - എന്നതിൽ നിന്നുള്ള പ്രവേശന ശ്രമം പരാജയപ്പെട്ടു",
|
||||
"FailedLoginAttemptWithUserName": "{0}ൽ നിന്നുള്ള പ്രവേശന ശ്രമം പരാജയപ്പെട്ടു",
|
||||
"Forced": "നിർബന്ധിച്ചു",
|
||||
"HeaderFavoriteAlbums": "പ്രിയപ്പെട്ട ആൽബങ്ങൾ",
|
||||
"HeaderFavoriteArtists": "പ്രിയപ്പെട്ട കലാകാരന്മാർ",
|
||||
@@ -125,5 +125,9 @@
|
||||
"TaskKeyframeExtractorDescription": "കൂടുതൽ കൃത്യമായ HLS പ്ലേലിസ്റ്റുകൾ സൃഷ്ടിക്കുന്നതിന് വീഡിയോ ഫയലുകളിൽ നിന്ന് കീഫ്രെയിമുകൾ എക്സ്ട്രാക്റ്റ് ചെയ്യുന്നു. ഈ പ്രവർത്തനം പൂർത്തിയാവാൻ കുറച്ചധികം സമയം എടുത്തേക്കാം.",
|
||||
"TaskKeyframeExtractor": "കീഫ്രെയിം എക്സ്ട്രാക്റ്റർ",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "നിലവിലില്ലാത്ത ശേഖരങ്ങളിൽ നിന്നും പ്ലേലിസ്റ്റുകളിൽ നിന്നും ഇനങ്ങൾ നീക്കംചെയ്യുന്നു.",
|
||||
"TaskCleanCollectionsAndPlaylists": "ശേഖരങ്ങളും പ്ലേലിസ്റ്റുകളും വൃത്തിയാക്കുക"
|
||||
"TaskCleanCollectionsAndPlaylists": "ശേഖരങ്ങളും പ്ലേലിസ്റ്റുകളും വൃത്തിയാക്കുക",
|
||||
"TaskAudioNormalization": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുക",
|
||||
"TaskAudioNormalizationDescription": "സാധാരണ ശബ്ദ നിലയിലെത്തിലെത്തിക്കുന്ന ഡാറ്റയ്ക്കായി ഫയലുകൾ സ്കാൻ ചെയ്യുക.",
|
||||
"TaskRefreshTrickplayImages": "ട്രിക്ക് പ്ലേ ചിത്രങ്ങൾ സൃഷ്ടിക്കുക",
|
||||
"TaskRefreshTrickplayImagesDescription": "പ്രവർത്തനക്ഷമമാക്കിയ ലൈബ്രറികളിൽ വീഡിയോകൾക്കായി ട്രിക്ക്പ്ലേ പ്രിവ്യൂകൾ സൃഷ്ടിക്കുന്നു."
|
||||
}
|
||||
|
||||
@@ -126,5 +126,15 @@
|
||||
"External": "Ekstern",
|
||||
"HearingImpaired": "Hørselshemmet",
|
||||
"TaskRefreshTrickplayImages": "Generer Trickplay bilder",
|
||||
"TaskRefreshTrickplayImagesDescription": "Oppretter trickplay-forhåndsvisninger for videoer i aktiverte biblioteker."
|
||||
"TaskRefreshTrickplayImagesDescription": "Oppretter trickplay-forhåndsvisninger for videoer i aktiverte biblioteker.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Rydd kolleksjoner og spillelister",
|
||||
"TaskAudioNormalization": "Lydnormalisering",
|
||||
"TaskAudioNormalizationDescription": "Skan filer for lydnormaliserende data.",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra kolleksjoner og spillelister som ikke lengere finnes.",
|
||||
"TaskDownloadMissingLyrics": "Last ned manglende tekster",
|
||||
"TaskDownloadMissingLyricsDescription": "Last ned sangtekster",
|
||||
"TaskExtractMediaSegments": "Skann mediasegment",
|
||||
"TaskMoveTrickplayImages": "Migrer bildeplassering for Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Flytter eksisterende Trickplay-filer i henhold til bibliotekseinstillingene.",
|
||||
"TaskExtractMediaSegmentsDescription": "Trekker ut eller henter mediasegmenter fra plugins som støtter MediaSegment."
|
||||
}
|
||||
|
||||
@@ -11,21 +11,21 @@
|
||||
"Collections": "Collecties",
|
||||
"DeviceOfflineWithName": "Verbinding met {0} is verbroken",
|
||||
"DeviceOnlineWithName": "{0} is verbonden",
|
||||
"FailedLoginAttemptWithUserName": "Mislukte inlogpoging van {0}",
|
||||
"FailedLoginAttemptWithUserName": "Mislukte aanmeldpoging vanaf {0}",
|
||||
"Favorites": "Favorieten",
|
||||
"Folders": "Mappen",
|
||||
"Genres": "Genres",
|
||||
"HeaderAlbumArtists": "Albumartiesten",
|
||||
"HeaderContinueWatching": "Kijken hervatten",
|
||||
"HeaderContinueWatching": "Verderkijken",
|
||||
"HeaderFavoriteAlbums": "Favoriete albums",
|
||||
"HeaderFavoriteArtists": "Favoriete artiesten",
|
||||
"HeaderFavoriteEpisodes": "Favoriete afleveringen",
|
||||
"HeaderFavoriteShows": "Favoriete shows",
|
||||
"HeaderFavoriteShows": "Favoriete series",
|
||||
"HeaderFavoriteSongs": "Favoriete nummers",
|
||||
"HeaderLiveTV": "Live TV",
|
||||
"HeaderNextUp": "Volgende",
|
||||
"HeaderLiveTV": "Live-tv",
|
||||
"HeaderNextUp": "Als volgende",
|
||||
"HeaderRecordingGroups": "Opnamegroepen",
|
||||
"HomeVideos": "Thuis video's",
|
||||
"HomeVideos": "Homevideo's",
|
||||
"Inherit": "Erven",
|
||||
"ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
|
||||
"ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
|
||||
@@ -34,8 +34,8 @@
|
||||
"Latest": "Nieuwste",
|
||||
"MessageApplicationUpdated": "Jellyfin Server is bijgewerkt",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server is bijgewerkt naar {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt",
|
||||
"MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de serverconfiguratie is bijgewerkt",
|
||||
"MessageServerConfigurationUpdated": "Serverconfiguratie is bijgewerkt",
|
||||
"MixedContent": "Gemengde inhoud",
|
||||
"Movies": "Films",
|
||||
"Music": "Muziek",
|
||||
@@ -50,14 +50,14 @@
|
||||
"NotificationOptionAudioPlaybackStopped": "Muziek gestopt",
|
||||
"NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload",
|
||||
"NotificationOptionInstallationFailed": "Installatie mislukt",
|
||||
"NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
|
||||
"NotificationOptionPluginError": "Plug-in fout",
|
||||
"NotificationOptionNewLibraryContent": "Nieuwe inhoud toegevoegd",
|
||||
"NotificationOptionPluginError": "Plug-in-fout",
|
||||
"NotificationOptionPluginInstalled": "Plug-in geïnstalleerd",
|
||||
"NotificationOptionPluginUninstalled": "Plug-in verwijderd",
|
||||
"NotificationOptionPluginUpdateInstalled": "Plug-in-update geïnstalleerd",
|
||||
"NotificationOptionServerRestartRequired": "Server herstart nodig",
|
||||
"NotificationOptionServerRestartRequired": "Herstarten server vereist",
|
||||
"NotificationOptionTaskFailed": "Geplande taak mislukt",
|
||||
"NotificationOptionUserLockedOut": "Gebruiker is vergrendeld",
|
||||
"NotificationOptionUserLockedOut": "Gebruiker buitengesloten",
|
||||
"NotificationOptionVideoPlayback": "Afspelen van video gestart",
|
||||
"NotificationOptionVideoPlaybackStopped": "Afspelen van video gestopt",
|
||||
"Photos": "Foto's",
|
||||
@@ -72,38 +72,38 @@
|
||||
"ServerNameNeedsToBeRestarted": "{0} moet herstart worden",
|
||||
"Shows": "Series",
|
||||
"Songs": "Nummers",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.",
|
||||
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden. Probeer het later opnieuw.",
|
||||
"SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertitels konden niet gedownload worden van {0} voor {1}",
|
||||
"SubtitleDownloadFailureFromForItem": "Ondertiteling kon niet gedownload worden van {0} voor {1}",
|
||||
"Sync": "Synchronisatie",
|
||||
"System": "Systeem",
|
||||
"TvShows": "TV-series",
|
||||
"TvShows": "Tv-series",
|
||||
"User": "Gebruiker",
|
||||
"UserCreatedWithName": "Gebruiker {0} is aangemaakt",
|
||||
"UserDeletedWithName": "Gebruiker {0} is verwijderd",
|
||||
"UserDownloadingItemWithValues": "{0} download {1}",
|
||||
"UserLockedOutWithName": "Gebruikersaccount {0} is vergrendeld",
|
||||
"UserOfflineFromDevice": "Verbinding van {0} met {1} is verbroken",
|
||||
"UserOnlineFromDevice": "{0} heeft verbinding met {1}",
|
||||
"UserDownloadingItemWithValues": "{0} downloadt {1}",
|
||||
"UserLockedOutWithName": "Gebruiker {0} is buitengesloten",
|
||||
"UserOfflineFromDevice": "Verbinding van {0} via {1} is verbroken",
|
||||
"UserOnlineFromDevice": "{0} is verbonden via {1}",
|
||||
"UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd",
|
||||
"UserPolicyUpdatedWithName": "Gebruikersbeleid gewijzigd voor {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} speelt {1} af op {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt op {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek",
|
||||
"ValueSpecialEpisodeName": "Speciaal - {0}",
|
||||
"ValueSpecialEpisodeName": "Special - {0}",
|
||||
"VersionNumber": "Versie {0}",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar ontbrekende ondertiteling gebaseerd op metadataconfiguratie.",
|
||||
"TaskDownloadMissingSubtitles": "Ontbrekende ondertiteling downloaden",
|
||||
"TaskRefreshChannelsDescription": "Vernieuwt informatie van internet kanalen.",
|
||||
"TaskRefreshChannelsDescription": "Vernieuwt informatie van internetkanalen.",
|
||||
"TaskRefreshChannels": "Kanalen vernieuwen",
|
||||
"TaskCleanTranscodeDescription": "Verwijdert transcode bestanden ouder dan 1 dag.",
|
||||
"TaskCleanTranscodeDescription": "Verwijdert transcoderingsbestanden ouder dan een dag.",
|
||||
"TaskCleanLogs": "Logboekmap opschonen",
|
||||
"TaskCleanTranscode": "Transcoderingsmap opschonen",
|
||||
"TaskUpdatePluginsDescription": "Downloadt en installeert updates van plug-ins waarvoor automatisch bijwerken is ingeschakeld.",
|
||||
"TaskUpdatePlugins": "Plug-ins bijwerken",
|
||||
"TaskRefreshPeopleDescription": "Updatet metadata voor acteurs en regisseurs in je mediabibliotheek.",
|
||||
"TaskRefreshPeopleDescription": "Werkt metadata bij voor acteurs en regisseurs in je mediabibliotheek.",
|
||||
"TaskRefreshPeople": "Personen vernieuwen",
|
||||
"TaskCleanLogsDescription": "Verwijdert log bestanden ouder dan {0} dagen.",
|
||||
"TaskCleanLogsDescription": "Verwijdert logboekbestanden ouder dan {0} dagen.",
|
||||
"TaskRefreshLibraryDescription": "Scant de mediabibliotheek op nieuwe bestanden en vernieuwt de metadata.",
|
||||
"TaskRefreshLibrary": "Mediabibliotheek scannen",
|
||||
"TaskRefreshChapterImagesDescription": "Maakt voorbeeldafbeedingen aan voor video's met hoofdstukken.",
|
||||
@@ -124,11 +124,17 @@
|
||||
"TaskKeyframeExtractorDescription": "Haalt keyframes uit videobestanden om preciezere HLS-afspeellijsten te maken. Deze taak kan lang duren.",
|
||||
"TaskKeyframeExtractor": "Keyframes uitpakken",
|
||||
"External": "Extern",
|
||||
"HearingImpaired": "Slechthorend",
|
||||
"HearingImpaired": "Slechthorenden",
|
||||
"TaskRefreshTrickplayImages": "Trickplay-afbeeldingen genereren",
|
||||
"TaskRefreshTrickplayImagesDescription": "Creëert trickplay-voorvertoningen voor video's in bibliotheken waarvoor dit is ingeschakeld.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Collecties en afspeellijsten opruimen",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Verwijdert niet langer bestaande items uit collecties en afspeellijsten.",
|
||||
"TaskAudioNormalization": "Geluidsnormalisatie",
|
||||
"TaskAudioNormalizationDescription": "Scant bestanden op gegevens voor geluidsnormalisatie."
|
||||
"TaskAudioNormalizationDescription": "Scant bestanden op gegevens voor geluidsnormalisatie.",
|
||||
"TaskDownloadMissingLyrics": "Ontbrekende liedteksten downloaden",
|
||||
"TaskDownloadMissingLyricsDescription": "Downloadt liedteksten",
|
||||
"TaskExtractMediaSegmentsDescription": "Verkrijgt mediasegmenten vanuit plug-ins met MediaSegment-ondersteuning.",
|
||||
"TaskMoveTrickplayImages": "Locatie trickplay-afbeeldingen migreren",
|
||||
"TaskMoveTrickplayImagesDescription": "Verplaatst bestaande trickplay-bestanden op basis van de bibliotheekinstellingen.",
|
||||
"TaskExtractMediaSegments": "Scannen op mediasegmenten"
|
||||
}
|
||||
|
||||
@@ -118,5 +118,6 @@
|
||||
"Undefined": "Udefinert",
|
||||
"Forced": "Tvungen",
|
||||
"Default": "Standard",
|
||||
"External": "Ekstern"
|
||||
"External": "Ekstern",
|
||||
"HearingImpaired": "Nedsett høyrsel"
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"Forced": "ਮਜਬੂਰ",
|
||||
"Folders": "ਫੋਲਡਰ",
|
||||
"Favorites": "ਮਨਪਸੰਦ",
|
||||
"FailedLoginAttemptWithUserName": "{0} ਤੋਂ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ",
|
||||
"FailedLoginAttemptWithUserName": "{0} ਤੋਂ ਲਾਗਇਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਫੇਲ ਹੋਈ",
|
||||
"DeviceOnlineWithName": "{0} ਜੁੜਿਆ ਹੋਇਆ ਹੈ",
|
||||
"DeviceOfflineWithName": "{0} ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ ਹੈ",
|
||||
"Default": "ਡਿਫੌਲਟ",
|
||||
@@ -119,5 +119,6 @@
|
||||
"AppDeviceValues": "ਐਪ: {0}, ਜੰਤਰ: {1}",
|
||||
"Albums": "ਐਲਬਮਾਂ",
|
||||
"TaskOptimizeDatabase": "ਡਾਟਾਬੇਸ ਅਨੁਕੂਲ ਬਣਾਓ",
|
||||
"External": "ਬਾਹਰੀ"
|
||||
"External": "ਬਾਹਰੀ",
|
||||
"HearingImpaired": "ਸੁਨਣ ਵਿਚ ਕਮਜ਼ੋਰ"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Kolekcje",
|
||||
"DeviceOfflineWithName": "{0} został rozłączony",
|
||||
"DeviceOnlineWithName": "{0} połączył się",
|
||||
"FailedLoginAttemptWithUserName": "Próba logowania przez {0} zakończona niepowodzeniem",
|
||||
"FailedLoginAttemptWithUserName": "Nieudana próba logowania przez {0}",
|
||||
"Favorites": "Ulubione",
|
||||
"Folders": "Foldery",
|
||||
"Genres": "Gatunki",
|
||||
@@ -98,8 +98,8 @@
|
||||
"TaskRefreshChannels": "Odśwież kanały",
|
||||
"TaskCleanTranscodeDescription": "Usuwa transkodowane pliki starsze niż 1 dzień.",
|
||||
"TaskCleanTranscode": "Wyczyść folder transkodowania",
|
||||
"TaskUpdatePluginsDescription": "Pobiera i instaluje aktualizacje dla pluginów, które są skonfigurowane do automatycznej aktualizacji.",
|
||||
"TaskUpdatePlugins": "Aktualizuj pluginy",
|
||||
"TaskUpdatePluginsDescription": "Pobiera i instaluje aktualizacje wtyczek, które są skonfigurowane do automatycznej aktualizacji.",
|
||||
"TaskUpdatePlugins": "Aktualizuj wtyczki",
|
||||
"TaskRefreshPeopleDescription": "Odświeża metadane o aktorów i reżyserów w Twojej bibliotece mediów.",
|
||||
"TaskRefreshPeople": "Odśwież obsadę",
|
||||
"TaskCleanLogsDescription": "Kasuje pliki logów starsze niż {0} dni.",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Usuwa elementy z kolekcji i list odtwarzania, które już nie istnieją.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Oczyść kolekcje i listy odtwarzania",
|
||||
"TaskAudioNormalization": "Normalizacja dźwięku",
|
||||
"TaskAudioNormalizationDescription": "Skanuje pliki w poszukiwaniu danych normalizacji dźwięku."
|
||||
"TaskAudioNormalizationDescription": "Skanuje pliki w poszukiwaniu danych normalizacji dźwięku.",
|
||||
"TaskDownloadMissingLyrics": "Pobierz brakujące słowa",
|
||||
"TaskDownloadMissingLyricsDescription": "Pobierz słowa piosenek",
|
||||
"TaskExtractMediaSegments": "Skanowanie segmentów mediów",
|
||||
"TaskMoveTrickplayImages": "Migruj lokalizację obrazu Trickplay",
|
||||
"TaskExtractMediaSegmentsDescription": "Wyodrębnia lub pobiera segmenty mediów z wtyczek obsługujących MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Przenosi istniejące pliki Trickplay zgodnie z ustawieniami biblioteki."
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"CameraImageUploadedFrom": "Uma nova imagem da câmera foi enviada de {0}",
|
||||
"Channels": "Canais",
|
||||
"ChapterNameValue": "Capítulo {0}",
|
||||
"Collections": "Coletâneas",
|
||||
"Collections": "Coleções",
|
||||
"DeviceOfflineWithName": "{0} se desconectou",
|
||||
"DeviceOnlineWithName": "{0} se conectou",
|
||||
"FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpe coleções e playlists",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e playlists que não existem mais.",
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskAudioNormalizationDescription": "Verifica arquivos em busca de dados de normalização de áudio."
|
||||
"TaskAudioNormalizationDescription": "Examina os ficheiros em busca de dados de normalização de áudio.",
|
||||
"TaskDownloadMissingLyricsDescription": "Baixar letras para músicas",
|
||||
"TaskDownloadMissingLyrics": "Baixar letra faltante",
|
||||
"TaskMoveTrickplayImagesDescription": "Move os arquivos do trickplay de acordo com as configurações da biblioteca.",
|
||||
"TaskExtractMediaSegments": "Varredura do segmento de mídia",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de mídia de plug-ins habilitados para MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migrar o local da imagem do Trickplay"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}",
|
||||
"Channels": "Canais",
|
||||
"ChapterNameValue": "Capítulo {0}",
|
||||
"Collections": "Colecções",
|
||||
"Collections": "Coleções",
|
||||
"DeviceOfflineWithName": "{0} desligou-se",
|
||||
"DeviceOnlineWithName": "{0} ligou-se",
|
||||
"FailedLoginAttemptWithUserName": "Tentativa de login falhada a partir de {0}",
|
||||
@@ -27,8 +27,8 @@
|
||||
"HeaderRecordingGroups": "Grupos de Gravação",
|
||||
"HomeVideos": "Vídeos Caseiros",
|
||||
"Inherit": "Herdar",
|
||||
"ItemAddedWithName": "{0} foi adicionado à biblioteca",
|
||||
"ItemRemovedWithName": "{0} foi removido da biblioteca",
|
||||
"ItemAddedWithName": "{0} foi adicionado à mediateca",
|
||||
"ItemRemovedWithName": "{0} foi removido da mediateca",
|
||||
"LabelIpAddressValue": "Endereço IP: {0}",
|
||||
"LabelRunningTimeValue": "Duração: {0}",
|
||||
"Latest": "Mais Recente",
|
||||
@@ -89,37 +89,37 @@
|
||||
"UserPolicyUpdatedWithName": "Política de utilizador alterada para {0}",
|
||||
"UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}",
|
||||
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
|
||||
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua mediateca",
|
||||
"ValueSpecialEpisodeName": "Especial - {0}",
|
||||
"VersionNumber": "Versão {0}",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Procurar na internet por legendas em falta baseado na configuração de metadados.",
|
||||
"TaskDownloadMissingSubtitles": "Fazer download de legendas em falta",
|
||||
"TaskDownloadMissingSubtitles": "Transferir legendas em falta",
|
||||
"TaskRefreshChannelsDescription": "Atualizar informação sobre canais da Internet.",
|
||||
"TaskRefreshChannels": "Atualizar Canais",
|
||||
"TaskCleanTranscodeDescription": "Apagar ficheiros de transcode com mais de um dia.",
|
||||
"TaskCleanTranscode": "Limpar a Diretoria de Transcode",
|
||||
"TaskUpdatePluginsDescription": "Faz o download e instala updates para os plugins que estão configurados para atualizar automaticamente.",
|
||||
"TaskUpdatePlugins": "Atualizar Plugins",
|
||||
"TaskRefreshPeopleDescription": "Atualizar metadados para atores e diretores na biblioteca.",
|
||||
"TaskRefreshPeopleDescription": "Atualizar metadados para elenco e equipa técnica da tua mediateca.",
|
||||
"TaskRefreshPeople": "Atualizar Pessoas",
|
||||
"TaskCleanLogsDescription": "Apagar ficheiros de log que têm mais de {0} dias.",
|
||||
"TaskCleanLogs": "Limpar a Diretoria de Logs",
|
||||
"TaskRefreshLibraryDescription": "Analisar a biblioteca de música para novos ficheiros e atualizar os metadados.",
|
||||
"TaskRefreshLibrary": "Analisar Biblioteca de Música",
|
||||
"TaskRefreshLibraryDescription": "Analisar a mediateca para novos ficheiros e atualizar os metadados.",
|
||||
"TaskRefreshLibrary": "Analisar mediateca",
|
||||
"TaskRefreshChapterImagesDescription": "Criar thumbnails para os vídeos que têm capítulos.",
|
||||
"TaskRefreshChapterImages": "Extrair Imagens dos Capítulos",
|
||||
"TaskCleanCacheDescription": "Apagar ficheiros em cache que já não são necessários.",
|
||||
"TaskCleanCache": "Limpar Cache",
|
||||
"TasksChannelsCategory": "Canais da Internet",
|
||||
"TasksApplicationCategory": "Aplicação",
|
||||
"TasksLibraryCategory": "Biblioteca",
|
||||
"TasksLibraryCategory": "Mediateca",
|
||||
"TasksMaintenanceCategory": "Manutenção",
|
||||
"TaskCleanActivityLogDescription": "Apaga as entradas do registo de atividade anteriores à data configurada.",
|
||||
"TaskCleanActivityLog": "Limpar registo de atividade",
|
||||
"Undefined": "Indefinido",
|
||||
"Forced": "Forçado",
|
||||
"Default": "Padrão",
|
||||
"TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
|
||||
"TaskOptimizeDatabaseDescription": "Otimiza e liberta espaço livre na base de dados. A execução desta tarefa depois de analisar a mediateca ou efetuar outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
|
||||
"TaskOptimizeDatabase": "Otimizar base de dados",
|
||||
"TaskKeyframeExtractorDescription": "Extrai quadros-chave de ficheiros de video para criar listas de reprodução HLS mais precisas. Esta tarefa pode demorar algum tempo.",
|
||||
"TaskKeyframeExtractor": "Extrator de Quadros-chave",
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||
"TaskAudioNormalization": "Normalização de áudio"
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskExtractMediaSegments": "Analisar segmentos de multimédia",
|
||||
"TaskDownloadMissingLyrics": "Transferir letra em falta",
|
||||
"TaskMoveTrickplayImages": "Migrar a localização da imagem do Trickplay",
|
||||
"TaskDownloadMissingLyricsDescription": "Transferir letra para músicas",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de multimédia a partir de plugins com suporte para MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Move os ficheiros trickplay existentes de acordo com as definições da mediateca."
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"Channels": "Canais",
|
||||
"UserDownloadingItemWithValues": "{0} está sendo baixado {1}",
|
||||
"VersionNumber": "Versão {0}",
|
||||
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
|
||||
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua mediateca",
|
||||
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
|
||||
"UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}",
|
||||
"UserPolicyUpdatedWithName": "A política do usuário {0} foi alterada",
|
||||
@@ -71,8 +71,8 @@
|
||||
"Latest": "Mais Recente",
|
||||
"LabelRunningTimeValue": "Duração: {0}",
|
||||
"LabelIpAddressValue": "Endereço de IP: {0}",
|
||||
"ItemRemovedWithName": "{0} foi removido da biblioteca",
|
||||
"ItemAddedWithName": "{0} foi adicionado à biblioteca",
|
||||
"ItemRemovedWithName": "{0} foi removido da mediateca",
|
||||
"ItemAddedWithName": "{0} foi adicionado à mediateca",
|
||||
"Inherit": "Herdar",
|
||||
"HomeVideos": "Vídeos Caseiros",
|
||||
"HeaderRecordingGroups": "Grupos de Gravação",
|
||||
@@ -93,33 +93,33 @@
|
||||
"AppDeviceValues": "Aplicação: {0}, Dispositivo: {1}",
|
||||
"TaskCleanCache": "Limpar Diretório de Cache",
|
||||
"TasksApplicationCategory": "Aplicação",
|
||||
"TasksLibraryCategory": "Biblioteca",
|
||||
"TasksLibraryCategory": "Mediateca",
|
||||
"TasksMaintenanceCategory": "Manutenção",
|
||||
"TaskRefreshChannels": "Atualizar Canais",
|
||||
"TaskUpdatePlugins": "Atualizar Plugins",
|
||||
"TaskCleanLogsDescription": "Deletar arquivos de log que existe a mais de {0} dias.",
|
||||
"TaskCleanLogs": "Limpar diretório de logs",
|
||||
"TaskRefreshLibrary": "Escanear biblioteca de mídias",
|
||||
"TaskRefreshLibrary": "Analisar mediateca",
|
||||
"TaskRefreshChapterImagesDescription": "Cria miniaturas para vídeos que têm capítulos.",
|
||||
"TaskCleanCacheDescription": "Apaga ficheiros em cache que já não são usados pelo sistema.",
|
||||
"TasksChannelsCategory": "Canais de Internet",
|
||||
"TaskRefreshChapterImages": "Extrair Imagens do Capítulo",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Pesquisa na Internet as legendas em falta com base na configuração de metadados.",
|
||||
"TaskDownloadMissingSubtitles": "Download das legendas em falta",
|
||||
"TaskDownloadMissingSubtitles": "Transferir legendas em falta",
|
||||
"TaskRefreshChannelsDescription": "Atualiza as informações do canal da Internet.",
|
||||
"TaskCleanTranscodeDescription": "Apagar os ficheiros com mais de um dia, de Transcode.",
|
||||
"TaskCleanTranscode": "Limpar o diretório de Transcode",
|
||||
"TaskUpdatePluginsDescription": "Baixa e instala as atualizações para plug-ins configurados para atualização automática.",
|
||||
"TaskRefreshPeopleDescription": "Atualiza os metadados para atores e diretores na tua biblioteca de media.",
|
||||
"TaskRefreshPeopleDescription": "Atualizar metadados para elenco e equipa técnica da tua mediateca.",
|
||||
"TaskRefreshPeople": "Atualizar pessoas",
|
||||
"TaskRefreshLibraryDescription": "Pesquisa sua biblioteca de media por novos arquivos e atualiza os metadados.",
|
||||
"TaskRefreshLibraryDescription": "Analisar a mediateca para novos ficheiros e atualizar os metadados.",
|
||||
"TaskCleanActivityLog": "Limpar registro de atividade",
|
||||
"Undefined": "Indefinido",
|
||||
"Forced": "Forçado",
|
||||
"Default": "Predefinição",
|
||||
"TaskCleanActivityLogDescription": "Apaga itens no registro com idade acima do que é configurado.",
|
||||
"TaskOptimizeDatabase": "Otimizar base de dados",
|
||||
"TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
|
||||
"TaskOptimizeDatabaseDescription": "Otimiza e liberta espaço livre na base de dados. A execução desta tarefa depois de analisar a mediateca ou efetuar outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.",
|
||||
"External": "Externo",
|
||||
"HearingImpaired": "Problemas auditivos",
|
||||
"TaskKeyframeExtractor": "Extrator de quadro-chave",
|
||||
@@ -129,5 +129,11 @@
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
|
||||
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
|
||||
"TaskAudioNormalization": "Normalização de áudio"
|
||||
"TaskAudioNormalization": "Normalização de áudio",
|
||||
"TaskDownloadMissingLyrics": "Transferir letra em falta",
|
||||
"TaskDownloadMissingLyricsDescription": "Transferir letra para músicas",
|
||||
"TaskMoveTrickplayImagesDescription": "Move os ficheiros trickplay existentes de acordo com as definições da mediateca.",
|
||||
"TaskExtractMediaSegments": "Analisar segmentos de multimédia",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de multimédia a partir de plugins com suporte para MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migrar a localização da imagem do Trickplay"
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"Genres": "Genuri",
|
||||
"Folders": "Dosare",
|
||||
"Favorites": "Favorite",
|
||||
"FailedLoginAttemptWithUserName": "Încercare de conectare nereușită de la {0}",
|
||||
"FailedLoginAttemptWithUserName": "Încercare de conectare eșuată pentru {0}",
|
||||
"DeviceOnlineWithName": "{0} este conectat",
|
||||
"DeviceOfflineWithName": "{0} s-a deconectat",
|
||||
"Collections": "Colecții",
|
||||
@@ -125,5 +125,15 @@
|
||||
"TaskKeyframeExtractor": "Extractor de cadre cheie",
|
||||
"HearingImpaired": "Ascultare Impară",
|
||||
"TaskRefreshTrickplayImages": "Generează imagini Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Generează previzualizările trickplay pentru videourile din librăriile selectate."
|
||||
"TaskRefreshTrickplayImagesDescription": "Generează previzualizările trickplay pentru videourile din librăriile selectate.",
|
||||
"TaskAudioNormalizationDescription": "Scanează fișiere pentru date necesare normalizării sunetului.",
|
||||
"TaskAudioNormalization": "Normalizare sunet",
|
||||
"TaskCleanCollectionsAndPlaylists": "Curăță colecțiile și listele de redare",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Elimină elementele care nu mai există din colecții și liste de redare.",
|
||||
"TaskExtractMediaSegments": "Scanează segmentele media",
|
||||
"TaskMoveTrickplayImagesDescription": "Mută fișierele trickplay existente conform setărilor librăriei.",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrage sau obține segmentele media de la pluginurile MediaSegment activate.",
|
||||
"TaskMoveTrickplayImages": "Migrează locația imaginii Trickplay",
|
||||
"TaskDownloadMissingLyrics": "Descarcă versurile lipsă",
|
||||
"TaskDownloadMissingLyricsDescription": "Descarcă versuri pentru melodii"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Collections": "Коллекции",
|
||||
"DeviceOfflineWithName": "{0} - отключено",
|
||||
"DeviceOnlineWithName": "{0} - подключено",
|
||||
"FailedLoginAttemptWithUserName": "{0} - попытка входа неудачна",
|
||||
"FailedLoginAttemptWithUserName": "Неудачная попытка входа с {0}",
|
||||
"Favorites": "Избранное",
|
||||
"Folders": "Папки",
|
||||
"Genres": "Жанры",
|
||||
@@ -31,7 +31,7 @@
|
||||
"ItemRemovedWithName": "{0} - изъято из медиатеки",
|
||||
"LabelIpAddressValue": "IP-адрес: {0}",
|
||||
"LabelRunningTimeValue": "Длительность: {0}",
|
||||
"Latest": "Последние добавленные",
|
||||
"Latest": "Последние",
|
||||
"MessageApplicationUpdated": "Jellyfin Server был обновлён",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Конфигурация сервера (раздел {0}) была обновлена",
|
||||
@@ -128,5 +128,13 @@
|
||||
"TaskRefreshTrickplayImages": "Сгенерировать изображения для Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "Создает предпросмотры для Trickplay для видео в библиотеках, где эта функция включена.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Очистка коллекций и списков воспроизведения",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Удаляет элементы из коллекций и списков воспроизведения, которые больше не существуют."
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Удаляет элементы из коллекций и списков воспроизведения, которые больше не существуют.",
|
||||
"TaskAudioNormalization": "Нормализация звука",
|
||||
"TaskAudioNormalizationDescription": "Сканирует файлы на наличие данных о нормализации звука.",
|
||||
"TaskDownloadMissingLyrics": "Загрузить недостающий текст",
|
||||
"TaskDownloadMissingLyricsDescription": "Загружает текст песен",
|
||||
"TaskMoveTrickplayImages": "Перенесение местоположения изображений Trickplay",
|
||||
"TaskExtractMediaSegments": "Сканирование медиасегментов",
|
||||
"TaskExtractMediaSegmentsDescription": "Извлекает или получает медиасегменты из плагинов MediaSegment.",
|
||||
"TaskMoveTrickplayImagesDescription": "Перемещает существующие файлы trickplay в соответствии с настройками медиатеки."
|
||||
}
|
||||
|
||||
@@ -130,5 +130,11 @@
|
||||
"TaskCleanCollectionsAndPlaylists": "Vyčistiť kolekcie a playlisty",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Odstráni položky z kolekcií a playlistov, ktoré už neexistujú.",
|
||||
"TaskAudioNormalization": "Normalizácia zvuku",
|
||||
"TaskAudioNormalizationDescription": "Skenovať súbory za účelom normalizácie zvuku."
|
||||
"TaskAudioNormalizationDescription": "Skenovať súbory za účelom normalizácie zvuku.",
|
||||
"TaskExtractMediaSegments": "Skenovanie segmentov médií",
|
||||
"TaskExtractMediaSegmentsDescription": "Extrahuje alebo získava segmenty médií zo zásuvných modulov s povolenou funkciou MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Presunúť umiestnenie obrázkov Trickplay",
|
||||
"TaskMoveTrickplayImagesDescription": "Presunie existujúce súbory Trickplay podľa nastavení knižnice.",
|
||||
"TaskDownloadMissingLyrics": "Stiahnuť chýbajúce texty piesní",
|
||||
"TaskDownloadMissingLyricsDescription": "Stiahne texty pre piesne"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"AppDeviceValues": "Aplikacija: {0}, Naprava: {1}",
|
||||
"Application": "Aplikacija",
|
||||
"Artists": "Izvajalci",
|
||||
"AuthenticationSucceededWithUserName": "{0} se je uspešno prijavil",
|
||||
"AuthenticationSucceededWithUserName": "{0} se je uspešno prijavil/a",
|
||||
"Books": "Knjige",
|
||||
"CameraImageUploadedFrom": "Nova fotografija je bila naložena iz {0}",
|
||||
"Channels": "Kanali",
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
"Channels": "Kanaler",
|
||||
"ChapterNameValue": "Kapitel {0}",
|
||||
"Collections": "Samlingar",
|
||||
"DeviceOfflineWithName": "{0} har avbrutit uppkopplingen",
|
||||
"DeviceOfflineWithName": "{0} har kopplat ned",
|
||||
"DeviceOnlineWithName": "{0} är ansluten",
|
||||
"FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
|
||||
"Favorites": "Favoriter",
|
||||
"Folders": "Mappar",
|
||||
"Genres": "Genrer",
|
||||
"HeaderAlbumArtists": "Albumartister",
|
||||
"HeaderContinueWatching": "Fortsätt titta på",
|
||||
"HeaderContinueWatching": "Fortsätt titta",
|
||||
"HeaderFavoriteAlbums": "Favoritalbum",
|
||||
"HeaderFavoriteArtists": "Favoritartister",
|
||||
"HeaderFavoriteEpisodes": "Favoritavsnitt",
|
||||
@@ -121,11 +121,20 @@
|
||||
"Default": "Standard",
|
||||
"TaskOptimizeDatabase": "Optimera databasen",
|
||||
"TaskOptimizeDatabaseDescription": "Komprimerar databasen och trunkerar ledigt utrymme. Prestandan kan förbättras genom att köra denna aktivitet efter att du har skannat biblioteket eller gjort andra förändringar som indikerar att databasen har modifierats.",
|
||||
"TaskKeyframeExtractorDescription": "Exporterar nyckelbildrutor från videofiler för att skapa mer exakta HLS-spellistor. Denna rutin kan ta lång tid.",
|
||||
"TaskKeyframeExtractorDescription": "Exporterar nyckelbildrutor från videofiler för att skapa mer exakta HLS-spellistor. Denna körning kan ta lång tid.",
|
||||
"TaskKeyframeExtractor": "Extraktor för nyckelbildrutor",
|
||||
"External": "Extern",
|
||||
"HearingImpaired": "Hörselskadad",
|
||||
"TaskRefreshTrickplayImages": "Generera Trickplay-bilder",
|
||||
"TaskRefreshTrickplayImagesDescription": "Skapar trickplay-förhandsvisningar för videor i aktiverade bibliotek.",
|
||||
"TaskCleanCollectionsAndPlaylists": "Rensa samlingar och spellistor"
|
||||
"TaskCleanCollectionsAndPlaylists": "Rensa upp samlingar och spellistor",
|
||||
"TaskAudioNormalization": "Ljudnormalisering",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "Tar bort objekt från samlingar och spellistor som inte längre finns.",
|
||||
"TaskAudioNormalizationDescription": "Skannar filer för ljudnormaliseringsdata.",
|
||||
"TaskDownloadMissingLyrics": "Ladda ner saknad låttext",
|
||||
"TaskDownloadMissingLyricsDescription": "Laddar ner låttexter",
|
||||
"TaskExtractMediaSegments": "Skanning av mediesegment",
|
||||
"TaskExtractMediaSegmentsDescription": "Extraherar eller hämtar ut mediesegmen från tillägg som stöder MediaSegment.",
|
||||
"TaskMoveTrickplayImages": "Migrera platsen för Trickplay-bilder",
|
||||
"TaskMoveTrickplayImagesDescription": "Flyttar befintliga trickplay-filer enligt bibliotekets inställningar."
|
||||
}
|
||||
|
||||
@@ -125,5 +125,9 @@
|
||||
"External": "வெளி",
|
||||
"HearingImpaired": "செவித்திறன் குறைபாடுடையவர்",
|
||||
"TaskRefreshTrickplayImages": "முன்னோட்ட படங்களை உருவாக்கு",
|
||||
"TaskRefreshTrickplayImagesDescription": "செயல்பாட்டில் உள்ள தொகுப்புகளுக்கு முன்னோட்ட படங்களை உருவாக்கும்."
|
||||
"TaskRefreshTrickplayImagesDescription": "செயல்பாட்டில் உள்ள தொகுப்புகளுக்கு முன்னோட்ட படங்களை உருவாக்கும்.",
|
||||
"TaskCleanCollectionsAndPlaylists": "சேகரிப்புகள் மற்றும் பிளேலிஸ்ட்களை சுத்தம் செய்யவும்",
|
||||
"TaskCleanCollectionsAndPlaylistsDescription": "சேகரிப்புகள் மற்றும் பிளேலிஸ்ட்களில் இருந்து உருப்படிகளை நீக்குகிறது.",
|
||||
"TaskAudioNormalization": "ஆடியோ இயல்பாக்கம்",
|
||||
"TaskAudioNormalizationDescription": "ஆடியோ இயல்பாக்குதல் தரவுக்காக கோப்புகளை ஸ்கேன் செய்கிறது."
|
||||
}
|
||||
|
||||
@@ -123,5 +123,7 @@
|
||||
"External": "ภายนอก",
|
||||
"HearingImpaired": "บกพร่องทางการได้ยิน",
|
||||
"TaskKeyframeExtractor": "ตัวแยกคีย์เฟรม",
|
||||
"TaskKeyframeExtractorDescription": "แยกคีย์เฟรมจากไฟล์วีดีโอเพื่อสร้างรายการ HLS ให้ถูกต้อง. กระบวนการนี้อาจใช้ระยะเวลานาน"
|
||||
"TaskKeyframeExtractorDescription": "แยกคีย์เฟรมจากไฟล์วีดีโอเพื่อสร้างรายการ HLS ให้ถูกต้อง. กระบวนการนี้อาจใช้ระยะเวลานาน",
|
||||
"TaskRefreshTrickplayImages": "สร้างไฟล์รูปภาพสำหรับ Trickplay",
|
||||
"TaskRefreshTrickplayImagesDescription": "สร้างภาพตัวอย่างของวีดีโอในคลังที่เปิดใช้งาน Trickplay"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user