Compare commits
630 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
762b83934a | ||
|
|
ae820877d5 | ||
|
|
0d1b37997a | ||
|
|
8990f4bbcb | ||
|
|
c265b9a729 | ||
|
|
6625943701 | ||
|
|
788c2088f8 | ||
|
|
629e9dc881 | ||
|
|
ec2ee2bfad | ||
|
|
b24f1da8b5 | ||
|
|
88a1099f06 | ||
|
|
bf574c16f4 | ||
|
|
6cac9a71ed | ||
|
|
6858a60fb1 | ||
|
|
01f1c8c5c8 | ||
|
|
e45d25beb4 | ||
|
|
bec1580991 | ||
|
|
f453995aa3 | ||
|
|
cfe163d5a6 | ||
|
|
51c3ce4c56 | ||
|
|
77fd354a22 | ||
|
|
c2a42c572c | ||
|
|
0bd53daed7 | ||
|
|
6358ac8b18 | ||
|
|
02eca7a50c | ||
|
|
f45e847ad2 | ||
|
|
5555c48bcb | ||
|
|
295e0a12e7 | ||
|
|
b2402acccf | ||
|
|
167cf1b693 | ||
|
|
606ba1fa45 | ||
|
|
c4ec9c9b0f | ||
|
|
c2ec3b94a9 | ||
|
|
163deaff28 | ||
|
|
cf14bf2f68 | ||
|
|
12facb53e4 | ||
|
|
89b8598cd7 | ||
|
|
33db1e49a1 | ||
|
|
96c89f7def | ||
|
|
a536f58daa | ||
|
|
cb0372343f | ||
|
|
748377b11c | ||
|
|
714d4f799b | ||
|
|
218d591f35 | ||
|
|
1bb92428a7 | ||
|
|
ccf29db1d3 | ||
|
|
de19818429 | ||
|
|
01e736bccc | ||
|
|
5f717d4e70 | ||
|
|
f79fb4dbc1 | ||
|
|
bd1926c57b | ||
|
|
6bebb04015 | ||
|
|
a72bc2ddd6 | ||
|
|
44951bf648 | ||
|
|
b1fc780f44 | ||
|
|
cfb20edb9f | ||
|
|
0753be9d12 | ||
|
|
db05479cbe | ||
|
|
c850737d24 | ||
|
|
333ba1b3f0 | ||
|
|
cf31d3aea4 | ||
|
|
27ad2b5a85 | ||
|
|
c76dfeefe4 | ||
|
|
9caf1d4029 | ||
|
|
e432f6a625 | ||
|
|
ade2c8c63a | ||
|
|
9c13a20cda | ||
|
|
f9f0aed2d8 | ||
|
|
1b4b2f401d | ||
|
|
a7bf8e452a | ||
|
|
c00fe4ac68 | ||
|
|
14c439b8e7 | ||
|
|
2c03451597 | ||
|
|
e85ebc0cab | ||
|
|
ea10333b23 | ||
|
|
e773cffa76 | ||
|
|
b795d72e39 | ||
|
|
be6c548ac1 | ||
|
|
23396821db | ||
|
|
78c04e4b2d | ||
|
|
61a1d72d7e | ||
|
|
ede6c52d63 | ||
|
|
372c904a96 | ||
|
|
b500c97440 | ||
|
|
daaf55c50f | ||
|
|
79358f0e58 | ||
|
|
e3fa6c656e | ||
|
|
1521810537 | ||
|
|
67e8a2a835 | ||
|
|
f770048c99 | ||
|
|
4d2db238cb | ||
|
|
4e21d46120 | ||
|
|
1c5c69ba5c | ||
|
|
ebc7e3c6ac | ||
|
|
f260f3ffcb | ||
|
|
ef12579ee8 | ||
|
|
82e70c39d3 | ||
|
|
7174a611ac | ||
|
|
75607c7835 | ||
|
|
dc58f00106 | ||
|
|
74774b917a | ||
|
|
e9a0b5216d | ||
|
|
79997c5dd0 | ||
|
|
d866e1e7e1 | ||
|
|
46fdee0acb | ||
|
|
4829b9fe62 | ||
|
|
7b437a0383 | ||
|
|
d7def5a37a | ||
|
|
13bb916c85 | ||
|
|
169522f401 | ||
|
|
8774e7c2f0 | ||
|
|
7440a433ba | ||
|
|
72b9728540 | ||
|
|
d6224ac2e4 | ||
|
|
f8ddf6af72 | ||
|
|
665e208932 | ||
|
|
48616ebbcf | ||
|
|
4b0734c988 | ||
|
|
28e7103dae | ||
|
|
990e86f717 | ||
|
|
85e93169b5 | ||
|
|
0e3a5611c6 | ||
|
|
31b9fe1605 | ||
|
|
7963342574 | ||
|
|
80264c2822 | ||
|
|
9be9c5874f | ||
|
|
8115ed383b | ||
|
|
81152f626e | ||
|
|
4f7c480a8a | ||
|
|
9d30664c14 | ||
|
|
cca86956cd | ||
|
|
bd0e06bdd6 | ||
|
|
e2581a3276 | ||
|
|
eef8d8d1be | ||
|
|
5fce383bb3 | ||
|
|
317c67d01c | ||
|
|
03e4904506 | ||
|
|
0461155b5d | ||
|
|
cd3d3d3389 | ||
|
|
fde96522e8 | ||
|
|
9ccfa6732a | ||
|
|
244f63c07c | ||
|
|
f3df30a727 | ||
|
|
de377e30b0 | ||
|
|
ded9fd4223 | ||
|
|
b8e77668aa | ||
|
|
1f0eea5789 | ||
|
|
49e50c2834 | ||
|
|
176172c262 | ||
|
|
ec1a32f126 | ||
|
|
8c5c19fa81 | ||
|
|
d6ccec99b0 | ||
|
|
102a0976e5 | ||
|
|
1082f65e75 | ||
|
|
a187331b6d | ||
|
|
9a5fb5cb80 | ||
|
|
42e4fe24b9 | ||
|
|
fa33819414 | ||
|
|
06351b0c16 | ||
|
|
5285e6424f | ||
|
|
3202a290dc | ||
|
|
b70617eada | ||
|
|
9ce924ce1f | ||
|
|
60c85832d6 | ||
|
|
0d96c6a380 | ||
|
|
7225cbdd61 | ||
|
|
098d29deeb | ||
|
|
4ce8e0c6a1 | ||
|
|
8d770217a2 | ||
|
|
462f2aa10a | ||
|
|
1d5af4e48a | ||
|
|
e62d392eee | ||
|
|
e0473b748d | ||
|
|
1da214a53f | ||
|
|
86f46297c6 | ||
|
|
136bd9d848 | ||
|
|
4b7ddc263c | ||
|
|
f1f4e5f1a6 | ||
|
|
2a8c57ba10 | ||
|
|
280f8776c5 | ||
|
|
82d3f45090 | ||
|
|
edeb9b062a | ||
|
|
3b717664b8 | ||
|
|
bf3d5a8835 | ||
|
|
5cf061af30 | ||
|
|
f3c72dc102 | ||
|
|
0b771f49fd | ||
|
|
b072aa4f9a | ||
|
|
3a782d8114 | ||
|
|
81eccea140 | ||
|
|
0f33ee5052 | ||
|
|
825efd4eb9 | ||
|
|
3d2758c6ad | ||
|
|
2f52413a7c | ||
|
|
b1d3159bd8 | ||
|
|
fcdf564d2b | ||
|
|
823efe5050 | ||
|
|
b88e012759 | ||
|
|
82a00bd388 | ||
|
|
a187fa2c8c | ||
|
|
d8b786a25a | ||
|
|
55485e105e | ||
|
|
293d8d6680 | ||
|
|
2eacacb021 | ||
|
|
459586ff77 | ||
|
|
3ed8d8ae98 | ||
|
|
d77d62e806 | ||
|
|
eab8db2734 | ||
|
|
623ce16801 | ||
|
|
dfac02cc53 | ||
|
|
b99e461e10 | ||
|
|
9f66ca34d9 | ||
|
|
53e075953d | ||
|
|
d060629477 | ||
|
|
b7b34c775c | ||
|
|
2f2b07cb4c | ||
|
|
900e6abc6d | ||
|
|
63458261a8 | ||
|
|
65776080a6 | ||
|
|
1016a9b9dc | ||
|
|
c518bcde8f | ||
|
|
17f49c3827 | ||
|
|
48e0cb6588 | ||
|
|
bb09928d73 | ||
|
|
2b8f10a2a7 | ||
|
|
db0ddf2a60 | ||
|
|
51849937bb | ||
|
|
e640ccb603 | ||
|
|
1e812a8ef5 | ||
|
|
2c186ab72e | ||
|
|
a6aa162527 | ||
|
|
fd2be921d0 | ||
|
|
5710dcc85f | ||
|
|
64bfd89225 | ||
|
|
41fd7334dc | ||
|
|
1afae2b77c | ||
|
|
9b1ff9fd6e | ||
|
|
64b4f8c1d1 | ||
|
|
d03e991cdc | ||
|
|
dfe73d2f95 | ||
|
|
dfb0aa9609 | ||
|
|
79805cea66 | ||
|
|
89130998a4 | ||
|
|
ec11a81d1e | ||
|
|
92d7993137 | ||
|
|
2ea8792568 | ||
|
|
4148fe6d28 | ||
|
|
7aea9e2927 | ||
|
|
37df1ddccd | ||
|
|
df64277c7f | ||
|
|
0505da4f83 | ||
|
|
b268ccedd8 | ||
|
|
80a60a5b13 | ||
|
|
46ace24f53 | ||
|
|
d0542d02da | ||
|
|
b050ca7714 | ||
|
|
b0684d679c | ||
|
|
76c642239f | ||
|
|
2542a0c6f8 | ||
|
|
dbacb315da | ||
|
|
66ec659354 | ||
|
|
25f9188fc1 | ||
|
|
aaf297e63f | ||
|
|
03a74ec5ec | ||
|
|
83f3c4f657 | ||
|
|
3725f4ea0e | ||
|
|
debc8aef69 | ||
|
|
b3e0235a9e | ||
|
|
c0972dd390 | ||
|
|
d90cadcb9c | ||
|
|
e40d61c7ef | ||
|
|
6aaac55017 | ||
|
|
d28a4ef3a0 | ||
|
|
09c8271289 | ||
|
|
57fea5698e | ||
|
|
30930734d8 | ||
|
|
50db2e31cf | ||
|
|
ec5b8e93a9 | ||
|
|
8f0ff70813 | ||
|
|
99c5b22745 | ||
|
|
6678b3ccfe | ||
|
|
41d95bc0f5 | ||
|
|
d58a2a2823 | ||
|
|
47569858fb | ||
|
|
33c161c836 | ||
|
|
8f568c0425 | ||
|
|
2e36378f2d | ||
|
|
143bfa97b6 | ||
|
|
70285d8b14 | ||
|
|
7fb6379d71 | ||
|
|
a4aff4551f | ||
|
|
000395fbd2 | ||
|
|
339032de14 | ||
|
|
30f5071e37 | ||
|
|
701a74b68c | ||
|
|
6a6ef9b13e | ||
|
|
8c333063be | ||
|
|
1ea59a76c2 | ||
|
|
dcfbb71d89 | ||
|
|
74a0650f11 | ||
|
|
a870cafd2c | ||
|
|
7b856e4556 | ||
|
|
d28918df94 | ||
|
|
5d3a93e4c4 | ||
|
|
9703d9db35 | ||
|
|
c6ff2e3c58 | ||
|
|
813aa85554 | ||
|
|
61b18c9442 | ||
|
|
d4d968f399 | ||
|
|
d22669272a | ||
|
|
871074ef45 | ||
|
|
2954334e1f | ||
|
|
1879cb20bc | ||
|
|
42b36e4bee | ||
|
|
4370232031 | ||
|
|
4bbf408a68 | ||
|
|
cb06de7f89 | ||
|
|
763f53f579 | ||
|
|
69fb501b37 | ||
|
|
ee027863ed | ||
|
|
7e9abcc3ee | ||
|
|
f5fe770991 | ||
|
|
91921d2179 | ||
|
|
cba0ad2862 | ||
|
|
d613e8c5d2 | ||
|
|
92b06c47d5 | ||
|
|
d547607feb | ||
|
|
400f025169 | ||
|
|
7372f7513c | ||
|
|
de509aca9f | ||
|
|
46abee647f | ||
|
|
378e503ea4 | ||
|
|
a7c54c4b96 | ||
|
|
71b64f61d0 | ||
|
|
6ae3245a79 | ||
|
|
e2c058db1c | ||
|
|
7aa476f822 | ||
|
|
77e60643f9 | ||
|
|
85e5613254 | ||
|
|
04f5fe02d5 | ||
|
|
b0b773fe44 | ||
|
|
75f884161e | ||
|
|
658f9e0c7b | ||
|
|
2e15a91c08 | ||
|
|
29b463fa4a | ||
|
|
eea53c71ab | ||
|
|
a6ca6075ad | ||
|
|
811c5e51ba | ||
|
|
e4e2da8790 | ||
|
|
a3c3740805 | ||
|
|
abf203db7e | ||
|
|
b824b1112c | ||
|
|
d75e568ad6 | ||
|
|
555e3aa095 | ||
|
|
cc2dc072a0 | ||
|
|
f47142acbe | ||
|
|
b3deccc8ea | ||
|
|
4609d25c32 | ||
|
|
90f018479a | ||
|
|
c5f78aebdc | ||
|
|
9572211cac | ||
|
|
09e82be391 | ||
|
|
8258c6ee53 | ||
|
|
9b7529956e | ||
|
|
876f477005 | ||
|
|
1f16cd9bf4 | ||
|
|
9c90bb67c2 | ||
|
|
e6ba81cb9c | ||
|
|
aa5d3e4a5c | ||
|
|
9f3c24cb6a | ||
|
|
a11c1b9ffe | ||
|
|
6d157e9129 | ||
|
|
245925f2e0 | ||
|
|
11067cb9ff | ||
|
|
ad38afe1f0 | ||
|
|
ef8d2cc743 | ||
|
|
4a398181ec | ||
|
|
809364090d | ||
|
|
f5531894e5 | ||
|
|
019e507f6e | ||
|
|
5cdb49b870 | ||
|
|
61e3fa5b4f | ||
|
|
bdfeef3763 | ||
|
|
b665811a5e | ||
|
|
7218ab7870 | ||
|
|
dad03c8e3d | ||
|
|
02ba32cade | ||
|
|
0fe1ff0e1b | ||
|
|
5784abbd9d | ||
|
|
a25dac0ad5 | ||
|
|
5766d2a6cb | ||
|
|
299f48eb8e | ||
|
|
bd7011c0ef | ||
|
|
b8e7ff7ea5 | ||
|
|
4646b441ae | ||
|
|
0db0905a89 | ||
|
|
24f1ed585a | ||
|
|
2148fd95d2 | ||
|
|
6e0d478e8e | ||
|
|
e6e86af878 | ||
|
|
5a57672c86 | ||
|
|
bfea4f3483 | ||
|
|
7af970de0a | ||
|
|
37c36eb673 | ||
|
|
2639c3ba6b | ||
|
|
d6f2610fa1 | ||
|
|
7fc46aae45 | ||
|
|
8aacd9f2b3 | ||
|
|
7deca69075 | ||
|
|
e07dc34bf2 | ||
|
|
1412c5912b | ||
|
|
427e20a0b2 | ||
|
|
4febdeb2bf | ||
|
|
036fe20cfd | ||
|
|
cd106d28d0 | ||
|
|
abbba50c1e | ||
|
|
6c0f2cf1e8 | ||
|
|
b505821b29 | ||
|
|
00734f12e6 | ||
|
|
a8819e7f42 | ||
|
|
fad9989a18 | ||
|
|
be5e2e2d66 | ||
|
|
36a5802c91 | ||
|
|
cee95719d4 | ||
|
|
4dab2be02d | ||
|
|
f168e09cf4 | ||
|
|
c3873754fc | ||
|
|
9916e58b37 | ||
|
|
2196c1dfa5 | ||
|
|
3da2c6c279 | ||
|
|
f54a58ebbb | ||
|
|
e9f46f7088 | ||
|
|
f06cf23111 | ||
|
|
a4b582b4cc | ||
|
|
56b4b01038 | ||
|
|
9aba66634e | ||
|
|
63ddd66306 | ||
|
|
232e832c1d | ||
|
|
5e91709421 | ||
|
|
d37ea1e473 | ||
|
|
096ff5d0d8 | ||
|
|
e20f59a66a | ||
|
|
2cb44c8933 | ||
|
|
64703c8497 | ||
|
|
d6e74a2ef5 | ||
|
|
b1d491165e | ||
|
|
e94c3a2355 | ||
|
|
71b05e16f8 | ||
|
|
4beed65983 | ||
|
|
ca03fcff33 | ||
|
|
d3333322c4 | ||
|
|
2b8172f25c | ||
|
|
9496292816 | ||
|
|
cf32549a22 | ||
|
|
13abf6da82 | ||
|
|
c72f697d57 | ||
|
|
03cfe18acd | ||
|
|
9939ef76c1 | ||
|
|
ae387507f7 | ||
|
|
969443acd1 | ||
|
|
3606612135 | ||
|
|
1ee48edfb5 | ||
|
|
cd2c4b35df | ||
|
|
d1d4cec00f | ||
|
|
6940f405eb | ||
|
|
3e6f7a554a | ||
|
|
4df451a540 | ||
|
|
fd06d67218 | ||
|
|
f546a4d382 | ||
|
|
c2ecf7ef57 | ||
|
|
b9771d7c11 | ||
|
|
d5b53d2bca | ||
|
|
f502cd47e1 | ||
|
|
358fab9a8f | ||
|
|
445e78825a | ||
|
|
e7d9824520 | ||
|
|
c9ebbdd4ec | ||
|
|
85fa211390 | ||
|
|
3f5db2cb03 | ||
|
|
79227b347e | ||
|
|
ffe0c22b3e | ||
|
|
25e5faf135 | ||
|
|
a6f8a9ef06 | ||
|
|
05b51e83a6 | ||
|
|
5625a9ae4f | ||
|
|
8e60a1954b | ||
|
|
52d2d75fe9 | ||
|
|
edb669ab36 | ||
|
|
e9ed28b44d | ||
|
|
343373bf4d | ||
|
|
698ede9eb6 | ||
|
|
3ae73f7cad | ||
|
|
340d36c628 | ||
|
|
703f782be1 | ||
|
|
2ef4514987 | ||
|
|
a89411aeec | ||
|
|
0cf89ca33c | ||
|
|
68ceada28b | ||
|
|
192ca44d89 | ||
|
|
3204aaf161 | ||
|
|
6cf6791fe6 | ||
|
|
6ebb18a932 | ||
|
|
7bde1bf44f | ||
|
|
3075ec066f | ||
|
|
3ddc3c3768 | ||
|
|
7b7b726ec5 | ||
|
|
5484506bc3 | ||
|
|
136f05b886 | ||
|
|
83cf03a10b | ||
|
|
7b56719716 | ||
|
|
348296763d | ||
|
|
5c7a57ac32 | ||
|
|
0c0b8ea455 | ||
|
|
2f20f43efe | ||
|
|
1662b793a5 | ||
|
|
2e4efe2500 | ||
|
|
3d01faed5f | ||
|
|
9bc3443a3c | ||
|
|
87dc32210e | ||
|
|
671216488e | ||
|
|
f596fc33a1 | ||
|
|
82756923ad | ||
|
|
14042563bf | ||
|
|
06e12396e8 | ||
|
|
b698eee3a1 | ||
|
|
9d15634dc8 | ||
|
|
5f6c298d04 | ||
|
|
f20a2ca781 | ||
|
|
6dcfbc24a9 | ||
|
|
ea9404301b | ||
|
|
da268b4429 | ||
|
|
2775960cf7 | ||
|
|
bff6b2ffb0 | ||
|
|
193600564e | ||
|
|
2abd683759 | ||
|
|
0163800a05 | ||
|
|
958ccd7f7d | ||
|
|
a0eb1df4fa | ||
|
|
3f1c6d1dd0 | ||
|
|
87a80e0caa | ||
|
|
debdd03a7a | ||
|
|
c58697aecd | ||
|
|
3b3ad37d64 | ||
|
|
d392b06e98 | ||
|
|
99a9f594e2 | ||
|
|
549a5b764d | ||
|
|
26592c31a9 | ||
|
|
378eb924e9 | ||
|
|
f8f4a87a99 | ||
|
|
55289e6837 | ||
|
|
60efbd0389 | ||
|
|
f3903c1aa5 | ||
|
|
b01e62007f | ||
|
|
7730890525 | ||
|
|
29977609aa | ||
|
|
88c3a7d0bf | ||
|
|
ba0335bb28 | ||
|
|
51e01ee40c | ||
|
|
b55ceda978 | ||
|
|
37b4f5c896 | ||
|
|
a78b42d9ab | ||
|
|
d1b6a4eb43 | ||
|
|
61bfaf012b | ||
|
|
92adc9b610 | ||
|
|
feb4a63bb0 | ||
|
|
30f8318531 | ||
|
|
5b040900a7 | ||
|
|
717666fc14 | ||
|
|
a012a6f0d5 | ||
|
|
3341c6db19 | ||
|
|
206d13594a | ||
|
|
37af406831 | ||
|
|
88f18a1b24 | ||
|
|
8bf410dbca | ||
|
|
c98411ca0e | ||
|
|
fcfb404edf | ||
|
|
a0c8b39f0c | ||
|
|
3a1f2540b1 | ||
|
|
9c680bc59c | ||
|
|
fde95a6a8e | ||
|
|
150a0332f6 | ||
|
|
618c32bdb8 | ||
|
|
ea35850b71 | ||
|
|
87561943f9 | ||
|
|
5fd8d4e847 | ||
|
|
eb6d0d7922 | ||
|
|
d3dd9099f6 | ||
|
|
a112b23d07 | ||
|
|
4c591f3827 | ||
|
|
62a28f57f6 | ||
|
|
ef689b0857 | ||
|
|
aa903da042 | ||
|
|
9587d8832d | ||
|
|
f125be1347 | ||
|
|
269301852a | ||
|
|
8e5dcd57ce | ||
|
|
920273197d | ||
|
|
1be2e9fbb2 | ||
|
|
7c93eededf | ||
|
|
1b17031523 | ||
|
|
2d76c3e84c | ||
|
|
03dd4370b9 | ||
|
|
157af15a2a | ||
|
|
b930ecdcd0 | ||
|
|
100242f0a6 | ||
|
|
d695f71d36 | ||
|
|
5d60b7a67c | ||
|
|
5d5d89dab9 | ||
|
|
35a625e04b | ||
|
|
1a2d3bb441 | ||
|
|
2e3ac02afb | ||
|
|
a5b8a65b7d | ||
|
|
dc320f2e6d | ||
|
|
acbca83553 | ||
|
|
cb26c5dfc8 | ||
|
|
b5c4174700 | ||
|
|
3e37d11c6a | ||
|
|
36e83a9d01 | ||
|
|
efcd759869 | ||
|
|
9f8830b341 | ||
|
|
7c81396ec5 | ||
|
|
9b50665375 | ||
|
|
83795581e6 | ||
|
|
af51524109 | ||
|
|
738aa12243 | ||
|
|
f25de4b4ce | ||
|
|
38e1db9c53 | ||
|
|
d71c929ba8 | ||
|
|
4865b742c7 | ||
|
|
1246549f4b |
12
.github/FUNDING.yml
vendored
@@ -1,12 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [vabene1111]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
94
.github/dependabot.yml
vendored
@@ -1,26 +1,92 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 20
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
semver-major-days: 30
|
||||
semver-minor-days: 7
|
||||
semver-patch-days: 3
|
||||
exclude:
|
||||
- "recipe-scrapers"
|
||||
directory: "/"
|
||||
groups:
|
||||
pip-patches:
|
||||
exclude-patterns: ["pytest*"]
|
||||
update-types: ["patch"]
|
||||
pip-minors:
|
||||
exclude-patterns: ["pytest*"]
|
||||
update-types: ["minor"]
|
||||
pip-pytest:
|
||||
patterns: ["pytest*"]
|
||||
update-types: ["minor", "patch"]
|
||||
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "python"
|
||||
- "dependencies"
|
||||
- "automerge"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/vue/"
|
||||
open-pull-requests-limit: 20
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
cooldown:
|
||||
semver-major-days: 30
|
||||
semver-minor-days: 3
|
||||
semver-patch-days: 3
|
||||
directory: "vue"
|
||||
ignore:
|
||||
- dependency-name: "vue"
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "vue*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "pinia"
|
||||
update-types: ["version-update:semver-major"]
|
||||
groups:
|
||||
npm-patches:
|
||||
patterns: ["*"]
|
||||
update-types: ["patch"]
|
||||
npm-minors:
|
||||
patterns: ["*"]
|
||||
update-types: ["minor"]
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "javascript"
|
||||
- "dependencies"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 20
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
directory: "/.github/"
|
||||
groups:
|
||||
actions-updates:
|
||||
patterns: ["*"]
|
||||
update-types: ["patch", "minor"]
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "github_actions"
|
||||
- "dependencies"
|
||||
- "automerge"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
open-pull-requests-limit: 5
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
directory: "/"
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "docker"
|
||||
- "dependencies"
|
||||
|
||||
|
||||
4
.github/workflows/build-docker-open-data.yml
vendored
@@ -1,6 +1,8 @@
|
||||
name: Build Docker Container with open data plugin installed
|
||||
|
||||
on: push
|
||||
on:
|
||||
push:
|
||||
branches: [disabled]
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
|
||||
57
.github/workflows/build-docker.yml
vendored
@@ -1,6 +1,8 @@
|
||||
name: Build Docker Container
|
||||
|
||||
on: push
|
||||
on:
|
||||
push:
|
||||
branches: [tandoor-1]
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
@@ -17,27 +19,16 @@ jobs:
|
||||
# Standard build config
|
||||
- name: Standard
|
||||
dockerfile: Dockerfile
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
platforms: linux/amd64,linux/arm64
|
||||
suffix: ""
|
||||
continue-on-error: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get version number
|
||||
id: get_version
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" = refs/tags/* ]]; then
|
||||
echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
|
||||
elif [[ "$GITHUB_REF" = refs/heads/beta ]]; then
|
||||
echo VERSION=beta >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo VERSION=develop >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Build Vue frontend
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '20'
|
||||
cache: yarn
|
||||
cache-dependency-path: vue/yarn.lock
|
||||
- name: Install dependencies
|
||||
@@ -75,11 +66,8 @@ jobs:
|
||||
latest=false
|
||||
suffix=${{ matrix.suffix }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=ref,event=branch
|
||||
type=raw,value=tandoor-v1-{{date 'YYYYMMDD'}}
|
||||
type=raw,value=tandoor-v1
|
||||
- name: Build and Push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -93,34 +81,3 @@ jobs:
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
notify-stable:
|
||||
name: Notify Stable
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-container
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Set tag name
|
||||
run: |
|
||||
# Strip "refs/tags/" prefix
|
||||
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
# Send stable discord notification
|
||||
- name: Discord notification
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: '🚀 Version {{ VERSION }} of tandoor has been released 🥳 Check it out https://github.com/vabene1111/recipes/releases/tag/{{ VERSION }}'
|
||||
|
||||
notify-beta:
|
||||
name: Notify Beta
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-container
|
||||
if: github.ref == 'refs/heads/beta'
|
||||
steps:
|
||||
# Send beta discord notification
|
||||
- name: Discord notification
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BETA_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: '🚀 The BETA Image has been updated! 🥳'
|
||||
|
||||
11
.github/workflows/ci.yml
vendored
@@ -1,6 +1,11 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches: [disabled]
|
||||
pull_request:
|
||||
branches: [disabled]
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -14,9 +19,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: awalsh128/cache-apt-pkgs-action@v1.4.2
|
||||
- uses: awalsh128/cache-apt-pkgs-action@v1.4.3
|
||||
with:
|
||||
packages: libsasl2-dev python3-dev libldap2-dev libssl-dev
|
||||
packages: libsasl2-dev python3-dev libxml2-dev libxmlsec1-dev libxslt-dev libxmlsec1-openssl libldap2-dev libssl-dev gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev xmlsec-dev xmlsec build-base g++ curl
|
||||
version: 1.0
|
||||
|
||||
# Setup python & dependencies
|
||||
|
||||
5
.github/workflows/codeql-analysis.yml
vendored
@@ -2,9 +2,10 @@ name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [disabled]
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 13 * * 2'
|
||||
branches: [disabled]
|
||||
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
235
.github/workflows/create-upstream-pr.yml
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
name: Create Upstream PR
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Push Workflow"]
|
||||
types:
|
||||
- completed
|
||||
branches: [working]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
create-upstream-pr:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: upstream-pr
|
||||
cancel-in-progress: true
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: Generate GitHub App token (for branch push)
|
||||
id: generate_token_push
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.BOT_APP_ID }}
|
||||
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout fork
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.generate_token_push.outputs.token }}
|
||||
|
||||
- name: Setup git user
|
||||
run: |
|
||||
git config user.name "GitHub Action"
|
||||
git config user.email "action@github.com"
|
||||
|
||||
- name: Add upstream remote
|
||||
run: |
|
||||
git remote get-url upstream || git remote add upstream https://github.com/TandoorRecipes/recipes.git
|
||||
git fetch upstream
|
||||
|
||||
- name: Ensure jq is available
|
||||
run: |
|
||||
if ! command -v jq &> /dev/null; then
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
fi
|
||||
|
||||
- name: Create upstream PR branch
|
||||
id: create_branch
|
||||
run: |
|
||||
BRANCH_NAME="upstream-pr-$(date +%Y%m%d-%H%M%S)"
|
||||
git checkout -b "$BRANCH_NAME" || { echo "❌ Failed to create branch $BRANCH_NAME"; exit 1; }
|
||||
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
echo "✅ Created branch: $BRANCH_NAME"
|
||||
|
||||
- name: Restore upstream infrastructure files
|
||||
id: restore_infra
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
git checkout "$BRANCH_NAME"
|
||||
git rm .gitattributes || echo "ℹ️ .gitattributes not present, skipping removal."
|
||||
git checkout upstream/tandoor-1 -- .github/workflows/ || echo "ℹ️ No workflows to restore."
|
||||
git checkout upstream/tandoor-1 -- cookbook/version_info.py || echo "ℹ️ No version_info.py to restore."
|
||||
git add .
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m $'Restore upstream infrastructure files for PR\n\n- Removed fork-specific .gitattributes\n- Restored upstream .github/workflows/\n- Restored upstream cookbook/version_info.py'
|
||||
echo "✅ Infrastructure files restored and committed."
|
||||
else
|
||||
echo "ℹ️ No infrastructure changes to commit."
|
||||
fi
|
||||
|
||||
- name: Push branch to fork (after infra commit)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
echo "Pushing branch $BRANCH_NAME after infra file restore."
|
||||
git push --set-upstream https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
|
||||
echo "✅ Branch pushed: $BRANCH_NAME (infra files)"
|
||||
|
||||
|
||||
- name: Merge upstream branch
|
||||
id: merge_upstream
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
git checkout "$BRANCH_NAME"
|
||||
if git merge --no-edit upstream/tandoor-1; then
|
||||
echo "✅ Merged upstream/tandoor-1 into $BRANCH_NAME"
|
||||
if ! git diff --cached --quiet || [ -n "$(git log origin/$BRANCH_NAME..$BRANCH_NAME --oneline)" ]; then
|
||||
echo "merge_commit=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "merge_commit=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "❌ Merge conflict detected during merge with upstream/tandoor-1. Please resolve conflicts manually." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Push branch to fork (after merge)
|
||||
if: steps.merge_upstream.outputs.merge_commit == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
echo "Pushing branch $BRANCH_NAME after merge."
|
||||
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
|
||||
echo "✅ Branch pushed: $BRANCH_NAME (after merge)"
|
||||
|
||||
|
||||
- name: Get commit list
|
||||
id: get_commits
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
COMMITS_RAW=$(git log upstream/tandoor-1..$BRANCH_NAME --oneline)
|
||||
if [ -z "$COMMITS_RAW" ]; then
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ No commits to contribute - exiting gracefully"
|
||||
exit 0
|
||||
fi
|
||||
echo "commits_raw<<EOF" >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$COMMITS_RAW" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Get changed files
|
||||
id: get_files
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
CHANGED_FILES=$(git diff upstream/tandoor-1..$BRANCH_NAME --name-only)
|
||||
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$CHANGED_FILES" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
CODE_COUNT=$(echo "$CHANGED_FILES" | grep -c '^' || true)
|
||||
echo "code_count=$CODE_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Summarize changes
|
||||
id: summarize_changes
|
||||
run: |
|
||||
CODE_COUNT=${{ steps.get_files.outputs.code_count }}
|
||||
CHANGES_SUMMARY="Modified $CODE_COUNT code files"
|
||||
echo "changes_summary=$CHANGES_SUMMARY" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare commit subjects and JSON
|
||||
id: prepare_commits
|
||||
run: |
|
||||
COMMITS_RAW="${{ steps.get_commits.outputs.commits_raw }}"
|
||||
CODE_FILES=( $(echo "${{ steps.get_files.outputs.changed_files }}") )
|
||||
FILTERED_COMMITS_JSON="[]"
|
||||
COMMIT_SUBJECTS_ARRAY=()
|
||||
INFRA_PATTERNS='^\.github/|^cookbook/version_info\.py$|^\.gitattributes$'
|
||||
while IFS= read -r commit_line; do
|
||||
if [ -z "$commit_line" ]; then continue; fi
|
||||
COMMIT_SHA=$(echo "$commit_line" | cut -d' ' -f1)
|
||||
COMMIT_SUBJECT=$(echo "$commit_line" | cut -d' ' -f2-)
|
||||
mapfile -t COMMIT_FILES < <(git diff-tree --no-commit-id --name-only -r "$COMMIT_SHA" | grep -Ev "$INFRA_PATTERNS")
|
||||
# Only include commit if it touches at least one non-infra file that is still different
|
||||
INCLUDE_COMMIT=false
|
||||
for file in "${COMMIT_FILES[@]}"; do
|
||||
for code_file in "${CODE_FILES[@]}"; do
|
||||
if [ "$file" = "$code_file" ]; then
|
||||
INCLUDE_COMMIT=true
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
if [ "$INCLUDE_COMMIT" = true ]; then
|
||||
COMMIT_SUBJECTS_ARRAY+=("- $COMMIT_SUBJECT")
|
||||
FILES_JSON=$(printf '%s\n' "${COMMIT_FILES[@]}" | jq -R . | jq -s .)
|
||||
COMMIT_JSON=$(jq -n --arg sha "$COMMIT_SHA" --arg subject "$COMMIT_SUBJECT" --argjson files "$FILES_JSON" '{sha: $sha, subject: $subject, files: $files}')
|
||||
FILTERED_COMMITS_JSON=$(echo "$FILTERED_COMMITS_JSON" | jq --argjson item "$COMMIT_JSON" '. + [$item]')
|
||||
fi
|
||||
done <<< "$COMMITS_RAW"
|
||||
echo 'commits_json<<EOF' >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$FILTERED_COMMITS_JSON" >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
echo "commit_subjects<<EOF" >> $GITHUB_OUTPUT
|
||||
printf '%s\n' "${COMMIT_SUBJECTS_ARRAY[@]}" >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Build PR content
|
||||
if: steps.get_commits.outputs.has_changes == 'true'
|
||||
id: build_pr_content
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
COMMITS_JSON: ${{ steps.prepare_commits.outputs.commits_json }}
|
||||
CHANGES_SUMMARY: ${{ steps.summarize_changes.outputs.changes_summary }}
|
||||
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
with:
|
||||
github-token: ${{ steps.generate_token_push.outputs.token }}
|
||||
script: |
|
||||
const commits = JSON.parse(process.env.COMMITS_JSON || '[]');
|
||||
const changesSummary = process.env.CHANGES_SUMMARY || 'Changes from fork';
|
||||
const branchName = process.env.BRANCH_NAME || '';
|
||||
const repo = process.env.GITHUB_REPOSITORY || '';
|
||||
const [owner, reponame] = repo.split('/');
|
||||
const nCommits = commits.length;
|
||||
let prTitle = 'Sync ' + nCommits + ' commit' + (nCommits !== 1 ? 's' : '') + ' from fork:';
|
||||
if (nCommits > 0) {
|
||||
prTitle += ' ' + commits[0].subject;
|
||||
}
|
||||
let prBody = `This PR syncs ${nCommits} commit${nCommits !== 1 ? 's' : ''} from branch ${branchName}.\n\n`;
|
||||
prBody += `**Changes Summary:**\n${changesSummary}\n\n`;
|
||||
prBody += `Commits included:\n`;
|
||||
for (const c of commits) {
|
||||
prBody += `- ${c.subject} ([${c.sha}](https://github.com/${owner}/${reponame}/commit/${c.sha}))\n`;
|
||||
}
|
||||
prBody += `\n---\n`;
|
||||
core.setOutput('prTitle', prTitle);
|
||||
core.setOutput('prBody', prBody);
|
||||
|
||||
|
||||
- name: Print PR creation instructions
|
||||
if: steps.get_commits.outputs.has_changes == 'true'
|
||||
env:
|
||||
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
|
||||
PR_TITLE: ${{ steps.build_pr_content.outputs.prTitle }}
|
||||
PR_BODY: ${{ steps.build_pr_content.outputs.prBody }}
|
||||
run: |
|
||||
echo "✅ Branch pushed: $BRANCH_NAME"
|
||||
echo
|
||||
echo "To create a pull request, open:"
|
||||
echo "https://github.com/TandoorRecipes/recipes/compare/tandoor-1...${{ github.repository_owner }}:$BRANCH_NAME?expand=1"
|
||||
echo
|
||||
echo "Suggested PR title:"
|
||||
echo "$PR_TITLE"
|
||||
echo
|
||||
echo "Suggested PR body:"
|
||||
echo "$PR_BODY"
|
||||
68
.github/workflows/dependabot-automerge.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
name: Dependabot Auto-merge
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'automerge') && github.event.pull_request.user.login != 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Remove automerge label
|
||||
uses: actions-ecosystem/action-remove-labels@d05162525702062b6bdef750ed8594fc024b3ed7 # v1.3.0
|
||||
with:
|
||||
labels: automerge
|
||||
|
||||
- name: Add invalid label
|
||||
uses: actions-ecosystem/action-add-labels@1a9c3715c0037e96b97bb38cb4c4b56a1f1d4871 # v1.1.0
|
||||
with:
|
||||
labels: invalid
|
||||
|
||||
- name: Comment restriction
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
⚠️ **Automerge Restriction Notice**
|
||||
|
||||
The `automerge` label has been removed from this PR because it has restricted use. Only PRs created by `dependabot[bot]` are allowed to use the automerge functionality.
|
||||
|
||||
If you believe this is an error, please contact a repository maintainer.
|
||||
|
||||
auto-merge:
|
||||
if: github.actor == 'dependabot[bot]' && contains(github.event.pull_request.labels.*.name, 'automerge')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Generate token
|
||||
id: generate_token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.BOT_APP_ID }}
|
||||
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Auto-approve PR
|
||||
uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v4.0.0
|
||||
with:
|
||||
github-token: ${{ steps.generate_token.outputs.token }}
|
||||
review-message: |
|
||||
🤖 **Dependabot Auto-merge**
|
||||
|
||||
This PR has been automatically approved and enabled for auto-merge. It will be merged automatically once all required checks pass.
|
||||
|
||||
- name: Enable auto-merge
|
||||
uses: daneden/enable-automerge-action@f8558b65c5b8d8bfb592c4e74e3d491624a38fbd # v1.0.0
|
||||
with:
|
||||
github-token: ${{ steps.generate_token.outputs.token }}
|
||||
allowed-author: "dependabot[bot]"
|
||||
merge-method: REBASE # Allowed values: MERGE | SQUASH | REBASE
|
||||
75
.github/workflows/docker-publish.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
name: publish docker image
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-container:
|
||||
concurrency:
|
||||
group: docker-build-${{ github.ref }}
|
||||
name: Build Tandoor Container
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.continue-on-error }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# Standard build config
|
||||
- name: Standard
|
||||
dockerfile: Dockerfile
|
||||
platforms: linux/amd64
|
||||
suffix: ""
|
||||
continue-on-error: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get version number
|
||||
id: get_version
|
||||
run: |
|
||||
echo VERSION=latest >> $GITHUB_OUTPUT
|
||||
|
||||
# Build Vue frontend
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: yarn
|
||||
cache-dependency-path: vue/yarn.lock
|
||||
- name: Install dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build dependencies
|
||||
working-directory: ./vue
|
||||
run: yarn build
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@05340d1c670183e7caabdb33ae9f1c80fae3b0c2 # v3.1.0
|
||||
- name: Set up Buildx
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.7.1
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@3d100841f68d4548bf57e52eb27bd33ec5069f55 # v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.USERNAME }}
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
- name: Docker Metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@be19121bfd18b9c1ac415d9571d4f67b9b357886 # v5.6.0
|
||||
with:
|
||||
images: |
|
||||
smilerz/recipes
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
- name: Build and Push
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.10.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.dockerfile }}
|
||||
pull: true
|
||||
push: true
|
||||
platforms: ${{ matrix.platforms }}
|
||||
tags: '${{ steps.meta.outputs.tags }}'
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
57
.github/workflows/push-orchestrator.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Push Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [working]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
detect-pr-merge:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
outputs:
|
||||
pr_merged: ${{ steps.detect_pr.outputs.result }}
|
||||
steps:
|
||||
- name: Check if commit is part of a PR
|
||||
id: detect_pr
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prs = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
commit_sha: context.sha
|
||||
});
|
||||
|
||||
const pr = prs.data.find(pr => pr.merged_at);
|
||||
const merged = pr ? 'true' : 'false';
|
||||
|
||||
// Set the output explicitly
|
||||
core.setOutput('pr_merged', merged);
|
||||
return merged;
|
||||
|
||||
|
||||
run-ci:
|
||||
needs: detect-pr-merge
|
||||
if: needs.detect-pr-merge.outputs.pr_merged != 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
uses: ./.github/workflows/ci.yml
|
||||
secrets: inherit
|
||||
|
||||
docker-publish:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
needs: [detect-pr-merge, run-ci]
|
||||
if: |
|
||||
needs.detect-pr-merge.outputs.pr_merged == 'true' ||
|
||||
needs.run-ci.result == 'success'
|
||||
uses: ./.github/workflows/docker-publish.yml
|
||||
secrets: inherit
|
||||
268
.github/workflows/stage-branch-for-pr.yml
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
name: Stage Branch for PR
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Push Workflow"]
|
||||
types:
|
||||
- completed
|
||||
branches: [working]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
create-upstream-pr:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: upstream-pr
|
||||
cancel-in-progress: true
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: Generate GitHub App token (for branch push)
|
||||
id: generate_token_push
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.BOT_APP_ID }}
|
||||
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout fork
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.generate_token_push.outputs.token }}
|
||||
|
||||
- name: Setup git user
|
||||
run: |
|
||||
git config user.name "GitHub Action"
|
||||
git config user.email "action@github.com"
|
||||
|
||||
- name: Add upstream remote
|
||||
run: |
|
||||
git remote get-url upstream || git remote add upstream https://github.com/TandoorRecipes/recipes.git
|
||||
git fetch upstream
|
||||
|
||||
- name: Ensure jq is available
|
||||
run: |
|
||||
if ! command -v jq &> /dev/null; then
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
fi
|
||||
|
||||
- name: Create upstream PR branch
|
||||
id: create_branch
|
||||
run: |
|
||||
BRANCH_NAME="upstream-pr-$(date +%Y%m%d-%H%M%S)"
|
||||
git checkout -b "$BRANCH_NAME" || { echo "❌ Failed to create branch $BRANCH_NAME"; exit 1; }
|
||||
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
echo "✅ Created branch: $BRANCH_NAME"
|
||||
|
||||
- name: Restore upstream infrastructure files
|
||||
id: restore_infra
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
git checkout "$BRANCH_NAME"
|
||||
git rm .gitattributes || echo "ℹ️ .gitattributes not present, skipping removal."
|
||||
git checkout upstream/tandoor-1 -- .github/workflows/ || echo "ℹ️ No workflows to restore."
|
||||
git checkout upstream/tandoor-1 -- cookbook/version_info.py || echo "ℹ️ No version_info.py to restore."
|
||||
git add .
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m $'Restore upstream infrastructure files for PR\n\n- Removed fork-specific .gitattributes\n- Restored upstream .github/workflows/\n- Restored upstream cookbook/version_info.py'
|
||||
echo "✅ Infrastructure files restored and committed."
|
||||
else
|
||||
echo "ℹ️ No infrastructure changes to commit."
|
||||
fi
|
||||
|
||||
- name: Push branch to fork (after infra commit)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
echo "Pushing branch $BRANCH_NAME after infra file restore."
|
||||
git push --set-upstream https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
|
||||
echo "✅ Branch pushed: $BRANCH_NAME (infra files)"
|
||||
|
||||
|
||||
- name: Merge upstream branch
|
||||
id: merge_upstream
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
git checkout "$BRANCH_NAME"
|
||||
if git merge --no-edit upstream/tandoor-1; then
|
||||
echo "✅ Merged upstream/tandoor-1 into $BRANCH_NAME"
|
||||
if ! git diff --cached --quiet || [ -n "$(git log origin/$BRANCH_NAME..$BRANCH_NAME --oneline)" ]; then
|
||||
echo "merge_commit=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "merge_commit=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "❌ Merge conflict detected during merge with upstream/tandoor-1. Please resolve conflicts manually." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Push branch to fork (after merge)
|
||||
if: steps.merge_upstream.outputs.merge_commit == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
echo "Pushing branch $BRANCH_NAME after merge."
|
||||
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
|
||||
echo "✅ Branch pushed: $BRANCH_NAME (after merge)"
|
||||
|
||||
|
||||
- name: Get commit list
|
||||
id: get_commits
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
COMMITS_RAW=$(git log upstream/tandoor-1..$BRANCH_NAME --oneline)
|
||||
if [ -z "$COMMITS_RAW" ]; then
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ No commits to contribute - exiting gracefully"
|
||||
exit 0
|
||||
fi
|
||||
echo "commits_raw<<EOF" >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$COMMITS_RAW" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Get changed files
|
||||
id: get_files
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
|
||||
INFRA_PATTERNS='^\.github/|^cookbook/version_info\.py$|^\.gitattributes$'
|
||||
CHANGED_FILES=$(git diff upstream/tandoor-1..$BRANCH_NAME --name-only | grep -Ev "$INFRA_PATTERNS" || true)
|
||||
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$CHANGED_FILES" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
CODE_COUNT=$(echo "$CHANGED_FILES" | grep -c '^' || true)
|
||||
echo "code_count=$CODE_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Summarize changes
|
||||
id: summarize_changes
|
||||
run: |
|
||||
CODE_COUNT=${{ steps.get_files.outputs.code_count }}
|
||||
CHANGED_FILES="${{ steps.get_files.outputs.changed_files }}"
|
||||
if [ "$CODE_COUNT" -eq 0 ]; then
|
||||
CHANGES_SUMMARY="No code files changed. No PR required."
|
||||
else
|
||||
CHANGES_SUMMARY="Modified $CODE_COUNT code files"
|
||||
CHANGES_SUMMARY+=$'\nFiles changed:'
|
||||
CHANGES_SUMMARY+=$'\n'$(echo "$CHANGED_FILES" | sed '/^$/d; s/^/- /')
|
||||
fi
|
||||
echo "changes_summary<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$CHANGES_SUMMARY" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare commit subjects and JSON
|
||||
id: prepare_commits
|
||||
run: |
|
||||
COMMITS_RAW="${{ steps.get_commits.outputs.commits_raw }}"
|
||||
CODE_FILES=( $(echo "${{ steps.get_files.outputs.changed_files }}") )
|
||||
FILTERED_COMMITS_JSON="[]"
|
||||
COMMIT_SUBJECTS_ARRAY=()
|
||||
INFRA_PATTERNS='^\.github/|^cookbook/version_info\.py$|^\.gitattributes$'
|
||||
while IFS= read -r commit_line; do
|
||||
if [ -z "$commit_line" ]; then continue; fi
|
||||
COMMIT_SHA=$(echo "$commit_line" | cut -d' ' -f1)
|
||||
COMMIT_SUBJECT=$(echo "$commit_line" | cut -d' ' -f2-)
|
||||
mapfile -t COMMIT_FILES < <(git diff-tree --no-commit-id --name-only -r "$COMMIT_SHA" | grep -Ev "$INFRA_PATTERNS")
|
||||
# Only include commit if it touches at least one non-infra file that is still different
|
||||
INCLUDE_COMMIT=false
|
||||
for file in "${COMMIT_FILES[@]}"; do
|
||||
for code_file in "${CODE_FILES[@]}"; do
|
||||
if [ "$file" = "$code_file" ]; then
|
||||
INCLUDE_COMMIT=true
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
if [ "$INCLUDE_COMMIT" = true ]; then
|
||||
COMMIT_SUBJECTS_ARRAY+=("- $COMMIT_SUBJECT")
|
||||
FILES_JSON=$(printf '%s\n' "${COMMIT_FILES[@]}" | jq -R . | jq -s .)
|
||||
COMMIT_JSON=$(jq -n --arg sha "$COMMIT_SHA" --arg subject "$COMMIT_SUBJECT" --argjson files "$FILES_JSON" '{sha: $sha, subject: $subject, files: $files}')
|
||||
FILTERED_COMMITS_JSON=$(echo "$FILTERED_COMMITS_JSON" | jq --argjson item "$COMMIT_JSON" '. + [$item]')
|
||||
fi
|
||||
done <<< "$COMMITS_RAW"
|
||||
echo 'commits_json<<EOF' >> $GITHUB_OUTPUT
|
||||
printf "%s\n" "$FILTERED_COMMITS_JSON" >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
echo "commit_subjects<<EOF" >> $GITHUB_OUTPUT
|
||||
printf '%s\n' "${COMMIT_SUBJECTS_ARRAY[@]}" >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: Build PR content
|
||||
if: steps.get_commits.outputs.has_changes == 'true'
|
||||
id: build_pr_content
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
COMMITS_JSON: ${{ steps.prepare_commits.outputs.commits_json }}
|
||||
CHANGES_SUMMARY: ${{ steps.summarize_changes.outputs.changes_summary }}
|
||||
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
with:
|
||||
github-token: ${{ steps.generate_token_push.outputs.token }}
|
||||
script: |
|
||||
const commits = JSON.parse(process.env.COMMITS_JSON || '[]');
|
||||
const changesSummary = process.env.CHANGES_SUMMARY || 'Changes from fork';
|
||||
const branchName = process.env.BRANCH_NAME || '';
|
||||
const repo = process.env.GITHUB_REPOSITORY || '';
|
||||
const [owner, reponame] = repo.split('/');
|
||||
const nCommits = commits.length;
|
||||
let prTitle = 'Sync ' + nCommits + ' commit' + (nCommits !== 1 ? 's' : '') + ' from fork:';
|
||||
if (nCommits > 0) {
|
||||
prTitle += ' ' + commits[0].subject;
|
||||
}
|
||||
let prBody = `This PR syncs ${nCommits} commit${nCommits !== 1 ? 's' : ''} from branch ${branchName}.\n\n`;
|
||||
prBody += `**Changes Summary:**\n${changesSummary}\n\n`;
|
||||
prBody += `Commits included:\n`;
|
||||
for (const c of commits) {
|
||||
prBody += `- ${c.subject} ([${c.sha}](https://github.com/${owner}/${reponame}/commit/${c.sha}))\n`;
|
||||
}
|
||||
core.setOutput('prTitle', prTitle);
|
||||
core.setOutput('prBody', prBody);
|
||||
|
||||
|
||||
- name: Open issue for PR checklist
|
||||
if: steps.get_files.outputs.code_count != '0' && steps.prepare_commits.outputs.commit_subjects != ''
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
|
||||
PR_TITLE: ${{ steps.build_pr_content.outputs.prTitle }}
|
||||
PR_BODY: ${{ steps.build_pr_content.outputs.prBody }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const branch = process.env.BRANCH_NAME || '';
|
||||
const prTitle = process.env.PR_TITLE || '';
|
||||
const prBody = process.env.PR_BODY || '';
|
||||
const repo = process.env.GITHUB_REPOSITORY || '';
|
||||
const [owner, reponame] = repo.split('/');
|
||||
const prLink = `https://github.com/TandoorRecipes/recipes/compare/tandoor-1...${owner}:${branch}?expand=1&title=${encodeURIComponent(prTitle)}`;
|
||||
const issueTitle = `Manual Upstream PR Checklist: ${branch}`;
|
||||
const issueBody = [
|
||||
`A new branch is ready for upstream PR submission.`,
|
||||
'',
|
||||
`- [ ] Submit PR: [Create PR](${prLink})`,
|
||||
'- [ ] PR merged',
|
||||
'- [ ] Branch deleted',
|
||||
'',
|
||||
'**Suggested PR title:**',
|
||||
'```',
|
||||
prTitle,
|
||||
'```',
|
||||
'**Suggested PR body:**',
|
||||
'```',
|
||||
prBody,
|
||||
'```',
|
||||
].join('\n');
|
||||
await github.rest.issues.create({
|
||||
owner,
|
||||
repo: reponame,
|
||||
title: issueTitle,
|
||||
body: issueBody
|
||||
});
|
||||
28
.vscode/launch.json
vendored
@@ -1,18 +1,18 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python Debugger: Django",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/manage.py",
|
||||
"args": ["runserver"],
|
||||
"django": true,
|
||||
"justMyCode": true
|
||||
},
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python Debugger: Django",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/manage.py",
|
||||
"args": ["runserver"],
|
||||
"django": true,
|
||||
"justMyCode": true
|
||||
},
|
||||
{
|
||||
"name": "Python: Debug Tests",
|
||||
"type": "debugpy",
|
||||
|
||||
25
.vscode/settings.json
vendored
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"python.testing.pytestArgs": [
|
||||
"cookbook/tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "eeyore.yapf",
|
||||
},
|
||||
"yapf.args": [],
|
||||
"isort.args": []
|
||||
"python.testing.pytestArgs": ["cookbook/tests"],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "eeyore.yapf"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit"
|
||||
},
|
||||
"yapf.args": [],
|
||||
"isort.args": []
|
||||
}
|
||||
|
||||
15
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12-alpine3.19
|
||||
FROM python:3.12.12-alpine3.21
|
||||
|
||||
#Install all dependencies.
|
||||
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev openldap git
|
||||
@@ -23,7 +23,7 @@ RUN \
|
||||
fi
|
||||
# remove Development dependencies from requirements.txt
|
||||
RUN sed -i '/# Development/,$d' requirements.txt
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev && \
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-dev jpeg-dev libwebp-dev openssl-dev libffi-dev cargo openldap-dev python3-dev xmlsec-dev xmlsec build-base && \
|
||||
echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so && \
|
||||
python -m venv venv && \
|
||||
/opt/recipes/venv/bin/python -m pip install --upgrade pip && \
|
||||
@@ -35,11 +35,12 @@ RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev zlib-de
|
||||
#Copy project and execute it.
|
||||
COPY . ./
|
||||
|
||||
HEALTHCHECK --interval=30s \
|
||||
--timeout=5s \
|
||||
--start-period=10s \
|
||||
--retries=3 \
|
||||
CMD [ "/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8080/openapi" ]
|
||||
# commented for now https://github.com/TandoorRecipes/recipes/issues/3478
|
||||
#HEALTHCHECK --interval=30s \
|
||||
# --timeout=5s \
|
||||
# --start-period=10s \
|
||||
# --retries=3 \
|
||||
# CMD [ "/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8080/openapi" ]
|
||||
|
||||
# collect information from git repositories
|
||||
RUN /opt/recipes/venv/bin/python version.py
|
||||
|
||||
3
boot.sh
@@ -41,6 +41,9 @@ if [ -f "${SOCIALACCOUNT_PROVIDERS_FILE}" ]; then
|
||||
export SOCIALACCOUNT_PROVIDERS=$(cat "$SOCIALACCOUNT_PROVIDERS_FILE")
|
||||
fi
|
||||
|
||||
if [ -f "${S3_SECRET_ACCESS_KEY_FILE}" ]; then
|
||||
export S3_SECRET_ACCESS_KEY=$(cat "$S3_SECRET_ACCESS_KEY_FILE")
|
||||
fi
|
||||
|
||||
echo "Waiting for database to be ready..."
|
||||
|
||||
|
||||
@@ -1,29 +1,62 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from cookbook.models import ShoppingListEntry, Space, ConnectorConfig
|
||||
from cookbook.models import ConnectorConfig, ShoppingListEntry, User
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserDTO:
|
||||
username: str
|
||||
first_name: Optional[str]
|
||||
|
||||
@staticmethod
|
||||
def create_from_user(instance: User) -> 'UserDTO':
|
||||
return UserDTO(username=instance.username, first_name=instance.first_name if instance.first_name else None)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ShoppingListEntryDTO:
|
||||
food_name: str
|
||||
amount: Optional[float]
|
||||
base_unit: Optional[str]
|
||||
unit_name: Optional[str]
|
||||
created_by: UserDTO
|
||||
|
||||
@staticmethod
|
||||
def try_create_from_entry(instance: ShoppingListEntry) -> Optional['ShoppingListEntryDTO']:
|
||||
if instance.food is None or instance.created_by is None:
|
||||
return None
|
||||
|
||||
return ShoppingListEntryDTO(
|
||||
food_name=instance.food.name,
|
||||
amount=instance.amount if instance.amount else None,
|
||||
unit_name=instance.unit.name if instance.unit else None,
|
||||
base_unit=instance.unit.base_unit if instance.unit and instance.unit.base_unit else None,
|
||||
created_by=UserDTO.create_from_user(instance.created_by),
|
||||
)
|
||||
|
||||
|
||||
# A Connector is 'destroyed' & recreated each time 'any' ConnectorConfig in a space changes.
|
||||
class Connector(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, config: ConnectorConfig):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_shopping_list_entry_created(self, space: Space, instance: ShoppingListEntry) -> None:
|
||||
async def on_shopping_list_entry_created(self, instance: ShoppingListEntryDTO) -> None:
|
||||
pass
|
||||
|
||||
# This method might not trigger on 'direct' entry updates: https://stackoverflow.com/a/35238823
|
||||
@abstractmethod
|
||||
async def on_shopping_list_entry_updated(self, space: Space, instance: ShoppingListEntry) -> None:
|
||||
async def on_shopping_list_entry_updated(self, instance: ShoppingListEntryDTO) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_shopping_list_entry_deleted(self, space: Space, instance: ShoppingListEntry) -> None:
|
||||
async def on_shopping_list_entry_deleted(self, instance: ShoppingListEntryDTO) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def close(self) -> None:
|
||||
pass
|
||||
|
||||
# TODO: Add Recipes & possibly Meal Place listeners/hooks (And maybe more?)
|
||||
|
||||
@@ -7,14 +7,14 @@ from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from logging import Logger
|
||||
from types import UnionType
|
||||
from typing import List, Any, Dict, Optional, Type
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
|
||||
from django.conf import settings
|
||||
from django_scopes import scope
|
||||
|
||||
from cookbook.connectors.connector import Connector
|
||||
from cookbook.connectors.connector import Connector, ShoppingListEntryDTO
|
||||
from cookbook.connectors.homeassistant import HomeAssistant
|
||||
from cookbook.models import ShoppingListEntry, Space, ConnectorConfig
|
||||
from cookbook.models import ConnectorConfig, ShoppingListEntry, Space
|
||||
|
||||
REGISTERED_CLASSES: UnionType | Type = ShoppingListEntry
|
||||
|
||||
@@ -56,15 +56,16 @@ class ConnectorManager(metaclass=Singleton):
|
||||
|
||||
def __init__(self):
|
||||
self._logger = logging.getLogger("recipes.connector")
|
||||
self._logger.debug("ConnectorManager initializing")
|
||||
self._queue = queue.Queue(maxsize=settings.EXTERNAL_CONNECTORS_QUEUE_SIZE)
|
||||
self._worker = threading.Thread(target=self.worker, args=(0, self._queue,), daemon=True)
|
||||
self._worker = threading.Thread(target=self.worker, args=(
|
||||
0,
|
||||
self._queue,
|
||||
), daemon=True)
|
||||
self._worker.start()
|
||||
|
||||
# Called by post save & post delete signals
|
||||
def __call__(self, instance: Any, **kwargs) -> None:
|
||||
if not isinstance(instance, self._listening_to_classes) or not hasattr(instance, "space"):
|
||||
return
|
||||
|
||||
action_type: ActionType
|
||||
if "created" in kwargs and kwargs["created"]:
|
||||
action_type = ActionType.CREATED
|
||||
@@ -75,16 +76,37 @@ class ConnectorManager(metaclass=Singleton):
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
self._queue.put_nowait(Work(instance, action_type))
|
||||
except queue.Full:
|
||||
self._logger.info(f"queue was full, so skipping {action_type} of type {type(instance)}")
|
||||
return
|
||||
self._add_work(action_type, instance)
|
||||
|
||||
def _add_work(self, action_type: ActionType, *instances: REGISTERED_CLASSES):
|
||||
for instance in instances:
|
||||
if not isinstance(instance, self._listening_to_classes) or not hasattr(instance, "space"):
|
||||
continue
|
||||
try:
|
||||
_force_load_instance(instance)
|
||||
self._queue.put_nowait(Work(instance, action_type))
|
||||
except queue.Full:
|
||||
self._logger.info(f"queue was full, so skipping {action_type} of type {type(instance)}")
|
||||
|
||||
def stop(self):
|
||||
self._queue.join()
|
||||
self._worker.join()
|
||||
|
||||
@classmethod
|
||||
def is_initialized(cls):
|
||||
return cls in cls._instances
|
||||
|
||||
@staticmethod
|
||||
def add_work(action_type: ActionType, *instances: REGISTERED_CLASSES):
|
||||
"""
|
||||
Manually inject work that failed to come in through the __call__ (aka Django signal)
|
||||
Before the work is processed, we check if the connectionManager is initialized, because if it's not, we don't want to accidentally initialize it.
|
||||
Be careful calling it, because it might result in a instance being processed twice.
|
||||
"""
|
||||
if not ConnectorManager.is_initialized():
|
||||
return
|
||||
ConnectorManager()._add_work(action_type, *instances)
|
||||
|
||||
@staticmethod
|
||||
def worker(worker_id: int, worker_queue: queue.Queue):
|
||||
logger = logging.getLogger("recipes.connector.worker")
|
||||
@@ -116,7 +138,7 @@ class ConnectorManager(metaclass=Singleton):
|
||||
|
||||
if connectors is None or refresh_connector_cache:
|
||||
if connectors is not None:
|
||||
loop.run_until_complete(close_connectors(connectors))
|
||||
loop.run_until_complete(_close_connectors(connectors))
|
||||
|
||||
with scope(space=space):
|
||||
connectors: List[Connector] = list()
|
||||
@@ -142,7 +164,7 @@ class ConnectorManager(metaclass=Singleton):
|
||||
|
||||
logger.debug(f"running {len(connectors)} connectors for {item.instance=} with {item.actionType=}")
|
||||
|
||||
loop.run_until_complete(run_connectors(connectors, space, item.instance, item.actionType))
|
||||
loop.run_until_complete(run_connectors(connectors, item.instance, item.actionType))
|
||||
worker_queue.task_done()
|
||||
|
||||
logger.info(f"terminating ConnectionManager worker {worker_id}")
|
||||
@@ -159,7 +181,14 @@ class ConnectorManager(metaclass=Singleton):
|
||||
return None
|
||||
|
||||
|
||||
async def close_connectors(connectors: List[Connector]):
|
||||
def _force_load_instance(instance: REGISTERED_CLASSES):
|
||||
if isinstance(instance, ShoppingListEntry):
|
||||
_ = instance.food # Force load food
|
||||
_ = instance.unit # Force load unit
|
||||
_ = instance.created_by # Force load created_by
|
||||
|
||||
|
||||
async def _close_connectors(connectors: List[Connector]):
|
||||
tasks: List[Task] = [asyncio.create_task(connector.close()) for connector in connectors]
|
||||
|
||||
if len(tasks) == 0:
|
||||
@@ -171,22 +200,24 @@ async def close_connectors(connectors: List[Connector]):
|
||||
logging.exception("received an exception while closing one of the connectors")
|
||||
|
||||
|
||||
async def run_connectors(connectors: List[Connector], space: Space, instance: REGISTERED_CLASSES, action_type: ActionType):
|
||||
async def run_connectors(connectors: List[Connector], instance: REGISTERED_CLASSES, action_type: ActionType):
|
||||
tasks: List[Task] = list()
|
||||
|
||||
if isinstance(instance, ShoppingListEntry):
|
||||
shopping_list_entry: ShoppingListEntry = instance
|
||||
shopping_list_entry = ShoppingListEntryDTO.try_create_from_entry(instance)
|
||||
if shopping_list_entry is None:
|
||||
return
|
||||
|
||||
match action_type:
|
||||
case ActionType.CREATED:
|
||||
for connector in connectors:
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_created(space, shopping_list_entry)))
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_created(shopping_list_entry)))
|
||||
case ActionType.UPDATED:
|
||||
for connector in connectors:
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_updated(space, shopping_list_entry)))
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_updated(shopping_list_entry)))
|
||||
case ActionType.DELETED:
|
||||
for connector in connectors:
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_deleted(space, shopping_list_entry)))
|
||||
tasks.append(asyncio.create_task(connector.on_shopping_list_entry_deleted(shopping_list_entry)))
|
||||
|
||||
if len(tasks) == 0:
|
||||
return
|
||||
|
||||
@@ -35,6 +35,21 @@ def get_filetype(name):
|
||||
return '.jpeg'
|
||||
|
||||
|
||||
def is_file_type_allowed(filename, image_only=False):
|
||||
is_file_allowed = False
|
||||
allowed_file_types = ['.pdf', '.docx', '.xlsx']
|
||||
allowed_image_types = ['.png', '.jpg', '.jpeg', '.gif', '.webp']
|
||||
check_list = allowed_image_types
|
||||
if not image_only:
|
||||
check_list += allowed_file_types
|
||||
|
||||
for file_type in check_list:
|
||||
if filename.lower().endswith(file_type):
|
||||
is_file_allowed = True
|
||||
|
||||
return is_file_allowed
|
||||
|
||||
|
||||
# TODO this whole file needs proper documentation, refactoring, and testing
|
||||
# TODO also add env variable to define which images sizes should be compressed
|
||||
# filetype argument can not be optional, otherwise this function will treat all images as if they were a jpeg
|
||||
|
||||
@@ -58,8 +58,7 @@ class IngredientParser:
|
||||
def parse_fraction(self, x):
|
||||
if len(x) == 1 and 'fraction' in unicodedata.decomposition(x):
|
||||
frac_split = unicodedata.decomposition(x[-1:]).split()
|
||||
return (float((frac_split[1]).replace('003', ''))
|
||||
/ float((frac_split[3]).replace('003', '')))
|
||||
return (float((frac_split[1]).replace('003', '')) / float((frac_split[3]).replace('003', '')))
|
||||
else:
|
||||
frac_split = x.split('/')
|
||||
if not len(frac_split) == 2:
|
||||
@@ -78,12 +77,7 @@ class IngredientParser:
|
||||
|
||||
did_check_frac = False
|
||||
end = 0
|
||||
while (end < len(x) and (x[end] in string.digits
|
||||
or (
|
||||
(x[end] == '.' or x[end] == ',' or x[end] == '/')
|
||||
and end + 1 < len(x)
|
||||
and x[end + 1] in string.digits
|
||||
))):
|
||||
while (end < len(x) and (x[end] in string.digits or ((x[end] == '.' or x[end] == ',' or x[end] == '/') and end + 1 < len(x) and x[end + 1] in string.digits))):
|
||||
end += 1
|
||||
if end > 0:
|
||||
if "/" in x[:end]:
|
||||
@@ -107,8 +101,9 @@ class IngredientParser:
|
||||
if unit is not None and unit.strip() == '':
|
||||
unit = None
|
||||
|
||||
if unit is not None and (unit.startswith('(') or unit.startswith(
|
||||
'-')): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
|
||||
if unit is not None and (
|
||||
unit.startswith('(') or unit.startswith('-')
|
||||
): # i dont know any unit that starts with ( or - so its likely an alternative like 1L (500ml) Water or 2-3
|
||||
unit = None
|
||||
note = x
|
||||
return amount, unit, note
|
||||
@@ -118,7 +113,7 @@ class IngredientParser:
|
||||
note = ''
|
||||
start = 0
|
||||
# search for first occurrence of an argument ending in a comma
|
||||
while start < len(tokens) and not tokens[start].endswith(','):
|
||||
while start < len(tokens) and not tokens[start].endswith((',', ';', ':')):
|
||||
start += 1
|
||||
if start == len(tokens):
|
||||
# no token ending in a comma found -> use everything as food
|
||||
|
||||
@@ -9,8 +9,7 @@ from django.utils import timezone, translation
|
||||
|
||||
from cookbook.helper.HelperFunctions import Round, str2bool
|
||||
from cookbook.managers import DICTIONARY
|
||||
from cookbook.models import (CookLog, CustomFilter, Food, Keyword, Recipe, SearchFields,
|
||||
SearchPreference, ViewLog)
|
||||
from cookbook.models import CookLog, CustomFilter, Food, Keyword, Recipe, SearchFields, SearchPreference, ViewLog
|
||||
from recipes import settings
|
||||
|
||||
|
||||
@@ -22,11 +21,8 @@ class RecipeSearch():
|
||||
self._request = request
|
||||
self._queryset = None
|
||||
if f := params.get('filter', None):
|
||||
custom_filter = (
|
||||
CustomFilter.objects.filter(id=f, space=self._request.space)
|
||||
.filter(Q(created_by=self._request.user) | Q(shared=self._request.user) | Q(recipebook__shared=self._request.user))
|
||||
.first()
|
||||
)
|
||||
custom_filter = (CustomFilter.objects.filter(id=f, space=self._request.space).filter(
|
||||
Q(created_by=self._request.user) | Q(shared=self._request.user) | Q(recipebook__shared=self._request.user)).first())
|
||||
if custom_filter:
|
||||
self._params = {**json.loads(custom_filter.search)}
|
||||
self._original_params = {**(params or {})}
|
||||
@@ -38,7 +34,7 @@ class RecipeSearch():
|
||||
else:
|
||||
self._params = {**(params or {})}
|
||||
if self._request.user.is_authenticated:
|
||||
CACHE_KEY = f'search_pref_{request.user.id}'
|
||||
CACHE_KEY = f"search_pref_{request.user.id}"
|
||||
cached_result = cache.get(CACHE_KEY, default=None)
|
||||
if cached_result is not None:
|
||||
self._search_prefs = cached_result
|
||||
@@ -47,44 +43,43 @@ class RecipeSearch():
|
||||
cache.set(CACHE_KEY, self._search_prefs, timeout=10)
|
||||
else:
|
||||
self._search_prefs = SearchPreference()
|
||||
self._string = self._params.get('query').strip(
|
||||
) if self._params.get('query', None) else None
|
||||
self._rating = self._params.get('rating', None)
|
||||
self._string = self._params.get("query").strip() if self._params.get("query", None) else None
|
||||
self._rating = self._params.get("rating", None)
|
||||
self._keywords = {
|
||||
'or': self._params.get('keywords_or', None) or self._params.get('keywords', None),
|
||||
'and': self._params.get('keywords_and', None),
|
||||
'or_not': self._params.get('keywords_or_not', None),
|
||||
'and_not': self._params.get('keywords_and_not', None)
|
||||
"or": self._params.get("keywords_or", None) or self._params.get("keywords", None),
|
||||
"and": self._params.get("keywords_and", None),
|
||||
"or_not": self._params.get("keywords_or_not", None),
|
||||
"and_not": self._params.get("keywords_and_not", None),
|
||||
}
|
||||
self._foods = {
|
||||
'or': self._params.get('foods_or', None) or self._params.get('foods', None),
|
||||
'and': self._params.get('foods_and', None),
|
||||
'or_not': self._params.get('foods_or_not', None),
|
||||
'and_not': self._params.get('foods_and_not', None)
|
||||
"or": self._params.get("foods_or", None) or self._params.get("foods", None),
|
||||
"and": self._params.get("foods_and", None),
|
||||
"or_not": self._params.get("foods_or_not", None),
|
||||
"and_not": self._params.get("foods_and_not", None),
|
||||
}
|
||||
self._books = {
|
||||
'or': self._params.get('books_or', None) or self._params.get('books', None),
|
||||
'and': self._params.get('books_and', None),
|
||||
'or_not': self._params.get('books_or_not', None),
|
||||
'and_not': self._params.get('books_and_not', None)
|
||||
"or": self._params.get("books_or", None) or self._params.get("books", None),
|
||||
"and": self._params.get("books_and", None),
|
||||
"or_not": self._params.get("books_or_not", None),
|
||||
"and_not": self._params.get("books_and_not", None),
|
||||
}
|
||||
self._steps = self._params.get('steps', None)
|
||||
self._units = self._params.get('units', None)
|
||||
self._steps = self._params.get("steps", None)
|
||||
self._units = self._params.get("units", None)
|
||||
# TODO add created by
|
||||
# TODO image exists
|
||||
self._sort_order = self._params.get('sort_order', None)
|
||||
self._internal = str2bool(self._params.get('internal', None))
|
||||
self._random = str2bool(self._params.get('random', False))
|
||||
self._new = str2bool(self._params.get('new', False))
|
||||
self._num_recent = int(self._params.get('num_recent', 0))
|
||||
self._include_children = str2bool(
|
||||
self._params.get('include_children', None))
|
||||
self._timescooked = self._params.get('timescooked', None)
|
||||
self._cookedon = self._params.get('cookedon', None)
|
||||
self._createdon = self._params.get('createdon', None)
|
||||
self._updatedon = self._params.get('updatedon', None)
|
||||
self._viewedon = self._params.get('viewedon', None)
|
||||
self._makenow = self._params.get('makenow', None)
|
||||
self._sort_order = self._params.get("sort_order", None)
|
||||
self._internal = str2bool(self._params.get("internal", None))
|
||||
self._random = str2bool(self._params.get("random", False))
|
||||
self._new = str2bool(self._params.get("new", False))
|
||||
self._num_recent = int(self._params.get("num_recent", 0))
|
||||
self._include_children = str2bool(self._params.get("include_children", None))
|
||||
self._timescooked = self._params.get("timescooked", None)
|
||||
self._cookedon = self._params.get("cookedon", None)
|
||||
self._createdon = self._params.get("createdon", None)
|
||||
self._updatedon = self._params.get("updatedon", None)
|
||||
self._viewedon = self._params.get("viewedon", None)
|
||||
self._makenow = self._params.get("makenow", None)
|
||||
self._never_used_food = str2bool(self._params.get("never_used_food", False))
|
||||
# this supports hidden feature to find recipes missing X ingredients
|
||||
if isinstance(self._makenow, bool) and self._makenow == True:
|
||||
self._makenow = 0
|
||||
@@ -96,7 +91,7 @@ class RecipeSearch():
|
||||
except (ValueError, TypeError):
|
||||
self._makenow = None
|
||||
|
||||
self._search_type = self._search_prefs.search or 'plain'
|
||||
self._search_type = self._search_prefs.search or "plain"
|
||||
if self._string:
|
||||
if self._postgres:
|
||||
self._unaccent_include = self._search_prefs.unaccent.values_list('field', flat=True)
|
||||
@@ -114,11 +109,7 @@ class RecipeSearch():
|
||||
|
||||
if self._search_type not in ['websearch', 'raw'] and self._trigram_include:
|
||||
self._trigram = True
|
||||
self.search_query = SearchQuery(
|
||||
self._string,
|
||||
search_type=self._search_type,
|
||||
config=self._language,
|
||||
)
|
||||
self.search_query = SearchQuery(self._string, search_type=self._search_type, config=self._language, )
|
||||
self.search_rank = None
|
||||
self.orderby = []
|
||||
self._filters = None
|
||||
@@ -127,7 +118,6 @@ class RecipeSearch():
|
||||
def get_queryset(self, queryset):
|
||||
self._queryset = queryset
|
||||
self._queryset = self._queryset.prefetch_related('keywords')
|
||||
|
||||
self._build_sort_order()
|
||||
self._recently_viewed(num_recent=self._num_recent)
|
||||
self._cooked_on_filter(cooked_date=self._cookedon)
|
||||
@@ -144,6 +134,7 @@ class RecipeSearch():
|
||||
self.step_filters(steps=self._steps)
|
||||
self.unit_filters(units=self._units)
|
||||
self._makenow_filter(missing=self._makenow)
|
||||
self._never_used_food_filter()
|
||||
self.string_filters(string=self._string)
|
||||
return self._queryset.filter(space=self._request.space).order_by(*self.orderby)
|
||||
|
||||
@@ -151,22 +142,22 @@ class RecipeSearch():
|
||||
for x in args:
|
||||
if x in self.orderby:
|
||||
return True
|
||||
elif '-' + x in self.orderby:
|
||||
elif "-" + x in self.orderby:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _build_sort_order(self):
|
||||
if self._random:
|
||||
self.orderby = ['?']
|
||||
self.orderby = ["?"]
|
||||
else:
|
||||
order = []
|
||||
# TODO add userpreference for default sort order and replace '-favorite'
|
||||
default_order = ['name']
|
||||
default_order = ["name"]
|
||||
# recent and new_recipe are always first; they float a few recipes to the top
|
||||
if self._num_recent:
|
||||
order += ['-recent']
|
||||
order += ["-recent"]
|
||||
if self._new:
|
||||
order += ['-new_recipe']
|
||||
order += ["-new_recipe"]
|
||||
|
||||
# if a sort order is provided by user - use that order
|
||||
if self._sort_order:
|
||||
@@ -175,20 +166,18 @@ class RecipeSearch():
|
||||
else:
|
||||
order += self._sort_order
|
||||
if not self._postgres or not self._string:
|
||||
if 'score' in order:
|
||||
order.remove('score')
|
||||
if '-score' in order:
|
||||
order.remove('-score')
|
||||
if "score" in order:
|
||||
order.remove("score")
|
||||
if "-score" in order:
|
||||
order.remove("-score")
|
||||
# if no sort order provided prioritize text search, followed by the default search
|
||||
elif self._postgres and self._string and (self._trigram or self._fulltext_include):
|
||||
order += ['-score', *default_order]
|
||||
order += ["-score", *default_order]
|
||||
# otherwise sort by the remaining order_by attributes or favorite by default
|
||||
else:
|
||||
order += default_order
|
||||
order[:] = [Lower('name').asc() if x ==
|
||||
'name' else x for x in order]
|
||||
order[:] = [Lower('name').desc() if x ==
|
||||
'-name' else x for x in order]
|
||||
order[:] = [Lower("name").asc() if x == "name" else x for x in order]
|
||||
order[:] = [Lower("name").desc() if x == "-name" else x for x in order]
|
||||
self.orderby = order
|
||||
|
||||
def string_filters(self, string=None):
|
||||
@@ -223,7 +212,7 @@ class RecipeSearch():
|
||||
self._queryset = self._queryset.annotate(score=F('rank') + F('simularity'))
|
||||
else:
|
||||
query_filter = Q()
|
||||
for f in [x + '__unaccent__iexact' if x in self._unaccent_include else x + '__iexact' for x in SearchFields.objects.all().values_list('field', flat=True)]:
|
||||
for f in [x + "__unaccent__iexact" if x in self._unaccent_include else x + "__iexact" for x in SearchFields.objects.all().values_list("field", flat=True)]:
|
||||
query_filter |= Q(**{"%s" % f: self._string})
|
||||
self._queryset = self._queryset.filter(query_filter).distinct()
|
||||
|
||||
@@ -235,12 +224,11 @@ class RecipeSearch():
|
||||
else:
|
||||
default = timezone.now()
|
||||
self._queryset = self._queryset.annotate(
|
||||
lastcooked=Coalesce(Max(Case(When(cooklog__created_by=self._request.user, cooklog__space=self._request.space, then='cooklog__created_at'))), Value(default))
|
||||
)
|
||||
lastcooked=Coalesce(Max(Case(When(cooklog__created_by=self._request.user, cooklog__space=self._request.space, then='cooklog__created_at'))), Value(default)))
|
||||
if cooked_date is None:
|
||||
return
|
||||
|
||||
cooked_date = date(*[int(x)for x in cooked_date.split('-') if x != ''])
|
||||
cooked_date = date(*[int(x) for x in cooked_date.split('-') if x != ''])
|
||||
|
||||
if lessthan:
|
||||
self._queryset = self._queryset.filter(lastcooked__date__lte=cooked_date).exclude(lastcooked=default)
|
||||
@@ -261,22 +249,21 @@ class RecipeSearch():
|
||||
if updated_date is None:
|
||||
return
|
||||
lessthan = '-' in updated_date[:1]
|
||||
updated_date = date(*[int(x)for x in updated_date.split('-') if x != ''])
|
||||
updated_date = date(*[int(x) for x in updated_date.split('-') if x != ''])
|
||||
if lessthan:
|
||||
self._queryset = self._queryset.filter(updated_at__date__lte=updated_date)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(updated_at__date__gte=updated_date)
|
||||
|
||||
def _viewed_on_filter(self, viewed_date=None):
|
||||
if self._sort_includes('lastviewed') or viewed_date:
|
||||
if self._sort_includes("lastviewed") or viewed_date:
|
||||
longTimeAgo = timezone.now() - timedelta(days=100000)
|
||||
self._queryset = self._queryset.annotate(
|
||||
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo))
|
||||
)
|
||||
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__created_at'))), Value(longTimeAgo)))
|
||||
if viewed_date is None:
|
||||
return
|
||||
lessthan = '-' in viewed_date[:1]
|
||||
viewed_date = date(*[int(x)for x in viewed_date.split('-') if x != ''])
|
||||
viewed_date = date(*[int(x) for x in viewed_date.split('-') if x != ''])
|
||||
|
||||
if lessthan:
|
||||
self._queryset = self._queryset.filter(lastviewed__date__lte=viewed_date).exclude(lastviewed=longTimeAgo)
|
||||
@@ -287,24 +274,17 @@ class RecipeSearch():
|
||||
# TODO make new days a user-setting
|
||||
if not self._new:
|
||||
return
|
||||
self._queryset = self._queryset.annotate(
|
||||
new_recipe=Case(
|
||||
When(created_at__gte=(timezone.now() - timedelta(days=new_days)), then=('pk')),
|
||||
default=Value(0),
|
||||
)
|
||||
)
|
||||
self._queryset = self._queryset.annotate(new_recipe=Case(When(created_at__gte=(timezone.now() - timedelta(days=new_days)), then=('pk')), default=Value(0), ))
|
||||
|
||||
def _recently_viewed(self, num_recent=None):
|
||||
if not num_recent:
|
||||
if self._sort_includes('lastviewed'):
|
||||
self._queryset = self._queryset.annotate(lastviewed=Coalesce(
|
||||
Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then='viewlog__pk'))), Value(0)))
|
||||
if self._sort_includes("lastviewed"):
|
||||
self._queryset = self._queryset.annotate(
|
||||
lastviewed=Coalesce(Max(Case(When(viewlog__created_by=self._request.user, viewlog__space=self._request.space, then="viewlog__pk"))), Value(0)))
|
||||
return
|
||||
|
||||
num_recent_recipes = (
|
||||
ViewLog.objects.filter(created_by=self._request.user, space=self._request.space)
|
||||
.values('recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent]
|
||||
)
|
||||
num_recent_recipes = (ViewLog.objects.filter(created_by=self._request.user,
|
||||
space=self._request.space).values('recipe').annotate(recent=Max('created_at')).order_by('-recent')[:num_recent])
|
||||
self._queryset = self._queryset.annotate(recent=Coalesce(Max(Case(When(pk__in=num_recent_recipes.values('recipe'), then='viewlog__pk'))), Value(0)))
|
||||
|
||||
def _favorite_recipes(self, times_cooked=None):
|
||||
@@ -314,17 +294,13 @@ class RecipeSearch():
|
||||
default = 1000
|
||||
else:
|
||||
default = 0
|
||||
favorite_recipes = (
|
||||
CookLog.objects.filter(created_by=self._request.user, space=self._request.space, recipe=OuterRef('pk'))
|
||||
.values('recipe')
|
||||
.annotate(count=Count('pk', distinct=True))
|
||||
.values('count')
|
||||
)
|
||||
favorite_recipes = (CookLog.objects.filter(created_by=self._request.user, space=self._request.space,
|
||||
recipe=OuterRef('pk')).values('recipe').annotate(count=Count('pk', distinct=True)).values('count'))
|
||||
self._queryset = self._queryset.annotate(favorite=Coalesce(Subquery(favorite_recipes), default))
|
||||
if times_cooked is None:
|
||||
return
|
||||
|
||||
if times_cooked == '0':
|
||||
if times_cooked == "0":
|
||||
self._queryset = self._queryset.filter(favorite=0)
|
||||
elif less_than:
|
||||
self._queryset = self._queryset.filter(favorite__lte=int(times_cooked.replace('-', ''))).exclude(favorite=0)
|
||||
@@ -341,23 +317,23 @@ class RecipeSearch():
|
||||
kwargs[kw_filter] = [kwargs[kw_filter]]
|
||||
|
||||
keywords = Keyword.objects.filter(pk__in=kwargs[kw_filter])
|
||||
if 'or' in kw_filter:
|
||||
if "or" in kw_filter:
|
||||
if self._include_children:
|
||||
f_or = Q(keywords__in=Keyword.include_descendants(keywords))
|
||||
else:
|
||||
f_or = Q(keywords__in=keywords)
|
||||
if 'not' in kw_filter:
|
||||
if "not" in kw_filter:
|
||||
self._queryset = self._queryset.exclude(f_or)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(f_or)
|
||||
elif 'and' in kw_filter:
|
||||
elif "and" in kw_filter:
|
||||
recipes = Recipe.objects.all()
|
||||
for kw in keywords:
|
||||
if self._include_children:
|
||||
f_and = Q(keywords__in=kw.get_descendants_and_self())
|
||||
else:
|
||||
f_and = Q(keywords=kw)
|
||||
if 'not' in kw_filter:
|
||||
if "not" in kw_filter:
|
||||
recipes = recipes.filter(f_and)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(f_and)
|
||||
@@ -374,24 +350,24 @@ class RecipeSearch():
|
||||
kwargs[fd_filter] = [kwargs[fd_filter]]
|
||||
|
||||
foods = Food.objects.filter(pk__in=kwargs[fd_filter])
|
||||
if 'or' in fd_filter:
|
||||
if "or" in fd_filter:
|
||||
if self._include_children:
|
||||
f_or = Q(steps__ingredients__food__in=Food.include_descendants(foods))
|
||||
else:
|
||||
f_or = Q(steps__ingredients__food__in=foods)
|
||||
|
||||
if 'not' in fd_filter:
|
||||
if "not" in fd_filter:
|
||||
self._queryset = self._queryset.exclude(f_or)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(f_or)
|
||||
elif 'and' in fd_filter:
|
||||
elif "and" in fd_filter:
|
||||
recipes = Recipe.objects.all()
|
||||
for food in foods:
|
||||
if self._include_children:
|
||||
f_and = Q(steps__ingredients__food__in=food.get_descendants_and_self())
|
||||
else:
|
||||
f_and = Q(steps__ingredients__food=food)
|
||||
if 'not' in fd_filter:
|
||||
if "not" in fd_filter:
|
||||
recipes = recipes.filter(f_and)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(f_and)
|
||||
@@ -416,11 +392,11 @@ class RecipeSearch():
|
||||
else:
|
||||
default = 0
|
||||
# TODO make ratings a settings user-only vs all-users
|
||||
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then='cooklog__rating'), default=default))))
|
||||
self._queryset = self._queryset.annotate(rating=Round(Avg(Case(When(cooklog__created_by=self._request.user, then="cooklog__rating"), default=default))))
|
||||
if rating is None:
|
||||
return
|
||||
|
||||
if rating == '0':
|
||||
if rating == "0":
|
||||
self._queryset = self._queryset.filter(rating=0)
|
||||
elif lessthan:
|
||||
self._queryset = self._queryset.filter(rating__lte=int(rating[1:])).exclude(rating=0)
|
||||
@@ -441,13 +417,13 @@ class RecipeSearch():
|
||||
if not isinstance(kwargs[bk_filter], list):
|
||||
kwargs[bk_filter] = [kwargs[bk_filter]]
|
||||
|
||||
if 'or' in bk_filter:
|
||||
if "or" in bk_filter:
|
||||
f = Q(recipebookentry__book__id__in=kwargs[bk_filter])
|
||||
if 'not' in bk_filter:
|
||||
if "not" in bk_filter:
|
||||
self._queryset = self._queryset.exclude(f)
|
||||
else:
|
||||
self._queryset = self._queryset.filter(f)
|
||||
elif 'and' in bk_filter:
|
||||
elif "and" in bk_filter:
|
||||
recipes = Recipe.objects.all()
|
||||
for book in kwargs[bk_filter]:
|
||||
if 'not' in bk_filter:
|
||||
@@ -520,62 +496,66 @@ class RecipeSearch():
|
||||
trigram += TrigramSimilarity(f, self._string)
|
||||
else:
|
||||
trigram = TrigramSimilarity(f, self._string)
|
||||
self._fuzzy_match = (
|
||||
Recipe.objects.annotate(trigram=trigram)
|
||||
.distinct()
|
||||
.annotate(simularity=Max('trigram'))
|
||||
.values('id', 'simularity')
|
||||
.filter(simularity__gt=self._search_prefs.trigram_threshold)
|
||||
)
|
||||
self._fuzzy_match = (Recipe.objects.annotate(trigram=trigram).distinct().annotate(simularity=Max('trigram')).values('id', 'simularity').filter(
|
||||
simularity__gt=self._search_prefs.trigram_threshold))
|
||||
self._filters += [Q(pk__in=self._fuzzy_match.values('pk'))]
|
||||
|
||||
def _makenow_filter(self, missing=None):
|
||||
if missing is None or (isinstance(missing, bool) and missing == False):
|
||||
return
|
||||
shopping_users = [*self._request.user.get_shopping_share(), self._request.user]
|
||||
onhand_filter = Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
||||
|
||||
onhand_filter = (
|
||||
Q(steps__ingredients__food__onhand_users__in=shopping_users) # food onhand
|
||||
# ignore substitutions when also using the never_used_food filter
|
||||
if not self._never_used_food:
|
||||
# or substitute food onhand
|
||||
| Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users)
|
||||
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
||||
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users))
|
||||
)
|
||||
makenow_recipes = Recipe.objects.annotate(
|
||||
count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
||||
count_onhand=Count('steps__ingredients__food__pk', filter=onhand_filter, distinct=True),
|
||||
count_ignore_shopping=Count(
|
||||
'steps__ingredients__food__pk', filter=Q(steps__ingredients__food__ignore_shopping=True, steps__ingredients__food__recipe__isnull=True), distinct=True
|
||||
),
|
||||
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users), then=Value(1)), default=Value(0)),
|
||||
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users), then=Value(1)), default=Value(0))
|
||||
).annotate(missingfood=F('count_food') - F('count_onhand') - F('count_ignore_shopping')).filter(missingfood__lte=missing)
|
||||
onhand_filter |= (Q(steps__ingredients__food__substitute__onhand_users__in=shopping_users)
|
||||
| Q(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users))
|
||||
| Q(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users)))
|
||||
makenow_recipes = (Recipe.objects.annotate(count_food=Count("steps__ingredients__food__pk", filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
||||
count_onhand=Count("steps__ingredients__food__pk", filter=onhand_filter, distinct=True),
|
||||
count_ignore_shopping=Count("steps__ingredients__food__pk",
|
||||
filter=Q(steps__ingredients__food__ignore_shopping=True,
|
||||
steps__ingredients__food__recipe__isnull=True),
|
||||
distinct=True),
|
||||
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users), then=Value(1)),
|
||||
default=Value(0)),
|
||||
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users), then=Value(1)),
|
||||
default=Value(0)),
|
||||
).annotate(missingfood=F("count_food") - F("count_onhand") - F("count_ignore_shopping")).filter(missingfood=missing))
|
||||
makenow_recipes = Recipe.objects.annotate(count_food=Count('steps__ingredients__food__pk', filter=Q(steps__ingredients__food__isnull=False), distinct=True),
|
||||
count_onhand=Count('steps__ingredients__food__pk', filter=onhand_filter, distinct=True),
|
||||
count_ignore_shopping=Count('steps__ingredients__food__pk',
|
||||
filter=Q(steps__ingredients__food__ignore_shopping=True,
|
||||
steps__ingredients__food__recipe__isnull=True),
|
||||
distinct=True),
|
||||
has_child_sub=Case(When(steps__ingredients__food__in=self.__children_substitute_filter(shopping_users), then=Value(1)),
|
||||
default=Value(0)),
|
||||
has_sibling_sub=Case(When(steps__ingredients__food__in=self.__sibling_substitute_filter(shopping_users), then=Value(1)),
|
||||
default=Value(0))).annotate(missingfood=F('count_food') - F('count_onhand')
|
||||
- F('count_ignore_shopping')).filter(missingfood__lte=missing)
|
||||
self._queryset = self._queryset.distinct().filter(id__in=makenow_recipes.values('id'))
|
||||
|
||||
def _never_used_food_filter(self):
|
||||
# filters recipes to include foods that have never been used
|
||||
if not self._never_used_food:
|
||||
return
|
||||
self._queryset = self._queryset.filter(steps__ingredients__food__in=Food.objects.filter(~Q(ingredient__step__recipe__cooklog__isnull=False)).distinct())
|
||||
|
||||
@staticmethod
|
||||
def __children_substitute_filter(shopping_users=None):
|
||||
children_onhand_subquery = Food.objects.filter(path__startswith=OuterRef('path'), depth__gt=OuterRef('depth'), onhand_users__in=shopping_users)
|
||||
return (
|
||||
Food.objects.exclude( # list of foods that are onhand and children of: foods that are not onhand and are set to use children as substitutes
|
||||
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users)
|
||||
)
|
||||
.exclude(depth=1, numchild=0)
|
||||
.filter(substitute_children=True)
|
||||
.annotate(child_onhand_count=Exists(children_onhand_subquery))
|
||||
.filter(child_onhand_count=True)
|
||||
)
|
||||
return (Food.objects.exclude( # list of foods that are onhand and children of: foods that are not onhand and are set to use children as substitutes
|
||||
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True)
|
||||
| Q(substitute__onhand_users__in=shopping_users)).exclude(depth=1, numchild=0).filter(substitute_children=True).annotate(
|
||||
child_onhand_count=Exists(children_onhand_subquery)).filter(child_onhand_count=True))
|
||||
|
||||
@staticmethod
|
||||
def __sibling_substitute_filter(shopping_users=None):
|
||||
sibling_onhand_subquery = Food.objects.filter(
|
||||
path__startswith=Substr(OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)), depth=OuterRef('depth'), onhand_users__in=shopping_users
|
||||
)
|
||||
return (
|
||||
Food.objects.exclude( # list of foods that are onhand and siblings of: foods that are not onhand and are set to use siblings as substitutes
|
||||
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True) | Q(substitute__onhand_users__in=shopping_users)
|
||||
)
|
||||
.exclude(depth=1, numchild=0)
|
||||
.filter(substitute_siblings=True)
|
||||
.annotate(sibling_onhand=Exists(sibling_onhand_subquery))
|
||||
.filter(sibling_onhand=True)
|
||||
)
|
||||
sibling_onhand_subquery = Food.objects.filter(path__startswith=Substr(OuterRef('path'), 1, Food.steplen * (OuterRef('depth') - 1)),
|
||||
depth=OuterRef('depth'),
|
||||
onhand_users__in=shopping_users)
|
||||
return (Food.objects.exclude( # list of foods that are onhand and siblings of: foods that are not onhand and are set to use siblings as substitutes
|
||||
Q(onhand_users__in=shopping_users) | Q(ignore_shopping=True, recipe__isnull=True)
|
||||
| Q(substitute__onhand_users__in=shopping_users)).exclude(depth=1, numchild=0).filter(substitute_siblings=True).annotate(
|
||||
sibling_onhand=Exists(sibling_onhand_subquery)).filter(sibling_onhand=True))
|
||||
|
||||
@@ -113,7 +113,7 @@ class RecipeShoppingEditor():
|
||||
if not self.servings:
|
||||
self.servings = getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', 1.0)
|
||||
|
||||
self._shopping_list_recipe = ShoppingListRecipe.objects.create(recipe=self.recipe, mealplan=self.mealplan, servings=self.servings)
|
||||
self._shopping_list_recipe = ShoppingListRecipe.objects.create(recipe=self.recipe, mealplan=self.mealplan, servings=self.servings, space=self.space, created_by=self.created_by)
|
||||
|
||||
if ingredients:
|
||||
self._add_ingredients(ingredients=ingredients)
|
||||
|
||||
@@ -94,7 +94,8 @@ class Paprika(Integration):
|
||||
url = recipe_json.get("image_url", None)
|
||||
if validate_import_url(url):
|
||||
response = requests.get(url)
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
if response.status_code == 200 and len(response.content) > 0:
|
||||
self.import_recipe_image(recipe, BytesIO(response.content))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-03-27 19:02+0000\n"
|
||||
"Last-Translator: Axel Breiterman <axelbreiterman@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-01-29 13:44+0000\n"
|
||||
"Last-Translator: Ángel <1024mb@users.noreply.translate.tandoor.dev>\n"
|
||||
"Language-Team: Spanish <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/es/>\n"
|
||||
"Language: es\n"
|
||||
@@ -23,7 +23,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -66,31 +66,30 @@ msgid ""
|
||||
"To prevent duplicates recipes with the same name as existing ones are "
|
||||
"ignored. Check this box to import everything."
|
||||
msgstr ""
|
||||
"Para evitar duplicados, las recetas con el mismo nombre serán ignoradas. "
|
||||
"Marca esta opción para importar todas las recetas."
|
||||
"Para evitar duplicados, las recetas con el mismo nombre que las ya "
|
||||
"existentes serán ignoradas. Marca esta casilla para importar todo."
|
||||
|
||||
#: .\cookbook\forms.py:143
|
||||
msgid "Add your comment: "
|
||||
msgstr "Añada su comentario: "
|
||||
msgstr "Añade tu comentario: "
|
||||
|
||||
#: .\cookbook\forms.py:151
|
||||
msgid "Leave empty for dropbox and enter app password for nextcloud."
|
||||
msgstr ""
|
||||
"Déjelo vacío para Dropbox e ingrese la contraseña de la aplicación para "
|
||||
"nextcloud."
|
||||
"Déjalo vacío para Dropbox o ingresa la contraseña de la aplicación para "
|
||||
"Nextcloud."
|
||||
|
||||
#: .\cookbook\forms.py:154
|
||||
msgid "Leave empty for nextcloud and enter api token for dropbox."
|
||||
msgstr ""
|
||||
"Déjelo en blanco para nextcloud e ingrese el token de api para dropbox."
|
||||
msgstr "Déjalo vacío para Nextcloud o ingresa el token API para Dropbox."
|
||||
|
||||
#: .\cookbook\forms.py:160
|
||||
msgid ""
|
||||
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
|
||||
"php/webdav/</code> is added automatically)"
|
||||
msgstr ""
|
||||
"Dejar vació para Dropbox e introducir sólo la URL base para Nextcloud "
|
||||
"(<code>/remote.php/webdav/</code> se añade automáticamente)"
|
||||
"Déjalo vacío para Dropbox o ingresa solo la URL base para Nextcloud "
|
||||
"(<code>/remote.php/webdav/</code> es añadido automáticamente)"
|
||||
|
||||
#: .\cookbook\forms.py:188
|
||||
msgid ""
|
||||
@@ -98,15 +97,16 @@ msgid ""
|
||||
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
|
||||
msgstr ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Token de larga duración</a>para tu instancia de HomeAssistant"
|
||||
"profile\">Token de acceso de larga duración</a> para tu instancia de "
|
||||
"HomeAssistant"
|
||||
|
||||
#: .\cookbook\forms.py:193
|
||||
msgid "Something like http://homeassistant.local:8123/api"
|
||||
msgstr "Algo similar a http://homeassistant.local:8123/api"
|
||||
msgstr "Algo como http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:205
|
||||
msgid "http://homeassistant.local:8123/api for example"
|
||||
msgstr "por ejemplo http://homeassistant.local:8123/api for example"
|
||||
msgstr "Por ejemplo http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
|
||||
msgid "Storage"
|
||||
|
||||
@@ -14,16 +14,16 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-05-28 00:57+0000\n"
|
||||
"Last-Translator: tarek EL SOL <tarek.elsol@gmail.com>\n"
|
||||
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/fr/>\n"
|
||||
"PO-Revision-Date: 2025-02-16 14:58+0000\n"
|
||||
"Last-Translator: Elvis Gosselin <elvis.gosselin@tutanota.com>\n"
|
||||
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -506,18 +506,16 @@ msgid "Nutrition"
|
||||
msgstr "Informations nutritionnelles"
|
||||
|
||||
#: .\cookbook\models.py:918
|
||||
#, fuzzy
|
||||
#| msgid "Merge"
|
||||
msgid "Allergen"
|
||||
msgstr "Fusionner"
|
||||
msgstr "Allergène"
|
||||
|
||||
#: .\cookbook\models.py:919
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Prix"
|
||||
|
||||
#: .\cookbook\models.py:919
|
||||
msgid "Goal"
|
||||
msgstr ""
|
||||
msgstr "Objectif"
|
||||
|
||||
#: .\cookbook\models.py:1408 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
@@ -1039,7 +1037,7 @@ msgstr "Exporter"
|
||||
|
||||
#: .\cookbook\templates\base.html:287
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
msgstr "Propriétés"
|
||||
|
||||
#: .\cookbook\templates\base.html:301 .\cookbook\views\lists.py:255
|
||||
#, fuzzy
|
||||
@@ -2112,6 +2110,11 @@ msgid ""
|
||||
"script to generate version information (done automatically in docker).\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Vous devez exécuter <code>version.py</code> dans votre script de "
|
||||
"mise à jour pour générer les informations de version (automatique avec "
|
||||
"docker).\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:46
|
||||
msgid "Media Serving"
|
||||
@@ -2199,7 +2202,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\system.html:86
|
||||
msgid "Allowed Hosts"
|
||||
msgstr ""
|
||||
msgstr "Hôtes autorisés"
|
||||
|
||||
#: .\cookbook\templates\system.html:90
|
||||
msgid ""
|
||||
@@ -2209,6 +2212,11 @@ msgid ""
|
||||
"this.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Votre configuration autorise tous les hôtes, cela ok dans "
|
||||
"certaines installations mais évité. Veuillez consulter les documentations à "
|
||||
"ce sujet.\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:97
|
||||
msgid "Database"
|
||||
@@ -2235,18 +2243,26 @@ msgid ""
|
||||
"issue.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Les migrations de données ne devraient jamais échouer!\n"
|
||||
" Les échecs de migrations vont causer des problèmes de "
|
||||
"fonctionnement majeurs dans l’application..\n"
|
||||
" Si une migration échoue, vérifiez que vous êtes sur la dernière "
|
||||
"version et si c'est le cas veuillez créer un ticket sur GitHub avec le "
|
||||
"contenu du journal de migration.\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:182
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
msgstr "Faux"
|
||||
|
||||
#: .\cookbook\templates\system.html:182
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
msgstr "Vrai"
|
||||
|
||||
#: .\cookbook\templates\system.html:207
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
msgstr "Cacher"
|
||||
|
||||
#: .\cookbook\templates\system.html:210
|
||||
#, fuzzy
|
||||
@@ -2328,11 +2344,13 @@ msgstr "{obj.name} a été ajouté(e) à la liste de courses."
|
||||
|
||||
#: .\cookbook\views\api.py:742
|
||||
msgid "Filter meal plans from date (inclusive) in the format of YYYY-MM-DD."
|
||||
msgstr ""
|
||||
msgstr "Filtrer les repas depuis la date (incluse) avec le format YYYY-MM-DD."
|
||||
|
||||
#: .\cookbook\views\api.py:743
|
||||
msgid "Filter meal plans to date (inclusive) in the format of YYYY-MM-DD."
|
||||
msgstr ""
|
||||
"Filtrer les plannings de repas depuis la date (incluse) avec le format YYYY-"
|
||||
"MM-DD."
|
||||
|
||||
#: .\cookbook\views\api.py:744
|
||||
#, fuzzy
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-09-08 12:58+0000\n"
|
||||
"Last-Translator: Tomer Alcavi <alcavi1991@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-03-07 15:08+0000\n"
|
||||
"Last-Translator: yonatan ben-menachem <2bmyonatan@gmail.com>\n"
|
||||
"Language-Team: Hebrew <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/he/>\n"
|
||||
"Language: he\n"
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
|
||||
"n % 10 == 0) ? 2 : 3));\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -59,6 +59,8 @@ msgid ""
|
||||
"To prevent duplicates recipes with the same name as existing ones are "
|
||||
"ignored. Check this box to import everything."
|
||||
msgstr ""
|
||||
"בשביל למנוע כפילויות, מתוכנים בעלי שם זהה למתכון קיים לא יעובדו. סמן כאן כדי "
|
||||
"לייבא בכל זאת."
|
||||
|
||||
#: .\cookbook\forms.py:143
|
||||
msgid "Add your comment: "
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-11-19 06:58+0000\n"
|
||||
"Last-Translator: Daniel Legin <daniel.legin@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-02-03 16:58+0000\n"
|
||||
"Last-Translator: Domagoj Levanić <levanicdomagoj@gmail.com>\n"
|
||||
"Language-Team: Croatian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/hr/>\n"
|
||||
"Language: hr\n"
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -757,11 +757,15 @@ msgid ""
|
||||
"for user %(user_display)s\n"
|
||||
" ."
|
||||
msgstr ""
|
||||
"Molimo potvrdite da je\n"
|
||||
" <a href=\"mailto:%(email)s\">%(email)s</a> e-mail adresa "
|
||||
"korisnika %(user_display)s\n"
|
||||
" ."
|
||||
|
||||
#: .\cookbook\templates\account\email_confirm.html:22
|
||||
#: .\cookbook\templates\generic\delete_template.html:72
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
msgstr "Potvrdi"
|
||||
|
||||
#: .\cookbook\templates\account\email_confirm.html:29
|
||||
#, python-format
|
||||
@@ -770,11 +774,14 @@ msgid ""
|
||||
" <a href=\"%(email_url)s\">issue a new e-mail confirmation "
|
||||
"request</a>."
|
||||
msgstr ""
|
||||
"Poveznica za potvrdu e-maila je istekla ili nevažeća. Molimo\n"
|
||||
" <a href=\"%(email_url)s\">zatražite slanje nove poveznice za "
|
||||
"potvrdu e-maila.</a>."
|
||||
|
||||
#: .\cookbook\templates\account\login.html:8 .\cookbook\templates\base.html:388
|
||||
#: .\cookbook\templates\openid\login.html:8
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
msgstr "Prijava"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:15
|
||||
#: .\cookbook\templates\account\login.html:31
|
||||
@@ -786,7 +793,7 @@ msgstr ""
|
||||
#: .\cookbook\templates\openid\login.html:26
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:15
|
||||
msgid "Sign In"
|
||||
msgstr ""
|
||||
msgstr "Prijava"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:34
|
||||
#: .\cookbook\templates\account\password_reset.html:41
|
||||
@@ -794,34 +801,34 @@ msgstr ""
|
||||
#: .\cookbook\templates\socialaccount\signup.html:8
|
||||
#: .\cookbook\templates\socialaccount\signup.html:57
|
||||
msgid "Sign Up"
|
||||
msgstr ""
|
||||
msgstr "Registracija"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:38
|
||||
msgid "Lost your password?"
|
||||
msgstr ""
|
||||
msgstr "Zaboravljena lozinka?"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:39
|
||||
#: .\cookbook\templates\account\password_reset.html:29
|
||||
msgid "Reset My Password"
|
||||
msgstr ""
|
||||
msgstr "Resetiraj moju lozinku"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:50
|
||||
msgid "Social Login"
|
||||
msgstr ""
|
||||
msgstr "Prijava putem društvenih mreža"
|
||||
|
||||
#: .\cookbook\templates\account\login.html:51
|
||||
msgid "You can use any of the following providers to sign in."
|
||||
msgstr ""
|
||||
msgstr "Možete koristiti bilo kojeg od sljedećih pružatelja usluga za prijavu."
|
||||
|
||||
#: .\cookbook\templates\account\logout.html:5
|
||||
#: .\cookbook\templates\account\logout.html:9
|
||||
#: .\cookbook\templates\account\logout.html:18
|
||||
msgid "Sign Out"
|
||||
msgstr ""
|
||||
msgstr "Odjava"
|
||||
|
||||
#: .\cookbook\templates\account\logout.html:11
|
||||
msgid "Are you sure you want to sign out?"
|
||||
msgstr ""
|
||||
msgstr "Jeste li sigurni da se želite odjaviti?"
|
||||
|
||||
#: .\cookbook\templates\account\password_change.html:6
|
||||
#: .\cookbook\templates\account\password_change.html:16
|
||||
@@ -831,43 +838,47 @@ msgstr ""
|
||||
#: .\cookbook\templates\account\password_reset_from_key_done.html:7
|
||||
#: .\cookbook\templates\account\password_reset_from_key_done.html:13
|
||||
msgid "Change Password"
|
||||
msgstr ""
|
||||
msgstr "Promijeni lozinku"
|
||||
|
||||
#: .\cookbook\templates\account\password_change.html:12
|
||||
#: .\cookbook\templates\account\password_set.html:12
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
msgstr "Lozinka"
|
||||
|
||||
#: .\cookbook\templates\account\password_change.html:22
|
||||
msgid "Forgot Password?"
|
||||
msgstr ""
|
||||
msgstr "Zaboravljena lozinka?"
|
||||
|
||||
#: .\cookbook\templates\account\password_reset.html:7
|
||||
#: .\cookbook\templates\account\password_reset.html:13
|
||||
#: .\cookbook\templates\account\password_reset_done.html:7
|
||||
#: .\cookbook\templates\account\password_reset_done.html:18
|
||||
msgid "Password Reset"
|
||||
msgstr ""
|
||||
msgstr "Ponovno postavljanje lozinke"
|
||||
|
||||
#: .\cookbook\templates\account\password_reset.html:24
|
||||
msgid ""
|
||||
"Forgotten your password? Enter your e-mail address below, and we'll send you "
|
||||
"an e-mail allowing you to reset it."
|
||||
msgstr ""
|
||||
"Zaboravili ste lozinku? Unesite svoju e-mail adresu u nastavku i poslat ćemo "
|
||||
"vam e-mail s poveznicom za postavljanje nove lozinke."
|
||||
|
||||
#: .\cookbook\templates\account\password_reset.html:32
|
||||
msgid "Password reset is disabled on this instance."
|
||||
msgstr ""
|
||||
msgstr "Reset lozinke nije omogućen na ovoj instanci."
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_done.html:25
|
||||
msgid ""
|
||||
"We have sent you an e-mail. Please contact us if you do not receive it "
|
||||
"within a few minutes."
|
||||
msgstr ""
|
||||
"Poslali smo vam e-mail. Molimo vas da nas kontaktirate ako ga ne primite u "
|
||||
"roku od nekoliko minuta."
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_from_key.html:13
|
||||
msgid "Bad Token"
|
||||
msgstr ""
|
||||
msgstr "Nevažeći token"
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_from_key.html:25
|
||||
#, python-format
|
||||
@@ -877,225 +888,231 @@ msgid ""
|
||||
" Please request a <a href=\"%(passwd_reset_url)s\">new "
|
||||
"password reset</a>."
|
||||
msgstr ""
|
||||
"Poveznica za reset lozinke je nevažeća, vjerojatno jer je već iskorištena.\n"
|
||||
" Molimo zatražite <a href=\"%(passwd_reset_url)s\">novu "
|
||||
"poveznicu za reset lozinke</a>."
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_from_key.html:33
|
||||
msgid "change password"
|
||||
msgstr ""
|
||||
msgstr "promijeni lozinku"
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_from_key.html:36
|
||||
#: .\cookbook\templates\account\password_reset_from_key_done.html:19
|
||||
msgid "Your password is now changed."
|
||||
msgstr ""
|
||||
msgstr "Tvoja lozinka je promijenjena."
|
||||
|
||||
#: .\cookbook\templates\account\password_set.html:6
|
||||
#: .\cookbook\templates\account\password_set.html:16
|
||||
#: .\cookbook\templates\account\password_set.html:21
|
||||
msgid "Set Password"
|
||||
msgstr ""
|
||||
msgstr "Postavi lozinku"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:6
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
msgstr "Registracija"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:12
|
||||
msgid "Create an Account"
|
||||
msgstr ""
|
||||
msgstr "Kreiraj račun"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:42
|
||||
#: .\cookbook\templates\socialaccount\signup.html:33
|
||||
msgid "I accept the follwoing"
|
||||
msgstr ""
|
||||
msgstr "Prihvaćam sljedeće"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:45
|
||||
#: .\cookbook\templates\socialaccount\signup.html:36
|
||||
msgid "Terms and Conditions"
|
||||
msgstr ""
|
||||
msgstr "Uvjeti i odredbe"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:48
|
||||
#: .\cookbook\templates\socialaccount\signup.html:39
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
msgstr "i"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:52
|
||||
#: .\cookbook\templates\socialaccount\signup.html:43
|
||||
msgid "Privacy Policy"
|
||||
msgstr ""
|
||||
msgstr "Politika privatnosti"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:65
|
||||
msgid "Create User"
|
||||
msgstr ""
|
||||
msgstr "Kreiraj korisnika"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:69
|
||||
msgid "Already have an account?"
|
||||
msgstr ""
|
||||
msgstr "Već imate račun?"
|
||||
|
||||
#: .\cookbook\templates\account\signup_closed.html:5
|
||||
#: .\cookbook\templates\account\signup_closed.html:11
|
||||
msgid "Sign Up Closed"
|
||||
msgstr ""
|
||||
msgstr "Registracija je zatvorena"
|
||||
|
||||
#: .\cookbook\templates\account\signup_closed.html:13
|
||||
msgid "We are sorry, but the sign up is currently closed."
|
||||
msgstr ""
|
||||
msgstr "Žao nam je, ali registracija je trenutno zatvorena."
|
||||
|
||||
#: .\cookbook\templates\api_info.html:5 .\cookbook\templates\base.html:378
|
||||
#: .\cookbook\templates\rest_framework\api.html:11
|
||||
msgid "API Documentation"
|
||||
msgstr ""
|
||||
msgstr "API Dokumentacija"
|
||||
|
||||
#: .\cookbook\templates\base.html:110 .\cookbook\templates\index.html:87
|
||||
msgid "Recipes"
|
||||
msgstr ""
|
||||
msgstr "Recepti"
|
||||
|
||||
#: .\cookbook\templates\base.html:161 .\cookbook\views\lists.py:120
|
||||
msgid "Foods"
|
||||
msgstr ""
|
||||
msgstr "Hrana"
|
||||
|
||||
#: .\cookbook\templates\base.html:173 .\cookbook\views\lists.py:137
|
||||
msgid "Units"
|
||||
msgstr ""
|
||||
msgstr "Jedinice"
|
||||
|
||||
#: .\cookbook\templates\base.html:187
|
||||
msgid "Supermarket"
|
||||
msgstr ""
|
||||
msgstr "Supermarket"
|
||||
|
||||
#: .\cookbook\templates\base.html:199
|
||||
msgid "Supermarket Category"
|
||||
msgstr ""
|
||||
msgstr "Kategorija Supermarketa"
|
||||
|
||||
#: .\cookbook\templates\base.html:211 .\cookbook\views\lists.py:186
|
||||
msgid "Automations"
|
||||
msgstr ""
|
||||
msgstr "Automatizacije"
|
||||
|
||||
#: .\cookbook\templates\base.html:225 .\cookbook\views\lists.py:222
|
||||
msgid "Files"
|
||||
msgstr ""
|
||||
msgstr "Datoteke"
|
||||
|
||||
#: .\cookbook\templates\base.html:237
|
||||
msgid "Batch Edit"
|
||||
msgstr ""
|
||||
msgstr "Masovno Uređivanje"
|
||||
|
||||
#: .\cookbook\templates\base.html:249 .\cookbook\templates\history.html:6
|
||||
#: .\cookbook\templates\history.html:14
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
msgstr "Povijest"
|
||||
|
||||
#: .\cookbook\templates\base.html:263
|
||||
#: .\cookbook\templates\ingredient_editor.html:7
|
||||
#: .\cookbook\templates\ingredient_editor.html:13
|
||||
msgid "Ingredient Editor"
|
||||
msgstr ""
|
||||
msgstr "Uređivač Sastojaka"
|
||||
|
||||
#: .\cookbook\templates\base.html:275
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
msgstr "Izvoz"
|
||||
|
||||
#: .\cookbook\templates\base.html:287
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
msgstr "Svojstva"
|
||||
|
||||
#: .\cookbook\templates\base.html:301 .\cookbook\views\lists.py:255
|
||||
msgid "Unit Conversions"
|
||||
msgstr ""
|
||||
msgstr "Konverzija Jedinica"
|
||||
|
||||
#: .\cookbook\templates\base.html:318 .\cookbook\templates\index.html:47
|
||||
msgid "Import Recipe"
|
||||
msgstr ""
|
||||
msgstr "Uvezi Recept"
|
||||
|
||||
#: .\cookbook\templates\base.html:320
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
msgstr "Kreiraj"
|
||||
|
||||
#: .\cookbook\templates\base.html:333
|
||||
#: .\cookbook\templates\generic\list_template.html:14
|
||||
msgid "External Recipes"
|
||||
msgstr ""
|
||||
msgstr "Vanjski Recepti"
|
||||
|
||||
#: .\cookbook\templates\base.html:336 .\cookbook\templates\space_manage.html:15
|
||||
msgid "Space Settings"
|
||||
msgstr ""
|
||||
msgstr "Postavke Prostora"
|
||||
|
||||
#: .\cookbook\templates\base.html:340
|
||||
msgid "External Connectors"
|
||||
msgstr ""
|
||||
msgstr "Vanjski Konektori"
|
||||
|
||||
#: .\cookbook\templates\base.html:345 .\cookbook\templates\system.html:13
|
||||
msgid "System"
|
||||
msgstr ""
|
||||
msgstr "Sustav"
|
||||
|
||||
#: .\cookbook\templates\base.html:347
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
msgstr "Administrator"
|
||||
|
||||
#: .\cookbook\templates\base.html:351
|
||||
#: .\cookbook\templates\space_overview.html:25
|
||||
msgid "Your Spaces"
|
||||
msgstr ""
|
||||
msgstr "Tvoji Prostori"
|
||||
|
||||
#: .\cookbook\templates\base.html:362
|
||||
#: .\cookbook\templates\space_overview.html:6
|
||||
msgid "Overview"
|
||||
msgstr ""
|
||||
msgstr "Pregled"
|
||||
|
||||
#: .\cookbook\templates\base.html:372
|
||||
msgid "Markdown Guide"
|
||||
msgstr ""
|
||||
msgstr "Vodič za Markdown"
|
||||
|
||||
#: .\cookbook\templates\base.html:374
|
||||
msgid "GitHub"
|
||||
msgstr ""
|
||||
msgstr "GitHub"
|
||||
|
||||
#: .\cookbook\templates\base.html:376
|
||||
msgid "Translate Tandoor"
|
||||
msgstr ""
|
||||
msgstr "Prevedi Tandoor"
|
||||
|
||||
#: .\cookbook\templates\base.html:380
|
||||
msgid "API Browser"
|
||||
msgstr ""
|
||||
msgstr "API Preglednik"
|
||||
|
||||
#: .\cookbook\templates\base.html:383
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
msgstr "Odjava"
|
||||
|
||||
#: .\cookbook\templates\base.html:406
|
||||
msgid "You are using the free version of Tandor"
|
||||
msgstr ""
|
||||
msgstr "Koristite besplatnu verziju Tandor aplikacije"
|
||||
|
||||
#: .\cookbook\templates\base.html:407
|
||||
msgid "Upgrade Now"
|
||||
msgstr ""
|
||||
msgstr "Nadogradi"
|
||||
|
||||
#: .\cookbook\templates\batch\edit.html:6
|
||||
msgid "Batch edit Category"
|
||||
msgstr ""
|
||||
msgstr "Masovno uređivanje Kategorija"
|
||||
|
||||
#: .\cookbook\templates\batch\edit.html:15
|
||||
msgid "Batch edit Recipes"
|
||||
msgstr ""
|
||||
msgstr "Masovno uređivanje Recepata"
|
||||
|
||||
#: .\cookbook\templates\batch\edit.html:20
|
||||
msgid "Add the specified keywords to all recipes containing a word"
|
||||
msgstr ""
|
||||
"Dodajte navedene ključne riječi svim receptima koji sadrže određenu riječ"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:75
|
||||
msgid "Sync"
|
||||
msgstr ""
|
||||
msgstr "Sinkroniziraj"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:10
|
||||
msgid "Manage watched Folders"
|
||||
msgstr ""
|
||||
msgstr "Upravljaj praćenim Mapama"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:14
|
||||
msgid ""
|
||||
"On this Page you can manage all storage folder locations that should be "
|
||||
"monitored and synced."
|
||||
msgstr ""
|
||||
"Na ovoj stranici možete upravljati svim lokacijama spremišnih mapa koje "
|
||||
"trebaju biti praćene i sinkronizirane."
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:16
|
||||
msgid "The path must be in the following format"
|
||||
msgstr ""
|
||||
msgstr "Putanja mora biti u sljedećem formatu"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:20
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
@@ -1103,128 +1120,130 @@ msgstr ""
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\settings.html:57
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
msgstr "Spremi"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:21
|
||||
msgid "Manage External Storage"
|
||||
msgstr ""
|
||||
msgstr "Upravljaj vanjskim Spremištem"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:28
|
||||
msgid "Sync Now!"
|
||||
msgstr ""
|
||||
msgstr "Sinkroniziraj Sada!"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:29
|
||||
msgid "Show Recipes"
|
||||
msgstr ""
|
||||
msgstr "Prikaži Recepte"
|
||||
|
||||
#: .\cookbook\templates\batch\monitor.html:30
|
||||
msgid "Show Log"
|
||||
msgstr ""
|
||||
msgstr "Prikaži Log"
|
||||
|
||||
#: .\cookbook\templates\batch\waiting.html:4
|
||||
#: .\cookbook\templates\batch\waiting.html:10
|
||||
msgid "Importing Recipes"
|
||||
msgstr ""
|
||||
msgstr "Uvoz Recepata"
|
||||
|
||||
#: .\cookbook\templates\batch\waiting.html:28
|
||||
msgid ""
|
||||
"This can take a few minutes, depending on the number of recipes in sync, "
|
||||
"please wait."
|
||||
msgstr ""
|
||||
"Ovo može potrajati nekoliko minuta, ovisno o broju recepata koji se "
|
||||
"sinkroniziraju, molimo pričekajte."
|
||||
|
||||
#: .\cookbook\templates\books.html:7
|
||||
msgid "Recipe Books"
|
||||
msgstr ""
|
||||
msgstr "Knjiga Recepata"
|
||||
|
||||
#: .\cookbook\templates\export.html:7 .\cookbook\templates\test2.html:6
|
||||
msgid "Export Recipes"
|
||||
msgstr ""
|
||||
msgstr "Izvoz Recepata"
|
||||
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:5
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:9
|
||||
msgid "Import new Recipe"
|
||||
msgstr ""
|
||||
msgstr "Uvezi novi Recept"
|
||||
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:7
|
||||
msgid "Edit Recipe"
|
||||
msgstr ""
|
||||
msgstr "Uredi Recept"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:21
|
||||
#, python-format
|
||||
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
|
||||
msgstr ""
|
||||
msgstr "Jeste li sigurni da želite obrisati %(title)s: <b>%(object)s</b> "
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:22
|
||||
msgid "This cannot be undone!"
|
||||
msgstr ""
|
||||
msgstr "Ovo se ne može poništiti!"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:27
|
||||
msgid "Protected"
|
||||
msgstr ""
|
||||
msgstr "Zaštićeno"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:42
|
||||
msgid "Cascade"
|
||||
msgstr ""
|
||||
msgstr "Kaskada"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:73
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
msgstr "Otkaži"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:6
|
||||
#: .\cookbook\templates\generic\edit_template.html:14
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
msgstr "Uredi"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:32
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
msgstr "Pogledaj"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:36
|
||||
msgid "Delete original file"
|
||||
msgstr ""
|
||||
msgstr "Izbriši izvornu datoteku"
|
||||
|
||||
#: .\cookbook\templates\generic\list_template.html:6
|
||||
#: .\cookbook\templates\generic\list_template.html:22
|
||||
msgid "List"
|
||||
msgstr ""
|
||||
msgstr "Lista"
|
||||
|
||||
#: .\cookbook\templates\generic\list_template.html:36
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Filter"
|
||||
|
||||
#: .\cookbook\templates\generic\list_template.html:41
|
||||
msgid "Import all"
|
||||
msgstr ""
|
||||
msgstr "Uvezi sve"
|
||||
|
||||
#: .\cookbook\templates\generic\new_template.html:6
|
||||
#: .\cookbook\templates\generic\new_template.html:14
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
msgstr "Novo"
|
||||
|
||||
#: .\cookbook\templates\generic\table_template.html:76
|
||||
msgid "previous"
|
||||
msgstr ""
|
||||
msgstr "prethodno"
|
||||
|
||||
#: .\cookbook\templates\generic\table_template.html:98
|
||||
msgid "next"
|
||||
msgstr ""
|
||||
msgstr "sljedeće"
|
||||
|
||||
#: .\cookbook\templates\history.html:20
|
||||
msgid "View Log"
|
||||
msgstr ""
|
||||
msgstr "Pogledaj Log"
|
||||
|
||||
#: .\cookbook\templates\history.html:24
|
||||
msgid "Cook Log"
|
||||
msgstr ""
|
||||
msgstr "Log Kuhanja"
|
||||
|
||||
#: .\cookbook\templates\import_response.html:7 .\cookbook\views\delete.py:90
|
||||
#: .\cookbook\views\edit.py:174
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
msgstr "Uvezi"
|
||||
|
||||
#: .\cookbook\templates\include\storage_backend_warning.html:4
|
||||
msgid "Security Warning"
|
||||
msgstr ""
|
||||
msgstr "Sigurnosno Upozorenje"
|
||||
|
||||
#: .\cookbook\templates\include\storage_backend_warning.html:5
|
||||
msgid ""
|
||||
@@ -1238,35 +1257,44 @@ msgid ""
|
||||
"can be used.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <b>Lozinka i token</b> polja su spremljena kao <b>obični tekst</b> "
|
||||
"unutar baze podataka.\n"
|
||||
" To je neophodno s obzirom na to da su potrebni za izvršavanje API "
|
||||
"zahtjeva, ali isto tako povećava \n"
|
||||
" rizik od krađe. <br/>\n"
|
||||
" Kako bi limitirali potencijalnu štetu u tom slučaju, predlažemo "
|
||||
"korištenje tokena ili računa s limitiranim pristupom.\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\index.html:29
|
||||
msgid "Search recipe ..."
|
||||
msgstr ""
|
||||
msgstr "Pretraži recept..."
|
||||
|
||||
#: .\cookbook\templates\index.html:44
|
||||
msgid "New Recipe"
|
||||
msgstr ""
|
||||
msgstr "Novi Recept"
|
||||
|
||||
#: .\cookbook\templates\index.html:53
|
||||
msgid "Advanced Search"
|
||||
msgstr ""
|
||||
msgstr "Napredno Pretraživanje"
|
||||
|
||||
#: .\cookbook\templates\index.html:57
|
||||
msgid "Reset Search"
|
||||
msgstr ""
|
||||
msgstr "Resetiraj Pretraživanje"
|
||||
|
||||
#: .\cookbook\templates\index.html:85
|
||||
msgid "Last viewed"
|
||||
msgstr ""
|
||||
msgstr "Zadnji put pregledano"
|
||||
|
||||
#: .\cookbook\templates\index.html:94
|
||||
msgid "Log in to view recipes"
|
||||
msgstr ""
|
||||
msgstr "Prijavi se kako bi vidio recepte"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:5
|
||||
#: .\cookbook\templates\markdown_info.html:13
|
||||
msgid "Markdown Info"
|
||||
msgstr ""
|
||||
msgstr "Informacije o Markdown-u"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:14
|
||||
msgid ""
|
||||
@@ -1283,34 +1311,46 @@ msgid ""
|
||||
"below.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Markdown je lagani jezik za označavanje koji se može koristiti za "
|
||||
"jednostavno formatiranje običnog teksta.\n"
|
||||
"Ova stranica koristi <a href=\"https://python-markdown.github.io/\" target="
|
||||
"\"_blank\">Python Markdown</a> biblioteku za\n"
|
||||
"pretvaranje vašeg teksta u lijepi HTML. Potpunu dokumentaciju za Markdown "
|
||||
"možete pronaći\n"
|
||||
"<a href=\"https://daringfireball.net/projects/markdown/syntax\" target="
|
||||
"\"_blank\">ovdje</a>.\n"
|
||||
"Nepotpuna, ali vjerojatno dovoljna dokumentacija može se pronaći u nastavku."
|
||||
"\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:25
|
||||
msgid "Headers"
|
||||
msgstr ""
|
||||
msgstr "Naslovi"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:54
|
||||
msgid "Formatting"
|
||||
msgstr ""
|
||||
msgstr "Formatiranje"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:56
|
||||
#: .\cookbook\templates\markdown_info.html:72
|
||||
msgid "Line breaks are inserted by adding two spaces after the end of a line"
|
||||
msgstr ""
|
||||
msgstr "Prekid linije se može umetnuti dodavanjem dva razmaka nakon kraja retka"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr ""
|
||||
msgstr "ili ostavljanjem prazne linije između."
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:59
|
||||
#: .\cookbook\templates\markdown_info.html:74
|
||||
msgid "This text is bold"
|
||||
msgstr ""
|
||||
msgstr "Ovaj tekst je boldan"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:60
|
||||
#: .\cookbook\templates\markdown_info.html:75
|
||||
msgid "This text is italic"
|
||||
msgstr ""
|
||||
msgstr "Ovaj tekst je italic"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:61
|
||||
#: .\cookbook\templates\markdown_info.html:77
|
||||
|
||||
@@ -12,7 +12,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-12-09 00:58+0000\n"
|
||||
"PO-Revision-Date: 2025-05-18 10:58+0000\n"
|
||||
"Last-Translator: Vincenzo Reale <smart2128vr@gmail.com>\n"
|
||||
"Language-Team: Italian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/it/>\n"
|
||||
@@ -1439,7 +1439,7 @@ msgid ""
|
||||
"editor like <a href=\"https://www.tablesgenerator.com/markdown_tables\" rel="
|
||||
"\"noreferrer noopener\" target=\"_blank\">this one.</a>"
|
||||
msgstr ""
|
||||
"Le tabelle in markdown sono difficili da creare a mano. Si raccomanda "
|
||||
"Le tabelle in markdown sono difficili da creare a mano. Si consiglia "
|
||||
"l'utilizzo di un editor di tabelle come <a href=\"https://www.tablesgenerator"
|
||||
".com/markdown_tables\" rel=\"noreferrer noopener\" target=\"_blank\""
|
||||
">questo.</a>"
|
||||
@@ -2098,7 +2098,7 @@ msgid ""
|
||||
" your installation.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"<b>Non è raccomandato</b> erogare i file multimediali con gunicorn/python!\n"
|
||||
"<b>Non è consigliato</b> erogare i file multimediali con gunicorn/python!\n"
|
||||
" Segui i passi descritti\n"
|
||||
" <a href=\"https://github.com/vabene1111/recipes/releases/tag/0.8."
|
||||
"1\">qui</a> per aggiornare\n"
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2023-08-19 21:36+0000\n"
|
||||
"Last-Translator: NeoID <neoid@animenord.com>\n"
|
||||
"PO-Revision-Date: 2025-01-26 05:58+0000\n"
|
||||
"Last-Translator: Ole Martin Ruud <nett@barskern.no>\n"
|
||||
"Language-Team: Norwegian Bokmål <http://translate.tandoor.dev/projects/"
|
||||
"tandoor/recipes-backend/nb_NO/>\n"
|
||||
"Language: nb_NO\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.15\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -326,10 +326,8 @@ msgid "Imported %s recipes."
|
||||
msgstr "Importerte %s oppskrifter."
|
||||
|
||||
#: .\cookbook\integration\openeats.py:28
|
||||
#, fuzzy
|
||||
#| msgid "Recipes"
|
||||
msgid "Recipe source:"
|
||||
msgstr "Oppskrifter"
|
||||
msgstr "Oppskriftskilde:"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:49
|
||||
msgid "Notes"
|
||||
@@ -555,7 +553,7 @@ msgstr "Oppskrift"
|
||||
|
||||
#: .\cookbook\models.py:1504
|
||||
msgid "Food"
|
||||
msgstr ""
|
||||
msgstr "Mat"
|
||||
|
||||
#: .\cookbook\models.py:1505 .\cookbook\templates\base.html:149
|
||||
msgid "Keyword"
|
||||
@@ -846,10 +844,8 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\templates\account\password_reset.html:32
|
||||
#, fuzzy
|
||||
#| msgid "Password reset is not implemented for the time being!"
|
||||
msgid "Password reset is disabled on this instance."
|
||||
msgstr "Det er foreløpig ikke implementert funksjon for å nullstille passord!"
|
||||
msgstr "Nullstilling av passord er skrudd av for denne instansen."
|
||||
|
||||
#: .\cookbook\templates\account\password_reset_done.html:25
|
||||
msgid ""
|
||||
@@ -912,7 +908,7 @@ msgstr ""
|
||||
#: .\cookbook\templates\account\signup.html:48
|
||||
#: .\cookbook\templates\socialaccount\signup.html:39
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
msgstr "og"
|
||||
|
||||
#: .\cookbook\templates\account\signup.html:52
|
||||
#: .\cookbook\templates\socialaccount\signup.html:43
|
||||
@@ -946,8 +942,6 @@ msgid "Recipes"
|
||||
msgstr "Oppskrifter"
|
||||
|
||||
#: .\cookbook\templates\base.html:161 .\cookbook\views\lists.py:120
|
||||
#, fuzzy
|
||||
#| msgid "New Food"
|
||||
msgid "Foods"
|
||||
msgstr "Ny matvare"
|
||||
|
||||
@@ -989,10 +983,8 @@ msgstr "Historikk"
|
||||
#: .\cookbook\templates\base.html:263
|
||||
#: .\cookbook\templates\ingredient_editor.html:7
|
||||
#: .\cookbook\templates\ingredient_editor.html:13
|
||||
#, fuzzy
|
||||
#| msgid "Ingredients"
|
||||
msgid "Ingredient Editor"
|
||||
msgstr "Ingredienser"
|
||||
msgstr "Ingrediensredigerer"
|
||||
|
||||
#: .\cookbook\templates\base.html:275
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
@@ -1002,7 +994,7 @@ msgstr "Eksporter"
|
||||
|
||||
#: .\cookbook\templates\base.html:287
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
msgstr "Egenskaper"
|
||||
|
||||
#: .\cookbook\templates\base.html:301 .\cookbook\views\lists.py:255
|
||||
msgid "Unit Conversions"
|
||||
@@ -1179,7 +1171,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:27
|
||||
msgid "Protected"
|
||||
msgstr ""
|
||||
msgstr "Beskyttet"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:42
|
||||
msgid "Cascade"
|
||||
@@ -1938,7 +1930,7 @@ msgstr ""
|
||||
#: .\cookbook\templates\system.html:75 .\cookbook\templates\system.html:88
|
||||
#: .\cookbook\templates\system.html:102 .\cookbook\templates\system.html:113
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
msgstr "Advarsel"
|
||||
|
||||
#: .\cookbook\templates\system.html:47 .\cookbook\templates\system.html:61
|
||||
#: .\cookbook\templates\system.html:75 .\cookbook\templates\system.html:88
|
||||
|
||||
@@ -13,8 +13,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-09-03 19:58+0000\n"
|
||||
"Last-Translator: \"S. v.d. Gevel\" <stefan18_gw@hotmail.com>\n"
|
||||
"PO-Revision-Date: 2025-02-16 14:58+0000\n"
|
||||
"Last-Translator: Cots Partier <cots.pastier.34@icloud.com>\n"
|
||||
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/nl/>\n"
|
||||
"Language: nl\n"
|
||||
@@ -22,7 +22,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -286,7 +286,7 @@ msgstr "omgekeerde rotatie"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:311
|
||||
msgid "careful rotation"
|
||||
msgstr "voorzichtige rotatie"
|
||||
msgstr "rotire atentă"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:312
|
||||
msgid "knead"
|
||||
|
||||
@@ -11,18 +11,18 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-03-19 23:47+0000\n"
|
||||
"Last-Translator: Tomasz Klimczak <klemensble@gmail.com>\n"
|
||||
"Language-Team: Polish <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/pl/>\n"
|
||||
"PO-Revision-Date: 2025-01-26 05:58+0000\n"
|
||||
"Last-Translator: Dominik Ruczajewski <slick.moose.dev@gmail.com>\n"
|
||||
"Language-Team: Polish <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/pl/>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n"
|
||||
"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
|
||||
"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && ("
|
||||
"n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && "
|
||||
"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -65,6 +65,8 @@ msgid ""
|
||||
"To prevent duplicates recipes with the same name as existing ones are "
|
||||
"ignored. Check this box to import everything."
|
||||
msgstr ""
|
||||
"Aby zapobiec duplikatom, przepisy o tej samej nazwie co istniejące zostaną "
|
||||
"pominięte. Zaznacz to pole, aby zaimportować wszystko."
|
||||
|
||||
#: .\cookbook\forms.py:143
|
||||
msgid "Add your comment: "
|
||||
@@ -91,14 +93,16 @@ msgid ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
|
||||
msgstr ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Long Lived Access Token</a> dla Twojej instancji Home Assistant"
|
||||
|
||||
#: .\cookbook\forms.py:193
|
||||
msgid "Something like http://homeassistant.local:8123/api"
|
||||
msgstr ""
|
||||
msgstr "Coś w stylu http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:205
|
||||
msgid "http://homeassistant.local:8123/api for example"
|
||||
msgstr ""
|
||||
msgstr "na przykład http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
|
||||
msgid "Storage"
|
||||
@@ -106,11 +110,11 @@ msgstr "Magazyn"
|
||||
|
||||
#: .\cookbook\forms.py:222
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Aktywuj"
|
||||
|
||||
#: .\cookbook\forms.py:226
|
||||
msgid "Search String"
|
||||
msgstr "Wyszukaj ciąg"
|
||||
msgstr "Wyszukaj tekst"
|
||||
|
||||
#: .\cookbook\forms.py:246
|
||||
msgid "File ID"
|
||||
@@ -118,101 +122,117 @@ msgstr "Numer identyfikacyjny pliku"
|
||||
|
||||
#: .\cookbook\forms.py:262
|
||||
msgid "Maximum number of users for this space reached."
|
||||
msgstr ""
|
||||
msgstr "Osiągnięto maksymalną liczbę użytkowników dla tej przestrzeni."
|
||||
|
||||
#: .\cookbook\forms.py:268
|
||||
msgid "Email address already taken!"
|
||||
msgstr ""
|
||||
msgstr "Wybrany adres email jest już zajęty!"
|
||||
|
||||
#: .\cookbook\forms.py:275
|
||||
msgid ""
|
||||
"An email address is not required but if present the invite link will be sent "
|
||||
"to the user."
|
||||
msgstr ""
|
||||
"Adres email nie jest wymagany, jednak gdy zostanie podany link z "
|
||||
"zaproszeniem zostanie wysłany do użytkownika."
|
||||
|
||||
#: .\cookbook\forms.py:287
|
||||
msgid "Name already taken."
|
||||
msgstr ""
|
||||
msgstr "Podana nazwa jest już zajęta."
|
||||
|
||||
#: .\cookbook\forms.py:298
|
||||
msgid "Accept Terms and Privacy"
|
||||
msgstr ""
|
||||
msgstr "Zaakceptuj Regulamin oraz Politykę Prywatności"
|
||||
|
||||
#: .\cookbook\forms.py:332
|
||||
msgid ""
|
||||
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
|
||||
"g. low values mean more typos are ignored)."
|
||||
msgstr ""
|
||||
"Określa, jak niedokładne może być wyszukiwanie, jeśli wykorzystuje "
|
||||
"dopasowanie podobieństwa trigramowego (np. niskie wartości oznaczają, że "
|
||||
"więcej literówek jest ignorowanych)."
|
||||
|
||||
#: .\cookbook\forms.py:340
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full description of choices."
|
||||
msgstr ""
|
||||
"Wybierz metodę wyszukiwania. Kliknij <a href=\"/docs/search/\">tutaj</a>, "
|
||||
"aby zapoznać się z pełnym opisem dostępnych opcji."
|
||||
|
||||
#: .\cookbook\forms.py:341
|
||||
msgid ""
|
||||
"Use fuzzy matching on units, keywords and ingredients when editing and "
|
||||
"importing recipes."
|
||||
msgstr ""
|
||||
"Użyj niedokładnego dopasowywania dla jednostek, słów kluczowych i składników "
|
||||
"podczas edytowania i importowania przepisów."
|
||||
|
||||
#: .\cookbook\forms.py:342
|
||||
msgid ""
|
||||
"Fields to search ignoring accents. Selecting this option can improve or "
|
||||
"degrade search quality depending on language"
|
||||
msgstr ""
|
||||
"Pola do przeszukiwania z pominięciem akcentów. Wybranie tej opcji może "
|
||||
"poprawić lub pogorszyć jakość wyszukiwania w zależności od języka"
|
||||
|
||||
#: .\cookbook\forms.py:343
|
||||
msgid ""
|
||||
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
|
||||
"'pie' and 'piece' and 'soapie')"
|
||||
msgstr ""
|
||||
"Pola do przeszukiwania częściowych dopasowań (np. wyszukiwanie 'Ciasto' "
|
||||
"zwróci 'ciasto', 'ciasteczko' i 'ciastolina')"
|
||||
|
||||
#: .\cookbook\forms.py:344
|
||||
msgid ""
|
||||
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
|
||||
"will return 'salad' and 'sandwich')"
|
||||
msgstr ""
|
||||
"Pola do przeszukiwania dopasowań na początku wyrazu (np. wyszukiwanie 'sa' "
|
||||
"zwróci 'sałatka' i 'sandwich')"
|
||||
|
||||
#: .\cookbook\forms.py:345
|
||||
msgid ""
|
||||
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
|
||||
"Note: this option will conflict with 'web' and 'raw' methods of search."
|
||||
msgstr ""
|
||||
"Pola do wyszukiwania z użyciem 'niedokładnego' dopasowywania (np. "
|
||||
"wyszukiwanie 'przepisz' znajdzie 'przepis'). Uwaga: ta opcja będzie "
|
||||
"kolidować z metodami wyszukiwania 'web' i 'raw'."
|
||||
|
||||
#: .\cookbook\forms.py:346
|
||||
msgid ""
|
||||
"Fields to full text search. Note: 'web', 'phrase', and 'raw' search methods "
|
||||
"only function with fulltext fields."
|
||||
msgstr ""
|
||||
"Pola do wyszukiwania pełno tekstowego. Uwaga: metody wyszukiwania 'web', "
|
||||
"'phrase' i 'raw' działają wyłącznie z polami pełno tekstowymi."
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
#, fuzzy
|
||||
#| msgid "Search"
|
||||
msgid "Search Method"
|
||||
msgstr "Szukaj"
|
||||
msgstr "Metoda wyszukiwania"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Fuzzy Lookups"
|
||||
msgstr ""
|
||||
msgstr "Niedokładne dopasowanie"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Ignore Accent"
|
||||
msgstr ""
|
||||
msgstr "Ignoruj akcenty"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Partial Match"
|
||||
msgstr ""
|
||||
msgstr "Częściowe dopasowanie"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
msgstr "Zaczyna się od"
|
||||
|
||||
#: .\cookbook\forms.py:351
|
||||
#, fuzzy
|
||||
#| msgid "Search"
|
||||
msgid "Fuzzy Search"
|
||||
msgstr "Szukaj"
|
||||
msgstr "Niedokładne wyszukiwanie"
|
||||
|
||||
#: .\cookbook\forms.py:351
|
||||
#, fuzzy
|
||||
@@ -225,6 +245,8 @@ msgid ""
|
||||
"In order to prevent spam, the requested email was not send. Please wait a "
|
||||
"few minutes and try again."
|
||||
msgstr ""
|
||||
"Aby zapobiec spamowi, żądany e-mail nie został wysłany. Proszę poczekać "
|
||||
"kilka minut i spróbować ponownie."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:164
|
||||
#: .\cookbook\helper\permission_helper.py:187 .\cookbook\views\views.py:117
|
||||
@@ -255,57 +277,57 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:402
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
msgstr "Osiągnąłeś maksymalną liczbę przepisów dla swojej przestrzeni."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:414
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
msgstr "Masz więcej użytkowników, niż jest dozwolone w Twojej przestrzeni."
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:310
|
||||
msgid "reverse rotation"
|
||||
msgstr ""
|
||||
msgstr "rotacja wsteczna"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:311
|
||||
msgid "careful rotation"
|
||||
msgstr ""
|
||||
msgstr "delikatna rotacja"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:312
|
||||
msgid "knead"
|
||||
msgstr ""
|
||||
msgstr "zagnieść"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:313
|
||||
msgid "thicken"
|
||||
msgstr ""
|
||||
msgstr "zagęścić"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:314
|
||||
msgid "warm up"
|
||||
msgstr ""
|
||||
msgstr "podgrzać"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:315
|
||||
msgid "ferment"
|
||||
msgstr ""
|
||||
msgstr "doprowadzić do wrzenia"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:316
|
||||
msgid "sous-vide"
|
||||
msgstr ""
|
||||
msgstr "gotować w próżni"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:150
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
msgstr "Musisz podać wielkość porcji"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:95
|
||||
#: .\cookbook\helper\template_helper.py:97
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
msgstr "Nie można przeanalizować kodu szablonu."
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:44
|
||||
#: .\cookbook\integration\melarecipes.py:37
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
msgstr "Ulubione"
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:50
|
||||
msgid "I made this"
|
||||
msgstr ""
|
||||
msgstr "Stworzyłem to"
|
||||
|
||||
#: .\cookbook\integration\integration.py:209
|
||||
msgid ""
|
||||
@@ -320,10 +342,12 @@ msgid ""
|
||||
"An unexpected error occurred during the import. Please make sure you have "
|
||||
"uploaded a valid file."
|
||||
msgstr ""
|
||||
"Wystąpił nieoczekiwany błąd podczas importu. Upewnij się, że przesłałeś "
|
||||
"prawidłowy plik."
|
||||
|
||||
#: .\cookbook\integration\integration.py:217
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
msgstr "Następujące przepisy zostały pominięte, ponieważ już istnieją:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
#, python-format
|
||||
@@ -341,14 +365,12 @@ msgid "Notes"
|
||||
msgstr "Notatka"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:52
|
||||
#, fuzzy
|
||||
#| msgid "Information"
|
||||
msgid "Nutritional Information"
|
||||
msgstr "Informacja"
|
||||
msgstr "Informacje o wartości odżywczej"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:56
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
msgstr "Źródło"
|
||||
|
||||
#: .\cookbook\integration\recettetek.py:54
|
||||
#: .\cookbook\integration\recipekeeper.py:70
|
||||
@@ -377,23 +399,25 @@ msgstr "Sekcja"
|
||||
|
||||
#: .\cookbook\management\commands\fix_duplicate_properties.py:15
|
||||
msgid "Fixes foods with "
|
||||
msgstr ""
|
||||
msgstr "Poprawia potrawy z "
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:14
|
||||
msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr ""
|
||||
msgstr "Odbudowuje indeks wyszukiwania pełno tekstowego dla przepisu"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Pełno tekstowe wyszukiwanie jest używane tylko w bazach danych PostgreSQL, "
|
||||
"brak indeksu do odbudowy"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
msgid "Recipe index rebuild complete."
|
||||
msgstr ""
|
||||
msgstr "Odbudowa indeksu przepisu zakończona."
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:31
|
||||
msgid "Recipe index rebuild failed."
|
||||
msgstr ""
|
||||
msgstr "Odbudowa indeksu przepisu nie powiodła się."
|
||||
|
||||
#: .\cookbook\migrations\0047_auto_20200602_1133.py:14
|
||||
msgid "Breakfast"
|
||||
@@ -412,8 +436,6 @@ msgid "Other"
|
||||
msgstr "Inne"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:17
|
||||
#, fuzzy
|
||||
#| msgid "Fats"
|
||||
msgid "Fat"
|
||||
msgstr "Tłuszcze"
|
||||
|
||||
@@ -421,7 +443,7 @@ msgstr "Tłuszcze"
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:18
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:19
|
||||
msgid "g"
|
||||
msgstr ""
|
||||
msgstr "g"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:18
|
||||
msgid "Carbohydrates"
|
||||
@@ -437,13 +459,15 @@ msgstr "Kalorie"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:20
|
||||
msgid "kcal"
|
||||
msgstr ""
|
||||
msgstr "kcal"
|
||||
|
||||
#: .\cookbook\models.py:325
|
||||
msgid ""
|
||||
"Maximum file storage for space in MB. 0 for unlimited, -1 to disable file "
|
||||
"upload."
|
||||
msgstr ""
|
||||
"Maksymalna pojemność na pliki dla przestrzeni w MB. 0 oznacza brak limitu, -"
|
||||
"1 wyłącza możliwość przesyłania plików."
|
||||
|
||||
#: .\cookbook\models.py:454 .\cookbook\templates\search.html:7
|
||||
#: .\cookbook\templates\settings.html:18
|
||||
|
||||
@@ -12,8 +12,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2023-10-07 18:02+0000\n"
|
||||
"Last-Translator: Guilherme Roda <glealroda@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-02-21 10:58+0000\n"
|
||||
"Last-Translator: Filipe Neves <homemdasneves@gmail.com>\n"
|
||||
"Language-Team: Portuguese <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/pt/>\n"
|
||||
"Language: pt\n"
|
||||
@@ -21,7 +21,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Weblate 4.15\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -94,14 +94,16 @@ msgid ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
|
||||
msgstr ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Token de longa duração</a>para a sua instância HomeAssistant"
|
||||
|
||||
#: .\cookbook\forms.py:193
|
||||
msgid "Something like http://homeassistant.local:8123/api"
|
||||
msgstr ""
|
||||
msgstr "Algo como http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:205
|
||||
msgid "http://homeassistant.local:8123/api for example"
|
||||
msgstr ""
|
||||
msgstr "http://homeassistant.local:8123/api por exemplo"
|
||||
|
||||
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
|
||||
msgid "Storage"
|
||||
@@ -181,18 +183,25 @@ msgid ""
|
||||
"Fields to search for partial matches. (e.g. searching for 'Pie' will return "
|
||||
"'pie' and 'piece' and 'soapie')"
|
||||
msgstr ""
|
||||
"Campos a pesquisar por correspondência. (Ex: pesquisar por 'mor' retorna "
|
||||
"'morango' e 'amora')"
|
||||
|
||||
#: .\cookbook\forms.py:344
|
||||
msgid ""
|
||||
"Fields to search for beginning of word matches. (e.g. searching for 'sa' "
|
||||
"will return 'salad' and 'sandwich')"
|
||||
msgstr ""
|
||||
"Campos a pesquisar para correspondências no início da palavra. (por exemplo, "
|
||||
"pesquisar por \"sa\" retornará \"salada\" e \"sanduíche\")"
|
||||
|
||||
#: .\cookbook\forms.py:345
|
||||
msgid ""
|
||||
"Fields to 'fuzzy' search. (e.g. searching for 'recpie' will find 'recipe'.) "
|
||||
"Note: this option will conflict with 'web' and 'raw' methods of search."
|
||||
msgstr ""
|
||||
"Campos para pesquisa aproximada. (por exemplo, pesquisar por \"recita\" "
|
||||
"encontrará \"receita\"). Nota: esta opção entra em conflito com os métodos "
|
||||
"de pesquisa \"web\" e \"raw\"."
|
||||
|
||||
#: .\cookbook\forms.py:346
|
||||
msgid ""
|
||||
@@ -206,19 +215,19 @@ msgstr "Método de Pesquisa"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Fuzzy Lookups"
|
||||
msgstr ""
|
||||
msgstr "Pesquisas Aproximadas"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Ignore Accent"
|
||||
msgstr ""
|
||||
msgstr "Ignorar pronúncia"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Partial Match"
|
||||
msgstr ""
|
||||
msgstr "Correspondência parcial"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
msgstr "Começa com"
|
||||
|
||||
#: .\cookbook\forms.py:351
|
||||
msgid "Fuzzy Search"
|
||||
@@ -233,6 +242,8 @@ msgid ""
|
||||
"In order to prevent spam, the requested email was not send. Please wait a "
|
||||
"few minutes and try again."
|
||||
msgstr ""
|
||||
"Para evitar spam, o email solicitado não foi enviado. Por favor, aguarde "
|
||||
"alguns minutos e tente novamente."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:164
|
||||
#: .\cookbook\helper\permission_helper.py:187 .\cookbook\views\views.py:117
|
||||
@@ -257,11 +268,11 @@ msgstr "Sem permissões para aceder a esta página!"
|
||||
#: .\cookbook\helper\permission_helper.py:237
|
||||
#: .\cookbook\helper\permission_helper.py:252
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
msgstr "Não pode interagir com este objeto, pois não é seu!"
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:402
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
msgstr "Atingiu o número máximo de receitas para o seu espaço."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:414
|
||||
msgid "You have more users than allowed in your space."
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2023-04-27 08:55+0000\n"
|
||||
"Last-Translator: noxonad <noxonad@proton.me>\n"
|
||||
"PO-Revision-Date: 2025-02-16 14:58+0000\n"
|
||||
"Last-Translator: Cots Partier <cots.pastier.34@icloud.com>\n"
|
||||
"Language-Team: Romanian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/ro/>\n"
|
||||
"Language: ro\n"
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
|
||||
"20)) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.15\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -91,14 +91,16 @@ msgid ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Long Lived Access Token</a> for your HomeAssistant instance"
|
||||
msgstr ""
|
||||
"<a href=\"https://www.home-assistant.io/docs/authentication/#your-account-"
|
||||
"profile\">Token the acces</a> pentru instanța ta de HomeAssistant"
|
||||
|
||||
#: .\cookbook\forms.py:193
|
||||
msgid "Something like http://homeassistant.local:8123/api"
|
||||
msgstr ""
|
||||
msgstr "Asemănător cu http://homeassistant.local:8123/api"
|
||||
|
||||
#: .\cookbook\forms.py:205
|
||||
msgid "http://homeassistant.local:8123/api for example"
|
||||
msgstr ""
|
||||
msgstr "http://homeassistant.local:8123/api de exemplu"
|
||||
|
||||
#: .\cookbook\forms.py:222 .\cookbook\views\edit.py:117
|
||||
msgid "Storage"
|
||||
@@ -150,10 +152,6 @@ msgstr ""
|
||||
"multe greșeli de scriere sunt ignorate)."
|
||||
|
||||
#: .\cookbook\forms.py:340
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Select type method of search. Click <a href=\"/docs/search/\">here</a> "
|
||||
#| "for full desciption of choices."
|
||||
msgid ""
|
||||
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
|
||||
"full description of choices."
|
||||
@@ -227,8 +225,6 @@ msgid "Partial Match"
|
||||
msgstr "Potrivire parțială"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
#, fuzzy
|
||||
#| msgid "Starts Wtih"
|
||||
msgid "Starts With"
|
||||
msgstr "Începe cu"
|
||||
|
||||
@@ -284,38 +280,36 @@ msgid "You have more users than allowed in your space."
|
||||
msgstr "Aveți mai mulți utilizatori decât este permis în spațiul dvs."
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:310
|
||||
#, fuzzy
|
||||
#| msgid "Use fractions"
|
||||
msgid "reverse rotation"
|
||||
msgstr "Utilizare fracții"
|
||||
msgstr "rotație inversă"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:311
|
||||
msgid "careful rotation"
|
||||
msgstr ""
|
||||
msgstr "rotire atentă"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:312
|
||||
msgid "knead"
|
||||
msgstr ""
|
||||
msgstr "frământă"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:313
|
||||
msgid "thicken"
|
||||
msgstr ""
|
||||
msgstr "se îngroașă"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:314
|
||||
msgid "warm up"
|
||||
msgstr ""
|
||||
msgstr "încălzire"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:315
|
||||
msgid "ferment"
|
||||
msgstr ""
|
||||
msgstr "ferment"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:316
|
||||
msgid "sous-vide"
|
||||
msgstr ""
|
||||
msgstr "sous-vide"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:150
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
msgstr "Trebuie să specificați dimensiunea porției"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:95
|
||||
#: .\cookbook\helper\template_helper.py:97
|
||||
@@ -325,11 +319,11 @@ msgstr "Nu s-a putut analiza codul șablonului."
|
||||
#: .\cookbook\integration\copymethat.py:44
|
||||
#: .\cookbook\integration\melarecipes.py:37
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
msgstr "Favorit"
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:50
|
||||
msgid "I made this"
|
||||
msgstr ""
|
||||
msgstr "Am făcut acest lucru"
|
||||
|
||||
#: .\cookbook\integration\integration.py:209
|
||||
msgid ""
|
||||
@@ -357,10 +351,8 @@ msgid "Imported %s recipes."
|
||||
msgstr "%s rețete importate."
|
||||
|
||||
#: .\cookbook\integration\openeats.py:28
|
||||
#, fuzzy
|
||||
#| msgid "Recipe Home"
|
||||
msgid "Recipe source:"
|
||||
msgstr "Rețetă acasă"
|
||||
msgstr "Sursa rețetei:"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:49
|
||||
msgid "Notes"
|
||||
@@ -376,10 +368,8 @@ msgstr "Sursă"
|
||||
|
||||
#: .\cookbook\integration\recettetek.py:54
|
||||
#: .\cookbook\integration\recipekeeper.py:70
|
||||
#, fuzzy
|
||||
#| msgid "Import Log"
|
||||
msgid "Imported from"
|
||||
msgstr "Jurnal de import"
|
||||
msgstr "Importat din"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
msgid "Servings"
|
||||
@@ -403,19 +393,17 @@ msgstr "Secțiune"
|
||||
|
||||
#: .\cookbook\management\commands\fix_duplicate_properties.py:15
|
||||
msgid "Fixes foods with "
|
||||
msgstr ""
|
||||
msgstr "Corectează alimentele cu "
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:14
|
||||
msgid "Rebuilds full text search index on Recipe"
|
||||
msgstr "Reconstruiește indexul de căutare text complet pe rețetă"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
#, fuzzy
|
||||
#| msgid "Only Postgress databases use full text search, no index to rebuild"
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Numai bazele de date Postgress utilizează căutare text complet, nici un "
|
||||
"index de reconstruit"
|
||||
"Numai bazele de date Postgress utilizează ccăutarea textului integral, nici "
|
||||
"un index de reconstruit"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
msgid "Recipe index rebuild complete."
|
||||
@@ -443,29 +431,29 @@ msgstr "Altele"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:17
|
||||
msgid "Fat"
|
||||
msgstr ""
|
||||
msgstr "Grăsime"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:17
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:18
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:19
|
||||
msgid "g"
|
||||
msgstr ""
|
||||
msgstr "g"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:18
|
||||
msgid "Carbohydrates"
|
||||
msgstr ""
|
||||
msgstr "Carbohidrați"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:19
|
||||
msgid "Proteins"
|
||||
msgstr ""
|
||||
msgstr "Proteine"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:20
|
||||
msgid "Calories"
|
||||
msgstr ""
|
||||
msgstr "Calorii"
|
||||
|
||||
#: .\cookbook\migrations\0190_auto_20230525_1506.py:20
|
||||
msgid "kcal"
|
||||
msgstr ""
|
||||
msgstr "kcal"
|
||||
|
||||
#: .\cookbook\models.py:325
|
||||
msgid ""
|
||||
@@ -500,24 +488,20 @@ msgid " is part of a recipe step and cannot be deleted"
|
||||
msgstr " face parte dintr-un pas de rețetă și nu poate fi șters"
|
||||
|
||||
#: .\cookbook\models.py:918
|
||||
#, fuzzy
|
||||
#| msgid "Automations"
|
||||
msgid "Nutrition"
|
||||
msgstr "Automatizări"
|
||||
msgstr "Nutriție"
|
||||
|
||||
#: .\cookbook\models.py:918
|
||||
#, fuzzy
|
||||
#| msgid "Merge"
|
||||
msgid "Allergen"
|
||||
msgstr "Unire"
|
||||
msgstr "Alergen"
|
||||
|
||||
#: .\cookbook\models.py:919
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Preț"
|
||||
|
||||
#: .\cookbook\models.py:919
|
||||
msgid "Goal"
|
||||
msgstr ""
|
||||
msgstr "Obiectiv"
|
||||
|
||||
#: .\cookbook\models.py:1408 .\cookbook\templates\search_info.html:28
|
||||
msgid "Simple"
|
||||
@@ -548,42 +532,32 @@ msgid "Keyword Alias"
|
||||
msgstr "Pseudonim cuvânt cheie"
|
||||
|
||||
#: .\cookbook\models.py:1470
|
||||
#, fuzzy
|
||||
#| msgid "Description"
|
||||
msgid "Description Replace"
|
||||
msgstr "Descriere"
|
||||
msgstr "Înlocuire Descriere"
|
||||
|
||||
#: .\cookbook\models.py:1471
|
||||
#, fuzzy
|
||||
#| msgid "Instructions"
|
||||
msgid "Instruction Replace"
|
||||
msgstr "Instrucțiuni"
|
||||
msgstr "Înlocuire Instrucțiuni"
|
||||
|
||||
#: .\cookbook\models.py:1472
|
||||
#, fuzzy
|
||||
#| msgid "Select Unit"
|
||||
msgid "Never Unit"
|
||||
msgstr "Selectare unitate"
|
||||
msgstr "Unitate nulă"
|
||||
|
||||
#: .\cookbook\models.py:1473
|
||||
msgid "Transpose Words"
|
||||
msgstr ""
|
||||
msgstr "Schimbă Ordinea Cuvintelor"
|
||||
|
||||
#: .\cookbook\models.py:1474
|
||||
#, fuzzy
|
||||
#| msgid "Food Alias"
|
||||
msgid "Food Replace"
|
||||
msgstr "Pseudonim produse alimentare"
|
||||
msgstr "Aliment echivalent"
|
||||
|
||||
#: .\cookbook\models.py:1475
|
||||
#, fuzzy
|
||||
#| msgid "Unit Alias"
|
||||
msgid "Unit Replace"
|
||||
msgstr "Pseudonim unități"
|
||||
msgstr "Unitate echivalentă"
|
||||
|
||||
#: .\cookbook\models.py:1476
|
||||
msgid "Name Replace"
|
||||
msgstr ""
|
||||
msgstr "Înlocuire Nume"
|
||||
|
||||
#: .\cookbook\models.py:1503 .\cookbook\views\delete.py:40
|
||||
#: .\cookbook\views\edit.py:210 .\cookbook\views\new.py:39
|
||||
@@ -591,10 +565,8 @@ msgid "Recipe"
|
||||
msgstr "Rețetă"
|
||||
|
||||
#: .\cookbook\models.py:1504
|
||||
#, fuzzy
|
||||
#| msgid "Foods"
|
||||
msgid "Food"
|
||||
msgstr "Alimente"
|
||||
msgstr "Mâncare"
|
||||
|
||||
#: .\cookbook\models.py:1505 .\cookbook\templates\base.html:149
|
||||
msgid "Keyword"
|
||||
@@ -610,7 +582,7 @@ msgstr "Ați atins limita de încărcare a fișierelor."
|
||||
|
||||
#: .\cookbook\serializer.py:328
|
||||
msgid "Cannot modify Space owner permission."
|
||||
msgstr ""
|
||||
msgstr "Nu se poate modifica permisiunea proprietarului spațiului."
|
||||
|
||||
#: .\cookbook\serializer.py:1270
|
||||
msgid "Hello"
|
||||
@@ -651,30 +623,35 @@ msgstr "Invitație Tandoor Recipes"
|
||||
|
||||
#: .\cookbook\serializer.py:1426
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
msgstr "Lista de cumpărături existentă de actualizat"
|
||||
|
||||
#: .\cookbook\serializer.py:1428
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
"ID-urile ingredientelor din rețetă pentru a fi adăugate, dacă nu sunt "
|
||||
"specificate toate ingrediente vor fi adăugate."
|
||||
|
||||
#: .\cookbook\serializer.py:1430
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
"Furnizarea unui ID de rețetă și un număr de porții egal cu 0 va șterge lista "
|
||||
"cumpărături."
|
||||
|
||||
#: .\cookbook\serializer.py:1439
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
msgstr "Cantitatea de mâncare pentru a fi adăugată în lista cumpărături"
|
||||
|
||||
#: .\cookbook\serializer.py:1441
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
msgstr "ID-ul unității pentru a fi utilizat în lista de cumpărături"
|
||||
|
||||
#: .\cookbook\serializer.py:1443
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
msgstr ""
|
||||
"Când este activ se șterge toată mâncarea din listele de cumpărături active."
|
||||
|
||||
#: .\cookbook\tables.py:69 .\cookbook\tables.py:83
|
||||
#: .\cookbook\templates\generic\delete_template.html:7
|
||||
@@ -1027,10 +1004,8 @@ msgstr "Istoric"
|
||||
#: .\cookbook\templates\base.html:263
|
||||
#: .\cookbook\templates\ingredient_editor.html:7
|
||||
#: .\cookbook\templates\ingredient_editor.html:13
|
||||
#, fuzzy
|
||||
#| msgid "Ingredients"
|
||||
msgid "Ingredient Editor"
|
||||
msgstr "Ingrediente"
|
||||
msgstr "Editor de Ingrediente"
|
||||
|
||||
#: .\cookbook\templates\base.html:275
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
@@ -1040,13 +1015,11 @@ msgstr "Exportă"
|
||||
|
||||
#: .\cookbook\templates\base.html:287
|
||||
msgid "Properties"
|
||||
msgstr ""
|
||||
msgstr "Atribute"
|
||||
|
||||
#: .\cookbook\templates\base.html:301 .\cookbook\views\lists.py:255
|
||||
#, fuzzy
|
||||
#| msgid "Account Connections"
|
||||
msgid "Unit Conversions"
|
||||
msgstr "Conexiuni de cont"
|
||||
msgstr "Conversii de unități"
|
||||
|
||||
#: .\cookbook\templates\base.html:318 .\cookbook\templates\index.html:47
|
||||
msgid "Import Recipe"
|
||||
@@ -1066,10 +1039,8 @@ msgid "Space Settings"
|
||||
msgstr "Setări spațiu"
|
||||
|
||||
#: .\cookbook\templates\base.html:340
|
||||
#, fuzzy
|
||||
#| msgid "External Recipes"
|
||||
msgid "External Connectors"
|
||||
msgstr "Rețete externe"
|
||||
msgstr "Conectori externi"
|
||||
|
||||
#: .\cookbook\templates\base.html:345 .\cookbook\templates\system.html:13
|
||||
msgid "System"
|
||||
@@ -1081,15 +1052,13 @@ msgstr "Admin"
|
||||
|
||||
#: .\cookbook\templates\base.html:351
|
||||
#: .\cookbook\templates\space_overview.html:25
|
||||
#, fuzzy
|
||||
#| msgid "No Space"
|
||||
msgid "Your Spaces"
|
||||
msgstr "Fără spațiu"
|
||||
msgstr "Spațiul tău"
|
||||
|
||||
#: .\cookbook\templates\base.html:362
|
||||
#: .\cookbook\templates\space_overview.html:6
|
||||
msgid "Overview"
|
||||
msgstr ""
|
||||
msgstr "Sumar"
|
||||
|
||||
#: .\cookbook\templates\base.html:372
|
||||
msgid "Markdown Guide"
|
||||
@@ -1113,11 +1082,11 @@ msgstr "Deconectare"
|
||||
|
||||
#: .\cookbook\templates\base.html:406
|
||||
msgid "You are using the free version of Tandor"
|
||||
msgstr ""
|
||||
msgstr "Utilizați o versiune gratuită de Tandor"
|
||||
|
||||
#: .\cookbook\templates\base.html:407
|
||||
msgid "Upgrade Now"
|
||||
msgstr ""
|
||||
msgstr "Actualizează acum"
|
||||
|
||||
#: .\cookbook\templates\batch\edit.html:6
|
||||
msgid "Batch edit Category"
|
||||
@@ -1213,7 +1182,7 @@ msgstr "Sunteți sigur că doriți să ștergeți %(title)s: <b>%(object)s</b> "
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:22
|
||||
msgid "This cannot be undone!"
|
||||
msgstr ""
|
||||
msgstr "Este ireversibil!"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:27
|
||||
msgid "Protected"
|
||||
@@ -1230,7 +1199,7 @@ msgstr "Anulare"
|
||||
#: .\cookbook\templates\generic\edit_template.html:6
|
||||
#: .\cookbook\templates\generic\edit_template.html:14
|
||||
msgid "Edit"
|
||||
msgstr "Editare"
|
||||
msgstr "Editează"
|
||||
|
||||
#: .\cookbook\templates\generic\edit_template.html:32
|
||||
msgid "View"
|
||||
@@ -1379,8 +1348,6 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:57
|
||||
#: .\cookbook\templates\markdown_info.html:73
|
||||
#, fuzzy
|
||||
#| msgid "or by leaving a blank line inbetween."
|
||||
msgid "or by leaving a blank line in between."
|
||||
msgstr "sau lăsând o linie goală între ele."
|
||||
|
||||
@@ -1404,10 +1371,6 @@ msgid "Lists"
|
||||
msgstr "Liste"
|
||||
|
||||
#: .\cookbook\templates\markdown_info.html:85
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Lists can ordered or unorderd. It is <b>important to leave a blank line "
|
||||
#| "before the list!</b>"
|
||||
msgid ""
|
||||
"Lists can ordered or unordered. It is <b>important to leave a blank line "
|
||||
"before the list!</b>"
|
||||
@@ -1539,11 +1502,11 @@ msgstr ""
|
||||
#: .\cookbook\templates\openid\login.html:27
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:27
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "Înapoi"
|
||||
|
||||
#: .\cookbook\templates\property_editor.html:7
|
||||
msgid "Property Editor"
|
||||
msgstr ""
|
||||
msgstr "Editor atribute"
|
||||
|
||||
#: .\cookbook\templates\recipe_view.html:36
|
||||
msgid "Comments"
|
||||
@@ -1620,15 +1583,6 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:29
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Simple searches ignore punctuation and common words such as "
|
||||
#| "'the', 'a', 'and'. And will treat seperate words as required.\n"
|
||||
#| " Searching for 'apple or flour' will return any recipe that "
|
||||
#| "includes both 'apple' and 'flour' anywhere in the fields that have been "
|
||||
#| "selected for a full text search.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Simple searches ignore punctuation and common words such as "
|
||||
@@ -1666,23 +1620,6 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:39
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Web searches simulate functionality found on many web search "
|
||||
#| "sites supporting special syntax.\n"
|
||||
#| " Placing quotes around several words will convert those words "
|
||||
#| "into a phrase.\n"
|
||||
#| " 'or' is recongized as searching for the word (or phrase) "
|
||||
#| "immediately before 'or' OR the word (or phrase) directly after.\n"
|
||||
#| " '-' is recognized as searching for recipes that do not "
|
||||
#| "include the word (or phrase) that comes immediately after. \n"
|
||||
#| " For example searching for 'apple pie' or cherry -butter will "
|
||||
#| "return any recipe that includes the phrase 'apple pie' or the word "
|
||||
#| "'cherry' \n"
|
||||
#| " in any field included in the full text search but exclude any "
|
||||
#| "recipe that has the word 'butter' in any field included.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Web searches simulate functionality found on many web search "
|
||||
@@ -1705,8 +1642,8 @@ msgstr ""
|
||||
"uri de căutare web care acceptă sintaxa specială.\n"
|
||||
" Plasarea ghilimelelor în jurul mai multor cuvinte va converti "
|
||||
"aceste cuvinte într-o frază.\n"
|
||||
" 'sau' este recunoscut pentru căutarea pentru cuvântul (sau "
|
||||
"fraza) imediat înainte de 'sau' SAU cuvântul (sau fraza) direct după.\n"
|
||||
" 'sau' este recunoscut pentru căutarea pentru cuvântul (sau fraza)"
|
||||
" imediat înainte de 'sau' SAU cuvântul (sau fraza) direct după.\n"
|
||||
" '-' este recunoscut pentru căutarea rețetelor care nu includ "
|
||||
"cuvântul (sau fraza) care vine imediat după. \n"
|
||||
" De exemplu, căutarea 'plăcintei cu mere' sau a untului de cireșe "
|
||||
@@ -1729,19 +1666,6 @@ msgstr ""
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\search_info.html:59
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| " \n"
|
||||
#| " Another approach to searching that also requires Postgresql "
|
||||
#| "is fuzzy search or trigram similarity. A trigram is a group of three "
|
||||
#| "consecutive characters.\n"
|
||||
#| " For example searching for 'apple' will create x trigrams "
|
||||
#| "'app', 'ppl', 'ple' and will create a score of how closely words match "
|
||||
#| "the generated trigrams.\n"
|
||||
#| " One benefit of searching trigams is that a search for "
|
||||
#| "'sandwich' will find mispelled words such as 'sandwhich' that would be "
|
||||
#| "missed by other methods.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
" \n"
|
||||
" Another approach to searching that also requires Postgresql is "
|
||||
@@ -1948,17 +1872,15 @@ msgstr "Creează cont superuser"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:7
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:23
|
||||
#, fuzzy
|
||||
#| msgid "Social Login"
|
||||
msgid "Social Network Login Failure"
|
||||
msgstr "Autentificare utilizând rețeaua socială"
|
||||
msgstr "Eșec la conectarea la rețeaua socială"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\authentication_error.html:25
|
||||
#, fuzzy
|
||||
#| msgid "An error occurred attempting to move "
|
||||
msgid ""
|
||||
"An error occurred while attempting to login via your social network account."
|
||||
msgstr "A apărut o eroare la încercarea de a muta "
|
||||
msgstr ""
|
||||
"S-a produs o eroare în timp ce se încearca autentificarea prin contul tău de "
|
||||
"rețea socială."
|
||||
|
||||
#: .\cookbook\templates\socialaccount\connections.html:4
|
||||
#: .\cookbook\templates\socialaccount\connections.html:15
|
||||
@@ -1994,17 +1916,18 @@ msgstr "Înregistrare"
|
||||
#: .\cookbook\templates\socialaccount\login.html:9
|
||||
#, python-format
|
||||
msgid "Connect %(provider)s"
|
||||
msgstr ""
|
||||
msgstr "Conectează %(provider)s"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\login.html:11
|
||||
#, python-format
|
||||
msgid "You are about to connect a new third party account from %(provider)s."
|
||||
msgstr ""
|
||||
"Sunteți pe cale să conectați un nou cont de terță parte din %(provider)s."
|
||||
|
||||
#: .\cookbook\templates\socialaccount\login.html:13
|
||||
#, python-format
|
||||
msgid "Sign In Via %(provider)s"
|
||||
msgstr ""
|
||||
msgstr "Intră în cont prin %(provider)s"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\login.html:15
|
||||
#, python-format
|
||||
@@ -2013,7 +1936,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\socialaccount\login.html:20
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
msgstr "Continuă"
|
||||
|
||||
#: .\cookbook\templates\socialaccount\signup.html:10
|
||||
#, python-format
|
||||
@@ -2046,7 +1969,7 @@ msgstr "Conectați-vă utilizând"
|
||||
|
||||
#: .\cookbook\templates\space_manage.html:7
|
||||
msgid "Space Management"
|
||||
msgstr ""
|
||||
msgstr "Managementul spațiului"
|
||||
|
||||
#: .\cookbook\templates\space_manage.html:26
|
||||
msgid "Space:"
|
||||
@@ -2057,10 +1980,8 @@ msgid "Manage Subscription"
|
||||
msgstr "Gestionarea abonamentului"
|
||||
|
||||
#: .\cookbook\templates\space_overview.html:13 .\cookbook\views\delete.py:184
|
||||
#, fuzzy
|
||||
#| msgid "Space:"
|
||||
msgid "Space"
|
||||
msgstr "Spațiu:"
|
||||
msgstr "Spațiu"
|
||||
|
||||
#: .\cookbook\templates\space_overview.html:17
|
||||
msgid ""
|
||||
@@ -2078,13 +1999,11 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\space_overview.html:53
|
||||
msgid "Owner"
|
||||
msgstr ""
|
||||
msgstr "Proprietar"
|
||||
|
||||
#: .\cookbook\templates\space_overview.html:57
|
||||
#, fuzzy
|
||||
#| msgid "Create Space"
|
||||
msgid "Leave Space"
|
||||
msgstr "Creare spațiu"
|
||||
msgstr "Părăsire spațiu"
|
||||
|
||||
#: .\cookbook\templates\space_overview.html:78
|
||||
#: .\cookbook\templates\space_overview.html:88
|
||||
@@ -2147,6 +2066,11 @@ msgid ""
|
||||
"script to generate version information (done automatically in docker).\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Trebuie să executați <code>version.py</code> în scripturile de "
|
||||
"actualizare pentru a genera informații despre versiune (realizate automat în "
|
||||
"docker).\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\system.html:46
|
||||
msgid "Media Serving"
|
||||
@@ -2237,7 +2161,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\system.html:86
|
||||
msgid "Allowed Hosts"
|
||||
msgstr ""
|
||||
msgstr "Domenii Permise"
|
||||
|
||||
#: .\cookbook\templates\system.html:90
|
||||
msgid ""
|
||||
@@ -2257,10 +2181,8 @@ msgid "Info"
|
||||
msgstr "Informație"
|
||||
|
||||
#: .\cookbook\templates\system.html:110 .\cookbook\templates\system.html:127
|
||||
#, fuzzy
|
||||
#| msgid "Use fractions"
|
||||
msgid "Migrations"
|
||||
msgstr "Utilizare fracții"
|
||||
msgstr "Migrări"
|
||||
|
||||
#: .\cookbook\templates\system.html:116
|
||||
msgid ""
|
||||
@@ -2276,19 +2198,17 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\templates\system.html:182
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
msgstr "Fals"
|
||||
|
||||
#: .\cookbook\templates\system.html:182
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
msgstr "Adevărat"
|
||||
|
||||
#: .\cookbook\templates\system.html:207
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
msgstr "Ascunde"
|
||||
|
||||
#: .\cookbook\templates\system.html:210
|
||||
#, fuzzy
|
||||
#| msgid "Show Log"
|
||||
msgid "Show"
|
||||
msgstr "Afișare jurnal"
|
||||
|
||||
@@ -2355,29 +2275,34 @@ msgstr "{child.name} a fost mutat cu succes la părintele {parent.name}"
|
||||
#: .\cookbook\views\api.py:589
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was removed from the shopping list."
|
||||
msgstr ""
|
||||
msgstr "{obj.name} a fost șters din lista de cumpărături."
|
||||
|
||||
#: .\cookbook\views\api.py:594 .\cookbook\views\api.py:1037
|
||||
#: .\cookbook\views\api.py:1050
|
||||
#, python-brace-format
|
||||
msgid "{obj.name} was added to the shopping list."
|
||||
msgstr ""
|
||||
msgstr "{obj.name} a fost adăugat la lista de cumpărături."
|
||||
|
||||
#: .\cookbook\views\api.py:742
|
||||
msgid "Filter meal plans from date (inclusive) in the format of YYYY-MM-DD."
|
||||
msgstr ""
|
||||
msgstr "Filtrează planurile de masă din data (inclusiv) în formatul AAAA-LL-ZZ."
|
||||
|
||||
#: .\cookbook\views\api.py:743
|
||||
msgid "Filter meal plans to date (inclusive) in the format of YYYY-MM-DD."
|
||||
msgstr ""
|
||||
"Filtrează planurile de masă până la data (inclusiv) în formatul AAAA-LL-ZZ."
|
||||
|
||||
#: .\cookbook\views\api.py:744
|
||||
msgid "Filter meal plans with MealType ID. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
"Filtrează planurile de masă cu ID-ul tipului de rețetă. Pentru mai multe "
|
||||
"repetă parametrul."
|
||||
|
||||
#: .\cookbook\views\api.py:872
|
||||
msgid "ID of recipe a step is part of. For multiple repeat parameter."
|
||||
msgstr ""
|
||||
"ID-ul rețetei din care face pasul face parte. Pentru mai multe repetă "
|
||||
"parametrul."
|
||||
|
||||
#: .\cookbook\views\api.py:873
|
||||
msgid "Query string matched (fuzzy) against object name."
|
||||
@@ -2555,8 +2480,6 @@ msgid "Bad URL Schema."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\api.py:1474
|
||||
#, fuzzy
|
||||
#| msgid "No useable data could be found."
|
||||
msgid "No usable data could be found."
|
||||
msgstr "Nu au putut fi găsite date utilizabile."
|
||||
|
||||
@@ -2611,20 +2534,16 @@ msgstr ""
|
||||
"puțin un supervizor."
|
||||
|
||||
#: .\cookbook\views\delete.py:135
|
||||
#, fuzzy
|
||||
#| msgid "Storage Backend"
|
||||
msgid "Connectors Config Backend"
|
||||
msgstr "Backend de stocare"
|
||||
msgstr "Configurare Backend Conectori"
|
||||
|
||||
#: .\cookbook\views\delete.py:157
|
||||
msgid "Invite Link"
|
||||
msgstr "Link de invitare"
|
||||
|
||||
#: .\cookbook\views\delete.py:168
|
||||
#, fuzzy
|
||||
#| msgid "Members"
|
||||
msgid "Space Membership"
|
||||
msgstr "Membri"
|
||||
msgstr "Membri spațiu"
|
||||
|
||||
#: .\cookbook\views\edit.py:84
|
||||
msgid "You cannot edit this storage!"
|
||||
@@ -2639,10 +2558,8 @@ msgid "There was an error updating this storage backend!"
|
||||
msgstr "A existat o eroare la actualizarea acestui backend de stocare!"
|
||||
|
||||
#: .\cookbook\views\edit.py:134
|
||||
#, fuzzy
|
||||
#| msgid "Changes saved!"
|
||||
msgid "Config saved!"
|
||||
msgstr "Modificări salvate!"
|
||||
msgstr "Configurare salvată!"
|
||||
|
||||
#: .\cookbook\views\edit.py:142
|
||||
msgid "ConnectorConfig"
|
||||
@@ -2675,10 +2592,8 @@ msgid "Shopping List"
|
||||
msgstr "Listă de cumpărături"
|
||||
|
||||
#: .\cookbook\views\lists.py:77 .\cookbook\views\new.py:98
|
||||
#, fuzzy
|
||||
#| msgid "Storage Backend"
|
||||
msgid "Connector Config Backend"
|
||||
msgstr "Backend de stocare"
|
||||
msgstr "Configurare Backend pentru Conector"
|
||||
|
||||
#: .\cookbook\views\lists.py:91
|
||||
msgid "Invite Links"
|
||||
@@ -2693,10 +2608,8 @@ msgid "Shopping Categories"
|
||||
msgstr "Categorii de cumpărături"
|
||||
|
||||
#: .\cookbook\views\lists.py:202
|
||||
#, fuzzy
|
||||
#| msgid "Filter"
|
||||
msgid "Custom Filters"
|
||||
msgstr "Filtru"
|
||||
msgstr "Filtre Personalizate"
|
||||
|
||||
#: .\cookbook\views\lists.py:239
|
||||
msgid "Steps"
|
||||
@@ -2707,10 +2620,8 @@ msgid "Property Types"
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\new.py:86
|
||||
#, fuzzy
|
||||
#| msgid "This feature is not available in the demo version!"
|
||||
msgid "This feature is not enabled by the server admin!"
|
||||
msgstr "Această funcție nu este disponibilă în versiunea demo!"
|
||||
msgstr "Această funcție nu a fost activată de către administrator!"
|
||||
|
||||
#: .\cookbook\views\new.py:123
|
||||
msgid "Imported new recipe!"
|
||||
@@ -2726,11 +2637,9 @@ msgid "This feature is not available in the demo version!"
|
||||
msgstr "Această funcție nu este disponibilă în versiunea demo!"
|
||||
|
||||
#: .\cookbook\views\views.py:74
|
||||
#, fuzzy
|
||||
#| msgid "You have reached the maximum number of recipes for your space."
|
||||
msgid ""
|
||||
"You have the reached the maximum amount of spaces that can be owned by you."
|
||||
msgstr "Ai ajuns la numărul maxim de rețete pentru spațiul dvs."
|
||||
msgstr "Ai ajuns la numărul maxim de spații pe care le poți deține."
|
||||
|
||||
#: .\cookbook\views\views.py:89
|
||||
msgid ""
|
||||
@@ -2779,29 +2688,15 @@ msgid "Unable to determine PostgreSQL version."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:317
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "\n"
|
||||
#| " This application is not running with a Postgres database "
|
||||
#| "backend. This is ok but not recommended as some\n"
|
||||
#| " features only work with postgres databases.\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
"This application is not running with a Postgres database backend. This is ok "
|
||||
"but not recommended as some features only work with postgres databases."
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Această aplicație nu se execută cu un backend de bază de date "
|
||||
"Postgres. Acest lucru este ok, dar nu este recomandat deoarece unele\n"
|
||||
" caracteristicile funcționează numai cu baze de date Postgres.\n"
|
||||
" "
|
||||
"Această aplicație nu se execută cu un backend de bază de date Postgres. "
|
||||
"Acest lucru este ok, dar nu este recomandat deoarece unele caracteristicile "
|
||||
"funcționează numai cu baze de date Postgres."
|
||||
|
||||
#: .\cookbook\views\views.py:360
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The setup page can only be used to create the first user! If you have "
|
||||
#| "forgotten your superuser credentials please consult the django "
|
||||
#| "documentation on how to reset passwords."
|
||||
msgid ""
|
||||
"The setup page can only be used to create the first "
|
||||
"user! If you have forgotten your superuser credentials "
|
||||
@@ -2852,10 +2747,8 @@ msgid "Manage recipes, shopping list, meal plans and more."
|
||||
msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:458
|
||||
#, fuzzy
|
||||
#| msgid "Meal-Plan"
|
||||
msgid "Plan"
|
||||
msgstr "Plan de alimentare"
|
||||
msgstr "Plan"
|
||||
|
||||
#: .\cookbook\views\views.py:458
|
||||
msgid "View your meal Plan"
|
||||
@@ -2863,13 +2756,11 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\views\views.py:459
|
||||
msgid "View your cookbooks"
|
||||
msgstr ""
|
||||
msgstr "Vizualizează cărțile de bucate"
|
||||
|
||||
#: .\cookbook\views\views.py:460
|
||||
#, fuzzy
|
||||
#| msgid "New Shopping List"
|
||||
msgid "View your shopping lists"
|
||||
msgstr "Listă de cumpărături nouă"
|
||||
msgstr "Vezi listele de cumpărături"
|
||||
|
||||
#~ msgid "Default unit"
|
||||
#~ msgstr "Unitate implicită"
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-09-17 11:58+0000\n"
|
||||
"Last-Translator: Bebbe K <kajolekk91@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-02-07 08:58+0000\n"
|
||||
"Last-Translator: Mattias G <mattias.granlund@gmail.com>\n"
|
||||
"Language-Team: Swedish <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/sv/>\n"
|
||||
"Language: sv\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -549,7 +549,7 @@ msgstr "Ersätt Enhet"
|
||||
|
||||
#: .\cookbook\models.py:1476
|
||||
msgid "Name Replace"
|
||||
msgstr ""
|
||||
msgstr "Ersättningsnamn"
|
||||
|
||||
#: .\cookbook\models.py:1503 .\cookbook\views\delete.py:40
|
||||
#: .\cookbook\views\edit.py:210 .\cookbook\views\new.py:39
|
||||
@@ -566,15 +566,15 @@ msgstr "Nyckelord"
|
||||
|
||||
#: .\cookbook\serializer.py:222
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
msgstr ""
|
||||
msgstr "Filuppladdning är inte aktiverat för det här utrymmet."
|
||||
|
||||
#: .\cookbook\serializer.py:233
|
||||
msgid "You have reached your file upload limit."
|
||||
msgstr ""
|
||||
msgstr "Du har nått din maxgräns för uppladdningar."
|
||||
|
||||
#: .\cookbook\serializer.py:328
|
||||
msgid "Cannot modify Space owner permission."
|
||||
msgstr ""
|
||||
msgstr "Kan inte modifiera utrymmets ägar-rättigheter."
|
||||
|
||||
#: .\cookbook\serializer.py:1270
|
||||
msgid "Hello"
|
||||
@@ -582,56 +582,61 @@ msgstr "Hej"
|
||||
|
||||
#: .\cookbook\serializer.py:1270
|
||||
msgid "You have been invited by "
|
||||
msgstr ""
|
||||
msgstr "Du har bjudits in av "
|
||||
|
||||
#: .\cookbook\serializer.py:1272
|
||||
msgid " to join their Tandoor Recipes space "
|
||||
msgstr ""
|
||||
msgstr " för att ansluta till deras Tandoor recept utrymme "
|
||||
|
||||
#: .\cookbook\serializer.py:1274
|
||||
msgid "Click the following link to activate your account: "
|
||||
msgstr ""
|
||||
msgstr "Klicka på länken för att aktivera ditt konto: "
|
||||
|
||||
#: .\cookbook\serializer.py:1276
|
||||
msgid ""
|
||||
"If the link does not work use the following code to manually join the space: "
|
||||
msgstr ""
|
||||
"Om länken inte fungerar kan du testa följande kod för att manuellt aktivera "
|
||||
"ditt utrymme: "
|
||||
|
||||
#: .\cookbook\serializer.py:1278
|
||||
msgid "The invitation is valid until "
|
||||
msgstr ""
|
||||
msgstr "Inbjudningen är giltig till "
|
||||
|
||||
#: .\cookbook\serializer.py:1280
|
||||
msgid ""
|
||||
"Tandoor Recipes is an Open Source recipe manager. Check it out on GitHub "
|
||||
msgstr ""
|
||||
"Tandoor recept är en recept-hanterar med öppen källkod. Se mer på GitHub "
|
||||
|
||||
#: .\cookbook\serializer.py:1283
|
||||
msgid "Tandoor Recipes Invite"
|
||||
msgstr ""
|
||||
msgstr "Tandoor recept inbjudan"
|
||||
|
||||
#: .\cookbook\serializer.py:1426
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
msgstr "Existerande inköpslistor att uppdatera"
|
||||
|
||||
#: .\cookbook\serializer.py:1428
|
||||
msgid ""
|
||||
"List of ingredient IDs from the recipe to add, if not provided all "
|
||||
"ingredients will be added."
|
||||
msgstr ""
|
||||
"Lista med ingrediens ID:n från receptet att lägga till, om inget angetts "
|
||||
"kommer alla ingredienser bli tillagda."
|
||||
|
||||
#: .\cookbook\serializer.py:1430
|
||||
msgid ""
|
||||
"Providing a list_recipe ID and servings of 0 will delete that shopping list."
|
||||
msgstr ""
|
||||
msgstr "Anges ett list_recept ID och 0 portioner kommer den listan raderas."
|
||||
|
||||
#: .\cookbook\serializer.py:1439
|
||||
msgid "Amount of food to add to the shopping list"
|
||||
msgstr ""
|
||||
msgstr "Mängd av ingrediens att lägga till på inköpslistan"
|
||||
|
||||
#: .\cookbook\serializer.py:1441
|
||||
msgid "ID of unit to use for the shopping list"
|
||||
msgstr ""
|
||||
msgstr "ID eller enhet att använda för inköpslistan"
|
||||
|
||||
#: .\cookbook\serializer.py:1443
|
||||
msgid "When set to true will delete all food from active shopping lists."
|
||||
@@ -681,7 +686,7 @@ msgstr "Email"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:19
|
||||
msgid "The following e-mail addresses are associated with your account:"
|
||||
msgstr ""
|
||||
msgstr "Följande epost-addresser är associerade med ditt konto:"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:36
|
||||
msgid "Verified"
|
||||
@@ -696,14 +701,12 @@ msgid "Primary"
|
||||
msgstr "Primär"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:47
|
||||
#, fuzzy
|
||||
#| msgid "Make Header"
|
||||
msgid "Make Primary"
|
||||
msgstr "Skapa titel"
|
||||
msgstr "Markera som primär"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:49
|
||||
msgid "Re-send Verification"
|
||||
msgstr ""
|
||||
msgstr "Sänd verifikationen igen"
|
||||
|
||||
#: .\cookbook\templates\account\email.html:50
|
||||
#: .\cookbook\templates\generic\delete_template.html:57
|
||||
|
||||
@@ -11,8 +11,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-07-03 16:38+0000\n"
|
||||
"Last-Translator: Taylan TATLI <uyelik-tandoor@tatli.me>\n"
|
||||
"PO-Revision-Date: 2025-01-20 05:20+0000\n"
|
||||
"Last-Translator: Yigit <yigit.gungor@outlook.com>\n"
|
||||
"Language-Team: Turkish <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/tr/>\n"
|
||||
"Language: tr\n"
|
||||
@@ -20,7 +20,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -199,7 +199,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Search Method"
|
||||
msgstr ""
|
||||
msgstr "Arama Metodu"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Fuzzy Lookups"
|
||||
@@ -207,15 +207,15 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Ignore Accent"
|
||||
msgstr ""
|
||||
msgstr "Harflerdeki Vurguları Görmezden Gel"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Partial Match"
|
||||
msgstr ""
|
||||
msgstr "Kısmi Eşleşme"
|
||||
|
||||
#: .\cookbook\forms.py:350
|
||||
msgid "Starts With"
|
||||
msgstr ""
|
||||
msgstr "İle başlayan"
|
||||
|
||||
#: .\cookbook\forms.py:351
|
||||
msgid "Fuzzy Search"
|
||||
@@ -223,18 +223,20 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:351
|
||||
msgid "Full Text"
|
||||
msgstr ""
|
||||
msgstr "Tam Metin"
|
||||
|
||||
#: .\cookbook\helper\AllAuthCustomAdapter.py:41
|
||||
msgid ""
|
||||
"In order to prevent spam, the requested email was not send. Please wait a "
|
||||
"few minutes and try again."
|
||||
msgstr ""
|
||||
"İstenmeyen e-postayı önlemek için istenen e-posta gönderilemedi. Lütfen "
|
||||
"birkaç dakika bekleyin ve tekrar deneyin."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:164
|
||||
#: .\cookbook\helper\permission_helper.py:187 .\cookbook\views\views.py:117
|
||||
msgid "You are not logged in and therefore cannot view this page!"
|
||||
msgstr ""
|
||||
msgstr "Giriş yapmadınız ve bu nedenle bu sayfayı görüntüleyemezsiniz!"
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:168
|
||||
#: .\cookbook\helper\permission_helper.py:174
|
||||
@@ -247,68 +249,68 @@ msgstr ""
|
||||
#: .\cookbook\helper\permission_helper.py:341 .\cookbook\views\data.py:35
|
||||
#: .\cookbook\views\views.py:127 .\cookbook\views\views.py:131
|
||||
msgid "You do not have the required permissions to view this page!"
|
||||
msgstr ""
|
||||
msgstr "Bu sayfayı görüntülemek için gerekli izinlere sahip değilsiniz!"
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:192
|
||||
#: .\cookbook\helper\permission_helper.py:215
|
||||
#: .\cookbook\helper\permission_helper.py:237
|
||||
#: .\cookbook\helper\permission_helper.py:252
|
||||
msgid "You cannot interact with this object as it is not owned by you!"
|
||||
msgstr ""
|
||||
msgstr "Bu nesne size ait olmadığı için onunla etkileşime giremezsiniz!"
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:402
|
||||
msgid "You have reached the maximum number of recipes for your space."
|
||||
msgstr ""
|
||||
msgstr "Alanınız için maksimum tarif sayısına ulaştınız."
|
||||
|
||||
#: .\cookbook\helper\permission_helper.py:414
|
||||
msgid "You have more users than allowed in your space."
|
||||
msgstr ""
|
||||
msgstr "Alanınızda izin verilenden daha fazla kullanıcı var."
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:310
|
||||
msgid "reverse rotation"
|
||||
msgstr ""
|
||||
msgstr "ters dönüş"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:311
|
||||
msgid "careful rotation"
|
||||
msgstr ""
|
||||
msgstr "dikkatli dönüş"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:312
|
||||
msgid "knead"
|
||||
msgstr ""
|
||||
msgstr "yoğur"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:313
|
||||
msgid "thicken"
|
||||
msgstr ""
|
||||
msgstr "kalınlaştır"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:314
|
||||
msgid "warm up"
|
||||
msgstr ""
|
||||
msgstr "ısıt"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:315
|
||||
msgid "ferment"
|
||||
msgstr ""
|
||||
msgstr "mayala"
|
||||
|
||||
#: .\cookbook\helper\recipe_url_import.py:316
|
||||
msgid "sous-vide"
|
||||
msgstr ""
|
||||
msgstr "sous-vide"
|
||||
|
||||
#: .\cookbook\helper\shopping_helper.py:150
|
||||
msgid "You must supply a servings size"
|
||||
msgstr ""
|
||||
msgstr "Bir porsiyon büyüklüğü vermelisiniz"
|
||||
|
||||
#: .\cookbook\helper\template_helper.py:95
|
||||
#: .\cookbook\helper\template_helper.py:97
|
||||
msgid "Could not parse template code."
|
||||
msgstr ""
|
||||
msgstr "Şablon kodu ayrıştırılamadı."
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:44
|
||||
#: .\cookbook\integration\melarecipes.py:37
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
msgstr "Favori"
|
||||
|
||||
#: .\cookbook\integration\copymethat.py:50
|
||||
msgid "I made this"
|
||||
msgstr ""
|
||||
msgstr "Bunu yaptım"
|
||||
|
||||
#: .\cookbook\integration\integration.py:209
|
||||
msgid ""
|
||||
@@ -324,28 +326,28 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\integration\integration.py:217
|
||||
msgid "The following recipes were ignored because they already existed:"
|
||||
msgstr ""
|
||||
msgstr "Aşağıdaki tarifler zaten mevcut olduğu için göz ardı edildi:"
|
||||
|
||||
#: .\cookbook\integration\integration.py:221
|
||||
#, python-format
|
||||
msgid "Imported %s recipes."
|
||||
msgstr ""
|
||||
msgstr "%s tarif içe aktarıldı."
|
||||
|
||||
#: .\cookbook\integration\openeats.py:28
|
||||
msgid "Recipe source:"
|
||||
msgstr ""
|
||||
msgstr "Tarif kaynağı:"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:49
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
msgstr "Notlar"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:52
|
||||
msgid "Nutritional Information"
|
||||
msgstr ""
|
||||
msgstr "Beslenme Bilgileri"
|
||||
|
||||
#: .\cookbook\integration\paprika.py:56
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
msgstr "Kaynak"
|
||||
|
||||
#: .\cookbook\integration\recettetek.py:54
|
||||
#: .\cookbook\integration\recipekeeper.py:70
|
||||
@@ -354,23 +356,23 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\integration\saffron.py:23
|
||||
msgid "Servings"
|
||||
msgstr ""
|
||||
msgstr "Porsiyon"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:25
|
||||
msgid "Waiting time"
|
||||
msgstr ""
|
||||
msgstr "Bekleme süresi"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:27
|
||||
msgid "Preparation Time"
|
||||
msgstr ""
|
||||
msgstr "Hazırlık Süresi"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:29 .\cookbook\templates\index.html:7
|
||||
msgid "Cookbook"
|
||||
msgstr ""
|
||||
msgstr "Yemek kitabı"
|
||||
|
||||
#: .\cookbook\integration\saffron.py:31
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
msgstr "Bölüm"
|
||||
|
||||
#: .\cookbook\management\commands\fix_duplicate_properties.py:15
|
||||
msgid "Fixes foods with "
|
||||
@@ -383,6 +385,8 @@ msgstr ""
|
||||
#: .\cookbook\management\commands\rebuildindex.py:18
|
||||
msgid "Only Postgresql databases use full text search, no index to rebuild"
|
||||
msgstr ""
|
||||
"Yalnızca Postgresql veritabanları tam metin araması kullanır, yeniden "
|
||||
"oluşturulacak dizin yoktur"
|
||||
|
||||
#: .\cookbook\management\commands\rebuildindex.py:29
|
||||
msgid "Recipe index rebuild complete."
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-01 15:04+0200\n"
|
||||
"PO-Revision-Date: 2024-11-22 07:58+0000\n"
|
||||
"Last-Translator: Oleh Hudyma <oleg.hudymaa@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-01-16 18:58+0000\n"
|
||||
"Last-Translator: Anton Shevtsov <ashevtsovs@gmail.com>\n"
|
||||
"Language-Team: Ukrainian <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/uk/>\n"
|
||||
"Language: uk\n"
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
"X-Generator: Weblate 5.8.4\n"
|
||||
|
||||
#: .\cookbook\forms.py:45
|
||||
msgid ""
|
||||
@@ -32,7 +32,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:62 .\cookbook\forms.py:246 .\cookbook\views\lists.py:103
|
||||
msgid "Keywords"
|
||||
msgstr ""
|
||||
msgstr "Ключові слова"
|
||||
|
||||
#: .\cookbook\forms.py:62
|
||||
msgid "Preparation time in minutes"
|
||||
@@ -941,13 +941,13 @@ msgstr ""
|
||||
#: .\cookbook\templates\ingredient_editor.html:7
|
||||
#: .\cookbook\templates\ingredient_editor.html:13
|
||||
msgid "Ingredient Editor"
|
||||
msgstr ""
|
||||
msgstr "Редактор Інгредієнтів"
|
||||
|
||||
#: .\cookbook\templates\base.html:275
|
||||
#: .\cookbook\templates\export_response.html:7
|
||||
#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
msgstr "Експорт"
|
||||
|
||||
#: .\cookbook\templates\base.html:287
|
||||
msgid "Properties"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.2.18 on 2025-03-14 10:50
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0219_connectorconfig_supports_description_field'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='shoppinglistrecipe',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='shoppinglistrecipe',
|
||||
name='space',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,42 @@
|
||||
# Generated by Django 4.2.18 on 2025-03-14 10:50
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db.models import F, Count
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
|
||||
def add_space_and_owner_to_shopping_list_recipe(apps, schema_editor):
|
||||
print('migrating shopping list recipe space attribute, this might take a while ...')
|
||||
with scopes_disabled():
|
||||
ShoppingListRecipe = apps.get_model('cookbook', 'ShoppingListRecipe')
|
||||
|
||||
# delete all shopping list recipes that do not have entries as those are of no use anyway
|
||||
ShoppingListRecipe.objects.annotate(entry_count=Count('entries')).filter(entry_count__lte=0).delete()
|
||||
|
||||
shopping_list_recipes = ShoppingListRecipe.objects.all().prefetch_related('entries')
|
||||
update_list = []
|
||||
|
||||
for slr in shopping_list_recipes:
|
||||
if entry := slr.entries.first():
|
||||
if entry.space and entry.created_by:
|
||||
slr.space = entry.space
|
||||
slr.created_by = entry.created_by
|
||||
update_list.append(slr)
|
||||
else:
|
||||
print(slr, 'missing data on entry')
|
||||
else:
|
||||
print(slr, 'missing entry')
|
||||
|
||||
ShoppingListRecipe.objects.bulk_update(update_list, ['space', 'created_by'], batch_size=500)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('cookbook', '0220_shoppinglistrecipe_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_space_and_owner_to_shopping_list_recipe),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 4.2.18 on 2025-03-14 12:41
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0221_migrate_shoppinglistrecipe_space_created_by'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='shoppinglistrecipe',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='shoppinglistrecipe',
|
||||
name='space',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.22 on 2025-07-13 19:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0222_alter_shoppinglistrecipe_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='userpreference',
|
||||
name='ingredient_context',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userpreference',
|
||||
name='use_fractions',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
||||
@@ -191,7 +191,7 @@ class TreeModel(MP_Node):
|
||||
|
||||
return queryset.model.objects.filter(id__in=queryset.values_list('id')).exclude(descendants)
|
||||
|
||||
def include_ancestors(queryset=None):
|
||||
def include_ancestors(queryset=None, filter=None):
|
||||
"""
|
||||
:param queryset: Model Queryset to add ancestors
|
||||
:param filter: Filter (include) the ancestors nodes with the provided Q filter
|
||||
@@ -487,6 +487,7 @@ class UserPreference(models.Model, PermissionModelMixin):
|
||||
shopping_recent_days = models.PositiveIntegerField(default=7)
|
||||
csv_delim = models.CharField(max_length=2, default=",")
|
||||
csv_prefix = models.CharField(max_length=10, blank=True, )
|
||||
ingredient_context = models.BooleanField(default=False)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
objects = ScopedManager(space='space')
|
||||
@@ -767,6 +768,22 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
obj.inherit_fields.set(fields)
|
||||
obj.save()
|
||||
|
||||
def get_substitutes(self, onhand=False, shopping_users=None):
|
||||
# filters = ~Q(id=self.id)
|
||||
filters = Q()
|
||||
if self.substitute:
|
||||
filters |= Q(id__in=self.substitute.values('id'))
|
||||
if self.substitute_children:
|
||||
filters |= Q(path__startswith=self.path, depth__gt=self.depth)
|
||||
if self.substitute_siblings:
|
||||
sibling_path = self.path[:Food.steplen * (self.depth - 1)]
|
||||
filters |= Q(path__startswith=sibling_path, depth=self.depth)
|
||||
|
||||
qs = Food.objects.filter(filters).exclude(id=self.id)
|
||||
if onhand:
|
||||
qs = qs.filter(onhand_users__in=shopping_users)
|
||||
return qs
|
||||
|
||||
@staticmethod
|
||||
def reset_inheritance(space=None, food=None):
|
||||
# resets inherited fields to the space defaults and updates all inherited fields to root object values
|
||||
@@ -1179,31 +1196,18 @@ class MealPlan(ExportModelOperationsMixin('meal_plan'), models.Model, Permission
|
||||
|
||||
class ShoppingListRecipe(ExportModelOperationsMixin('shopping_list_recipe'), models.Model, PermissionModelMixin):
|
||||
name = models.CharField(max_length=32, blank=True, default='')
|
||||
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True, blank=True) # TODO make required after old shoppinglist deprecated
|
||||
servings = models.DecimalField(default=1, max_digits=8, decimal_places=4)
|
||||
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True, blank=True)
|
||||
mealplan = models.ForeignKey(MealPlan, on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
objects = ScopedManager(space='recipe__space')
|
||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
|
||||
@staticmethod
|
||||
def get_space_key():
|
||||
return 'recipe', 'space'
|
||||
|
||||
def get_space(self):
|
||||
return self.recipe.space
|
||||
objects = ScopedManager(space='space')
|
||||
|
||||
def __str__(self):
|
||||
return f'Shopping list recipe {self.id} - {self.recipe}'
|
||||
|
||||
def get_owner(self):
|
||||
try:
|
||||
if not self.entries.exists():
|
||||
return 'orphan'
|
||||
else:
|
||||
return getattr(self.entries.first(), 'created_by', None)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
|
||||
class ShoppingListEntry(ExportModelOperationsMixin('shopping_list_entry'), models.Model, PermissionModelMixin):
|
||||
list_recipe = models.ForeignKey(ShoppingListRecipe, on_delete=models.CASCADE, null=True, blank=True, related_name='entries')
|
||||
|
||||
@@ -12,21 +12,25 @@ class Local(Provider):
|
||||
|
||||
@staticmethod
|
||||
def import_all(monitor):
|
||||
if '/etc/' in monitor.path or '/root/' in monitor.path or '/mediafiles/' in monitor.path or '/usr/' in monitor.path:
|
||||
return False
|
||||
|
||||
files = [f for f in listdir(monitor.path) if isfile(join(monitor.path, f))]
|
||||
|
||||
import_count = 0
|
||||
for file in files:
|
||||
path = monitor.path + '/' + file
|
||||
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||
name = os.path.splitext(file)[0]
|
||||
new_recipe = RecipeImport(
|
||||
name=name,
|
||||
file_path=path,
|
||||
storage=monitor.storage,
|
||||
space=monitor.space,
|
||||
)
|
||||
new_recipe.save()
|
||||
import_count += 1
|
||||
if file.endswith('.pdf') or file.endswith('.png') or file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.gif'):
|
||||
path = monitor.path + '/' + file
|
||||
if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists():
|
||||
name = os.path.splitext(file)[0]
|
||||
new_recipe = RecipeImport(
|
||||
name=name,
|
||||
file_path=path,
|
||||
storage=monitor.storage,
|
||||
space=monitor.space,
|
||||
)
|
||||
new_recipe.save()
|
||||
import_count += 1
|
||||
|
||||
log_entry = SyncLog(
|
||||
status='SUCCESS',
|
||||
|
||||
177
cookbook/static/pdfjs/LICENSE
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
0
cookbook/static/pdfjs/LICENSE:Zone.Identifier
Normal file
|
Before Width: | Height: | Size: 193 B |
|
Before Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 199 B |
|
Before Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 326 B |
|
Before Width: | Height: | Size: 326 B |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 403 B |
|
Before Width: | Height: | Size: 933 B |
|
Before Width: | Height: | Size: 179 B |
|
Before Width: | Height: | Size: 266 B |
|
Before Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 583 B |
|
Before Width: | Height: | Size: 175 B |
|
Before Width: | Height: | Size: 276 B |
|
Before Width: | Height: | Size: 360 B |
|
Before Width: | Height: | Size: 731 B |
|
Before Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 349 B |
|
Before Width: | Height: | Size: 297 B |
|
Before Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 347 B |
|
Before Width: | Height: | Size: 694 B |
|
Before Width: | Height: | Size: 179 B |
|
Before Width: | Height: | Size: 261 B |
|
Before Width: | Height: | Size: 344 B |
|
Before Width: | Height: | Size: 621 B |
|
Before Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 174 B |
|
Before Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 425 B |
|
Before Width: | Height: | Size: 107 B |
|
Before Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 238 B |
|
Before Width: | Height: | Size: 396 B |
|
Before Width: | Height: | Size: 246 B |
|
Before Width: | Height: | Size: 403 B |
|
Before Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 464 B |