Compare commits
400 Commits
feat/effic
...
feat/remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0230ccf3b | ||
|
|
224bb46b4a | ||
|
|
ad0b96a1e5 | ||
|
|
38226fd240 | ||
|
|
f193c5a53f | ||
|
|
debc35a4d5 | ||
|
|
5de76dbaee | ||
|
|
d4b110fc47 | ||
|
|
f7acf1886c | ||
|
|
ba0cfb76ed | ||
|
|
cee6bcc5ef | ||
|
|
b2f3bf7079 | ||
|
|
fe416b121c | ||
|
|
35b62cd016 | ||
|
|
b33e8abcdd | ||
|
|
0be71c82b3 | ||
|
|
a582d3a03e | ||
|
|
6609e70fa8 | ||
|
|
7a0107fc79 | ||
|
|
0bbeb20595 | ||
|
|
afc4085b55 | ||
|
|
02569d52f0 | ||
|
|
aaeac2ab73 | ||
|
|
de57fecb69 | ||
|
|
1e0b4fac04 | ||
|
|
34339ea69f | ||
|
|
6da039780e | ||
|
|
3f2e0780d5 | ||
|
|
52363cf0fb | ||
|
|
86df09a0e4 | ||
|
|
e1e24f3d60 | ||
|
|
33d76fb386 | ||
|
|
642065f506 | ||
|
|
de897f6069 | ||
|
|
68f3ed89c5 | ||
|
|
78516a97b3 | ||
|
|
b8a17c3c26 | ||
|
|
e42886b767 | ||
|
|
d36c26bf97 | ||
|
|
dcbc266b83 | ||
|
|
c37d13691b | ||
|
|
9ae42106cc | ||
|
|
28e9892ed3 | ||
|
|
532ec10d5f | ||
|
|
2411bf8374 | ||
|
|
0b60cc8965 | ||
|
|
2d816e89ad | ||
|
|
eee94207ce | ||
|
|
dfa38ec3ef | ||
|
|
edc0698e2a | ||
|
|
0e987352bb | ||
|
|
98ea3847e5 | ||
|
|
53c67f4d71 | ||
|
|
20733bd7df | ||
|
|
11e72a0f35 | ||
|
|
53a6724039 | ||
|
|
0b20d1df9f | ||
|
|
6bb8903b05 | ||
|
|
26e0cb3eb4 | ||
|
|
a8f683ed15 | ||
|
|
4dfa011eef | ||
|
|
0c0bec6ae2 | ||
|
|
61c3f27fdc | ||
|
|
b2ca208dbb | ||
|
|
2e945281fc | ||
|
|
9ac120c772 | ||
|
|
e6e8ae7c74 | ||
|
|
29fd981587 | ||
|
|
585b74f233 | ||
|
|
f118bb7e08 | ||
|
|
1710230d61 | ||
|
|
2012b07645 | ||
|
|
a88a9a7d5e | ||
|
|
ae539dfdf3 | ||
|
|
69bb8d834f | ||
|
|
9693d07a8b | ||
|
|
453b30069d | ||
|
|
c9daefccc4 | ||
|
|
6ffd8e679e | ||
|
|
7fe2f19258 | ||
|
|
dac545496e | ||
|
|
d5b112be53 | ||
|
|
75322179fd | ||
|
|
3f4b6a8e7c | ||
|
|
7ce1d73c20 | ||
|
|
2bf484c91c | ||
|
|
4e9bdd5e6c | ||
|
|
f05ef81c4f | ||
|
|
c21860fb97 | ||
|
|
449368eee7 | ||
|
|
31e098517d | ||
|
|
b9e2590752 | ||
|
|
41641ec000 | ||
|
|
8821c251c3 | ||
|
|
1d6b98ff86 | ||
|
|
4d00261bc1 | ||
|
|
df7ea4d8ea | ||
|
|
1e7cb1165f | ||
|
|
d9ef041b87 | ||
|
|
87a172ab0c | ||
|
|
9e0553e0c4 | ||
|
|
a7addfece8 | ||
|
|
fda215f97f | ||
|
|
5fad1fd899 | ||
|
|
880f2bc2c5 | ||
|
|
0f79e0c38e | ||
|
|
5fb0afb0d0 | ||
|
|
4f4a50ac11 | ||
|
|
3d883b27aa | ||
|
|
01fddd58c6 | ||
|
|
81eb5ab40d | ||
|
|
8d849d226d | ||
|
|
a9b82a8e32 | ||
|
|
cc9e07401f | ||
|
|
9b5f3552c0 | ||
|
|
a52a3247d7 | ||
|
|
c86c957860 | ||
|
|
eb15a2725a | ||
|
|
b394046d2a | ||
|
|
859b2451bb | ||
|
|
b79a2eb6b9 | ||
|
|
ee96b285f2 | ||
|
|
77340075f0 | ||
|
|
5c06ec5e0b | ||
|
|
dcee34095b | ||
|
|
15f182902f | ||
|
|
b26b452530 | ||
|
|
2dcb32f7d0 | ||
|
|
27d2f3efe2 | ||
|
|
d38468439b | ||
|
|
0166e99d90 | ||
|
|
71e33e35dc | ||
|
|
a122d4b969 | ||
|
|
dad81af6e3 | ||
|
|
ac6b42e1e8 | ||
|
|
4059638151 | ||
|
|
1823a28e59 | ||
|
|
b6bf1852cd | ||
|
|
cdc26f2c7b | ||
|
|
913b3789cc | ||
|
|
994a770921 | ||
|
|
17bbcdf584 | ||
|
|
23aa661324 | ||
|
|
a10a946d1a | ||
|
|
04c9531624 | ||
|
|
d84cc450f1 | ||
|
|
4153848c68 | ||
|
|
f29230c8a6 | ||
|
|
03af60e8eb | ||
|
|
ae827e1406 | ||
|
|
7893ac25fb | ||
|
|
42a03f2556 | ||
|
|
722a464e23 | ||
|
|
39c1ebf698 | ||
|
|
ef6e4f4699 | ||
|
|
0700e61d20 | ||
|
|
7e6cd48783 | ||
|
|
e524c59560 | ||
|
|
b4c72fb609 | ||
|
|
74e14b6495 | ||
|
|
03207a13ec | ||
|
|
529b8c285d | ||
|
|
1213f6df10 | ||
|
|
9e8132c363 | ||
|
|
2d2673c114 | ||
|
|
56e5236a39 | ||
|
|
8529f92ebc | ||
|
|
761ac074c9 | ||
|
|
7e377d3e42 | ||
|
|
f7d9215464 | ||
|
|
9af44fbd69 | ||
|
|
170306af1a | ||
|
|
417d3bbf50 | ||
|
|
e239b8d2fa | ||
|
|
2c7b980eed | ||
|
|
9a5a3c0a1d | ||
|
|
027dab1487 | ||
|
|
e18e4c5962 | ||
|
|
67a8cab286 | ||
|
|
39eee6a634 | ||
|
|
ee98e69097 | ||
|
|
41c1d4d44b | ||
|
|
b21084b851 | ||
|
|
8bf45eb718 | ||
|
|
9d3ca3ad3f | ||
|
|
0090b9db4a | ||
|
|
bee0ae430a | ||
|
|
cc08ebdf80 | ||
|
|
71578b76a7 | ||
|
|
8e5d52abbb | ||
|
|
e52cc259d5 | ||
|
|
00c88b2636 | ||
|
|
e95096d14f | ||
|
|
4c918254b9 | ||
|
|
b97d73d7a7 | ||
|
|
2801b0953d | ||
|
|
7a1c45c364 | ||
|
|
5acd6b70d0 | ||
|
|
edaedca03f | ||
|
|
7b3e1037b6 | ||
|
|
27bc8eba7b | ||
|
|
23fb2e0fae | ||
|
|
59accbf32a | ||
|
|
059a0e8aa8 | ||
|
|
6a55c36762 | ||
|
|
c0bff4b493 | ||
|
|
fd4c2acde8 | ||
|
|
5acf909235 | ||
|
|
fb1458c720 | ||
|
|
255dabc239 | ||
|
|
27751f8fd4 | ||
|
|
72ffa37dd9 | ||
|
|
5a7042364b | ||
|
|
db0ea0f3a8 | ||
|
|
88c0243a20 | ||
|
|
3a29522df6 | ||
|
|
50eae23f3a | ||
|
|
95419750bb | ||
|
|
5fb858a865 | ||
|
|
18084a49ec | ||
|
|
f107cb044a | ||
|
|
f4e7ea47a6 | ||
|
|
8747fc4935 | ||
|
|
287fa79d75 | ||
|
|
bcfb5bee1f | ||
|
|
538263dc38 | ||
|
|
51aec1e93d | ||
|
|
53825cc3d6 | ||
|
|
6e7c2817a3 | ||
|
|
7bd79b551c | ||
|
|
5fe954b3c9 | ||
|
|
7f81a5bd6f | ||
|
|
37a79292c0 | ||
|
|
bf6211776f | ||
|
|
6c178a04dc | ||
|
|
036d314cb6 | ||
|
|
1fc5da398a | ||
|
|
4d84338086 | ||
|
|
0ac49b00ee | ||
|
|
e427778a96 | ||
|
|
b82e29fbb4 | ||
|
|
ff19aea4ac | ||
|
|
28179a3a1d | ||
|
|
af1e18d07e | ||
|
|
270a0ff986 | ||
|
|
9d3f10372d | ||
|
|
2f1385a236 | ||
|
|
183a285584 | ||
|
|
5ce946bb5b | ||
|
|
674faf2e57 | ||
|
|
4f7702c6bf | ||
|
|
28edf5664d | ||
|
|
ec2f94cae8 | ||
|
|
873f7921da | ||
|
|
f06b054087 | ||
|
|
0df910c0cd | ||
|
|
5b8d72e91a | ||
|
|
e7b0a47be2 | ||
|
|
60af3a4003 | ||
|
|
6a4b6699e3 | ||
|
|
7d57fd1320 | ||
|
|
bbc1c8186c | ||
|
|
b76d69c0e5 | ||
|
|
fd2b7a344c | ||
|
|
03dafba522 | ||
|
|
f15376a107 | ||
|
|
32955915dd | ||
|
|
aacb27ea5f | ||
|
|
d6b8c0926f | ||
|
|
225af973c1 | ||
|
|
b3372064e0 | ||
|
|
303307e1ac | ||
|
|
f75c9dfe37 | ||
|
|
f5954f4c9b | ||
|
|
147accd957 | ||
|
|
9487241481 | ||
|
|
460e1d4715 | ||
|
|
b6223af5ca | ||
|
|
8853079c54 | ||
|
|
662d44536e | ||
|
|
80fa5ec198 | ||
|
|
0df88fc22b | ||
|
|
e78144ea31 | ||
|
|
227789225a | ||
|
|
1298a74230 | ||
|
|
a3808c26ce | ||
|
|
e2169f5316 | ||
|
|
f65dabd43a | ||
|
|
a5841a8bf4 | ||
|
|
dc6ac3aaec | ||
|
|
ae104ad7cc | ||
|
|
868d5f56e2 | ||
|
|
88072910da | ||
|
|
25a94bd117 | ||
|
|
76eaee3657 | ||
|
|
d5fec0edab | ||
|
|
a7821a0b79 | ||
|
|
73e67ebfea | ||
|
|
0eaa054218 | ||
|
|
2024d06cb7 | ||
|
|
204299d500 | ||
|
|
70e59c00d5 | ||
|
|
5405810a38 | ||
|
|
e67265cef2 | ||
|
|
19c53609e1 | ||
|
|
0d0bb0e2d9 | ||
|
|
8f1b505ba0 | ||
|
|
d04675fb41 | ||
|
|
acfd40b77a | ||
|
|
840e43430c | ||
|
|
a3e0c6cef5 | ||
|
|
63088b22e0 | ||
|
|
d9d8beb92f | ||
|
|
38a8a67be9 | ||
|
|
7531ffcbfb | ||
|
|
d5f3629c49 | ||
|
|
be5b4cb1d1 | ||
|
|
5fb8d651ec | ||
|
|
c2313f7a99 | ||
|
|
59627e2b4c | ||
|
|
530bf059ad | ||
|
|
b44d2a241d | ||
|
|
1af10ded74 | ||
|
|
3f1e11afcc | ||
|
|
28dce2d0df | ||
|
|
605764f226 | ||
|
|
44e1c83c84 | ||
|
|
0729887c9c | ||
|
|
3bfa8b7575 | ||
|
|
3138048b96 | ||
|
|
f8b41ea8aa | ||
|
|
1d33ed6bed | ||
|
|
2be1a58c5b | ||
|
|
03e7922589 | ||
|
|
801af34d9a | ||
|
|
bedaa729e9 | ||
|
|
13c8a6e61d | ||
|
|
01edf6533b | ||
|
|
30d0bea4df | ||
|
|
571504aa5e | ||
|
|
65fafcab37 | ||
|
|
2fe0d17fe1 | ||
|
|
b6a91746d8 | ||
|
|
89533a858f | ||
|
|
dc5a0f8c33 | ||
|
|
c443ab854c | ||
|
|
379c73818a | ||
|
|
73bb05c5f9 | ||
|
|
b69470c69e | ||
|
|
34255453b1 | ||
|
|
4e03b06ff7 | ||
|
|
9bb211f56f | ||
|
|
6f4f79d8cc | ||
|
|
ed3997d844 | ||
|
|
fb59fa343d | ||
|
|
ab2849781a | ||
|
|
66c657ca8a | ||
|
|
c245208106 | ||
|
|
99d6673503 | ||
|
|
9ff37b6870 | ||
|
|
0e7816130b | ||
|
|
a1beb0a87d | ||
|
|
c4ac2e345f | ||
|
|
f422b341d1 | ||
|
|
90538d2535 | ||
|
|
abc7bfa0ba | ||
|
|
60a809d7b4 | ||
|
|
cda7249a6a | ||
|
|
47566c1a4a | ||
|
|
f08002d48f | ||
|
|
7186914531 | ||
|
|
d38ab93484 | ||
|
|
845b0f2073 | ||
|
|
acb1e513a7 | ||
|
|
4d4e54967d | ||
|
|
e2dcebfe6c | ||
|
|
d4f2b43f64 | ||
|
|
f343b0e58f | ||
|
|
a8b4a5e856 | ||
|
|
e7e030279b | ||
|
|
9ff664ed36 | ||
|
|
e00556a34a | ||
|
|
a313e4338e | ||
|
|
257b0c74af | ||
|
|
3d515f5072 | ||
|
|
ec01db5c8b | ||
|
|
cd6d8fcdfe | ||
|
|
1198311d64 | ||
|
|
1a4eab9655 | ||
|
|
1926c90780 | ||
|
|
4d5975b717 | ||
|
|
8cbd6b29c4 | ||
|
|
8c1b630a2b | ||
|
|
c961d2aaf7 | ||
|
|
41c75dc93e | ||
|
|
f92247c99b | ||
|
|
53f9fc2d1c | ||
|
|
bede19a3ca | ||
|
|
aefa62b234 | ||
|
|
b3fb831994 |
@@ -12,7 +12,6 @@ services:
|
|||||||
- server_node_modules:/workspaces/immich/server/node_modules
|
- server_node_modules:/workspaces/immich/server/node_modules
|
||||||
- web_node_modules:/workspaces/immich/web/node_modules
|
- web_node_modules:/workspaces/immich/web/node_modules
|
||||||
- ${UPLOAD_LOCATION}/photos:/data
|
- ${UPLOAD_LOCATION}/photos:/data
|
||||||
- ${UPLOAD_LOCATION}/photos/upload:/data/upload
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
database:
|
database:
|
||||||
|
|||||||
@@ -49,10 +49,11 @@ fix_permissions() {
|
|||||||
|
|
||||||
log "Fixing permissions for ${IMMICH_WORKSPACE}"
|
log "Fixing permissions for ${IMMICH_WORKSPACE}"
|
||||||
|
|
||||||
run_cmd sudo find "${IMMICH_WORKSPACE}/server/upload" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres/*" -not -path "${IMMICH_WORKSPACE}/server/upload/postgres" -exec chown node {} +
|
|
||||||
|
|
||||||
# Change ownership for directories that exist
|
# Change ownership for directories that exist
|
||||||
for dir in "${IMMICH_WORKSPACE}/.vscode" \
|
for dir in "${IMMICH_WORKSPACE}/.vscode" \
|
||||||
|
"${IMMICH_WORKSPACE}/server/upload" \
|
||||||
|
"${IMMICH_WORKSPACE}/.pnpm-store" \
|
||||||
|
"${IMMICH_WORKSPACE}/.github/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/cli/node_modules" \
|
"${IMMICH_WORKSPACE}/cli/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/e2e/node_modules" \
|
"${IMMICH_WORKSPACE}/e2e/node_modules" \
|
||||||
"${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \
|
"${IMMICH_WORKSPACE}/open-api/typescript-sdk/node_modules" \
|
||||||
|
|||||||
@@ -8,21 +8,23 @@ services:
|
|||||||
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
|
- IMMICH_SERVER_URL=http://127.0.0.1:2283/
|
||||||
volumes: !override
|
volumes: !override
|
||||||
- ..:/workspaces/immich
|
- ..:/workspaces/immich
|
||||||
- cli_node_modules:/workspaces/immich/cli/node_modules
|
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
||||||
- e2e_node_modules:/workspaces/immich/e2e/node_modules
|
|
||||||
- open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules
|
|
||||||
- server_node_modules:/workspaces/immich/server/node_modules
|
|
||||||
- web_node_modules:/workspaces/immich/web/node_modules
|
|
||||||
- ${UPLOAD_LOCATION:-upload1-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
|
||||||
- ${UPLOAD_LOCATION:-upload2-devcontainer-volume}${UPLOAD_LOCATION:+/photos/upload}:/data/upload
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- pnpm-store:/usr/src/app/.pnpm-store
|
||||||
|
- server-node_modules:/usr/src/app/server/node_modules
|
||||||
|
- web-node_modules:/usr/src/app/web/node_modules
|
||||||
|
- github-node_modules:/usr/src/app/.github/node_modules
|
||||||
|
- cli-node_modules:/usr/src/app/cli/node_modules
|
||||||
|
- docs-node_modules:/usr/src/app/docs/node_modules
|
||||||
|
- e2e-node_modules:/usr/src/app/e2e/node_modules
|
||||||
|
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
|
||||||
|
- app-node_modules:/usr/src/app/node_modules
|
||||||
|
- sveltekit:/usr/src/app/web/.svelte-kit
|
||||||
|
- coverage:/usr/src/app/web/coverage
|
||||||
immich-web:
|
immich-web:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
|
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
|
|
||||||
database:
|
database:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
environment: !override
|
environment: !override
|
||||||
@@ -33,17 +35,8 @@ services:
|
|||||||
POSTGRES_HOST_AUTH_METHOD: md5
|
POSTGRES_HOST_AUTH_METHOD: md5
|
||||||
volumes:
|
volumes:
|
||||||
- ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data
|
- ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# Node modules for each service to avoid conflicts and ensure consistent dependencies
|
upload-devcontainer-volume:
|
||||||
cli_node_modules:
|
|
||||||
e2e_node_modules:
|
|
||||||
open_api_node_modules:
|
|
||||||
server_node_modules:
|
|
||||||
web_node_modules:
|
|
||||||
upload1-devcontainer-volume:
|
|
||||||
upload2-devcontainer-volume:
|
|
||||||
postgres-devcontainer-volume:
|
postgres-devcontainer-volume:
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
source /immich-devcontainer/container-common.sh
|
source /immich-devcontainer/container-common.sh
|
||||||
|
|
||||||
|
log "Preparing Immich Nest API Server"
|
||||||
|
log ""
|
||||||
|
export CI=1
|
||||||
|
run_cmd pnpm --filter immich install
|
||||||
|
|
||||||
log "Starting Nest API Server"
|
log "Starting Nest API Server"
|
||||||
log ""
|
log ""
|
||||||
cd "${IMMICH_WORKSPACE}/server" || (
|
cd "${IMMICH_WORKSPACE}/server" || (
|
||||||
@@ -11,7 +16,7 @@ cd "${IMMICH_WORKSPACE}/server" || (
|
|||||||
)
|
)
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
run_cmd node ./node_modules/.bin/nest start --debug "0.0.0.0:9230" --watch
|
run_cmd pnpm --filter immich exec nest start --debug "0.0.0.0:9230" --watch
|
||||||
log "Nest API Server crashed with exit code $?. Respawning in 3s ..."
|
log "Nest API Server crashed with exit code $?. Respawning in 3s ..."
|
||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -3,6 +3,13 @@
|
|||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
source /immich-devcontainer/container-common.sh
|
source /immich-devcontainer/container-common.sh
|
||||||
|
|
||||||
|
export CI=1
|
||||||
|
log "Preparing Immich Web Frontend"
|
||||||
|
log ""
|
||||||
|
run_cmd pnpm --filter @immich/sdk install
|
||||||
|
run_cmd pnpm --filter @immich/sdk build
|
||||||
|
run_cmd pnpm --filter immich-web install
|
||||||
|
|
||||||
log "Starting Immich Web Frontend"
|
log "Starting Immich Web Frontend"
|
||||||
log ""
|
log ""
|
||||||
cd "${IMMICH_WORKSPACE}/web" || (
|
cd "${IMMICH_WORKSPACE}/web" || (
|
||||||
@@ -16,7 +23,7 @@ until curl --output /dev/null --silent --head --fail "http://127.0.0.1:${IMMICH_
|
|||||||
done
|
done
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
run_cmd node ./node_modules/.bin/vite dev --host 0.0.0.0 --port "${DEV_PORT}"
|
run_cmd pnpm --filter immich-web exec vite dev --host 0.0.0.0 --port "${DEV_PORT}"
|
||||||
log "Web crashed with exit code $?. Respawning in 3s ..."
|
log "Web crashed with exit code $?. Respawning in 3s ..."
|
||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ source /immich-devcontainer/container-common.sh
|
|||||||
log "Setting up Immich dev container..."
|
log "Setting up Immich dev container..."
|
||||||
fix_permissions
|
fix_permissions
|
||||||
|
|
||||||
log "Installing npm dependencies (node_modules)..."
|
|
||||||
install_dependencies
|
|
||||||
|
|
||||||
log "Setup complete, please wait while backend and frontend services automatically start"
|
log "Setup complete, please wait while backend and frontend services automatically start"
|
||||||
log
|
log
|
||||||
log "If necessary, the services may be manually started using"
|
log "If necessary, the services may be manually started using"
|
||||||
|
|||||||
2
.github/.nvmrc
vendored
2
.github/.nvmrc
vendored
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
5
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
5
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -64,6 +64,11 @@ body:
|
|||||||
- label: Web
|
- label: Web
|
||||||
- label: Mobile
|
- label: Mobile
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Device make and model
|
||||||
|
placeholder: Samsung S25 Android 16
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
1
.github/labeler.yml
vendored
1
.github/labeler.yml
vendored
@@ -6,7 +6,6 @@ cli:
|
|||||||
documentation:
|
documentation:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- docs/blob/**
|
|
||||||
- docs/docs/**
|
- docs/docs/**
|
||||||
- docs/src/**
|
- docs/src/**
|
||||||
- docs/static/**
|
- docs/static/**
|
||||||
|
|||||||
28
.github/package-lock.json
generated
vendored
28
.github/package-lock.json
generated
vendored
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"name": ".github",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"devDependencies": {
|
|
||||||
"prettier": "^3.5.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/prettier": {
|
|
||||||
"version": "3.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
|
|
||||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"prettier": "bin/prettier.cjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@@ -34,3 +34,7 @@ The `/api/something` endpoint is now `/api/something-else`
|
|||||||
- [ ] I have followed naming conventions/patterns in the surrounding code
|
- [ ] I have followed naming conventions/patterns in the surrounding code
|
||||||
- [ ] All code in `src/services/` uses repositories implementations for database calls, filesystem operations, etc.
|
- [ ] All code in `src/services/` uses repositories implementations for database calls, filesystem operations, etc.
|
||||||
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services/`)
|
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services/`)
|
||||||
|
|
||||||
|
## Please describe to which degree, if any, an LLM was used in creating this pull request.
|
||||||
|
|
||||||
|
...
|
||||||
|
|||||||
30
.github/workflows/build-mobile.yml
vendored
30
.github/workflows/build-mobile.yml
vendored
@@ -32,24 +32,18 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
mobile:
|
mobile:
|
||||||
- 'mobile/**'
|
- 'mobile/**'
|
||||||
workflow:
|
force-filters: |
|
||||||
- '.github/workflows/build-mobile.yml'
|
- '.github/workflows/build-mobile.yml'
|
||||||
- name: Check if we should force jobs to run
|
force-events: 'workflow_call,workflow_dispatch'
|
||||||
id: should_force
|
|
||||||
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
build-sign-android:
|
build-sign-android:
|
||||||
name: Build and sign Android
|
name: Build and sign Android
|
||||||
@@ -57,11 +51,11 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
# Skip when PR from a fork
|
# Skip when PR from a fork
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||||
runs-on: mich
|
runs-on: mich
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
ref: ${{ inputs.ref || github.sha }}
|
ref: ${{ inputs.ref || github.sha }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
@@ -79,7 +73,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Restore Gradle Cache
|
- name: Restore Gradle Cache
|
||||||
id: cache-gradle-restore
|
id: cache-gradle-restore
|
||||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
@@ -106,7 +100,7 @@ jobs:
|
|||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Generate translation file
|
- name: Generate translation file
|
||||||
run: make translation
|
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
- name: Generate platform APIs
|
- name: Generate platform APIs
|
||||||
@@ -136,7 +130,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Save Gradle Cache
|
- name: Save Gradle Cache
|
||||||
id: cache-gradle-save
|
id: cache-gradle-save
|
||||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4
|
uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
2
.github/workflows/cache-cleanup.yml
vendored
2
.github/workflows/cache-cleanup.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
actions: write
|
actions: write
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|||||||
33
.github/workflows/cli.yml
vendored
33
.github/workflows/cli.yml
vendored
@@ -29,25 +29,28 @@ jobs:
|
|||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
# Setup .npmrc file to publish to npm
|
- name: Setup pnpm
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Prepare SDK
|
- name: Setup typescript-sdk
|
||||||
run: npm ci --prefix ../open-api/typescript-sdk/
|
run: pnpm install && pnpm run build
|
||||||
- name: Build SDK
|
working-directory: ./open-api/typescript-sdk
|
||||||
run: npm run build --prefix ../open-api/typescript-sdk/
|
|
||||||
- run: npm ci
|
- run: pnpm install --frozen-lockfile
|
||||||
- run: npm run build
|
- run: pnpm build
|
||||||
- run: npm publish
|
- run: pnpm publish
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
@@ -62,7 +65,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
@@ -73,7 +76,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -88,7 +91,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: metadata
|
id: metadata
|
||||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=false
|
latest=false
|
||||||
|
|||||||
29
.github/workflows/close-duplicates.yml
vendored
29
.github/workflows/close-duplicates.yml
vendored
@@ -8,8 +8,18 @@ name: Close likely duplicates
|
|||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
should_run:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
should_run: ${{ steps.should_run.outputs.run }}
|
||||||
|
steps:
|
||||||
|
- id: should_run
|
||||||
|
run: echo "run=${{ github.event_name == 'issues' || github.event.discussion.category.name == 'Feature Request' }}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
get_body:
|
get_body:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: should_run
|
||||||
|
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
||||||
env:
|
env:
|
||||||
EVENT: ${{ toJSON(github.event) }}
|
EVENT: ${{ toJSON(github.event) }}
|
||||||
outputs:
|
outputs:
|
||||||
@@ -22,23 +32,24 @@ jobs:
|
|||||||
|
|
||||||
get_checkbox_json:
|
get_checkbox_json:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: get_body
|
needs: [get_body, should_run]
|
||||||
|
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
||||||
container:
|
container:
|
||||||
image: yshavit/mdq:0.7.2
|
image: ghcr.io/immich-app/mdq:main@sha256:d8ae47cf2e6cf4e2559bd57a60b73674fe44f897cba2c2bddff2987a05be10a4
|
||||||
outputs:
|
outputs:
|
||||||
json: ${{ steps.get_checkbox.outputs.json }}
|
checked: ${{ steps.get_checkbox.outputs.checked }}
|
||||||
steps:
|
steps:
|
||||||
- id: get_checkbox
|
- id: get_checkbox
|
||||||
env:
|
env:
|
||||||
BODY: ${{ needs.get_body.outputs.body }}
|
BODY: ${{ needs.get_body.outputs.body }}
|
||||||
run: |
|
run: |
|
||||||
JSON=$(echo "$BODY" | base64 -d | /mdq --output json '# I have searched | - [?] Yes')
|
CHECKED=$(echo "$BODY" | base64 -d | /mdq --output json '# I have searched | - [?] Yes' | jq '.items[0].list[0].checked // false')
|
||||||
echo "json=$JSON" >> $GITHUB_OUTPUT
|
echo "checked=$CHECKED" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
close_and_comment:
|
close_and_comment:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: get_checkbox_json
|
needs: [get_checkbox_json, should_run]
|
||||||
if: ${{ !fromJSON(needs.get_checkbox_json.outputs.json).items[0].list[0].checked }}
|
if: ${{ needs.should_run.outputs.should_run == 'true' && needs.get_checkbox_json.outputs.checked != 'true' }}
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
discussions: write
|
discussions: write
|
||||||
@@ -51,7 +62,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gh api graphql \
|
gh api graphql \
|
||||||
-f issueId="$NODE_ID" \
|
-f issueId="$NODE_ID" \
|
||||||
-f body="This issue has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one." \
|
-f body="This issue has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one. If you're sure this is not a duplicate, please leave a comment and we will reopen the thread if necessary." \
|
||||||
-f query='
|
-f query='
|
||||||
mutation CommentAndCloseIssue($issueId: ID!, $body: String!) {
|
mutation CommentAndCloseIssue($issueId: ID!, $body: String!) {
|
||||||
addComment(input: {
|
addComment(input: {
|
||||||
@@ -77,7 +88,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gh api graphql \
|
gh api graphql \
|
||||||
-f discussionId="$NODE_ID" \
|
-f discussionId="$NODE_ID" \
|
||||||
-f body="This discussion has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one." \
|
-f body="This discussion has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one. If you're sure this is not a duplicate, please leave a comment and we will reopen the thread if necessary." \
|
||||||
-f query='
|
-f query='
|
||||||
mutation CommentAndCloseDiscussion($discussionId: ID!, $body: String!) {
|
mutation CommentAndCloseDiscussion($discussionId: ID!, $body: String!) {
|
||||||
addDiscussionComment(input: {
|
addDiscussionComment(input: {
|
||||||
|
|||||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -44,13 +44,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -76,6 +76,6 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|||||||
37
.github/workflows/docker.yml
vendored
37
.github/workflows/docker.yml
vendored
@@ -20,15 +20,11 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
server:
|
server:
|
||||||
@@ -38,14 +34,11 @@ jobs:
|
|||||||
- 'i18n/**'
|
- 'i18n/**'
|
||||||
machine-learning:
|
machine-learning:
|
||||||
- 'machine-learning/**'
|
- 'machine-learning/**'
|
||||||
workflow:
|
force-filters: |
|
||||||
- '.github/workflows/docker.yml'
|
- '.github/workflows/docker.yml'
|
||||||
- '.github/workflows/multi-runner-build.yml'
|
- '.github/workflows/multi-runner-build.yml'
|
||||||
- '.github/actions/image-build'
|
- '.github/actions/image-build'
|
||||||
|
force-events: 'workflow_dispatch,release'
|
||||||
- name: Check if we should force jobs to run
|
|
||||||
id: should_force
|
|
||||||
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
retag_ml:
|
retag_ml:
|
||||||
name: Re-Tag ML
|
name: Re-Tag ML
|
||||||
@@ -53,14 +46,14 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
if: ${{ needs.pre-job.outputs.should_run_ml == 'false' && !github.event.pull_request.head.repo.fork }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -82,14 +75,14 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
if: ${{ needs.pre-job.outputs.should_run_server == 'false' && !github.event.pull_request.head.repo.fork }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
suffix: ['']
|
suffix: ['']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -108,7 +101,7 @@ jobs:
|
|||||||
machine-learning:
|
machine-learning:
|
||||||
name: Build and Push ML
|
name: Build and Push ML
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -153,7 +146,7 @@ jobs:
|
|||||||
server:
|
server:
|
||||||
name: Build and Push Server
|
name: Build and Push Server
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
|
||||||
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1
|
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
39
.github/workflows/docs-build.yml
vendored
39
.github/workflows/docs-build.yml
vendored
@@ -18,32 +18,28 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.found_paths.outputs.open-api == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
docs:
|
docs:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
workflow:
|
|
||||||
- '.github/workflows/docs-build.yml'
|
|
||||||
open-api:
|
open-api:
|
||||||
- 'open-api/immich-openapi-specs.json'
|
- 'open-api/immich-openapi-specs.json'
|
||||||
- name: Check if we should force jobs to run
|
force-filters: |
|
||||||
id: should_force
|
- '.github/workflows/docs-build.yml'
|
||||||
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' || github.ref_name == 'main' }}" >> "$GITHUB_OUTPUT"
|
force-events: 'release'
|
||||||
|
force-branches: 'main'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Docs Build
|
name: Docs Build
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).docs == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -51,25 +47,28 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './docs/.nvmrc'
|
node-version-file: './docs/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run install
|
||||||
run: npm ci
|
run: pnpm install
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
|
|
||||||
- name: Run build
|
- name: Run build
|
||||||
run: npm run build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Upload build output
|
- name: Upload build output
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
|||||||
10
.github/workflows/docs-deploy.yml
vendored
10
.github/workflows/docs-deploy.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
run: echo 'The triggering workflow did not succeed' && exit 1
|
run: echo 'The triggering workflow did not succeed' && exit 1
|
||||||
- name: Get artifact
|
- name: Get artifact
|
||||||
id: get-artifact
|
id: get-artifact
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
return { found: true, id: matchArtifact.id };
|
return { found: true, id: matchArtifact.id };
|
||||||
- name: Determine deploy parameters
|
- name: Determine deploy parameters
|
||||||
id: parameters
|
id: parameters
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
env:
|
env:
|
||||||
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||||
with:
|
with:
|
||||||
@@ -108,13 +108,13 @@ jobs:
|
|||||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Load parameters
|
- name: Load parameters
|
||||||
id: parameters
|
id: parameters
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
env:
|
env:
|
||||||
PARAM_JSON: ${{ needs.checks.outputs.parameters }}
|
PARAM_JSON: ${{ needs.checks.outputs.parameters }}
|
||||||
with:
|
with:
|
||||||
@@ -125,7 +125,7 @@ jobs:
|
|||||||
core.setOutput("shouldDeploy", parameters.shouldDeploy);
|
core.setOutput("shouldDeploy", parameters.shouldDeploy);
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
env:
|
env:
|
||||||
ARTIFACT_JSON: ${{ needs.checks.outputs.artifact }}
|
ARTIFACT_JSON: ${{ needs.checks.outputs.artifact }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
2
.github/workflows/docs-destroy.yml
vendored
2
.github/workflows/docs-destroy.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|||||||
13
.github/workflows/fix-format.yml
vendored
13
.github/workflows/fix-format.yml
vendored
@@ -16,24 +16,27 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Fix formatting
|
- name: Fix formatting
|
||||||
run: make install-all && make format-all
|
run: make install-all && make format-all
|
||||||
@@ -45,7 +48,7 @@ jobs:
|
|||||||
message: 'chore: fix formatting'
|
message: 'chore: fix formatting'
|
||||||
|
|
||||||
- name: Remove label
|
- name: Remove label
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
|
|||||||
128
.github/workflows/merge-translations.yml
vendored
Normal file
128
.github/workflows/merge-translations.yml
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
name: Merge translations
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
secrets:
|
||||||
|
PUSH_O_MATIC_APP_ID:
|
||||||
|
required: true
|
||||||
|
PUSH_O_MATIC_APP_KEY:
|
||||||
|
required: true
|
||||||
|
WEBLATE_TOKEN:
|
||||||
|
required: true
|
||||||
|
inputs:
|
||||||
|
skip:
|
||||||
|
description: 'Skip translations'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
env:
|
||||||
|
WEBLATE_HOST: 'https://hosted.weblate.org'
|
||||||
|
WEBLATE_COMPONENT: 'immich/immich'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- name: Find translation PR
|
||||||
|
id: find_pr
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PR=$(gh pr list --repo $GITHUB_REPOSITORY --author weblate --json number,mergeable)
|
||||||
|
echo "$PR"
|
||||||
|
|
||||||
|
PR_NUMBER=$(echo "$PR" | jq '
|
||||||
|
if length == 1 then
|
||||||
|
.[0].number
|
||||||
|
else
|
||||||
|
error("Expected exactly 1 entry, got \(length)")
|
||||||
|
end
|
||||||
|
' 2>&1) || exit 1
|
||||||
|
|
||||||
|
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
echo "Selected PR $PR_NUMBER"
|
||||||
|
|
||||||
|
if ! echo "$PR" | jq -e '.[0].mergeable == "MERGEABLE"'; then
|
||||||
|
echo "PR is not mergeable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Generate a token
|
||||||
|
id: generate_token
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
|
- name: Lock weblate
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=true
|
||||||
|
|
||||||
|
- name: Commit translations
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=commit
|
||||||
|
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=push
|
||||||
|
|
||||||
|
- name: Merge PR
|
||||||
|
id: merge_pr
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||||
|
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REVIEW_ID=$(gh api -X POST "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" --field event='APPROVE' --field body='Automatically merging translations PR' \
|
||||||
|
| jq '.id')
|
||||||
|
echo "REVIEW_ID=$REVIEW_ID" >> $GITHUB_OUTPUT
|
||||||
|
gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --auto --squash
|
||||||
|
|
||||||
|
- name: Wait for PR to merge
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||||
|
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
|
||||||
|
REVIEW_ID: ${{ steps.merge_pr.outputs.REVIEW_ID }}
|
||||||
|
run: |
|
||||||
|
# So we clean up no matter what
|
||||||
|
set +e
|
||||||
|
|
||||||
|
for i in {1..100}; do
|
||||||
|
if gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json state | jq -e '.state == "MERGED"'; then
|
||||||
|
echo "PR merged"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "PR not merged yet, waiting..."
|
||||||
|
sleep 6
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "PR did not merge in time"
|
||||||
|
gh api -X PUT "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews/$REVIEW_ID/dismissals" --field message='Merge attempt timed out' --field event='DISMISS'
|
||||||
|
gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --disable-auto
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Unlock weblate
|
||||||
|
if: ${{ inputs.skip != true }}
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=false
|
||||||
|
|
||||||
|
- name: Report success
|
||||||
|
run: |
|
||||||
|
echo "Workflow completed successfully (or was skipped)"
|
||||||
13
.github/workflows/org-checks.yml
vendored
13
.github/workflows/org-checks.yml
vendored
@@ -1,13 +0,0 @@
|
|||||||
name: Org Checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_review:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-approvals:
|
|
||||||
name: Check for Team/Admin Review
|
|
||||||
uses: immich-app/devtools/.github/workflows/required-approval.yml@main
|
|
||||||
permissions:
|
|
||||||
pull-requests: read
|
|
||||||
contents: read
|
|
||||||
12
.github/workflows/org-pr-require-conventional-commit.yml
vendored
Normal file
12
.github/workflows/org-pr-require-conventional-commit.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
name: PR Conventional Commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, edited]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate-pr-title:
|
||||||
|
name: Validate PR Title (conventional commit)
|
||||||
|
uses: immich-app/devtools/.github/workflows/shared-pr-require-conventional-commit.yml@main
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
15
.github/workflows/org-zizmor.yml
vendored
Normal file
15
.github/workflows/org-zizmor.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: Zizmor
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
zizmor:
|
||||||
|
name: Zizmor
|
||||||
|
uses: immich-app/devtools/.github/workflows/shared-zizmor.yml@main
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
name: PR Conventional Commit Validation
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened, edited]
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
validate-pr-title:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- name: PR Conventional Commit Validation
|
|
||||||
uses: ytanikin/PRConventionalCommits@b628c5a234cc32513014b7bfdd1e47b532124d98 # 1.3.0
|
|
||||||
with:
|
|
||||||
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]'
|
|
||||||
add_label: 'false'
|
|
||||||
38
.github/workflows/prepare-release.yml
vendored
38
.github/workflows/prepare-release.yml
vendored
@@ -10,12 +10,17 @@ on:
|
|||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
- 'false'
|
- 'false'
|
||||||
|
- major
|
||||||
- minor
|
- minor
|
||||||
- patch
|
- patch
|
||||||
mobileBump:
|
mobileBump:
|
||||||
description: 'Bump mobile build number'
|
description: 'Bump mobile build number'
|
||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
|
skipTranslations:
|
||||||
|
description: 'Skip translations'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}-root
|
group: ${{ github.workflow }}-${{ github.ref }}-root
|
||||||
@@ -24,28 +29,51 @@ concurrency:
|
|||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
merge_translations:
|
||||||
|
uses: ./.github/workflows/merge-translations.yml
|
||||||
|
with:
|
||||||
|
skip: ${{ inputs.skipTranslations }}
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
secrets:
|
||||||
|
PUSH_O_MATIC_APP_ID: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
|
PUSH_O_MATIC_APP_KEY: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
|
||||||
bump_version:
|
bump_version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: [merge_translations]
|
||||||
outputs:
|
outputs:
|
||||||
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
|
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
|
||||||
permissions: {} # No job-level permissions are needed because it uses the app-token
|
permissions: {} # No job-level permissions are needed because it uses the app-token
|
||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
ref: main
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
|
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
|
with:
|
||||||
|
node-version-file: './server/.nvmrc'
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
env:
|
env:
|
||||||
SERVER_BUMP: ${{ inputs.serverBump }}
|
SERVER_BUMP: ${{ inputs.serverBump }}
|
||||||
@@ -83,13 +111,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
@@ -100,7 +128,7 @@ jobs:
|
|||||||
name: release-apk-signed
|
name: release-apk-signed
|
||||||
|
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
|
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
tag_name: ${{ env.IMMICH_VERSION }}
|
tag_name: ${{ env.IMMICH_VERSION }}
|
||||||
|
|||||||
2
.github/workflows/preview-label.yaml
vendored
2
.github/workflows/preview-label.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
- uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
github.rest.issues.removeLabel({
|
github.rest.issues.removeLabel({
|
||||||
|
|||||||
15
.github/workflows/sdk.yml
vendored
15
.github/workflows/sdk.yml
vendored
@@ -16,22 +16,25 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
|
|
||||||
# Setup .npmrc file to publish to npm
|
# Setup .npmrc file to publish to npm
|
||||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
node-version-file: './open-api/typescript-sdk/.nvmrc'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: pnpm build
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: npm publish
|
run: pnpm publish
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
57
.github/workflows/static_analysis.yml
vendored
57
.github/workflows/static_analysis.yml
vendored
@@ -17,28 +17,23 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
mobile:
|
mobile:
|
||||||
- 'mobile/**'
|
- 'mobile/**'
|
||||||
workflow:
|
force-filters: |
|
||||||
- '.github/workflows/static_analysis.yml'
|
- '.github/workflows/static_analysis.yml'
|
||||||
- name: Check if we should force jobs to run
|
force-events: 'workflow_dispatch,release'
|
||||||
id: should_force
|
|
||||||
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
mobile-dart-analyze:
|
mobile-dart-analyze:
|
||||||
name: Run Dart Code Analysis
|
name: Run Dart Code Analysis
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -47,7 +42,7 @@ jobs:
|
|||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
@@ -68,7 +63,7 @@ jobs:
|
|||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
- name: Generate translation file
|
- name: Generate translation file
|
||||||
run: make translation
|
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
||||||
|
|
||||||
- name: Run Build Runner
|
- name: Run Build Runner
|
||||||
run: make build
|
run: make build
|
||||||
@@ -100,36 +95,10 @@ jobs:
|
|||||||
- name: Run dart format
|
- name: Run dart format
|
||||||
run: make format
|
run: make format
|
||||||
|
|
||||||
- name: Run dart custom_lint
|
# TODO: Re-enable after upgrading custom_lint
|
||||||
run: dart run custom_lint
|
# - name: Run dart custom_lint
|
||||||
|
# run: dart run custom_lint
|
||||||
|
|
||||||
# TODO: Use https://github.com/CQLabs/dcm-action
|
# TODO: Use https://github.com/CQLabs/dcm-action
|
||||||
- name: Run DCM
|
- name: Run DCM
|
||||||
run: dcm analyze lib --fatal-style --fatal-warnings
|
run: dcm analyze lib --fatal-style --fatal-warnings
|
||||||
|
|
||||||
zizmor:
|
|
||||||
name: zizmor
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
security-events: write
|
|
||||||
contents: read
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: Install the latest version of uv
|
|
||||||
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
|
|
||||||
|
|
||||||
- name: Run zizmor 🌈
|
|
||||||
run: uvx zizmor --format=sarif . > results.sarif
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Upload SARIF file
|
|
||||||
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
||||||
category: zizmor
|
|
||||||
|
|||||||
549
.github/workflows/test.yml
vendored
549
.github/workflows/test.yml
vendored
@@ -4,37 +4,21 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-job:
|
pre-job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run_i18n: ${{ steps.found_paths.outputs.i18n == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
should_run_web: ${{ steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_cli: ${{ steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_e2e: ${{ steps.found_paths.outputs.e2e == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_mobile: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }}
|
|
||||||
should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
i18n:
|
i18n:
|
||||||
@@ -54,260 +38,225 @@ jobs:
|
|||||||
- 'mobile/**'
|
- 'mobile/**'
|
||||||
machine-learning:
|
machine-learning:
|
||||||
- 'machine-learning/**'
|
- 'machine-learning/**'
|
||||||
workflow:
|
|
||||||
- '.github/workflows/test.yml'
|
|
||||||
.github:
|
.github:
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
|
force-filters: |
|
||||||
- name: Check if we should force jobs to run
|
- '.github/workflows/test.yml'
|
||||||
id: should_force
|
force-events: 'workflow_dispatch'
|
||||||
run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
server-unit-tests:
|
server-unit-tests:
|
||||||
name: Test & Lint Server
|
name: Test & Lint Server
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
- name: Run package manager install
|
||||||
- name: Run npm install
|
run: pnpm install
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run small tests & coverage
|
- name: Run small tests & coverage
|
||||||
run: npm test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
cli-unit-tests:
|
cli-unit-tests:
|
||||||
name: Unit Test CLI
|
name: Unit Test CLI
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Setup typescript-sdk
|
- name: Setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install && pnpm run build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
cli-unit-tests-win:
|
cli-unit-tests-win:
|
||||||
name: Unit Test CLI (Windows)
|
name: Unit Test CLI (Windows)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }}
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './cli/.nvmrc'
|
node-version-file: './cli/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Setup typescript-sdk
|
- name: Setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# Skip linter & formatter in Windows test.
|
# Skip linter & formatter in Windows test.
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
web-lint:
|
web-lint:
|
||||||
name: Lint Web
|
name: Lint Web
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_web == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
|
||||||
runs-on: mich
|
runs-on: mich
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
- name: Run pnpm install
|
||||||
- name: Run npm install
|
run: pnpm rebuild && pnpm install --frozen-lockfile
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint:p
|
run: pnpm lint:p
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run svelte checks
|
- name: Run svelte checks
|
||||||
run: npm run check:svelte
|
run: pnpm check:svelte
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
web-unit-tests:
|
web-unit-tests:
|
||||||
name: Test Web
|
name: Test Web
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_web == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
|
|
||||||
- name: Run npm install
|
- name: Run npm install
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check:typescript
|
run: pnpm check:typescript
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run unit tests & coverage
|
- name: Run unit tests & coverage
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
i18n-tests:
|
i18n-tests:
|
||||||
name: Test i18n
|
name: Test i18n
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_i18n == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './web/.nvmrc'
|
node-version-file: './web/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm --prefix=web ci
|
run: pnpm --filter=immich-web install --frozen-lockfile
|
||||||
|
|
||||||
- name: Format
|
- name: Format
|
||||||
run: npm --prefix=web run format:i18n
|
run: pnpm --filter=immich-web format:i18n
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
i18n/**
|
i18n/**
|
||||||
|
|
||||||
- name: Verify files have not changed
|
- name: Verify files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -316,87 +265,77 @@ jobs:
|
|||||||
echo "ERROR: i18n files not up to date!"
|
echo "ERROR: i18n files not up to date!"
|
||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
e2e-tests-lint:
|
e2e-tests-lint:
|
||||||
name: End-to-End Lint
|
name: End-to-End Lint
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_e2e == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./e2e
|
working-directory: ./e2e
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: pnpm lint
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: npm run check
|
run: pnpm check
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
server-medium-tests:
|
server-medium-tests:
|
||||||
name: Medium Tests (Server)
|
name: Medium Tests (Server)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
- name: Run pnpm install
|
||||||
- name: Run npm install
|
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run medium tests
|
- name: Run medium tests
|
||||||
run: npm run test:medium
|
run: pnpm test:medium
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
e2e-tests-server-cli:
|
e2e-tests-server-cli:
|
||||||
name: End-to-End Tests (Server & CLI)
|
name: End-to-End Tests (Server & CLI)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_e2e_server_cli == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }}
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -406,47 +345,45 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
- name: Run setup web
|
||||||
|
run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync
|
||||||
|
working-directory: ./web
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
- name: Run setup cli
|
- name: Run setup cli
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./cli
|
working-directory: ./cli
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
run: docker compose build
|
run: docker compose build
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (api & cli)
|
- name: Run e2e tests (api & cli)
|
||||||
run: npm run test
|
run: pnpm test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
e2e-tests-web:
|
e2e-tests-web:
|
||||||
name: End-to-End Tests (Web)
|
name: End-to-End Tests (Web)
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_e2e_web == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }}
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -456,42 +393,36 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './e2e/.nvmrc'
|
node-version-file: './e2e/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Run setup typescript-sdk
|
- name: Run setup typescript-sdk
|
||||||
run: npm ci && npm run build
|
run: pnpm install --frozen-lockfile && pnpm build
|
||||||
working-directory: ./open-api/typescript-sdk
|
working-directory: ./open-api/typescript-sdk
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: npx playwright install chromium --only-shell
|
run: npx playwright install chromium --only-shell
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
run: docker compose build
|
run: docker compose build
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
- name: Run e2e tests (web)
|
- name: Run e2e tests (web)
|
||||||
run: npx playwright test
|
run: npx playwright test
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
success-check-e2e:
|
success-check-e2e:
|
||||||
name: End-to-End Tests Success
|
name: End-to-End Tests Success
|
||||||
needs: [e2e-tests-server-cli, e2e-tests-web]
|
needs: [e2e-tests-server-cli, e2e-tests-web]
|
||||||
@@ -502,37 +433,32 @@ jobs:
|
|||||||
- uses: immich-app/devtools/actions/success-check@68f10eb389bb02a3cf9d1156111964c549eb421b # 0.0.4
|
- uses: immich-app/devtools/actions/success-check@68f10eb389bb02a3cf9d1156111964c549eb421b # 0.0.4
|
||||||
with:
|
with:
|
||||||
needs: ${{ toJSON(needs) }}
|
needs: ${{ toJSON(needs) }}
|
||||||
|
|
||||||
mobile-unit-tests:
|
mobile-unit-tests:
|
||||||
name: Unit Test Mobile
|
name: Unit Test Mobile
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@fd55f4c5af5b953cc57a2be44cb082c8f6635e8e # v2.21.0
|
uses: subosito/flutter-action@fd55f4c5af5b953cc57a2be44cb082c8f6635e8e # v2.21.0
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version-file: ./mobile/pubspec.yaml
|
flutter-version-file: ./mobile/pubspec.yaml
|
||||||
|
|
||||||
- name: Generate translation file
|
- name: Generate translation file
|
||||||
run: make translation
|
run: dart run easy_localization:generate -S ../i18n && dart run bin/generate_keys.dart
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
run: flutter test -j 1
|
run: flutter test -j 1
|
||||||
|
|
||||||
ml-unit-tests:
|
ml-unit-tests:
|
||||||
name: Unit Test ML
|
name: Unit Test ML
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -540,10 +466,9 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
working-directory: ./machine-learning
|
working-directory: ./machine-learning
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
|
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
|
||||||
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||||
@@ -566,56 +491,48 @@ jobs:
|
|||||||
- name: Run tests and coverage
|
- name: Run tests and coverage
|
||||||
run: |
|
run: |
|
||||||
uv run pytest --cov=immich_ml --cov-report term-missing
|
uv run pytest --cov=immich_ml --cov-report term-missing
|
||||||
|
|
||||||
github-files-formatting:
|
github-files-formatting:
|
||||||
name: .github Files Formatting
|
name: .github Files Formatting
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run)['.github'] == true }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./.github
|
working-directory: ./.github
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './.github/.nvmrc'
|
node-version-file: './.github/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
- name: Run pnpm install
|
||||||
- name: Run npm install
|
run: pnpm install --frozen-lockfile
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: npm run format
|
run: pnpm format
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
name: ShellCheck
|
name: ShellCheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Run ShellCheck
|
- name: Run ShellCheck
|
||||||
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
|
||||||
with:
|
with:
|
||||||
ignore_paths: >-
|
ignore_paths: >-
|
||||||
**/open-api/**
|
**/open-api/** **/openapi** **/node_modules/**
|
||||||
**/openapi**
|
|
||||||
**/node_modules/**
|
|
||||||
|
|
||||||
generated-api-up-to-date:
|
generated-api-up-to-date:
|
||||||
name: OpenAPI Clients
|
name: OpenAPI Clients
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -623,26 +540,24 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: npm --prefix=server ci
|
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build the app
|
- name: Build the app
|
||||||
run: npm --prefix=server run build
|
run: pnpm --filter immich build
|
||||||
|
|
||||||
- name: Run API generation
|
- name: Run API generation
|
||||||
run: make open-api
|
run: ./bin/generate-open-api.sh
|
||||||
|
working-directory: open-api
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
@@ -651,7 +566,6 @@ jobs:
|
|||||||
mobile/openapi
|
mobile/openapi
|
||||||
open-api/typescript-sdk
|
open-api/typescript-sdk
|
||||||
open-api/immich-openapi-specs.json
|
open-api/immich-openapi-specs.json
|
||||||
|
|
||||||
- name: Verify files have not changed
|
- name: Verify files have not changed
|
||||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -660,7 +574,6 @@ jobs:
|
|||||||
echo "ERROR: Generated files not up to date!"
|
echo "ERROR: Generated files not up to date!"
|
||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
sql-schema-up-to-date:
|
sql-schema-up-to-date:
|
||||||
name: SQL Schema Checks
|
name: SQL Schema Checks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -668,51 +581,42 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:ec713143dca1a426eba2e03707c319e2ec3cc9d304ef767f777f8e297dee820c
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:da52bbead5d818adaa8077c8dcdaad0aaf93038c31ad8348b51f9f0ec1310a4d
|
||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_DB: immich
|
POSTGRES_DB: immich
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd pg_isready
|
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
- name: Setup pnpm
|
||||||
|
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: './server/.nvmrc'
|
node-version-file: './server/.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||||
|
|
||||||
- name: Install server dependencies
|
- name: Install server dependencies
|
||||||
run: npm ci
|
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build the app
|
- name: Build the app
|
||||||
run: npm run build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Run existing migrations
|
- name: Run existing migrations
|
||||||
run: npm run migrations:run
|
run: pnpm migrations:run
|
||||||
|
|
||||||
- name: Test npm run schema:reset command works
|
- name: Test npm run schema:reset command works
|
||||||
run: npm run schema:reset
|
run: pnpm schema:reset
|
||||||
|
|
||||||
- name: Generate new migrations
|
- name: Generate new migrations
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: npm run migrations:generate src/TestMigration
|
run: pnpm migrations:generate src/TestMigration
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-files
|
id: verify-changed-files
|
||||||
@@ -728,19 +632,16 @@ jobs:
|
|||||||
echo "Changed files: ${CHANGED_FILES}"
|
echo "Changed files: ${CHANGED_FILES}"
|
||||||
cat ./src/*-TestMigration.ts
|
cat ./src/*-TestMigration.ts
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Run SQL generation
|
- name: Run SQL generation
|
||||||
run: npm run sync:sql
|
run: pnpm sync:sql
|
||||||
env:
|
env:
|
||||||
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
DB_URL: postgres://postgres:postgres@localhost:5432/immich
|
||||||
|
|
||||||
- name: Find file changes
|
- name: Find file changes
|
||||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||||
id: verify-changed-sql-files
|
id: verify-changed-sql-files
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
server/src/queries
|
server/src/queries
|
||||||
|
|
||||||
- name: Verify SQL files have not changed
|
- name: Verify SQL files have not changed
|
||||||
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
|
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
|
||||||
env:
|
env:
|
||||||
@@ -751,77 +652,77 @@ jobs:
|
|||||||
git diff
|
git diff
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
# mobile-integration-tests:
|
# mobile-integration-tests:
|
||||||
# name: Run mobile end-to-end integration tests
|
# name: Run mobile end-to-end integration tests
|
||||||
# runs-on: macos-latest
|
# runs-on: macos-latest
|
||||||
# steps:
|
# steps:
|
||||||
# - uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
# - uses: actions/setup-java@v3
|
# - uses: actions/setup-java@v3
|
||||||
# with:
|
# with:
|
||||||
# distribution: 'zulu'
|
# distribution: 'zulu'
|
||||||
# java-version: '12.x'
|
# java-version: '12.x'
|
||||||
# cache: 'gradle'
|
# cache: 'gradle'
|
||||||
# - name: Cache android SDK
|
# - name: Cache android SDK
|
||||||
# uses: actions/cache@v3
|
# uses: actions/cache@v3
|
||||||
# id: android-sdk
|
# id: android-sdk
|
||||||
# with:
|
# with:
|
||||||
# key: android-sdk
|
# key: android-sdk
|
||||||
# path: |
|
# path: |
|
||||||
# /usr/local/lib/android/
|
# /usr/local/lib/android/
|
||||||
# ~/.android
|
# ~/.android
|
||||||
# - name: Cache Gradle
|
# - name: Cache Gradle
|
||||||
# uses: actions/cache@v3
|
# uses: actions/cache@v3
|
||||||
# with:
|
# with:
|
||||||
# path: |
|
# path: |
|
||||||
# ./mobile/build/
|
# ./mobile/build/
|
||||||
# ./mobile/android/.gradle/
|
# ./mobile/android/.gradle/
|
||||||
# key: ${{ runner.os }}-flutter-${{ hashFiles('**/*.gradle*', 'pubspec.lock') }}
|
# key: ${{ runner.os }}-flutter-${{ hashFiles('**/*.gradle*', 'pubspec.lock') }}
|
||||||
# - name: Setup Android SDK
|
# - name: Setup Android SDK
|
||||||
# if: steps.android-sdk.outputs.cache-hit != 'true'
|
# if: steps.android-sdk.outputs.cache-hit != 'true'
|
||||||
# uses: android-actions/setup-android@v2
|
# uses: android-actions/setup-android@v2
|
||||||
# - name: AVD cache
|
# - name: AVD cache
|
||||||
# uses: actions/cache@v3
|
# uses: actions/cache@v3
|
||||||
# id: avd-cache
|
# id: avd-cache
|
||||||
# with:
|
# with:
|
||||||
# path: |
|
# path: |
|
||||||
# ~/.android/avd/*
|
# ~/.android/avd/*
|
||||||
# ~/.android/adb*
|
# ~/.android/adb*
|
||||||
# key: avd-29
|
# key: avd-29
|
||||||
# - name: create AVD and generate snapshot for caching
|
# - name: create AVD and generate snapshot for caching
|
||||||
# if: steps.avd-cache.outputs.cache-hit != 'true'
|
# if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||||
# uses: reactivecircus/android-emulator-runner@v2.27.0
|
# uses: reactivecircus/android-emulator-runner@v2.27.0
|
||||||
# with:
|
# with:
|
||||||
# working-directory: ./mobile
|
# working-directory: ./mobile
|
||||||
# cores: 2
|
# cores: 2
|
||||||
# api-level: 29
|
# api-level: 29
|
||||||
# arch: x86_64
|
# arch: x86_64
|
||||||
# profile: pixel
|
# profile: pixel
|
||||||
# target: default
|
# target: default
|
||||||
# force-avd-creation: false
|
# force-avd-creation: false
|
||||||
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
# disable-animations: false
|
# disable-animations: false
|
||||||
# script: echo "Generated AVD snapshot for caching."
|
# script: echo "Generated AVD snapshot for caching."
|
||||||
# - name: Setup Flutter SDK
|
# - name: Setup Flutter SDK
|
||||||
# uses: subosito/flutter-action@v2
|
# uses: subosito/flutter-action@v2
|
||||||
# with:
|
# with:
|
||||||
# channel: 'stable'
|
# channel: 'stable'
|
||||||
# flutter-version: '3.7.3'
|
# flutter-version: '3.7.3'
|
||||||
# cache: true
|
# cache: true
|
||||||
# - name: Run integration tests
|
# - name: Run integration tests
|
||||||
# uses: Wandalen/wretry.action@master
|
# uses: Wandalen/wretry.action@master
|
||||||
# with:
|
# with:
|
||||||
# action: reactivecircus/android-emulator-runner@v2.27.0
|
# action: reactivecircus/android-emulator-runner@v2.27.0
|
||||||
# with: |
|
# with: |
|
||||||
# working-directory: ./mobile
|
# working-directory: ./mobile
|
||||||
# cores: 2
|
# cores: 2
|
||||||
# api-level: 29
|
# api-level: 29
|
||||||
# arch: x86_64
|
# arch: x86_64
|
||||||
# profile: pixel
|
# profile: pixel
|
||||||
# target: default
|
# target: default
|
||||||
# force-avd-creation: false
|
# force-avd-creation: false
|
||||||
# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
# disable-animations: true
|
# disable-animations: true
|
||||||
# script: |
|
# script: |
|
||||||
# flutter pub get
|
# flutter pub get
|
||||||
# flutter test integration_test
|
# flutter test integration_test
|
||||||
# attempt_limit: 3
|
# attempt_limit: 3
|
||||||
|
|||||||
44
.github/workflows/weblate-lock.yml
vendored
44
.github/workflows/weblate-lock.yml
vendored
@@ -3,48 +3,52 @@ name: Weblate checks
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- ready_for_review
|
||||||
|
- auto_merge_enabled
|
||||||
|
- auto_merge_disabled
|
||||||
|
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
|
env:
|
||||||
|
BOT_NAME: immich-push-o-matic
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-job:
|
pre-job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check what should run
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
id: check
|
||||||
with:
|
uses: immich-app/devtools/actions/pre-job@24820aa4ef67959b0dcf69a438cccf00d7c7042b # pre-job-action-v1.0.1
|
||||||
persist-credentials: false
|
|
||||||
- id: found_paths
|
|
||||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
i18n:
|
i18n:
|
||||||
- 'i18n/!(en)**\.json'
|
- 'i18n/!(en)**\.json'
|
||||||
|
exclude-branches: 'chore/translations'
|
||||||
|
skip-force-logic: 'true'
|
||||||
|
|
||||||
enforce-lock:
|
enforce-lock:
|
||||||
name: Check Weblate Lock
|
name: Check Weblate Lock
|
||||||
needs: [pre-job]
|
needs: [pre-job]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions: {}
|
permissions: {}
|
||||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check weblate lock
|
- name: Bot review status
|
||||||
|
env:
|
||||||
|
PR_NUMBER: ${{ github.event.pull_request.number || github.event.pull_request_review.pull_request.number }}
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "false" = $(curl https://hosted.weblate.org/api/components/immich/immich/lock/ | jq .locked) ]]; then
|
# Then check for APPROVED by the bot, if absent fail
|
||||||
exit 1
|
gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json reviews | jq -e '.reviews | map(select(.author.login == env.BOT_NAME and .state == "APPROVED")) | length > 0' \
|
||||||
fi
|
|| (echo "The push-o-matic bot has not approved this PR yet" && exit 1)
|
||||||
- name: Find Pull Request
|
|
||||||
uses: juliangruber/find-pull-request-action@952b3bb1ddb2dcc0aa3479e98bb1c2d1a922f096 # v1.10.0
|
|
||||||
id: find-pr
|
|
||||||
with:
|
|
||||||
branch: chore/translations
|
|
||||||
- name: Fail if existing weblate PR
|
|
||||||
if: ${{ steps.find-pr.outputs.number }}
|
|
||||||
run: exit 1
|
|
||||||
success-check-lock:
|
success-check-lock:
|
||||||
name: Weblate Lock Check Success
|
name: Weblate Lock Check Success
|
||||||
needs: [enforce-lock]
|
needs: [enforce-lock]
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -18,6 +18,7 @@ mobile/libisar.dylib
|
|||||||
mobile/openapi/test
|
mobile/openapi/test
|
||||||
mobile/openapi/doc
|
mobile/openapi/doc
|
||||||
mobile/openapi/.openapi-generator/FILES
|
mobile/openapi/.openapi-generator/FILES
|
||||||
|
mobile/ios/build
|
||||||
|
|
||||||
open-api/typescript-sdk/build
|
open-api/typescript-sdk/build
|
||||||
mobile/android/fastlane/report.xml
|
mobile/android/fastlane/report.xml
|
||||||
@@ -25,3 +26,5 @@ mobile/ios/fastlane/report.xml
|
|||||||
|
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
|
.devcontainer/library
|
||||||
|
.devcontainer/.env*
|
||||||
|
|||||||
18
.pnpmfile.cjs
Normal file
18
.pnpmfile.cjs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
module.exports = {
|
||||||
|
hooks: {
|
||||||
|
readPackage: (pkg) => {
|
||||||
|
if (!pkg.name) {
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
if (pkg.name === "exiftool-vendored") {
|
||||||
|
if (pkg.optionalDependencies["exiftool-vendored.pl"]) {
|
||||||
|
// make exiftool-vendored.pl a regular dependency
|
||||||
|
pkg.dependencies["exiftool-vendored.pl"] =
|
||||||
|
pkg.optionalDependencies["exiftool-vendored.pl"];
|
||||||
|
delete pkg.optionalDependencies["exiftool-vendored.pl"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkg;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -56,7 +56,8 @@
|
|||||||
"explorer.fileNesting.enabled": true,
|
"explorer.fileNesting.enabled": true,
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
|
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
|
||||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
||||||
|
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb, bun.lock, pnpm-workspace.yaml, .pnpmfile.cjs"
|
||||||
},
|
},
|
||||||
"svelte.enable-ts-plugin": true,
|
"svelte.enable-ts-plugin": true,
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative"
|
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/.github/ @bo0tzz
|
/.github/ @bo0tzz
|
||||||
/docker/ @bo0tzz
|
/docker/ @bo0tzz
|
||||||
/server/ @danieldietzler
|
/server/ @danieldietzler
|
||||||
|
/web/ @danieldietzler
|
||||||
/machine-learning/ @mertalev
|
/machine-learning/ @mertalev
|
||||||
/e2e/ @danieldietzler
|
/e2e/ @danieldietzler
|
||||||
|
/mobile/ @shenlong-tanwen
|
||||||
|
|||||||
98
Makefile
98
Makefile
@@ -8,14 +8,14 @@ dev-update:
|
|||||||
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans
|
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans
|
||||||
|
|
||||||
dev-scale:
|
dev-scale:
|
||||||
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
|
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
|
||||||
|
|
||||||
dev-docs:
|
dev-docs:
|
||||||
npm --prefix docs run start
|
npm --prefix docs run start
|
||||||
|
|
||||||
.PHONY: e2e
|
.PHONY: e2e
|
||||||
e2e:
|
e2e:
|
||||||
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
|
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --remove-orphans
|
||||||
|
|
||||||
e2e-update:
|
e2e-update:
|
||||||
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
|
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
|
||||||
@@ -43,7 +43,7 @@ open-api-typescript:
|
|||||||
cd ./open-api && bash ./bin/generate-open-api.sh typescript
|
cd ./open-api && bash ./bin/generate-open-api.sh typescript
|
||||||
|
|
||||||
sql:
|
sql:
|
||||||
npm --prefix server run sync:sql
|
pnpm --filter immich run sync:sql
|
||||||
|
|
||||||
attach-server:
|
attach-server:
|
||||||
docker exec -it docker_immich-server_1 sh
|
docker exec -it docker_immich-server_1 sh
|
||||||
@@ -51,33 +51,59 @@ attach-server:
|
|||||||
renovate:
|
renovate:
|
||||||
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
LOG_LEVEL=debug npx renovate --platform=local --repository-cache=reset
|
||||||
|
|
||||||
|
# Directories that need to be created for volumes or build output
|
||||||
|
VOLUME_DIRS = \
|
||||||
|
./.pnpm-store \
|
||||||
|
./web/.svelte-kit \
|
||||||
|
./web/node_modules \
|
||||||
|
./web/coverage \
|
||||||
|
./e2e/node_modules \
|
||||||
|
./docs/node_modules \
|
||||||
|
./server/node_modules \
|
||||||
|
./open-api/typescript-sdk/node_modules \
|
||||||
|
./.github/node_modules \
|
||||||
|
./node_modules \
|
||||||
|
./cli/node_modules
|
||||||
|
|
||||||
|
# Include .env file if it exists
|
||||||
|
-include docker/.env
|
||||||
|
|
||||||
MODULES = e2e server web cli sdk docs .github
|
MODULES = e2e server web cli sdk docs .github
|
||||||
|
|
||||||
|
# directory to package name mapping function
|
||||||
|
# cli = @immich/cli
|
||||||
|
# docs = documentation
|
||||||
|
# e2e = immich-e2e
|
||||||
|
# open-api/typescript-sdk = @immich/sdk
|
||||||
|
# server = immich
|
||||||
|
# web = immich-web
|
||||||
|
map-package = $(subst sdk,@immich/sdk,$(subst cli,@immich/cli,$(subst docs,documentation,$(subst e2e,immich-e2e,$(subst server,immich,$(subst web,immich-web,$1))))))
|
||||||
|
|
||||||
audit-%:
|
audit-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) audit fix
|
pnpm --filter $(call map-package,$*) audit fix
|
||||||
install-%:
|
install-%:
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) i
|
pnpm --filter $(call map-package,$*) install $(if $(FROZEN),--frozen-lockfile) $(if $(OFFLINE),--offline)
|
||||||
ci-%:
|
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) ci
|
|
||||||
build-cli: build-sdk
|
build-cli: build-sdk
|
||||||
build-web: build-sdk
|
build-web: build-sdk
|
||||||
build-%: install-%
|
build-%: install-%
|
||||||
npm --prefix $(subst sdk,open-api/typescript-sdk,$*) run build
|
pnpm --filter $(call map-package,$*) run build
|
||||||
format-%:
|
format-%:
|
||||||
npm --prefix $* run format:fix
|
pnpm --filter $(call map-package,$*) run format:fix
|
||||||
lint-%:
|
lint-%:
|
||||||
npm --prefix $* run lint:fix
|
pnpm --filter $(call map-package,$*) run lint:fix
|
||||||
|
lint-web:
|
||||||
|
pnpm --filter $(call map-package,$*) run lint:p
|
||||||
check-%:
|
check-%:
|
||||||
npm --prefix $* run check
|
pnpm --filter $(call map-package,$*) run check
|
||||||
check-web:
|
check-web:
|
||||||
npm --prefix web run check:typescript
|
pnpm --filter immich-web run check:typescript
|
||||||
npm --prefix web run check:svelte
|
pnpm --filter immich-web run check:svelte
|
||||||
test-%:
|
test-%:
|
||||||
npm --prefix $* run test
|
pnpm --filter $(call map-package,$*) run test
|
||||||
test-e2e:
|
test-e2e:
|
||||||
docker compose -f ./e2e/docker-compose.yml build
|
docker compose -f ./e2e/docker-compose.yml build
|
||||||
npm --prefix e2e run test
|
pnpm --filter immich-e2e run test
|
||||||
npm --prefix e2e run test:web
|
pnpm --filter immich-e2e run test:web
|
||||||
test-medium:
|
test-medium:
|
||||||
docker run \
|
docker run \
|
||||||
--rm \
|
--rm \
|
||||||
@@ -87,27 +113,39 @@ test-medium:
|
|||||||
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
|
-v ./server/tsconfig.json:/usr/src/app/tsconfig.json \
|
||||||
-e NODE_ENV=development \
|
-e NODE_ENV=development \
|
||||||
immich-server:latest \
|
immich-server:latest \
|
||||||
-c "npm ci && npm run test:medium -- --run"
|
-c "pnpm test:medium -- --run"
|
||||||
test-medium-dev:
|
test-medium-dev:
|
||||||
docker exec -it immich_server /bin/sh -c "npm run test:medium"
|
docker exec -it immich_server /bin/sh -c "pnpm run test:medium"
|
||||||
|
|
||||||
build-all: $(foreach M,$(filter-out e2e .github,$(MODULES)),build-$M) ;
|
install-all:
|
||||||
install-all: $(foreach M,$(MODULES),install-$M) ;
|
pnpm -r --filter '!documentation' install
|
||||||
ci-all: $(foreach M,$(filter-out .github,$(MODULES)),ci-$M) ;
|
|
||||||
check-all: $(foreach M,$(filter-out sdk cli docs .github,$(MODULES)),check-$M) ;
|
build-all: $(foreach M,$(filter-out e2e docs .github,$(MODULES)),build-$M) ;
|
||||||
lint-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),lint-$M) ;
|
|
||||||
format-all: $(foreach M,$(filter-out sdk,$(MODULES)),format-$M) ;
|
check-all:
|
||||||
audit-all: $(foreach M,$(MODULES),audit-$M) ;
|
pnpm -r --filter '!documentation' run "/^(check|check\:svelte|check\:typescript)$/"
|
||||||
hygiene-all: lint-all format-all check-all sql audit-all;
|
lint-all:
|
||||||
test-all: $(foreach M,$(filter-out sdk docs .github,$(MODULES)),test-$M) ;
|
pnpm -r --filter '!documentation' run lint:fix
|
||||||
|
format-all:
|
||||||
|
pnpm -r --filter '!documentation' run format:fix
|
||||||
|
audit-all:
|
||||||
|
pnpm -r --filter '!documentation' audit fix
|
||||||
|
hygiene-all: audit-all
|
||||||
|
pnpm -r --filter '!documentation' run "/(format:fix|check|check:svelte|check:typescript|sql)/"
|
||||||
|
|
||||||
|
test-all:
|
||||||
|
pnpm -r --filter '!documentation' run "/^test/"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name "node_modules" -type d -prune -exec rm -rf {} +
|
find . -name "node_modules" -type d -prune -exec rm -rf {} +
|
||||||
find . -name "dist" -type d -prune -exec rm -rf '{}' +
|
find . -name "dist" -type d -prune -exec rm -rf '{}' +
|
||||||
find . -name "build" -type d -prune -exec rm -rf '{}' +
|
find . -name "build" -type d -prune -exec rm -rf '{}' +
|
||||||
find . -name "svelte-kit" -type d -prune -exec rm -rf '{}' +
|
find . -name ".svelte-kit" -type d -prune -exec rm -rf '{}' +
|
||||||
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml rm -v -f || true
|
find . -name "coverage" -type d -prune -exec rm -rf '{}' +
|
||||||
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml rm -v -f || true
|
find . -name ".pnpm-store" -type d -prune -exec rm -rf '{}' +
|
||||||
|
command -v docker >/dev/null 2>&1 && docker compose -f ./docker/docker-compose.dev.yml down -v --remove-orphans || true
|
||||||
|
command -v docker >/dev/null 2>&1 && docker compose -f ./e2e/docker-compose.yml down -v --remove-orphans || true
|
||||||
|
|
||||||
|
|
||||||
setup-server-dev: install-server
|
setup-server-dev: install-server
|
||||||
setup-web-dev: install-sdk build-sdk install-web
|
setup-web-dev: install-sdk build-sdk install-web
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -1,19 +1,14 @@
|
|||||||
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e AS core
|
FROM node:22.16.0-alpine3.20@sha256:2289fb1fba0f4633b08ec47b94a89c7e20b829fc5679f9b7b298eaa2f1ed8b7e AS core
|
||||||
|
|
||||||
WORKDIR /usr/src/open-api/typescript-sdk
|
|
||||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
|
||||||
RUN npm ci
|
|
||||||
COPY open-api/typescript-sdk/ ./
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
COPY package* pnpm* .pnpmfile.cjs ./
|
||||||
COPY cli/package.json cli/package-lock.json ./
|
COPY ./cli ./cli/
|
||||||
RUN npm ci
|
COPY ./open-api/typescript-sdk ./open-api/typescript-sdk/
|
||||||
|
RUN corepack enable pnpm && \
|
||||||
COPY cli .
|
pnpm install --filter @immich/sdk --filter @immich/cli --frozen-lockfile && \
|
||||||
RUN npm run build
|
pnpm --filter @immich/sdk build && \
|
||||||
|
pnpm --filter @immich/cli build
|
||||||
|
|
||||||
WORKDIR /import
|
WORKDIR /import
|
||||||
|
|
||||||
ENTRYPOINT ["node", "/usr/src/app/dist"]
|
ENTRYPOINT ["node", "/usr/src/app/cli/dist"]
|
||||||
|
|||||||
4600
cli/package-lock.json
generated
4600
cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.77",
|
"version": "2.2.92",
|
||||||
"description": "Command Line Interface (CLI) for Immich",
|
"description": "Command Line Interface (CLI) for Immich",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
"cli"
|
"cli"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@types/byte-size": "^8.1.0",
|
"@types/byte-size": "^8.1.0",
|
||||||
@@ -21,7 +20,7 @@
|
|||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/micromatch": "^4.0.9",
|
"@types/micromatch": "^4.0.9",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.17.0",
|
"@types/node": "^22.18.1",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
"byte-size": "^9.0.0",
|
"byte-size": "^9.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
@@ -69,6 +68,6 @@
|
|||||||
"micromatch": "^4.0.8"
|
"micromatch": "^4.0.8"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.1"
|
version = "4.52.5"
|
||||||
constraints = "4.52.1"
|
constraints = "4.52.5"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:2lHvafwGbLdmc9lYkuJFw3nsInaQjRpjX/JfIRKmq/M=",
|
"h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
|
||||||
"h1:596JomwjrtUrOSreq9NNCS+rj70+jOV+0pfja5MXiTI=",
|
"h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
|
||||||
"h1:7mBOA5TVAIt3qAwPXKCtE0RSYeqij9v30mnksuBbpEg=",
|
"h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
|
||||||
"h1:ELVgzh4kHKBCYdL+2A8JjWS0E1snLUN3Mmz3Vo6qSfw=",
|
"h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
|
||||||
"h1:FGGM5yLFf72g3kSXM3LAN64Gf/AkXr5WCmhixgnP+l4=",
|
"h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
|
||||||
"h1:JupkJbQALcIVoMhHImrLeLDsQR1ET7VJLGC7ONxjqGU=",
|
"h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
|
||||||
"h1:KsaE4JNq+1uV1nJsuTcYar/8lyY6zKS5UBEpfYg3wvc=",
|
"h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
|
||||||
"h1:NHZ5RJIzQDLhie/ykl3uI6UPfNQR9Lu5Ti7JPR6X904=",
|
"h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
|
||||||
"h1:NfAuMbn6LQPLDtJhbzO1MX9JMIGLMa8K6CpekvtsuX8=",
|
"h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
|
||||||
"h1:e+vNKokamDsp/kJvFr2pRudzwEz2r49iZ/oSggw+1LY=",
|
"h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
|
||||||
"h1:jnb4VdfNZ79I3yj7Q8x+JmOT+FxbfjjRfrF0dL0yCW8=",
|
"h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
|
||||||
"h1:kmF//O539d7NuHU7qIxDj7Wz4eJmLKFiI5glwQivldU=",
|
"h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
|
||||||
"h1:s6XriaKwOgV4jvKAGPXkrxhhOQxpNU5dceZwi9Z/1k8=",
|
"h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
|
||||||
"h1:wt3WBEBAeSGTlC9OlnTlAALxRiK4SQgLy0KgBIS7qzs=",
|
"h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
|
||||||
"zh:2fb95e1d3229b9b6c704e1a413c7481c60f139780d9641f657b6eb9b633b90f2",
|
"zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
|
||||||
"zh:379c7680983383862236e9e6e720c3114195c40526172188e88d0ffcf50dfe2e",
|
"zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
|
||||||
"zh:55533beb6cfc02d22ffda8cba8027bc2c841bb172cd637ed0d28323d41395f8f",
|
"zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
|
||||||
"zh:5abd70760e4eb1f37a1c307cbd2989ea7c9ba0afb93818c67c1d363a31f75703",
|
"zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
|
||||||
"zh:699f1c8cd66129176fe659ebf0e6337632a8967a28d2630b6ae5948665c0c2ae",
|
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
|
||||||
"zh:69c15acd73c451e89de6477059cda2f3ec200b48ae4b9ff3646c4d389fd3205e",
|
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
|
||||||
"zh:6e02b687de21b844f8266dff99e93e7c61fc8eb688f4bbb23803caceb251839e",
|
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
|
||||||
"zh:7a51d17b87ed87b7bebf2ad9fc7c3a74f16a1b44eee92c779c08eb89258c0496",
|
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
|
||||||
"zh:88ad84436837b0f55302f22748505972634e87400d6902260fd6b7ba1610f937",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8d46c3d9f4f7ad20ac6ef01daa63f4e30a2d16dcb1bb5c7c7ee3dc6be38e9ca1",
|
"zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
|
||||||
"zh:913d64e72a4929dae1d4793e2004f4f9a58b138ea337d9d94fa35cafbf06550a",
|
"zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
|
||||||
"zh:c8d93cf86e2e49f6cec665cfe78b82c144cce15a8b2e30f343385fadd1251849",
|
"zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
|
||||||
"zh:cc4f69397d9bc34a528a5609a024c3a48f54f21616c0008792dd417297add955",
|
"zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
|
||||||
"zh:df99cdb8b064aad35ffea77e645cf6541d0b1b2ebc51b6d26c42031de60ab69e",
|
"zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
|
||||||
|
"zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.1"
|
version = "4.52.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,37 +2,37 @@
|
|||||||
# Manual edits may be lost in future updates.
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
provider "registry.opentofu.org/cloudflare/cloudflare" {
|
||||||
version = "4.52.1"
|
version = "4.52.5"
|
||||||
constraints = "4.52.1"
|
constraints = "4.52.5"
|
||||||
hashes = [
|
hashes = [
|
||||||
"h1:2lHvafwGbLdmc9lYkuJFw3nsInaQjRpjX/JfIRKmq/M=",
|
"h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=",
|
||||||
"h1:596JomwjrtUrOSreq9NNCS+rj70+jOV+0pfja5MXiTI=",
|
"h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=",
|
||||||
"h1:7mBOA5TVAIt3qAwPXKCtE0RSYeqij9v30mnksuBbpEg=",
|
"h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=",
|
||||||
"h1:ELVgzh4kHKBCYdL+2A8JjWS0E1snLUN3Mmz3Vo6qSfw=",
|
"h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=",
|
||||||
"h1:FGGM5yLFf72g3kSXM3LAN64Gf/AkXr5WCmhixgnP+l4=",
|
"h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=",
|
||||||
"h1:JupkJbQALcIVoMhHImrLeLDsQR1ET7VJLGC7ONxjqGU=",
|
"h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=",
|
||||||
"h1:KsaE4JNq+1uV1nJsuTcYar/8lyY6zKS5UBEpfYg3wvc=",
|
"h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=",
|
||||||
"h1:NHZ5RJIzQDLhie/ykl3uI6UPfNQR9Lu5Ti7JPR6X904=",
|
"h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=",
|
||||||
"h1:NfAuMbn6LQPLDtJhbzO1MX9JMIGLMa8K6CpekvtsuX8=",
|
"h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=",
|
||||||
"h1:e+vNKokamDsp/kJvFr2pRudzwEz2r49iZ/oSggw+1LY=",
|
"h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=",
|
||||||
"h1:jnb4VdfNZ79I3yj7Q8x+JmOT+FxbfjjRfrF0dL0yCW8=",
|
"h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=",
|
||||||
"h1:kmF//O539d7NuHU7qIxDj7Wz4eJmLKFiI5glwQivldU=",
|
"h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=",
|
||||||
"h1:s6XriaKwOgV4jvKAGPXkrxhhOQxpNU5dceZwi9Z/1k8=",
|
"h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=",
|
||||||
"h1:wt3WBEBAeSGTlC9OlnTlAALxRiK4SQgLy0KgBIS7qzs=",
|
"h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=",
|
||||||
"zh:2fb95e1d3229b9b6c704e1a413c7481c60f139780d9641f657b6eb9b633b90f2",
|
"zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b",
|
||||||
"zh:379c7680983383862236e9e6e720c3114195c40526172188e88d0ffcf50dfe2e",
|
"zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a",
|
||||||
"zh:55533beb6cfc02d22ffda8cba8027bc2c841bb172cd637ed0d28323d41395f8f",
|
"zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7",
|
||||||
"zh:5abd70760e4eb1f37a1c307cbd2989ea7c9ba0afb93818c67c1d363a31f75703",
|
"zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238",
|
||||||
"zh:699f1c8cd66129176fe659ebf0e6337632a8967a28d2630b6ae5948665c0c2ae",
|
"zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b",
|
||||||
"zh:69c15acd73c451e89de6477059cda2f3ec200b48ae4b9ff3646c4d389fd3205e",
|
"zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072",
|
||||||
"zh:6e02b687de21b844f8266dff99e93e7c61fc8eb688f4bbb23803caceb251839e",
|
"zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661",
|
||||||
"zh:7a51d17b87ed87b7bebf2ad9fc7c3a74f16a1b44eee92c779c08eb89258c0496",
|
"zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c",
|
||||||
"zh:88ad84436837b0f55302f22748505972634e87400d6902260fd6b7ba1610f937",
|
|
||||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||||
"zh:8d46c3d9f4f7ad20ac6ef01daa63f4e30a2d16dcb1bb5c7c7ee3dc6be38e9ca1",
|
"zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54",
|
||||||
"zh:913d64e72a4929dae1d4793e2004f4f9a58b138ea337d9d94fa35cafbf06550a",
|
"zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852",
|
||||||
"zh:c8d93cf86e2e49f6cec665cfe78b82c144cce15a8b2e30f343385fadd1251849",
|
"zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0",
|
||||||
"zh:cc4f69397d9bc34a528a5609a024c3a48f54f21616c0008792dd417297add955",
|
"zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5",
|
||||||
"zh:df99cdb8b064aad35ffea77e645cf6541d0b1b2ebc51b6d26c42031de60ab69e",
|
"zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036",
|
||||||
|
"zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
version = "4.52.1"
|
version = "4.52.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,16 +23,24 @@ services:
|
|||||||
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
|
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
|
||||||
build:
|
build:
|
||||||
context: ../
|
context: ../
|
||||||
dockerfile: server/Dockerfile
|
dockerfile: server/Dockerfile.dev
|
||||||
target: dev
|
target: dev
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ../server:/usr/src/app/server
|
- ..:/usr/src/app
|
||||||
- ../open-api:/usr/src/app/open-api
|
|
||||||
- ${UPLOAD_LOCATION}/photos:/data
|
- ${UPLOAD_LOCATION}/photos:/data
|
||||||
- ${UPLOAD_LOCATION}/photos/upload:/data/upload
|
|
||||||
- /usr/src/app/server/node_modules
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- pnpm-store:/usr/src/app/.pnpm-store
|
||||||
|
- server-node_modules:/usr/src/app/server/node_modules
|
||||||
|
- web-node_modules:/usr/src/app/web/node_modules
|
||||||
|
- github-node_modules:/usr/src/app/.github/node_modules
|
||||||
|
- cli-node_modules:/usr/src/app/cli/node_modules
|
||||||
|
- docs-node_modules:/usr/src/app/docs/node_modules
|
||||||
|
- e2e-node_modules:/usr/src/app/e2e/node_modules
|
||||||
|
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
|
||||||
|
- app-node_modules:/usr/src/app/node_modules
|
||||||
|
- sveltekit:/usr/src/app/web/.svelte-kit
|
||||||
|
- coverage:/usr/src/app/web/coverage
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -58,19 +66,20 @@ services:
|
|||||||
- 9231:9231
|
- 9231:9231
|
||||||
- 2283:2283
|
- 2283:2283
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
redis:
|
||||||
- database
|
condition: service_started
|
||||||
|
database:
|
||||||
|
condition: service_started
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: false
|
disable: false
|
||||||
|
|
||||||
immich-web:
|
immich-web:
|
||||||
container_name: immich_web
|
container_name: immich_web
|
||||||
image: immich-web-dev:latest
|
image: immich-web-dev:latest
|
||||||
# Needed for rootless docker setup, see https://github.com/moby/moby/issues/45919
|
|
||||||
# user: 0:0
|
|
||||||
build:
|
build:
|
||||||
context: ../
|
context: ../
|
||||||
dockerfile: web/Dockerfile
|
dockerfile: server/Dockerfile.dev
|
||||||
|
target: dev
|
||||||
command: ['immich-web']
|
command: ['immich-web']
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
@@ -78,18 +87,26 @@ services:
|
|||||||
- 3000:3000
|
- 3000:3000
|
||||||
- 24678:24678
|
- 24678:24678
|
||||||
volumes:
|
volumes:
|
||||||
- ../web:/usr/src/app/web
|
- ..:/usr/src/app
|
||||||
- ../i18n:/usr/src/app/i18n
|
- pnpm-store:/usr/src/app/.pnpm-store
|
||||||
- ../open-api/:/usr/src/app/open-api/
|
- server-node_modules:/usr/src/app/server/node_modules
|
||||||
# - ../../ui:/usr/ui
|
- web-node_modules:/usr/src/app/web/node_modules
|
||||||
- /usr/src/app/web/node_modules
|
- github-node_modules:/usr/src/app/.github/node_modules
|
||||||
|
- cli-node_modules:/usr/src/app/cli/node_modules
|
||||||
|
- docs-node_modules:/usr/src/app/docs/node_modules
|
||||||
|
- e2e-node_modules:/usr/src/app/e2e/node_modules
|
||||||
|
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
|
||||||
|
- app-node_modules:/usr/src/app/node_modules
|
||||||
|
- sveltekit:/usr/src/app/web/.svelte-kit
|
||||||
|
- coverage:/usr/src/app/web/coverage
|
||||||
ulimits:
|
ulimits:
|
||||||
nofile:
|
nofile:
|
||||||
soft: 1048576
|
soft: 1048576
|
||||||
hard: 1048576
|
hard: 1048576
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- immich-server
|
immich-server:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
immich-machine-learning:
|
immich-machine-learning:
|
||||||
container_name: immich_machine_learning
|
container_name: immich_machine_learning
|
||||||
@@ -117,13 +134,13 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:facc1d2c3462975c34e10fccb167bfa92b0e0dbd992fc282c29a61c3243afb11
|
image: docker.io/valkey/valkey:8-bookworm@sha256:fea8b3e67b15729d4bb70589eb03367bab9ad1ee89c876f54327fc7c6e618571
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -161,3 +178,14 @@ volumes:
|
|||||||
model-cache:
|
model-cache:
|
||||||
prometheus-data:
|
prometheus-data:
|
||||||
grafana-data:
|
grafana-data:
|
||||||
|
pnpm-store:
|
||||||
|
server-node_modules:
|
||||||
|
web-node_modules:
|
||||||
|
github-node_modules:
|
||||||
|
cli-node_modules:
|
||||||
|
docs-node_modules:
|
||||||
|
e2e-node_modules:
|
||||||
|
sdk-node_modules:
|
||||||
|
app-node_modules:
|
||||||
|
sveltekit:
|
||||||
|
coverage:
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:facc1d2c3462975c34e10fccb167bfa92b0e0dbd992fc282c29a61c3243afb11
|
image: docker.io/valkey/valkey:8-bookworm@sha256:fea8b3e67b15729d4bb70589eb03367bab9ad1ee89c876f54327fc7c6e618571
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -95,7 +95,7 @@ services:
|
|||||||
command: ['./run.sh', '-disable-reporting']
|
command: ['./run.sh', '-disable-reporting']
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:12.1.0-ubuntu@sha256:397aa30dd1af16cb6c5c9879498e467973a7f87eacf949f6d5a29407a3843809
|
image: grafana/grafana:12.1.1-ubuntu@sha256:d1da838234ff2de93e0065ee1bf0e66d38f948dcc5d718c25fa6237e14b4424a
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:facc1d2c3462975c34e10fccb167bfa92b0e0dbd992fc282c29a61c3243afb11
|
image: docker.io/valkey/valkey:8-bookworm@sha256:fea8b3e67b15729d4bb70589eb03367bab9ad1ee89c876f54327fc7c6e618571
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
POSTGRES_USER: ${DB_USERNAME}
|
POSTGRES_USER: ${DB_USERNAME}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati
|
|||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
```
|
```
|
||||||
$ npm install
|
$ pnpm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Local Development
|
### Local Development
|
||||||
|
|
||||||
```
|
```
|
||||||
$ npm run start
|
$ pnpm run start
|
||||||
```
|
```
|
||||||
|
|
||||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||||
@@ -19,7 +19,7 @@ This command starts a local development server and opens up a browser window. Mo
|
|||||||
### Build
|
### Build
|
||||||
|
|
||||||
```
|
```
|
||||||
$ npm run build
|
$ pnpm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||||
@@ -29,13 +29,13 @@ This command generates static content into the `build` directory and can be serv
|
|||||||
Using SSH:
|
Using SSH:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ USE_SSH=true npm run deploy
|
$ USE_SSH=true pnpm run deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
Not using SSH:
|
Not using SSH:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ GIT_USER=<Your GitHub username> npm run deploy
|
$ GIT_USER=<Your GitHub username> pnpm run deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
---
|
|
||||||
slug: release-1-36
|
|
||||||
title: Release v1.36.0
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [release]
|
|
||||||
date: 2022-11-10
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello everyone, it is my pleasure to deliver the new release of Immich to you. The team has been working hard to bring you the new features and improvements. This release includes some big features that the community has been asking since the beginning of Immich. We hope you will enjoy it.
|
|
||||||
|
|
||||||
Some notable features are:
|
|
||||||
|
|
||||||
- OAuth integration
|
|
||||||
- LivePhoto support on iOS
|
|
||||||
- User config system
|
|
||||||
|
|
||||||
<!--truncate-->
|
|
||||||
|
|
||||||
## LivePhoto iOS Support 🎉
|
|
||||||
|
|
||||||
LivePhoto on iOS is now supported in Immich.
|
|
||||||
|
|
||||||
The motion part will now be uploaded and can be played on the mobile app and the web.
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
|
|
||||||
- The server and the app has to be on version **1.36.x** for the application to work correctly.
|
|
||||||
- Previous uploaded photos will not be updated automatically, you will have to remove and reupload them if you want to keep the LivePhoto functionality.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://media.giphy.com/media/fTrGceZd7t1ewi8ESc/giphy.gif"
|
|
||||||
width="100%"
|
|
||||||
style={{
|
|
||||||
borderRadius: '10px',
|
|
||||||
boxShadow: 'rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px',
|
|
||||||
}}
|
|
||||||
title="LivePhoto playback on the web"
|
|
||||||
/>
|
|
||||||
|
|
||||||
## OAuth Integration 🎉
|
|
||||||
|
|
||||||
I want to borrow this chance to express my gratitude to [@EnricoBilla](https://github.com/EnricoBilla), who has been the trailblazer for this feature since the beginning days of Immich. His PR has sparked ideas, suggestions, and discussion among the team member on how to integrate this feature successfully into the app. Thank you so much for your work and your time.
|
|
||||||
|
|
||||||
OAuth is now integrated into the system. Please follow the guide [here](https://immich.app/docs/usage/oauth) to set up your OAuth integration
|
|
||||||
|
|
||||||
After setting up the correct environment variables in the `.env` file, as shown below
|
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
|
||||||
| ------------------- | ------- | -------------------- | ------------------------------------------------------------------------- |
|
|
||||||
| OAUTH_ENABLED | boolean | false | Enable/disable OAuth2 |
|
|
||||||
| OAUTH_ISSUER_URL | URL | (required) | Required. Self-discovery URL for client |
|
|
||||||
| OAUTH_CLIENT_ID | string | (required) | Required. Client ID |
|
|
||||||
| OAUTH_CLIENT_SECRET | string | (required) | Required. Client Secret |
|
|
||||||
| OAUTH_SCOPE | string | openid email profile | Full list of scopes to send with the request (space delimited) |
|
|
||||||
| OAUTH_AUTO_REGISTER | boolean | true | When true, will automatically register a user the first time they sign in |
|
|
||||||
| OAUTH_BUTTON_TEXT | string | Login with OAuth | Text for the OAuth button on the web |
|
|
||||||
|
|
||||||
```bash title="Authentik Example"
|
|
||||||
OAUTH_ENABLED=true
|
|
||||||
OAUTH_ISSUER_URL=http://10.1.15.216:9000/application/o/immich-test/
|
|
||||||
OAUTH_CLIENT_ID=30596v8f78a4b6a97d5985c3076b6b4c4d12ddc33
|
|
||||||
OAUTH_CLIENT_SECRET=50f1eafdec353b95b1c638db390db4ab67ef035a51212dbec2f56175e2eb272b5d572c099176e6fe116ecf47ffdd544bgdb9e2edc588307ee0339d25eeccd88
|
|
||||||
OAUTH_BUTTON_TEXT=Login with Authentik
|
|
||||||
```
|
|
||||||
|
|
||||||
The web will have the option to sign in with OAuth.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://user-images.githubusercontent.com/27055614/202923726-f43fa148-47f5-4182-8f29-b0b87e4586fa.png"
|
|
||||||
width="50%"
|
|
||||||
title="Web Sign in with OAuth"
|
|
||||||
style={{
|
|
||||||
borderRadius: '10px',
|
|
||||||
boxShadow: 'rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
The mobile app will check if the server has OAuth enabled before displaying the OAuth
|
|
||||||
sign-in button.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://media.giphy.com/media/3iy3SaNkVYtlkEiw06/giphy.gif"
|
|
||||||
title="Mobile sign in with OAuth"
|
|
||||||
style={{
|
|
||||||
borderRadius: '10px',
|
|
||||||
boxShadow: 'rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://media.giphy.com/media/LStqgGESXW8XnuCv5y/giphy.gif"
|
|
||||||
width="300"
|
|
||||||
style={{
|
|
||||||
borderRadius: '10px',
|
|
||||||
boxShadow: 'rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px',
|
|
||||||
}}
|
|
||||||
title="Support the project"
|
|
||||||
/>
|
|
||||||
|
|
||||||
If you find the project helpful and it helps you in some ways, you can support the project [one time](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) or [monthly](https://github.com/sponsors/alextran1502) from GitHub Sponsor
|
|
||||||
|
|
||||||
It is a great way to let me know that you want me to continue developing and working on this project for years to come.
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
For more details, please check out the [release note](https://github.com/immich-app/immich/releases/tag/v1.36.0_55-dev)
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
---
|
|
||||||
title: Immich Update - June 2023
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [update]
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello everybody, Alex here!
|
|
||||||
|
|
||||||
I am back with another update on Immich. It has been only a month since my last update (May 18th, 2023), but it seems forever. I think the rapid releases of Immich and the amount of work make the perspective of time change in Immich’s world. We have some exciting updates that I think you will like.
|
|
||||||
|
|
||||||
Before going into detail, on behalf of the core team, I would like to thank all of you for loving Immich and contributing to the project. Thank you for helping me make Immich an enjoyable alternative solution to Google Photos so that you have complete control of your data and privacy. I know we are still young and have a lot of work to do, but I am confident we will get there with help from the community. I appreciate all of you from the bottom of my heart!
|
|
||||||
|
|
||||||
<!--truncate-->
|
|
||||||
|
|
||||||
And now, to the exciting part, what is new in Immich’s world?
|
|
||||||
|
|
||||||
- Initial support for existing gallery.
|
|
||||||
- Memory feature.
|
|
||||||
- Support XMP sidecar.
|
|
||||||
- Support more raw formats.
|
|
||||||
- Justified layout for web timeline and blurred thumbnail hash.
|
|
||||||
- Mechanism to host machine learning on a completely different machine.
|
|
||||||
|
|
||||||
## Support for existing gallery
|
|
||||||
|
|
||||||
I know this is the most controversial feature when it comes to Immich’s way of ingesting photos and videos. For many users, having to upload photos and videos to Immich is simply not working. We listen, discuss, and digest this feature internally more than you imagine because it is not a simple feature to tackle while keeping the performance and the user experience at the top level, which is Immich’s primary goal.
|
|
||||||
|
|
||||||
Thankfully, we have many great contributors and developers that want to make this come true. So we came up with an initial implementation of this feature in the form of a supporting read-only gallery.
|
|
||||||
|
|
||||||
To be concise, Immich can now read in the gallery files, register the path into the database, and then generate necessary files and put them through Immich’s machine learning pipeline so you can use all the goodness of Immich without the need to upload them. Since this is the initial implementation, some actions/behavior are not yet supported, and we aim to build toward them in future releases, namely:
|
|
||||||
|
|
||||||
- Assets are not automatically synced and must instead be manually synced with the CLI tool.
|
|
||||||
- Only new files that are added to the gallery will be detected.
|
|
||||||
- Deleted and moved files will not be detected.
|
|
||||||
|
|
||||||
## Memory feature
|
|
||||||
|
|
||||||
This is considered a fun feature that the team and I wanted to build for so long, but we had to put it off because of the refactoring of the code base. The code base is now in a good enough form to circle back and add more exciting features.
|
|
||||||
|
|
||||||
This memory feature is very much similar to GPhotos' implementation of “x years since…”. We are aiming to add more categories of memories in the future, such as “Spotlight of the day” or “Day of the Week highlights”
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://www.youtube.com/embed/j5XZKvViPew"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
This feature is now available on the web and will be ported to the mobile app in the near future.
|
|
||||||
|
|
||||||
## Support XMP Sidecar
|
|
||||||
|
|
||||||
Immich can now import/upload XMP sidecars from the CLI and use the information as the metadata of assets.
|
|
||||||
|
|
||||||
## Support more raw formats.
|
|
||||||
|
|
||||||
With the recent updates on the dependencies of Immich, we are now extending and hardening support for multiple raw formats. So users with DSLR or mirrorless cameras can now upload their original files to Immich and have them displayed in high-quality thumbnails on the web and mobile view.
|
|
||||||
|
|
||||||
## Justified layout for web timeline and blurred thumbnail hash
|
|
||||||
|
|
||||||
This is an aesthetic improvement in user experience when browsing the timeline. Photos and videos are now displayed correctly with perspective orientation, making the browsing experience more pleasurable.
|
|
||||||
|
|
||||||
To further improve the browsing experience, we now added a blur hash to the thumbnail, so the transition is more natural with a dreamy fade in effect, similar to how our brain goes from faded to vivid memory
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://www.youtube.com/embed/b95FLmGHRFc"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
## Hosting machine learning container on a different machine
|
|
||||||
|
|
||||||
With more capabilities Immich is building toward, machine learning will get more powerful and therefore require more resources to run effectively. However, we understand that users might not have the best server resources where they host the Immich instance. Therefore, we changed how machine learning interacts and receives the photos and videos to run through its inference pipeline.
|
|
||||||
|
|
||||||
The machine learning container is now a headless system that can run on any machine. As long as your Immich instance can communicate with the system running the machine learning container, it can send the files and receive the required information to make Immich powerful in terms of searching and intelligence. This helps you to utilize a more powerful machine in your home/infrastructure to perform the CPU-intensive tasks while letting Immich only handle the I/O operations for a pleasant and smooth experience.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
So, those are the highlights for the team and the community after a busy month. There are a lot more changes and improvements. I encourage you to read some release notes, starting from version [v1.57.0](https://github.com/immich-app/immich/releases/tag/v1.57.0) to now.
|
|
||||||
|
|
||||||
Thank you, and I am asking for your support for the project. I hope to be a full-time maintainer of Immich one day to dedicate myself to the project as my life works for the community and my family. You can find the support channels below:
|
|
||||||
|
|
||||||
- Monthly donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502)
|
|
||||||
- One-time donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502)
|
|
||||||
- [Liberapay](https://liberapay.com/alex.tran1502/)
|
|
||||||
- [buymeacoffee](https://www.buymeacoffee.com/altran1502)
|
|
||||||
- Bitcoin: 3QVAb9dCHutquVejeNXitPqZX26Yg5kxb7
|
|
||||||
- Give a project a star - the contributors love gazing at the stars and seeing their creations shining in the sky.
|
|
||||||
|
|
||||||
Join our friendly [Discord](https://discord.immich.app) to talk and discuss Immich, tech, or anything
|
|
||||||
|
|
||||||
Cheer!
|
|
||||||
|
|
||||||
Until next time!
|
|
||||||
|
|
||||||
Alex
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 MiB |
@@ -1,151 +0,0 @@
|
|||||||
---
|
|
||||||
title: Immich Update - July 2023
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [update, v1.64.0-v1.71.0]
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello, Immich fans, another month, another milestone. We hope you are staying cool and safe in this scorching hot summer across the globe.
|
|
||||||
|
|
||||||
Immich recently got some good recognition when getting to the front page of HackerNews, which helped to let more people know about the project's existence. The project will help more and more people find a solution to control the privacy of their most precious moments. And with the gain in popularity and recognition, we have gotten new users and more questions from the community than ever.
|
|
||||||
|
|
||||||
I want to express my gratitude to all the contributors and the community who have been tremendously helpful to new users' questions and provided technical support.
|
|
||||||
|
|
||||||
Below are the highlights of new features we added to the application over the past month, along with countless bug fixes and improvements across the board, from developer experience to resource optimization and UI/UX improvement. I hope you find these topics as exciting as I am.
|
|
||||||
|
|
||||||
## Highlights
|
|
||||||
|
|
||||||
- Memories feature.
|
|
||||||
- Facial recognition improvements.
|
|
||||||
- Improvements on multi selection behavior on the web.
|
|
||||||
- Shortcuts for common actions on the web.
|
|
||||||
- Support viewer for 360-panorama photos.
|
|
||||||
|
|
||||||
<!--truncate-->
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Memories feature
|
|
||||||
|
|
||||||
We've added the memory feature on the mobile app, so you can reminisce about your past memories.
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://youtube.com/embed/c7OTl-RqNRE"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
### Facial recognition improvements
|
|
||||||
|
|
||||||
Over the past few releases, we have added many UI improvements to the facial recognition feature to help you manage the recognized people better. Some of the highlights:
|
|
||||||
|
|
||||||
#### Choose a new feature photo for a person.
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://youtube.com/embed/PmJp8DmSh1U"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
#### Hide and show faces.
|
|
||||||
|
|
||||||
You can now select irrelevant faces to hide them. The hidden faces won’t be displayed in search results and the people section in the info panel.
|
|
||||||
|
|
||||||
#### Merge faces.
|
|
||||||
|
|
||||||
This is useful when you have multiple faces of the same person in your photos, and you want to merge them into one.
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://youtube.com/embed/-Xskhw-vpc4"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
We also added a nifty mechanism that when naming a face, similar names will prompt you a merge face option for the convenience.
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://youtube.com/embed/XzE6wficbl4"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
### Improvements on multi selection behavior on the web
|
|
||||||
|
|
||||||
We have added a new multi selection behavior on the web to help you select multiple items easier. You can now select a range of photos and videos by holding the `Shift` key.
|
|
||||||
|
|
||||||
<iframe
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
src="https://youtube.com/embed/e_SiuHpVnmM"
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
### Shortcuts for common actions on the web.
|
|
||||||
|
|
||||||
Some of us only navigate the world and the web with a keyboard (looking at you, Vim and Emacs users). So it would take away the sacred weapon of choice to require many clicks to perform repetitive actions. So we added quick shortcuts for the following action on the web.
|
|
||||||
|
|
||||||
<img
|
|
||||||
src={require('./images/web-shortcuts-panel.png').default}
|
|
||||||
width="100%"
|
|
||||||
style={{ borderRadius: '25px' }}
|
|
||||||
alt="Dot Env Example"
|
|
||||||
/>
|
|
||||||
|
|
||||||
### Support viewer for 360-panorama photos.
|
|
||||||
|
|
||||||
Photos with the EXIF property of `ProjectionType` will now have a special viewer on the web to view all the angles of the panorama.
|
|
||||||
|
|
||||||
The thumbnail of the 360 degrees panoramas will have a special icon on the top right of the thumbnail
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://github.com/immich-app/immich/assets/61410067/728ca1b0-375c-4631-8081-a609843e702f"
|
|
||||||
width="50%"
|
|
||||||
style={{ borderRadius: '25px' }}
|
|
||||||
alt="Dot Env Example"
|
|
||||||
/>
|
|
||||||
|
|
||||||
Panorama in the detail view
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="https://github.com/immich-app/immich/assets/61410067/3c89dac4-395d-45fa-9bc5-98a6248fd476"
|
|
||||||
width="50%"
|
|
||||||
style={{ borderRadius: '25px' }}
|
|
||||||
alt="Dot Env Example"
|
|
||||||
/>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Thank you, and I am asking for your support for the project. I hope to be a full-time maintainer of Immich one day to dedicate myself to the project as my life's work for the community and my family. You can find the support channels below:
|
|
||||||
|
|
||||||
- Monthly donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502)
|
|
||||||
- One-time donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502)
|
|
||||||
- [Liberapay](https://liberapay.com/alex.tran1502/)
|
|
||||||
- [buymeacoffee](https://www.buymeacoffee.com/altran1502)
|
|
||||||
- Bitcoin: 3QVAb9dCHutquVejeNXitPqZX26Yg5kxb7
|
|
||||||
- Give a project a star - the contributors love gazing at the stars and seeing their creations shining in the sky.
|
|
||||||
|
|
||||||
Join our friendly [Discord](https://discord.immich.app) to talk and discuss Immich, tech, or anything
|
|
||||||
|
|
||||||
Cheer!
|
|
||||||
|
|
||||||
Until next time!
|
|
||||||
|
|
||||||
Alex
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
---
|
|
||||||
title: Immich Recap 2023
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [update, recap-2023]
|
|
||||||
date: 2023-12-30T00:00
|
|
||||||
---
|
|
||||||
|
|
||||||
Hi everyone,
|
|
||||||
|
|
||||||
Alex from Immich here.
|
|
||||||
|
|
||||||
We are entering the last few weeks of 2023, and it has been quite a year for Immich. The project has grown so much in terms of users, developers, features, maturity, and the community around it. When I started working on Immich, it was simply a challenge for myself and an opportunity to learn new technologies, crafting something fun and useful for my wife during my free time to satisfy my urge to build and create things. I never thought it would become so popular and help so many people. At the end of the day, all we have is memory. I am proud that the team and I have created something to make storing and viewing those precious memories easier without restrictions and without sacrificing our privacy. As the year closes, here’s a recap of everything the project accomplished in 2023.
|
|
||||||
|
|
||||||
# Milestones
|
|
||||||
|
|
||||||
- Public shared links
|
|
||||||
- Favorites page
|
|
||||||
- Immich turned 1
|
|
||||||
- Material Design 3 on the mobile app
|
|
||||||
- Auto-link LivePhotos server-side
|
|
||||||
- iOS background backup
|
|
||||||
- Explore page
|
|
||||||
- CLIP search
|
|
||||||
- Search by metadata
|
|
||||||
- Responsive web app
|
|
||||||
- Archive page
|
|
||||||
- Asset descriptions
|
|
||||||
- 10,000 stars on GitHub
|
|
||||||
- Manage auth devices
|
|
||||||
- Map view
|
|
||||||
- Facial recognition, clustering, searching, renaming, and person management
|
|
||||||
- Partner sharing and unifying timeline between partners' users
|
|
||||||
- Custom storage label
|
|
||||||
- XMP sidecar reading
|
|
||||||
- RAW file formats
|
|
||||||
- Justified layout on the web
|
|
||||||
- Memories
|
|
||||||
- Multi-select via SHIFT
|
|
||||||
- Android Motion Photos
|
|
||||||
- 360° Photos
|
|
||||||
- Album description
|
|
||||||
- Album performance improvements (time buckets)
|
|
||||||
- Video hardware transcoding
|
|
||||||
- Slideshow mode on the web
|
|
||||||
- Configuration file
|
|
||||||
- External libraries
|
|
||||||
- Trash page
|
|
||||||
- Custom theme
|
|
||||||
- Asset Stacking
|
|
||||||
- 20,000 stars on GitHub
|
|
||||||
- Shared album activity and comments
|
|
||||||
- CLI v2
|
|
||||||
- Down to 5 containers (from 8)
|
|
||||||
|
|
||||||
# Fun Statistics
|
|
||||||
|
|
||||||
- We have gone from the release version `1.41.0` to `1.90.0` at the time of writing. On average, we see a release every 7 days.
|
|
||||||
- According to GitHub's metrics, the `immich-server` container image has been pulled almost _4 million_ times.
|
|
||||||
- According to mobile app store metrics, we have 22,000 installations on Android and 6700 installation units on iOS (opt-in only).
|
|
||||||
- Immich is making around $1200/month on average from donations. (Thank you all so much!)
|
|
||||||
- We were guests on two podcasts:
|
|
||||||
- [Self-hosted](https://selfhosted.show/110)
|
|
||||||
- [The Vergecast](https://www.theverge.com/23938533/self-hosting-local-first-software-vergecast)
|
|
||||||
- There are over 4,500 members on the Discord server.
|
|
||||||
- We have over 22,000 stars on the main GitHub repository, gaining 15,000 stars since January 2023.
|
|
||||||
|
|
||||||
Diving into the next year, the team will continue to build on the foundation we have laid out over the past year, implementing more advanced features for searching, organizing, and sharing between users. Bugs will continue to be squashed and conquered. “Shit Alex wrote'' code will continue to be replaced by beautiful, clean code from Jason, Zack, Boet, Daniel, Osorin, Mert, Fynn, Marty, Martin, and Jonathan. The team has my eternal gratitude for creating a welcoming environment for new contributors, helping, teaching, and learning from each other. I’ve realized that hardly a day has gone by where the team hasn’t been in communication about Immich related topics over the past year.
|
|
||||||
|
|
||||||
My long-term goal is to help hone Immich into a diamond in the FOSS space, where the UI, UX, development experiences, documentation, and quality are at a high standard while remaining free for everybody to use.
|
|
||||||
|
|
||||||
I hope you enjoy Immich and have a happy and peaceful holiday.
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
title: The Immich core team goes full-time
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [update, announcement, FUTO]
|
|
||||||
date: 2024-05-01T00:00
|
|
||||||
---
|
|
||||||
|
|
||||||
**Immich is joining [FUTO](https://futo.org/)!**
|
|
||||||
|
|
||||||
Since the beginning of this adventure, my goal has always been to create a better world for my children. Memories are priceless, and privacy should not be a luxury. However, building quality open source has its challenges. Over the past two years, it has taken significant dedication, time, and effort.
|
|
||||||
|
|
||||||
Recently, a company in Austin, Texas, called FUTO contacted the team. FUTO strives to develop quality and sustainable open software. They build software alternatives that focus on giving control to users. From their mission statement:
|
|
||||||
|
|
||||||
“Computers should belong to you, the people. We develop and fund technology to give them back.”
|
|
||||||
|
|
||||||
FUTO loved Immich and wanted to see if we’d consider working with them to take the project to the next level. In short, FUTO offered to:
|
|
||||||
|
|
||||||
- Pay the core team to work on Immich full-time
|
|
||||||
- Let us keep full autonomy about the project’s direction and leadership
|
|
||||||
- Continue to license Immich under AGPL
|
|
||||||
- Keep Immich’s development direction with no paywalled features
|
|
||||||
- Keep Immich “built for the people” (no ads, data mining/selling, or alternative motives)
|
|
||||||
- Provide us with financial, technical, legal, and administrative support
|
|
||||||
|
|
||||||
After careful deliberation, the team decided that FUTO’s vision closely aligns with our own: to build a better future by providing a polished, performant, and privacy-preserving open-source software solution for photo and video management delivered in a sustainable way.
|
|
||||||
|
|
||||||
Immich’s future has never looked brighter, and we look forward to realizing our vision for Immich as part of FUTO.
|
|
||||||
|
|
||||||
If you have more questions, we’ll host a Q&A live stream on May 9th at 3PM UTC (10AM CST). [You can ask questions here](https://www.live-ask.com/event/01HWP2SB99A1K8EXFBDKZ5Z9CF), and the stream will be live [here on our YouTube channel](https://youtube.com/live/cwz2iZwYpgg).
|
|
||||||
|
|
||||||
Cheers,
|
|
||||||
|
|
||||||
The Immich Team
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## FAQs
|
|
||||||
|
|
||||||
### What is FUTO?
|
|
||||||
|
|
||||||
[https://futo.org/what-is-futo/](https://futo.org/what-is-futo/)
|
|
||||||
|
|
||||||
### Will the license change?
|
|
||||||
|
|
||||||
No. Immich will continue to be licensed under AGPL without a CLA.
|
|
||||||
|
|
||||||
### Will Immich continue to be free?
|
|
||||||
|
|
||||||
Yes. The Immich source code will remain freely available under the AGPL license.
|
|
||||||
|
|
||||||
### Is Immich getting VC funding?
|
|
||||||
|
|
||||||
No. Venture capital implies investment in a business, often with the expectation of a future payout (exit plan). Immich is neither a business that can be acquired nor comes with a money-making exit plan.
|
|
||||||
|
|
||||||
### I am currently supporting Immich through GitHub sponsors. What will happen to my donation?
|
|
||||||
|
|
||||||
Effective immediately, all donations to the Immich organization will be canceled. In the future, we will offer an optional, modest payment option instead. Thank you to everyone who donated to help us get this far!
|
|
||||||
|
|
||||||
### How is funding sustainable?
|
|
||||||
|
|
||||||
Immich and FUTO believe a sustainable future requires a model that does not rely on users-as-a-product. To this end, FUTO advocates that users pay for good, open software. In keeping with this model, we will adopt a purchase price. This means we no longer accept donations, but — _without limiting features for those who do not pay_ — we will soon allow you to purchase Immich through a modest payment. We encourage you to pay for the high-quality software you use to foster a healthy software culture where developers build great applications without hidden motives for their users.
|
|
||||||
|
|
||||||
### When does this change take effect?
|
|
||||||
|
|
||||||
This change takes effect immediately.
|
|
||||||
|
|
||||||
### What will change?
|
|
||||||
|
|
||||||
The following things will change as Immich joins FUTO:
|
|
||||||
|
|
||||||
- The brand, logo, and other Immich trademarks will be transferred to FUTO.
|
|
||||||
- We will stop all donations to the project.
|
|
||||||
- The core team can now dedicate our full attention to Immich
|
|
||||||
- Before the end of the year, we plan to have a roadmap for what it will take to get Immich to a stable release.
|
|
||||||
- Bugs will be squashed, and features will be delivered faster.
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
---
|
|
||||||
title: Licensing announcement - Purchase a license to support Immich
|
|
||||||
authors: [alextran]
|
|
||||||
tags: [update, announcement, FUTO]
|
|
||||||
date: 2024-07-18T00:00
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello everybody,
|
|
||||||
|
|
||||||
Firstly, on behalf of the Immich team, I'd like to thank everybody for your continuous support of Immich since the very first day! Your contributions, encouragement, and community engagement have helped bring Immich to its current state. The team and I are forever grateful for that.
|
|
||||||
|
|
||||||
Since our [last announcement of the core team joining FUTO to work on Immich full-time](https://immich.app/blog/2024/immich-core-team-goes-fulltime), one of the goals of our new position is to foster a healthy relationship between the developers and the users. We believe that this enables us to create great software, establish transparent policies and build trust.
|
|
||||||
|
|
||||||
We want to build a great software application that brings value to you and your loved ones' lives. We are not using you as a product, i.e., selling or tracking your data. We are not putting annoying ads into our software. We respect your privacy. We want to be compensated for the hard work we put in to build Immich for you.
|
|
||||||
|
|
||||||
With those notes, we have enabled a way for you to financially support the continued development of Immich, ensuring the software can move forward and will be maintained, by offering a lifetime license of the software. We think if you like and use software, you should pay for it, but _we're never going to force anyone to pay or try to limit Immich for those who don't._
|
|
||||||
|
|
||||||
There are two types of license that you can choose to purchase: **Server License** and **Individual License**.
|
|
||||||
|
|
||||||
### Server License
|
|
||||||
|
|
||||||
This is a lifetime license costing **$99.99**. The license is applied to the whole server. You and all users that use your server are licensed.
|
|
||||||
|
|
||||||
### Individual License
|
|
||||||
|
|
||||||
This is a lifetime license costing **$24.99**. The license is applied to a single user, and can be used on any server they choose to connect to.
|
|
||||||
|
|
||||||
<img
|
|
||||||
width="837"
|
|
||||||
alt="license-social-gh"
|
|
||||||
src="https://github.com/user-attachments/assets/241932ed-ef3b-44ec-a9e2-ee80754e0cca"
|
|
||||||
/>
|
|
||||||
|
|
||||||
You can purchase the license on [our page - https://buy.immich.app](https://buy.immich.app).
|
|
||||||
|
|
||||||
Starting with release `v1.109.0` you can purchase and enter your purchased license key directly in the app.
|
|
||||||
|
|
||||||
<img
|
|
||||||
width="1414"
|
|
||||||
alt="license-page-gh"
|
|
||||||
src="https://github.com/user-attachments/assets/364fc32a-f6ef-4594-9fea-28d5a26ad77c"
|
|
||||||
/>
|
|
||||||
|
|
||||||
## Thank you
|
|
||||||
|
|
||||||
Thank you again for your support, this will help create a strong foundation and stability for the Immich team to continue developing and maintaining the project that you love to use.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img
|
|
||||||
src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjY2eWc5Y2F0ZW56MmR4aWE0dDhzZXlidXRmYWZyajl1bWZidXZpcyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/87CKDqErVfMqY/giphy.gif"
|
|
||||||
width="550"
|
|
||||||
title="SUPPORT THE PROJECT!"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
|
|
||||||
Cheers! 🎉
|
|
||||||
|
|
||||||
Immich team
|
|
||||||
|
|
||||||
# FAQ
|
|
||||||
|
|
||||||
### 1. Where can I purchase a license?
|
|
||||||
|
|
||||||
There are several places where you can purchase the license from
|
|
||||||
|
|
||||||
- [https://buy.immich.app](https://buy.immich.app)
|
|
||||||
- [https://pay.futo.org](https://pay.futo.org/)
|
|
||||||
- or directly from the app.
|
|
||||||
|
|
||||||
### 2. Do I need both _Individual License_ and _Server License_?
|
|
||||||
|
|
||||||
No,
|
|
||||||
|
|
||||||
If you are the admin and the sole user, or your instance has less than a total of 4 users, you can buy the **Individual License** for each user.
|
|
||||||
|
|
||||||
If your instance has more than 4 users, it is more cost-effective to buy the **Server License**, which will license all the users on your instance.
|
|
||||||
|
|
||||||
### 3. What do I do if I don't pay?
|
|
||||||
|
|
||||||
You can continue using Immich without any restriction.
|
|
||||||
|
|
||||||
### 4. Will there be any paywalled features?
|
|
||||||
|
|
||||||
No, there will never be any paywalled features.
|
|
||||||
|
|
||||||
### 5. Where can I get support regarding payment issues?
|
|
||||||
|
|
||||||
You can email us with your `orderId` and your email address `billing@futo.org` or on our Discord server.
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
---
|
|
||||||
title: Immich Update - July 2024
|
|
||||||
authors: [alextran]
|
|
||||||
date: 2024-07-01T00:00
|
|
||||||
tags: [update, v1.106.0]
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello everybody! Alex from Immich here and I am back with another development progress update for the project.
|
|
||||||
|
|
||||||
Summer has returned once again, and the night sky is filled with stars, thank you for **38_000 shining stars** you have sent to our [GitHub repo](https://github.com/immich-app/immich)! Since the last announcement several core contributors have started full time. Everything is going great with development, PRs get merged with _brrrrrrr_ rate, conversation exchange between team members is on a new high, we met and are working with the great engineers at FUTO. The spirit is high and we have a lot of things brewing that we think you will like.
|
|
||||||
|
|
||||||
Let's go over some of the updates we had since the last post.
|
|
||||||
|
|
||||||
### Container consolidation
|
|
||||||
|
|
||||||
Reduced the number of total containers from 5 to 4 by making the microservices thread get spawned directly in the server container. Woohoo, remember when Immich had 7 containers?
|
|
||||||
|
|
||||||
### Email notifications
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
We added email notifications to the app with SMTP settings that you can configure for the following events
|
|
||||||
|
|
||||||
- A new account is created for you.
|
|
||||||
- You are added to a shared album.
|
|
||||||
- New media is added to an album.
|
|
||||||
|
|
||||||
### Versioned docs
|
|
||||||
|
|
||||||
You can now jump back into the past or take a peek at the unreleased version of the documentation by selecting the version on the website.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Similarity deduplication
|
|
||||||
|
|
||||||
With more machine learning and CLIP magic, we now have similarity deduplication built into the application where it will search for closely similar images and let you decide what to do with them; i.e keep or trash.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Permanent URL for asset on the web
|
|
||||||
|
|
||||||
The detail view for an asset now has a permanent URL so you can easily share them with your loved ones.
|
|
||||||
|
|
||||||
### Web app translations
|
|
||||||
|
|
||||||
We now have a public Weblate project which the community can use to translate the webapp to their native languages. We are planning to port the mobile app translation to this platform as well. If you would like to contribute, you can take a look [here](https://hosted.weblate.org/projects/immich/immich/). We're already close to 50% translations -- we really appreciate everyone contributing to that!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Read-only/Editor mode on shared album
|
|
||||||
|
|
||||||
As the owner of the album, you can choose if the shared user can edit the album or to only view the content of the album without any modification.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Better video thumbnails
|
|
||||||
|
|
||||||
Immich now tries to find a descriptive video thumbnail instead of simply using the first frame. No more black images for thumbnails!
|
|
||||||
|
|
||||||
### Public Roadmap
|
|
||||||
|
|
||||||
We now have a [public roadmap](https://immich.app/roadmap), giving you a high-level overview of things the team is working on. The first goal of this roadmap is to bring Immich to a stable release, which is expected sometime later this year. Some of the highlights include
|
|
||||||
|
|
||||||
- Auto stacking - Auto stacking of burst photos
|
|
||||||
- Basic editor - Basic photo editing capabilities
|
|
||||||
- Workflows - Automate tasks with workflows
|
|
||||||
- Fine grained access controls - Granular access controls for users and api keys
|
|
||||||
- Better background backups - Rework background backups to be more reliable
|
|
||||||
- Private/locked photos - Private assets with extra protections
|
|
||||||
|
|
||||||
Beyond the items in the roadmap, we have _many many_ more ideas for Immich. The team and I hope that you are enjoying the application, find it helpful in your life and we have nothing but the intention of building out great software for you all!
|
|
||||||
|
|
||||||
Have an amazing Summer or Winter for those in the southern hemisphere! :D
|
|
||||||
|
|
||||||
Until next time,
|
|
||||||
|
|
||||||
Cheers!
|
|
||||||
Alex
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
alextran:
|
|
||||||
name: Alex Tran
|
|
||||||
title: Maintainer of Immich
|
|
||||||
url: https://github.com/alextran1502
|
|
||||||
image_url: https://github.com/alextran1502.png
|
|
||||||
@@ -1,5 +1,31 @@
|
|||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
|
## Commercial Guidelines
|
||||||
|
|
||||||
|
### Are you open to commercial partnerships and collaborations?
|
||||||
|
|
||||||
|
We are working to commercialize Immich and we'd love for you to help us by making Immich better. FUTO is dedicated to developing sustainable models for developing open source software for our customers. We want our customers to be delighted by the products our engineers deliver, and we want our engineers to be paid when they succeed.
|
||||||
|
|
||||||
|
If you wish to use Immich in a commercial product not owned by FUTO, we have the following requirements:
|
||||||
|
|
||||||
|
- Plugin Integrations: Integrations for other platforms are typically approved, provided proper notification is given.
|
||||||
|
|
||||||
|
- Reseller Partnerships: Must adhere to the guidelines outlined below regarding trademark usage, and proper representation.
|
||||||
|
|
||||||
|
- Strategic Collaborations: We welcome discussions about mutually beneficial partnerships that enhance the value proposition for both organizations.
|
||||||
|
|
||||||
|
### What are your guidelines for resellers and trademark usage?
|
||||||
|
|
||||||
|
For organizations seeking to resell Immich, we have established the following guidelines to protect our brand integrity and ensure proper representation.
|
||||||
|
|
||||||
|
- We request that resellers do not display our trademarks on their websites or marketing materials. If such usage is discovered, we will contact you to request removal.
|
||||||
|
|
||||||
|
- Do not misrepresent your reseller site or services as being officially affiliated with or endorsed by Immich or our development team.
|
||||||
|
|
||||||
|
- For small resellers who wish to contribute financially to Immich's development, we recommend directing your customers to purchase licenses directy from us rather than attempting to broker revenue-sharing arrangements. We ask that you refrain from misrepresenting reseller activities as directly supporting our development work.
|
||||||
|
|
||||||
|
When in doubt or if you have an edge case scenario, we encourage you to contact us directly via email to discuss the use of our trademark. We can provide clear guidance on what is acceptable and what is not. You can reach out at: questions@immich.app
|
||||||
|
|
||||||
## User
|
## User
|
||||||
|
|
||||||
### How can I reset the admin password?
|
### How can I reset the admin password?
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Unable to set `app.immich:///oauth-callback` as a valid redirect URI? See [Mobil
|
|||||||
|
|
||||||
Immich supports 3rd party authentication via [OpenID Connect][oidc] (OIDC), an identity layer built on top of OAuth2. OIDC is supported by most identity providers, including:
|
Immich supports 3rd party authentication via [OpenID Connect][oidc] (OIDC), an identity layer built on top of OAuth2. OIDC is supported by most identity providers, including:
|
||||||
|
|
||||||
- [Authentik](https://goauthentik.io/integrations/sources/oauth/#openid-connect)
|
- [Authentik](https://integrations.goauthentik.io/media/immich/)
|
||||||
- [Authelia](https://www.authelia.com/integration/openid-connect/immich/)
|
- [Authelia](https://www.authelia.com/integration/openid-connect/immich/)
|
||||||
- [Okta](https://www.okta.com/openid-connect/)
|
- [Okta](https://www.okta.com/openid-connect/)
|
||||||
- [Google](https://developers.google.com/identity/openid-connect/openid-connect)
|
- [Google](https://developers.google.com/identity/openid-connect/openid-connect)
|
||||||
@@ -88,7 +88,7 @@ The `.well-known/openid-configuration` part of the url is optional and will be a
|
|||||||
## Auto Launch
|
## Auto Launch
|
||||||
|
|
||||||
When Auto Launch is enabled, the login page will automatically redirect the user to the OAuth authorization url, to login with OAuth. To access the login screen again, use the browser's back button, or navigate directly to `/auth/login?autoLaunch=0`.
|
When Auto Launch is enabled, the login page will automatically redirect the user to the OAuth authorization url, to login with OAuth. To access the login screen again, use the browser's back button, or navigate directly to `/auth/login?autoLaunch=0`.
|
||||||
Auto Launch can also be enabled on a per-request basis by navigating to `/auth/login?authLaunch=1`, this can be useful in situations where Immich is called from e.g. Nextcloud using the _External sites_ app and the _oidc_ app so as to enable users to directly interact with a logged-in instance of Immich.
|
Auto Launch can also be enabled on a per-request basis by navigating to `/auth/login?autoLaunch=1`, this can be useful in situations where Immich is called from e.g. Nextcloud using the _External sites_ app and the _oidc_ app so as to enable users to directly interact with a logged-in instance of Immich.
|
||||||
|
|
||||||
## Mobile Redirect URI
|
## Mobile Redirect URI
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ After making any changes in the `server/src/schema`, a database migration need t
|
|||||||
1. Run the command
|
1. Run the command
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run migrations:generate <migration-name>
|
pnpm run migrations:generate <migration-name>
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Check if the migration file makes sense.
|
2. Check if the migration file makes sense.
|
||||||
|
|||||||
@@ -204,8 +204,8 @@ When the Dev Container starts, it automatically:
|
|||||||
|
|
||||||
1. **Runs post-create script** (`container-server-post-create.sh`):
|
1. **Runs post-create script** (`container-server-post-create.sh`):
|
||||||
- Adjusts file permissions for the `node` user
|
- Adjusts file permissions for the `node` user
|
||||||
- Installs dependencies: `npm install` in all packages
|
- Installs dependencies: `pnpm install` in all packages
|
||||||
- Builds TypeScript SDK: `npm run build` in `open-api/typescript-sdk`
|
- Builds TypeScript SDK: `pnpm run build` in `open-api/typescript-sdk`
|
||||||
|
|
||||||
2. **Starts development servers** via VS Code tasks:
|
2. **Starts development servers** via VS Code tasks:
|
||||||
- `Immich API Server (Nest)` - API server with hot-reloading on port 2283
|
- `Immich API Server (Nest)` - API server with hot-reloading on port 2283
|
||||||
@@ -243,7 +243,7 @@ To connect the mobile app to your Dev Container:
|
|||||||
|
|
||||||
- **Server code** (`/server`): Changes trigger automatic restart
|
- **Server code** (`/server`): Changes trigger automatic restart
|
||||||
- **Web code** (`/web`): Changes trigger hot module replacement
|
- **Web code** (`/web`): Changes trigger hot module replacement
|
||||||
- **Database migrations**: Run `npm run sync:sql` in the server directory
|
- **Database migrations**: Run `pnpm run sync:sql` in the server directory
|
||||||
- **API changes**: Regenerate TypeScript SDK with `make open-api`
|
- **API changes**: Regenerate TypeScript SDK with `make open-api`
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
@@ -273,19 +273,19 @@ make test-medium-dev # End-to-end tests
|
|||||||
```bash
|
```bash
|
||||||
# Server tests
|
# Server tests
|
||||||
cd /workspaces/immich/server
|
cd /workspaces/immich/server
|
||||||
npm test # Run all tests
|
pnpm test # Run all tests
|
||||||
npm run test:watch # Watch mode
|
pnpm run test:watch # Watch mode
|
||||||
npm run test:cov # Coverage report
|
pnpm run test:cov # Coverage report
|
||||||
|
|
||||||
# Web tests
|
# Web tests
|
||||||
cd /workspaces/immich/web
|
cd /workspaces/immich/web
|
||||||
npm test # Run all tests
|
pnpm test # Run all tests
|
||||||
npm run test:watch # Watch mode
|
pnpm run test:watch # Watch mode
|
||||||
|
|
||||||
# E2E tests
|
# E2E tests
|
||||||
cd /workspaces/immich/e2e
|
cd /workspaces/immich/e2e
|
||||||
npm run test # Run API tests
|
pnpm run test # Run API tests
|
||||||
npm run test:web # Run web UI tests
|
pnpm run test:web # Run web UI tests
|
||||||
```
|
```
|
||||||
|
|
||||||
### Code Quality Commands
|
### Code Quality Commands
|
||||||
@@ -476,5 +476,5 @@ Recommended minimums:
|
|||||||
|
|
||||||
- Read the [architecture overview](/docs/developer/architecture)
|
- Read the [architecture overview](/docs/developer/architecture)
|
||||||
- Learn about [database migrations](/docs/developer/database-migrations)
|
- Learn about [database migrations](/docs/developer/database-migrations)
|
||||||
- Explore [API documentation](/docs/api)
|
- Explore [API documentation](https://api.immich.app/)
|
||||||
- Join `#immich` on [Discord](https://discord.immich.app)
|
- Join `#immich` on [Discord](https://discord.immich.app)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# OpenAPI
|
# OpenAPI
|
||||||
|
|
||||||
Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generate API documentation. To view the published docs see [here](/docs/api).
|
Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generate API documentation. To view the published docs see [here](https://api.immich.app/).
|
||||||
|
|
||||||
## Generator
|
## Generator
|
||||||
|
|
||||||
|
|||||||
@@ -8,34 +8,34 @@ When contributing code through a pull request, please check the following:
|
|||||||
|
|
||||||
## Web Checks
|
## Web Checks
|
||||||
|
|
||||||
- [ ] `npm run lint` (linting via ESLint)
|
- [ ] `pnpm run lint` (linting via ESLint)
|
||||||
- [ ] `npm run format` (formatting via Prettier)
|
- [ ] `pnpm run format` (formatting via Prettier)
|
||||||
- [ ] `npm run check:svelte` (Type checking via SvelteKit)
|
- [ ] `pnpm run check:svelte` (Type checking via SvelteKit)
|
||||||
- [ ] `npm run check:typescript` (check typescript)
|
- [ ] `pnpm run check:typescript` (check typescript)
|
||||||
- [ ] `npm test` (unit tests)
|
- [ ] `pnpm test` (unit tests)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [ ] `npm run format` (formatting via Prettier)
|
- [ ] `pnpm run format` (formatting via Prettier)
|
||||||
- [ ] Update the `_redirects` file if you have renamed a page or removed it from the documentation.
|
- [ ] Update the `_redirects` file if you have renamed a page or removed it from the documentation.
|
||||||
|
|
||||||
:::tip AIO
|
:::tip AIO
|
||||||
Run all web checks with `npm run check:all`
|
Run all web checks with `pnpm run check:all`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Server Checks
|
## Server Checks
|
||||||
|
|
||||||
- [ ] `npm run lint` (linting via ESLint)
|
- [ ] `pnpm run lint` (linting via ESLint)
|
||||||
- [ ] `npm run format` (formatting via Prettier)
|
- [ ] `pnpm run format` (formatting via Prettier)
|
||||||
- [ ] `npm run check` (Type checking via `tsc`)
|
- [ ] `pnpm run check` (Type checking via `tsc`)
|
||||||
- [ ] `npm test` (unit tests)
|
- [ ] `pnpm test` (unit tests)
|
||||||
|
|
||||||
:::tip AIO
|
:::tip AIO
|
||||||
Run all server checks with `npm run check:all`
|
Run all server checks with `pnpm run check:all`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
:::info Auto Fix
|
:::info Auto Fix
|
||||||
You can use `npm run __:fix` to potentially correct some issues automatically for `npm run format` and `lint`.
|
You can use `pnpm run __:fix` to potentially correct some issues automatically for `pnpm run format` and `lint`.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Mobile Checks
|
## Mobile Checks
|
||||||
|
|||||||
@@ -54,20 +54,20 @@ You can access the web from `http://your-machine-ip:3000` or `http://localhost:3
|
|||||||
|
|
||||||
If you only want to do web development connected to an existing, remote backend, follow these steps:
|
If you only want to do web development connected to an existing, remote backend, follow these steps:
|
||||||
|
|
||||||
1. Build the Immich SDK - `cd open-api/typescript-sdk && npm i && npm run build && cd -`
|
1. Build the Immich SDK - `cd open-api/typescript-sdk && pnpm i && pnpm run build && cd -`
|
||||||
2. Enter the web directory - `cd web/`
|
2. Enter the web directory - `cd web/`
|
||||||
3. Install web dependencies - `npm i`
|
3. Install web dependencies - `pnpm i`
|
||||||
4. Start the web development server
|
4. Start the web development server
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
IMMICH_SERVER_URL=https://demo.immich.app/ npm run dev
|
IMMICH_SERVER_URL=https://demo.immich.app/ pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're using PowerShell on Windows you may need to set the env var separately like so:
|
If you're using PowerShell on Windows you may need to set the env var separately like so:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$env:IMMICH_SERVER_URL = "https://demo.immich.app/"
|
$env:IMMICH_SERVER_URL = "https://demo.immich.app/"
|
||||||
npm run dev
|
pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `@immich/ui`
|
#### `@immich/ui`
|
||||||
@@ -75,12 +75,12 @@ npm run dev
|
|||||||
To see local changes to `@immich/ui` in Immich, do the following:
|
To see local changes to `@immich/ui` in Immich, do the following:
|
||||||
|
|
||||||
1. Install `@immich/ui` as a sibling to `immich/`, for example `/home/user/immich` and `/home/user/ui`
|
1. Install `@immich/ui` as a sibling to `immich/`, for example `/home/user/immich` and `/home/user/ui`
|
||||||
2. Build the `@immich/ui` project via `npm run build`
|
2. Build the `@immich/ui` project via `pnpm run build`
|
||||||
3. Uncomment the corresponding volume in web service of the `docker/docker-compose.dev.yaml` file (`../../ui:/usr/ui`)
|
3. Uncomment the corresponding volume in web service of the `docker/docker-compose.dev.yaml` file (`../../ui:/usr/ui`)
|
||||||
4. Uncomment the corresponding alias in the `web/vite.config.js` file (`'@immich/ui': path.resolve(\_\_dirname, '../../ui')`)
|
4. Uncomment the corresponding alias in the `web/vite.config.js` file (`'@immich/ui': path.resolve(\_\_dirname, '../../ui')`)
|
||||||
5. Uncomment the import statement in `web/src/app.css` file `@import '/usr/ui/dist/theme/default.css';` and comment out `@import '@immich/ui/theme/default.css';`
|
5. Uncomment the import statement in `web/src/app.css` file `@import '/usr/ui/dist/theme/default.css';` and comment out `@import '@immich/ui/theme/default.css';`
|
||||||
6. Start up the stack via `make dev`
|
6. Start up the stack via `make dev`
|
||||||
7. After making changes in `@immich/ui`, rebuild it (`npm run build`)
|
7. After making changes in `@immich/ui`, rebuild it (`pnpm run build`)
|
||||||
|
|
||||||
### Mobile app
|
### Mobile app
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
### Unit tests
|
### Unit tests
|
||||||
|
|
||||||
Unit are run by calling `npm run test` from the `server/` directory.
|
Unit are run by calling `pnpm run test` from the `server/` directory.
|
||||||
You need to run `npm install` (in `server/`) before _once_.
|
You need to run `pnpm install` (in `server/`) before _once_.
|
||||||
|
|
||||||
### End to end tests
|
### End to end tests
|
||||||
|
|
||||||
@@ -17,14 +17,14 @@ make e2e
|
|||||||
|
|
||||||
Before you can run the tests, you need to run the following commands _once_:
|
Before you can run the tests, you need to run the following commands _once_:
|
||||||
|
|
||||||
- `npm install` (in `e2e/`)
|
- `pnpm install` (in `e2e/`)
|
||||||
- `make open-api` (in the project root `/`)
|
- `make open-api` (in the project root `/`)
|
||||||
|
|
||||||
Once the test environment is running, the e2e tests can be run via:
|
Once the test environment is running, the e2e tests can be run via:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd e2e/
|
cd e2e/
|
||||||
npm test
|
pnpm test
|
||||||
```
|
```
|
||||||
|
|
||||||
The tests check various things including:
|
The tests check various things including:
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -33,7 +33,7 @@ Sometimes, an external library will not scan correctly. This can happen if Immic
|
|||||||
- Are the permissions set correctly?
|
- Are the permissions set correctly?
|
||||||
- Make sure you are using forward slashes (`/`) and not backward slashes.
|
- Make sure you are using forward slashes (`/`) and not backward slashes.
|
||||||
|
|
||||||
To validate that Immich can reach your external library, start a shell inside the container. Run `docker exec -it immich_server bash` to a bash shell. If your import path is `/data/import/photos`, check it with `ls /data/import/photos`. Do the same check for the same in any microservices containers.
|
To validate that Immich can reach your external library, start a shell inside the container. Run `docker exec -it immich_server bash` to a bash shell. If your import path is `/mnt/photos`, check it with `ls /mnt/photos`. If you are using a dedicated microservices container, make sure to add the same mount point and check for availability within the microservices container as well.
|
||||||
|
|
||||||
### Exclusion Patterns
|
### Exclusion Patterns
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ The provided file is just a starting point. There are a ton of ways to configure
|
|||||||
After bringing down the containers with `docker compose down` and back up with `docker compose up -d`, a Prometheus instance will now collect metrics from the immich server and microservices containers. Note that we didn't need to expose any new ports for these containers - the communication is handled in the internal Docker network.
|
After bringing down the containers with `docker compose down` and back up with `docker compose up -d`, a Prometheus instance will now collect metrics from the immich server and microservices containers. Note that we didn't need to expose any new ports for these containers - the communication is handled in the internal Docker network.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
To see exactly what metrics are made available, you can additionally add `8081:8081` to the server container's ports and `8082:8082` to the microservices container's ports.
|
To see exactly what metrics are made available, you can additionally add `8081:8081` (API metrics) and `8082:8082` (microservices metrics) to the immich_server container's ports.
|
||||||
Visiting the `/metrics` endpoint for these services will show the same raw data that Prometheus collects.
|
Visiting the `/metrics` endpoint for these services will show the same raw data that Prometheus collects.
|
||||||
To configure these ports see [`IMMICH_API_METRICS_PORT` & `IMMICH_MICROSERVICES_METRICS_PORT`](/docs/install/environment-variables/#general).
|
To configure these ports see [`IMMICH_API_METRICS_PORT` & `IMMICH_MICROSERVICES_METRICS_PORT`](/docs/install/environment-variables/#general).
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Tags
|
# Tags
|
||||||
|
|
||||||
Immich supports hierarchical tags, with the ability to read existing tags from the `TagList` and `Keywords` EXIF properties. Any changes to tags made through Immich are also written back to a [sidecar](/docs/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags.
|
Immich supports hierarchical tags, with the ability to read existing tags from the XMP `TagsList` field and IPTC `Keywords` field. Any changes to tags made through Immich are also written back to a [sidecar](/docs/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags.
|
||||||
|
|
||||||
## Enable tags feature
|
## Enable tags feature
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,68 @@
|
|||||||
# XMP Sidecars
|
# XMP Sidecars
|
||||||
|
|
||||||
Immich can ingest XMP sidecars on file upload (via the CLI) as well as detect new sidecars that are placed in the filesystem for existing images.
|
Immich supports XMP sidecar files — external `.xmp` files that store metadata for an image or video in XML format. During the metadata extraction job Immich will read & import metadata from `.xmp` files, and during the Sidecar Write job it will _write_ metadata back to `.xmp`.
|
||||||
|
|
||||||
<img src={require('./img/xmp-sidecars.webp').default} title='XMP sidecars' />
|
:::tip
|
||||||
|
Tools like Lightroom, Darktable, digiKam and other applications can also be configured to write changes to `.xmp` files, in order to avoid modifying the original file.
|
||||||
|
:::
|
||||||
|
|
||||||
XMP sidecars are external XML files that contain metadata related to media files. Many applications read and write these files either exclusively or in addition to the metadata written to image files. They can be a powerful tool for editing and storing metadata of a media file without modifying the media file itself. When Immich receives or detects an XMP sidecar for a media file, it will attempt to extract the metadata from both the sidecar as well as the media file. It will prioritize the metadata for fields in the sidecar but will fall back and use the metadata in the media file if necessary.
|
## Metadata Fields
|
||||||
|
|
||||||
When importing files via the CLI bulk uploader or parsing photo metadata for external libraries, Immich will automatically detect XMP sidecar files as files that exist next to the original media file. Immich will look files that have the same name as the photo, but with the `.xmp` file extension. The same name can either include the photo's file extension or without the photo's file extension. For example, for a photo named `PXL_20230401_203352928.MP.jpg`, Immich will look for an XMP file named either `PXL_20230401_203352928.MP.jpg.xmp` or `PXL_20230401_203352928.MP.xmp`. If both `PXL_20230401_203352928.MP.jpg.xmp` and `PXL_20230401_203352928.MP.xmp` are present, Immich will prefer `PXL_20230401_203352928.MP.jpg.xmp`.
|
Immich does not support _all_ metadata fields. Below is a table showing what fields Immich can _read_ and _write_. It's important to note that writes do not replace the entire file contents, but are merged together with any existing fields.
|
||||||
|
|
||||||
There are 2 administrator jobs associated with sidecar files: `SYNC` and `DISCOVER`. The sync job will re-scan all media with existing sidecar files and queue them for a metadata refresh. This is a great use case when third-party applications are used to modify the metadata of media. The discover job will attempt to scan the filesystem for new sidecar files for all media that does not currently have a sidecar file associated with it.
|
:::info
|
||||||
|
Immich automatically queues a Sidecar Write job after editing the description, rating, or updating tags.
|
||||||
|
:::
|
||||||
|
|
||||||
<img src={require('./img/sidecar-jobs.webp').default} title='Sidecar Administrator Jobs' />
|
| Metadata | Immich writes to XMP | Immich reads from XMP |
|
||||||
|
| --------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **Description** | `dc:description`, `tiff:ImageDescription` | `dc:description`, `tiff:ImageDescription` |
|
||||||
|
| **Rating** | `xmp:Rating` | `xmp:Rating` |
|
||||||
|
| **DateTime** | `exif:DateTimeOriginal`, `photoshop:DateCreated` | In prioritized order:<br/>`exif:SubSecDateTimeOriginal`<br/>`exif:DateTimeOriginal`<br/>`xmp:SubSecCreateDate`<br/>`xmp:CreateDate`<br/>`xmp:CreationDate`<br/>`xmp:MediaCreateDate`<br/>`xmp:SubSecMediaCreateDate`<br/>`xmp:DateTimeCreated` |
|
||||||
|
| **Location** | `exif:GPSLatitude`, `exif:GPSLongitude` | `exif:GPSLatitude`, `exif:GPSLongitude` |
|
||||||
|
| **Tags** | `digiKam:TagsList` | In prioritized order: <br/>`digiKam:TagsList`<br/>`lr:HierarchicalSubject`<br/>`IPTC:Keywords` |
|
||||||
|
|
||||||
|
:::note
|
||||||
|
All other fields (e.g. `Creator`, `Source`, IPTC, Lightroom edits) remain in the `.xmp` file and are **not searchable** in Immich.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## File Naming Rules
|
||||||
|
|
||||||
|
A sidecar must share the base name of the media file:
|
||||||
|
|
||||||
|
- ✅ `IMG_0001.jpg.xmp` ← preferred
|
||||||
|
- ✅ `IMG_0001.xmp` ← fallback
|
||||||
|
- ❌ `myphoto_meta.xmp` ← not recognized
|
||||||
|
|
||||||
|
If both `.jpg.xmp` and `.xmp` are present, Immich uses the **`.jpg.xmp`** file.
|
||||||
|
|
||||||
|
## CLI Support
|
||||||
|
|
||||||
|
1. **Detect** – Immich looks for a `.xmp` file placed next to each media file during upload.
|
||||||
|
2. **Copy** – Both the media and the sidecar file are copied into Immich’s internal library folder.
|
||||||
|
The sidecar is renamed to match the internal filename template, e.g.:
|
||||||
|
`upload/library/<user>/YYYY/YYYY-MM-DD/IMG_0001.jpg`
|
||||||
|
`upload/library/<user>/YYYY/YYYY-MM-DD/IMG_0001.jpg.xmp`
|
||||||
|
3. **Extract** – Selected metadata (title, description, date, rating, tags) is parsed from the sidecar and saved to the database.
|
||||||
|
4. **Write-back** – If you later update tags, rating, or description in the web UI, Immich will update **both** the database _and_ the copied `.xmp` file to stay in sync.
|
||||||
|
|
||||||
|
## External Library (Mounted Folder) Support
|
||||||
|
|
||||||
|
1. **Detect** – The `DISCOVER` job automatically associates `.xmp` files that sit next to existing media files in your mounted folder. No files are moved or renamed.
|
||||||
|
2. **Extract** – Immich reads and saves the same metadata fields from the sidecar to the database.
|
||||||
|
3. **Write-back** – If Immich has **write access** to the mount, any future metadata edits (e.g., rating or tags) are also written back to the original `.xmp` file on disk.
|
||||||
|
|
||||||
|
:::danger
|
||||||
|
If the mount is **read-only**, Immich cannot update either the sidecar **or** the database — **metadata edits will silently fail** with no warning see issue [#10538](https://github.com/immich-app/immich/issues/10538) for more details.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Admin Jobs
|
||||||
|
|
||||||
|
Immich provides two admin jobs for managing sidecars:
|
||||||
|
|
||||||
|
| Job | What it does |
|
||||||
|
| ---------- | ------------------------------------------------------------------------------------------------- |
|
||||||
|
| `DISCOVER` | Finds new `.xmp` files next to media that don’t already have one linked |
|
||||||
|
| `SYNC` | Re-reads existing `.xmp` files and refreshes metadata in the database (e.g. after external edits) |
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
@@ -147,7 +147,10 @@ SELECT "key", "value" FROM "system_metadata" WHERE "key" = 'system-config';
|
|||||||
### File properties
|
### File properties
|
||||||
|
|
||||||
```sql title="Without thumbnails"
|
```sql title="Without thumbnails"
|
||||||
SELECT * FROM "asset" WHERE "asset"."previewPath" IS NULL OR "asset"."thumbnailPath" IS NULL;
|
SELECT * FROM "asset"
|
||||||
|
WHERE (NOT EXISTS (SELECT 1 FROM "asset_file" WHERE "asset"."id" = "asset_file"."assetId" AND "asset_file"."type" = 'thumbnail')
|
||||||
|
OR NOT EXISTS (SELECT 1 FROM "asset_file" WHERE "asset"."id" = "asset_file"."assetId" AND "asset_file"."type" = 'preview'))
|
||||||
|
AND "asset"."visibility" = 'timeline';
|
||||||
```
|
```
|
||||||
|
|
||||||
```sql title="Failed file movements"
|
```sql title="Failed file movements"
|
||||||
|
|||||||
@@ -169,8 +169,6 @@ Redis (Sentinel) URL example JSON before encoding:
|
|||||||
| `MACHINE_LEARNING_ANN_TUNING_LEVEL` | ARM-NN GPU tuning level (1: rapid, 2: normal, 3: exhaustive) | `2` | machine learning |
|
| `MACHINE_LEARNING_ANN_TUNING_LEVEL` | ARM-NN GPU tuning level (1: rapid, 2: normal, 3: exhaustive) | `2` | machine learning |
|
||||||
| `MACHINE_LEARNING_DEVICE_IDS`<sup>\*4</sup> | Device IDs to use in multi-GPU environments | `0` | machine learning |
|
| `MACHINE_LEARNING_DEVICE_IDS`<sup>\*4</sup> | Device IDs to use in multi-GPU environments | `0` | machine learning |
|
||||||
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
|
| `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning |
|
||||||
| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server |
|
|
||||||
| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server |
|
|
||||||
| `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning |
|
| `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning |
|
||||||
| `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning |
|
| `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning |
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const config = {
|
|||||||
],
|
],
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
'docusaurus-preset-openapi',
|
'classic',
|
||||||
/** @type {import('docusaurus-preset-openapi').Options} */
|
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||||
({
|
({
|
||||||
docs: {
|
docs: {
|
||||||
showLastUpdateAuthor: true,
|
showLastUpdateAuthor: true,
|
||||||
@@ -54,14 +54,6 @@ const config = {
|
|||||||
// Remove this to remove the "edit this page" links.
|
// Remove this to remove the "edit this page" links.
|
||||||
editUrl: 'https://github.com/immich-app/immich/tree/main/docs/',
|
editUrl: 'https://github.com/immich-app/immich/tree/main/docs/',
|
||||||
},
|
},
|
||||||
api: {
|
|
||||||
path: '../open-api/immich-openapi-specs.json',
|
|
||||||
routeBasePath: '/docs/api',
|
|
||||||
},
|
|
||||||
// blog: {
|
|
||||||
// showReadingTime: true,
|
|
||||||
// editUrl: "https://github.com/immich-app/immich/tree/main/docs/",
|
|
||||||
// },
|
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve('./src/css/custom.css'),
|
customCss: require.resolve('./src/css/custom.css'),
|
||||||
},
|
},
|
||||||
@@ -100,12 +92,12 @@ const config = {
|
|||||||
label: 'Docs',
|
label: 'Docs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/roadmap',
|
href: 'https://immich.app/roadmap',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
label: 'Roadmap',
|
label: 'Roadmap',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/docs/api',
|
href: 'https://api.immich.app/',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
label: 'API',
|
label: 'API',
|
||||||
},
|
},
|
||||||
@@ -161,15 +153,15 @@ const config = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: 'Roadmap',
|
label: 'Roadmap',
|
||||||
to: '/roadmap',
|
href: 'https://immich.app/roadmap',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'API',
|
label: 'API',
|
||||||
to: '/docs/api',
|
href: 'https://api.immich.app/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Cursed Knowledge',
|
label: 'Cursed Knowledge',
|
||||||
to: '/cursed-knowledge',
|
href: 'https://immich.app/cursed-knowledge',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
20545
docs/package-lock.json
generated
20545
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -24,10 +24,7 @@
|
|||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.17",
|
||||||
"classnames": "^2.3.2",
|
|
||||||
"clsx": "^2.0.0",
|
|
||||||
"docusaurus-lunr-search": "^3.3.2",
|
"docusaurus-lunr-search": "^3.3.2",
|
||||||
"docusaurus-preset-openapi": "^0.7.5",
|
|
||||||
"lunr": "^2.3.9",
|
"lunr": "^2.3.9",
|
||||||
"postcss": "^8.4.25",
|
"postcss": "^8.4.25",
|
||||||
"prism-react-renderer": "^2.3.1",
|
"prism-react-renderer": "^2.3.1",
|
||||||
@@ -60,6 +57,6 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ const guides: CommunityGuidesProps[] = [
|
|||||||
description: `synchronize folders in imported library with albums having the folders name.`,
|
description: `synchronize folders in imported library with albums having the folders name.`,
|
||||||
url: 'https://github.com/immich-app/immich/discussions/3382',
|
url: 'https://github.com/immich-app/immich/discussions/3382',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Immich Podman Quadlets Handbook',
|
||||||
|
description:
|
||||||
|
'A rewrite of the original Immich Docker Compose file using Podman Quadlets, with a set of extra guides in the repository’s wiki.',
|
||||||
|
url: 'https://github.com/linux-universe/immich-podman-quadlets/blob/main/README.md',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Podman/Quadlets Install',
|
title: 'Podman/Quadlets Install',
|
||||||
description: 'Documentation for simple podman setup using quadlets.',
|
description: 'Documentation for simple podman setup using quadlets.',
|
||||||
|
|||||||
@@ -105,6 +105,21 @@ const projects: CommunityProjectProps[] = [
|
|||||||
description: 'Speed up your machine learning by load balancing your requests to multiple computers',
|
description: 'Speed up your machine learning by load balancing your requests to multiple computers',
|
||||||
url: 'https://github.com/apetersson/immich_ml_balancer',
|
url: 'https://github.com/apetersson/immich_ml_balancer',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Immich Drop Uploader',
|
||||||
|
description: 'A tiny, zero-login web app for collecting photos/videos from anyone into your Immich server.',
|
||||||
|
url: 'https://github.com/Nasogaa/immich-drop',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Immich Birthday Sync',
|
||||||
|
description: 'Bulk-upload and -download birthdays, with CardDAV sync support',
|
||||||
|
url: 'https://github.com/sid3windr/immich-birthday',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Immich Stack',
|
||||||
|
description: 'Auto-stack photos with identical filenames and differing extensions (i.e. JPG+RAW)',
|
||||||
|
url: 'https://github.com/sid3windr/immich-stack',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {
|
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {
|
||||||
|
|||||||
@@ -1,273 +0,0 @@
|
|||||||
import {
|
|
||||||
mdiBug,
|
|
||||||
mdiCalendarToday,
|
|
||||||
mdiCrosshairsOff,
|
|
||||||
mdiCrop,
|
|
||||||
mdiDatabase,
|
|
||||||
mdiLeadPencil,
|
|
||||||
mdiLockOff,
|
|
||||||
mdiLockOutline,
|
|
||||||
mdiMicrosoftWindows,
|
|
||||||
mdiSecurity,
|
|
||||||
mdiSpeedometerSlow,
|
|
||||||
mdiTrashCan,
|
|
||||||
mdiWeb,
|
|
||||||
mdiWrap,
|
|
||||||
mdiCloudKeyOutline,
|
|
||||||
mdiRegex,
|
|
||||||
mdiCodeJson,
|
|
||||||
mdiClockOutline,
|
|
||||||
mdiAccountOutline,
|
|
||||||
mdiRestart,
|
|
||||||
} from '@mdi/js';
|
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
import React from 'react';
|
|
||||||
import { Timeline, Item as TimelineItem } from '../components/timeline';
|
|
||||||
|
|
||||||
const withLanguage = (date: Date) => (language: string) => date.toLocaleDateString(language);
|
|
||||||
|
|
||||||
type Item = Omit<TimelineItem, 'done' | 'getDateLabel'> & { date: Date };
|
|
||||||
|
|
||||||
const items: Item[] = [
|
|
||||||
{
|
|
||||||
icon: mdiClockOutline,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'setTimeout is cursed',
|
|
||||||
description:
|
|
||||||
'The setTimeout method in JavaScript is cursed when used with small values because the implementation may or may not actually wait the specified time.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/20655',
|
|
||||||
text: '#20655',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 7, 4),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiAccountOutline,
|
|
||||||
iconColor: '#DAB1DA',
|
|
||||||
title: 'PostgreSQL USER is cursed',
|
|
||||||
description:
|
|
||||||
'The USER keyword in PostgreSQL is cursed because you can select from it like a table, which leads to confusion if you have a table name user as well.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/19891',
|
|
||||||
text: '#19891',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 7, 4),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiRestart,
|
|
||||||
iconColor: '#8395e3',
|
|
||||||
title: 'PostgreSQL RESET is cursed',
|
|
||||||
description:
|
|
||||||
'PostgreSQL RESET is cursed because it is impossible to RESET a PostgreSQL extension parameter if the extension has been uninstalled.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/19363',
|
|
||||||
text: '#19363',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 5, 20),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiRegex,
|
|
||||||
iconColor: 'purple',
|
|
||||||
title: 'Zitadel Actions are cursed',
|
|
||||||
description:
|
|
||||||
"Zitadel is cursed because its custom scripting feature is executed with a JS engine that doesn't support regex named capture groups.",
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/dop251/goja',
|
|
||||||
text: 'Go JS engine',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 5, 4),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiCloudKeyOutline,
|
|
||||||
iconColor: '#0078d4',
|
|
||||||
title: 'Entra is cursed',
|
|
||||||
description:
|
|
||||||
"Microsoft Entra supports PKCE, but doesn't include it in its OpenID discovery document. This leads to clients thinking PKCE isn't available.",
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/18725',
|
|
||||||
text: '#18725',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 4, 30),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiCrop,
|
|
||||||
iconColor: 'tomato',
|
|
||||||
title: 'Image dimensions in EXIF metadata are cursed',
|
|
||||||
description:
|
|
||||||
'The dimensions in EXIF metadata can be different from the actual dimensions of the image, causing issues with cropping and resizing.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/17974',
|
|
||||||
text: '#17974',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 4, 5),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiCodeJson,
|
|
||||||
iconColor: 'yellow',
|
|
||||||
title: 'YAML whitespace is cursed',
|
|
||||||
description: 'YAML whitespaces are often handled in unintuitive ways.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/17309',
|
|
||||||
text: '#17309',
|
|
||||||
},
|
|
||||||
date: new Date(2025, 3, 1),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiMicrosoftWindows,
|
|
||||||
iconColor: '#357EC7',
|
|
||||||
title: 'Hidden files in Windows are cursed',
|
|
||||||
description:
|
|
||||||
'Hidden files in Windows cannot be opened with the "w" flag. That, combined with SMB option "hide dot files" leads to a lot of confusion.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/12812',
|
|
||||||
text: '#12812',
|
|
||||||
},
|
|
||||||
date: new Date(2024, 8, 20),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiWrap,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'Carriage returns in bash scripts are cursed',
|
|
||||||
description: 'Git can be configured to automatically convert LF to CRLF on checkout and CRLF breaks bash scripts.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/11613',
|
|
||||||
text: '#11613',
|
|
||||||
},
|
|
||||||
date: new Date(2024, 7, 7),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiLockOff,
|
|
||||||
iconColor: 'red',
|
|
||||||
title: 'Fetch inside Cloudflare Workers is cursed',
|
|
||||||
description:
|
|
||||||
'Fetch requests in Cloudflare Workers use http by default, even if you explicitly specify https, which can often cause redirect loops.',
|
|
||||||
link: {
|
|
||||||
url: 'https://community.cloudflare.com/t/does-cloudflare-worker-allow-secure-https-connection-to-fetch-even-on-flexible-ssl/68051/5',
|
|
||||||
text: 'Cloudflare',
|
|
||||||
},
|
|
||||||
date: new Date(2024, 7, 7),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiCrosshairsOff,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'GPS sharing on mobile is cursed',
|
|
||||||
description:
|
|
||||||
'Some phones will silently strip GPS data from images when apps without location permission try to access them.',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/discussions/11268',
|
|
||||||
text: '#11268',
|
|
||||||
},
|
|
||||||
date: new Date(2024, 6, 21),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiLeadPencil,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'PostgreSQL NOTIFY is cursed',
|
|
||||||
description:
|
|
||||||
'PostgreSQL does everything in a transaction, including NOTIFY. This means using the socket.io postgres-adapter writes to WAL every 5 seconds.',
|
|
||||||
link: { url: 'https://github.com/immich-app/immich/pull/10801', text: '#10801' },
|
|
||||||
date: new Date(2024, 6, 3),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiWeb,
|
|
||||||
iconColor: 'lightskyblue',
|
|
||||||
title: 'npm scripts are cursed',
|
|
||||||
description:
|
|
||||||
'npm scripts make a http call to the npm registry each time they run, which means they are a terrible way to execute a health check.',
|
|
||||||
link: { url: 'https://github.com/immich-app/immich/issues/10796', text: '#10796' },
|
|
||||||
date: new Date(2024, 6, 3),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiSpeedometerSlow,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: '50 extra packages are cursed',
|
|
||||||
description:
|
|
||||||
'There is a user in the JavaScript community who goes around adding "backwards compatibility" to projects. They do this by adding 50 extra package dependencies to your project, which are maintained by them.',
|
|
||||||
link: { url: 'https://github.com/immich-app/immich/pull/10690', text: '#10690' },
|
|
||||||
date: new Date(2024, 5, 28),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiLockOutline,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'Long passwords are cursed',
|
|
||||||
description:
|
|
||||||
'The bcrypt implementation only uses the first 72 bytes of a string. Any characters after that are ignored.',
|
|
||||||
// link: GHSA-4p64-9f7h-3432
|
|
||||||
date: new Date(2024, 5, 25),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiCalendarToday,
|
|
||||||
iconColor: 'greenyellow',
|
|
||||||
title: 'JavaScript Date objects are cursed',
|
|
||||||
description: 'JavaScript date objects are 1 indexed for years and days, but 0 indexed for months.',
|
|
||||||
link: { url: 'https://github.com/immich-app/immich/pull/6787', text: '#6787' },
|
|
||||||
date: new Date(2024, 0, 31),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiBug,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'ESM imports are cursed',
|
|
||||||
description:
|
|
||||||
'Prior to Node.js v20.8 using --experimental-vm-modules in a CommonJS project that imported an ES module that imported a CommonJS modules would create a segfault and crash Node.js',
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/6719',
|
|
||||||
text: '#6179',
|
|
||||||
},
|
|
||||||
date: new Date(2024, 0, 9),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiDatabase,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'PostgreSQL parameters are cursed',
|
|
||||||
description: `PostgresSQL has a limit of ${Number(65535).toLocaleString()} parameters, so bulk inserts can fail with large datasets.`,
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/pull/6034',
|
|
||||||
text: '#6034',
|
|
||||||
},
|
|
||||||
date: new Date(2023, 11, 28),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiSecurity,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'Secure contexts are cursed',
|
|
||||||
description: `Some web features like the clipboard API only work in "secure contexts" (ie. https or localhost)`,
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/immich-app/immich/issues/2981',
|
|
||||||
text: '#2981',
|
|
||||||
},
|
|
||||||
date: new Date(2023, 5, 26),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: mdiTrashCan,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'TypeORM deletes are cursed',
|
|
||||||
description: `The remove implementation in TypeORM mutates the input, deleting the id property from the original object.`,
|
|
||||||
link: {
|
|
||||||
url: 'https://github.com/typeorm/typeorm/issues/7024#issuecomment-948519328',
|
|
||||||
text: 'typeorm#6034',
|
|
||||||
},
|
|
||||||
date: new Date(2023, 1, 23),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function CursedKnowledgePage(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<Layout title="Cursed Knowledge" description="Things we wish we didn't know">
|
|
||||||
<section className="my-8">
|
|
||||||
<h1 className="md:text-6xl text-center mb-10 text-immich-primary dark:text-immich-dark-primary px-2">
|
|
||||||
Cursed Knowledge
|
|
||||||
</h1>
|
|
||||||
<p className="text-center text-xl px-2">
|
|
||||||
Cursed knowledge we have learned as a result of building Immich that we wish we never knew.
|
|
||||||
</p>
|
|
||||||
<div className="flex justify-around mt-8 w-full max-w-full">
|
|
||||||
<Timeline
|
|
||||||
items={items
|
|
||||||
.sort((a, b) => b.date.getTime() - a.date.getTime())
|
|
||||||
.map((item) => ({ ...item, getDateLabel: withLanguage(item.date) }))}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,17 @@
|
|||||||
|
|
||||||
## TypeORM Upgrade
|
## TypeORM Upgrade
|
||||||
|
|
||||||
In order to update to Immich to `v1.137.0` (or above), the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to v1.137.0 (or above). We recommend users upgrade to `1.132.0` since it does not have any other breaking changes.
|
If you encountered "Migrations failed: Error: Invalid upgrade path" then perform an intermediate upgrade to `v1.132.3` first.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
We recommend users upgrade to `v1.132.3` since it does not have any breaking changes or bugs on this upgrade path.
|
||||||
|
:::
|
||||||
|
|
||||||
|
In order to update to Immich `v1.137.0` or above, the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to `v1.137.0` (or above).
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
Avoid `v1.136.0` if upgrading from `v1.131.0` (or earlier) due to a bug blocking this upgrade in some installations.
|
||||||
|
:::
|
||||||
|
|
||||||
## Inconsistent Media Location
|
## Inconsistent Media Location
|
||||||
|
|
||||||
|
|||||||
@@ -1,123 +1,5 @@
|
|||||||
import React from 'react';
|
import { Redirect } from '@docusaurus/router';
|
||||||
import Link from '@docusaurus/Link';
|
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
import { discordPath, discordViewBox } from '@site/src/components/svg-paths';
|
|
||||||
import ThemedImage from '@theme/ThemedImage';
|
|
||||||
import Icon from '@mdi/react';
|
|
||||||
|
|
||||||
function HomepageHeader() {
|
|
||||||
return (
|
|
||||||
<header>
|
|
||||||
<div className="top-[calc(12%)] md:top-[calc(30%)] h-screen w-full absolute -z-10">
|
|
||||||
<img src={'img/immich-logo.svg'} className="h-[110%] w-[110%] mb-2 antialiased -z-10" alt="Immich logo" />
|
|
||||||
<div className="w-full h-[120vh] absolute left-0 top-0 backdrop-blur-3xl bg-immich-bg/40 dark:bg-transparent"></div>
|
|
||||||
</div>
|
|
||||||
<section className="text-center pt-12 sm:pt-24 bg-immich-bg/50 dark:bg-immich-dark-bg/80">
|
|
||||||
<a href="https://futo.org" target="_blank" rel="noopener noreferrer">
|
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: 'img/logomark-dark-with-futo.svg', light: 'img/logomark-light-with-futo.svg' }}
|
|
||||||
className="h-[125px] w-[125px] mb-2 antialiased rounded-none"
|
|
||||||
alt="Immich logo"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div className="mt-8">
|
|
||||||
<p className="text-3xl md:text-5xl sm:leading-tight mb-1 font-extrabold text-black/90 dark:text-white px-4">
|
|
||||||
Self-hosted{' '}
|
|
||||||
<span className="text-immich-primary dark:text-immich-dark-primary">
|
|
||||||
photo and <span className="block"></span>
|
|
||||||
video management{' '}
|
|
||||||
</span>
|
|
||||||
solution<span className="block"></span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="max-w-1/4 m-auto mt-4 px-4 text-lg text-gray-700 dark:text-gray-100">
|
|
||||||
Easily back up, organize, and manage your photos on your own server. Immich helps you
|
|
||||||
<span className="sm:block"></span> browse, search and organize your photos and videos with ease, without
|
|
||||||
sacrificing your privacy.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col sm:flex-row place-items-center place-content-center mt-9 gap-4 ">
|
|
||||||
<Link
|
|
||||||
className="flex place-items-center place-content-center py-3 px-8 border bg-immich-primary dark:bg-immich-dark-primary rounded-xl no-underline hover:no-underline text-white hover:text-gray-50 dark:text-immich-dark-bg font-bold"
|
|
||||||
to="docs/overview/quick-start"
|
|
||||||
>
|
|
||||||
Get Started
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link
|
|
||||||
className="flex place-items-center place-content-center py-3 px-8 border bg-white/90 dark:bg-gray-300 rounded-xl hover:no-underline text-immich-primary dark:text-immich-dark-bg font-bold"
|
|
||||||
to="https://demo.immich.app/"
|
|
||||||
>
|
|
||||||
Open Demo
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="my-8 flex gap-1 font-medium place-items-center place-content-center text-immich-primary dark:text-immich-dark-primary">
|
|
||||||
<Icon
|
|
||||||
path={discordPath}
|
|
||||||
viewBox={discordViewBox} /* viewBox may show an error in your IDE but it is normal. */
|
|
||||||
size={1}
|
|
||||||
/>
|
|
||||||
<Link to="https://discord.immich.app/">Join our Discord</Link>
|
|
||||||
</div>
|
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: '/img/screenshot-dark.webp', light: '/img/screenshot-light.webp' }}
|
|
||||||
alt="screenshots"
|
|
||||||
className="w-[95%] lg:w-[85%] xl:w-[70%] 2xl:w-[60%] "
|
|
||||||
/>
|
|
||||||
<div className="mx-[25%] m-auto my-14 md:my-28">
|
|
||||||
<hr className="border bg-gray-500 dark:bg-gray-400" />
|
|
||||||
</div>
|
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: 'img/logomark-dark.svg', light: 'img/logomark-light.svg' }}
|
|
||||||
className="h-[115px] w-[115px] mb-2 antialiased rounded-none"
|
|
||||||
alt="Immich logo"
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<p className="font-bold text-2xl md:text-5xl ">Download the mobile app</p>
|
|
||||||
<p className="text-lg">
|
|
||||||
Download the Immich app and start backing up your photos and videos securely to your own server
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col sm:flex-row place-items-center place-content-center mt-4 gap-1">
|
|
||||||
<div className="h-24">
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=app.alextran.immich">
|
|
||||||
<img className="h-24" alt="Get it on Google Play" src="/img/google-play-badge.png" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="h-24">
|
|
||||||
<a href="https://apps.apple.com/sg/app/immich/id1613945652">
|
|
||||||
<img className="h-24 sm:p-3.5 p-3" alt="Download on the App Store" src="/img/ios-app-store-badge.svg" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="h-24">
|
|
||||||
<a href="https://github.com/immich-app/immich/releases/latest">
|
|
||||||
<img className="h-24 sm:p-3.5 p-3" alt="Download APK" src="/img/download-apk-github.svg" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ThemedImage
|
|
||||||
sources={{ dark: '/img/app-qr-code-dark.svg', light: '/img/app-qr-code-light.svg' }}
|
|
||||||
alt="app qr code"
|
|
||||||
width={'150px'}
|
|
||||||
className="shadow-lg p-3 my-8 dark:bg-immich-dark-bg "
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</header>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Home(): JSX.Element {
|
export default function Home(): JSX.Element {
|
||||||
return (
|
return <Redirect to="/docs/overview/welcome" />;
|
||||||
<Layout title="Home" description="Self-hosted photo and video management solution" noFooter={true}>
|
|
||||||
<HomepageHeader />
|
|
||||||
<div className="flex flex-col place-items-center text-center place-content-center dark:bg-immich-dark-bg py-8">
|
|
||||||
<p>This project is available under GNU AGPL v3 license.</p>
|
|
||||||
<p className="text-sm">Privacy should not be a luxury</p>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,944 +0,0 @@
|
|||||||
import {
|
|
||||||
mdiAccountGroup,
|
|
||||||
mdiAccountGroupOutline,
|
|
||||||
mdiAndroid,
|
|
||||||
mdiAppleIos,
|
|
||||||
mdiArchiveOutline,
|
|
||||||
mdiBash,
|
|
||||||
mdiBookSearchOutline,
|
|
||||||
mdiBookmark,
|
|
||||||
mdiCakeVariant,
|
|
||||||
mdiCameraBurst,
|
|
||||||
mdiChartBoxMultipleOutline,
|
|
||||||
mdiCheckAll,
|
|
||||||
mdiCheckboxMarked,
|
|
||||||
mdiCloudUploadOutline,
|
|
||||||
mdiCollage,
|
|
||||||
mdiContentDuplicate,
|
|
||||||
mdiCrop,
|
|
||||||
mdiDevices,
|
|
||||||
mdiEmailOutline,
|
|
||||||
mdiExpansionCard,
|
|
||||||
mdiEyeOutline,
|
|
||||||
mdiEyeRefreshOutline,
|
|
||||||
mdiFaceMan,
|
|
||||||
mdiFaceManOutline,
|
|
||||||
mdiFile,
|
|
||||||
mdiFileSearch,
|
|
||||||
mdiFlash,
|
|
||||||
mdiFolder,
|
|
||||||
mdiFolderMultiple,
|
|
||||||
mdiForum,
|
|
||||||
mdiHandshakeOutline,
|
|
||||||
mdiHeart,
|
|
||||||
mdiHistory,
|
|
||||||
mdiImage,
|
|
||||||
mdiImageAlbum,
|
|
||||||
mdiImageEdit,
|
|
||||||
mdiImageMultipleOutline,
|
|
||||||
mdiImageSearch,
|
|
||||||
mdiKeyboardSettingsOutline,
|
|
||||||
mdiLicense,
|
|
||||||
mdiLockOutline,
|
|
||||||
mdiMagnify,
|
|
||||||
mdiMagnifyScan,
|
|
||||||
mdiMap,
|
|
||||||
mdiMaterialDesign,
|
|
||||||
mdiMatrix,
|
|
||||||
mdiMerge,
|
|
||||||
mdiMonitor,
|
|
||||||
mdiMotionPlayOutline,
|
|
||||||
mdiPalette,
|
|
||||||
mdiPanVertical,
|
|
||||||
mdiPartyPopper,
|
|
||||||
mdiPencil,
|
|
||||||
mdiRaw,
|
|
||||||
mdiRocketLaunch,
|
|
||||||
mdiRotate360,
|
|
||||||
mdiScaleBalance,
|
|
||||||
mdiSecurity,
|
|
||||||
mdiServer,
|
|
||||||
mdiShare,
|
|
||||||
mdiShareAll,
|
|
||||||
mdiShareCircle,
|
|
||||||
mdiStar,
|
|
||||||
mdiStarOutline,
|
|
||||||
mdiTableKey,
|
|
||||||
mdiTag,
|
|
||||||
mdiTagMultiple,
|
|
||||||
mdiText,
|
|
||||||
mdiThemeLightDark,
|
|
||||||
mdiTrashCanOutline,
|
|
||||||
mdiVectorCombine,
|
|
||||||
mdiFolderSync,
|
|
||||||
mdiFaceRecognition,
|
|
||||||
mdiVideo,
|
|
||||||
mdiWeb,
|
|
||||||
mdiDatabaseOutline,
|
|
||||||
mdiLinkEdit,
|
|
||||||
mdiTagFaces,
|
|
||||||
mdiMovieOpenPlayOutline,
|
|
||||||
mdiCast,
|
|
||||||
} from '@mdi/js';
|
|
||||||
import Layout from '@theme/Layout';
|
|
||||||
import React from 'react';
|
|
||||||
import { Item, Timeline } from '../components/timeline';
|
|
||||||
|
|
||||||
const releases = {
|
|
||||||
'v1.135.0': new Date(2025, 5, 18),
|
|
||||||
'v1.133.0': new Date(2025, 4, 21),
|
|
||||||
'v1.130.0': new Date(2025, 2, 25),
|
|
||||||
'v1.127.0': new Date(2025, 1, 26),
|
|
||||||
'v1.122.0': new Date(2024, 11, 5),
|
|
||||||
'v1.120.0': new Date(2024, 10, 6),
|
|
||||||
'v1.114.0': new Date(2024, 8, 6),
|
|
||||||
'v1.113.0': new Date(2024, 7, 30),
|
|
||||||
'v1.112.0': new Date(2024, 7, 14),
|
|
||||||
'v1.111.0': new Date(2024, 6, 26),
|
|
||||||
'v1.110.0': new Date(2024, 5, 11),
|
|
||||||
'v1.109.0': new Date(2024, 6, 18),
|
|
||||||
'v1.106.1': new Date(2024, 5, 11),
|
|
||||||
'v1.104.0': new Date(2024, 4, 13),
|
|
||||||
'v1.103.0': new Date(2024, 3, 29),
|
|
||||||
'v1.102.0': new Date(2024, 3, 15),
|
|
||||||
'v1.99.0': new Date(2024, 2, 20),
|
|
||||||
'v1.98.0': new Date(2024, 2, 7),
|
|
||||||
'v1.95.0': new Date(2024, 1, 20),
|
|
||||||
'v1.94.0': new Date(2024, 0, 31),
|
|
||||||
'v1.93.0': new Date(2024, 0, 19),
|
|
||||||
'v1.91.0': new Date(2023, 11, 15),
|
|
||||||
'v1.90.0': new Date(2023, 11, 7),
|
|
||||||
'v1.88.0': new Date(2023, 10, 20),
|
|
||||||
'v1.84.0': new Date(2023, 10, 1),
|
|
||||||
'v1.83.0': new Date(2023, 9, 28),
|
|
||||||
'v1.82.0': new Date(2023, 9, 17),
|
|
||||||
'v1.79.0': new Date(2023, 8, 21),
|
|
||||||
'v1.76.0': new Date(2023, 7, 29),
|
|
||||||
'v1.75.0': new Date(2023, 7, 26),
|
|
||||||
'v1.72.0': new Date(2023, 7, 6),
|
|
||||||
'v1.71.0': new Date(2023, 6, 29),
|
|
||||||
'v1.69.0': new Date(2023, 6, 23),
|
|
||||||
'v1.68.0': new Date(2023, 6, 20),
|
|
||||||
'v1.67.0': new Date(2023, 6, 14),
|
|
||||||
'v1.66.0': new Date(2023, 6, 4),
|
|
||||||
'v1.65.0': new Date(2023, 5, 30),
|
|
||||||
'v1.63.0': new Date(2023, 5, 24),
|
|
||||||
'v1.61.0': new Date(2023, 5, 16),
|
|
||||||
'v1.58.0': new Date(2023, 4, 28),
|
|
||||||
'v1.57.0': new Date(2023, 4, 23),
|
|
||||||
'v1.56.0': new Date(2023, 4, 18),
|
|
||||||
'v1.55.0': new Date(2023, 4, 9),
|
|
||||||
'v1.54.0': new Date(2023, 3, 18),
|
|
||||||
'v1.52.0': new Date(2023, 2, 29),
|
|
||||||
'v1.51.0': new Date(2023, 2, 20),
|
|
||||||
'v1.48.0': new Date(2023, 1, 21),
|
|
||||||
'v1.47.0': new Date(2023, 1, 13),
|
|
||||||
'v1.46.0': new Date(2023, 1, 9),
|
|
||||||
'v1.43.0': new Date(2023, 1, 3),
|
|
||||||
'v1.41.0': new Date(2023, 0, 10),
|
|
||||||
'v1.39.0': new Date(2022, 11, 19),
|
|
||||||
'v1.36.0': new Date(2022, 10, 20),
|
|
||||||
'v1.33.1': new Date(2022, 9, 26),
|
|
||||||
'v1.32.0': new Date(2022, 9, 14),
|
|
||||||
'v1.27.0': new Date(2022, 8, 6),
|
|
||||||
'v1.24.0': new Date(2022, 7, 19),
|
|
||||||
'v1.10.0': new Date(2022, 4, 29),
|
|
||||||
'v1.7.0': new Date(2022, 3, 24),
|
|
||||||
'v1.3.0': new Date(2022, 2, 22),
|
|
||||||
'v1.2.0': new Date(2022, 1, 8),
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const weirdTags = {
|
|
||||||
'v1.41.0': 'v1.41.1_64-dev',
|
|
||||||
'v1.39.0': 'v1.39.0_61-dev',
|
|
||||||
'v1.36.0': 'v1.36.0_55-dev',
|
|
||||||
'v1.33.1': 'v1.33.0_52-dev',
|
|
||||||
'v1.32.0': 'v1.32.0_50-dev',
|
|
||||||
'v1.27.0': 'v1.27.0_37-dev',
|
|
||||||
'v1.24.0': 'v1.24.0_34-dev',
|
|
||||||
'v1.10.0': 'v1.10.0_15-dev',
|
|
||||||
'v1.7.0': 'v1.7.0_11-dev ',
|
|
||||||
'v1.3.0': 'v1.3.0-dev ',
|
|
||||||
'v1.2.0': 'v0.2-dev ',
|
|
||||||
};
|
|
||||||
|
|
||||||
const title = 'Roadmap';
|
|
||||||
const description = 'A list of future plans and goals, as well as past achievements and milestones.';
|
|
||||||
|
|
||||||
const withLanguage = (date: Date) => (language: string) => date.toLocaleDateString(language);
|
|
||||||
|
|
||||||
type Base = { icon: string; iconColor?: React.CSSProperties['color']; title: string; description: string };
|
|
||||||
const withRelease = ({
|
|
||||||
icon,
|
|
||||||
iconColor,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
release: version,
|
|
||||||
}: Base & { release: keyof typeof releases }) => {
|
|
||||||
return {
|
|
||||||
icon,
|
|
||||||
iconColor: iconColor ?? 'gray',
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
link: {
|
|
||||||
url: `https://github.com/immich-app/immich/releases/tag/${weirdTags[version] ?? version}`,
|
|
||||||
text: version,
|
|
||||||
},
|
|
||||||
getDateLabel: withLanguage(releases[version]),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const roadmap: Item[] = [
|
|
||||||
{
|
|
||||||
done: false,
|
|
||||||
icon: mdiFlash,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'Workflows',
|
|
||||||
description: 'Automate tasks with workflows',
|
|
||||||
getDateLabel: () => 'Planned for 2025',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
done: false,
|
|
||||||
icon: mdiImageEdit,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Basic editor',
|
|
||||||
description: 'Basic photo editing capabilities',
|
|
||||||
getDateLabel: () => 'Planned for 2025',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
done: false,
|
|
||||||
icon: mdiRocketLaunch,
|
|
||||||
iconColor: 'indianred',
|
|
||||||
title: 'Stable release',
|
|
||||||
description: 'Immich goes stable',
|
|
||||||
getDateLabel: () => 'Planned for 2025',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
done: false,
|
|
||||||
icon: mdiCloudUploadOutline,
|
|
||||||
iconColor: 'cornflowerblue',
|
|
||||||
title: 'Better background backups',
|
|
||||||
description: 'Rework background backups to be more reliable',
|
|
||||||
getDateLabel: () => 'Planned for 2025',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
done: false,
|
|
||||||
icon: mdiCameraBurst,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Auto stacking',
|
|
||||||
description: 'Auto stack burst photos',
|
|
||||||
getDateLabel: () => 'Planned for 2025',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const milestones: Item[] = [
|
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '70,000 Stars',
|
|
||||||
description: 'Reached 70K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2025, 6, 9)),
|
|
||||||
},
|
|
||||||
withRelease({
|
|
||||||
icon: mdiTableKey,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'Fine grained access controls',
|
|
||||||
description: 'Granular access controls for api keys',
|
|
||||||
release: 'v1.135.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCast,
|
|
||||||
iconColor: 'aqua',
|
|
||||||
title: 'Google Cast (web and mobile)',
|
|
||||||
description: 'Cast assets to Google Cast/Chromecast compatible devices',
|
|
||||||
release: 'v1.135.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiLockOutline,
|
|
||||||
iconColor: 'sandybrown',
|
|
||||||
title: 'Private/locked photos',
|
|
||||||
description: 'Private assets with extra protections',
|
|
||||||
release: 'v1.133.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFolderMultiple,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Folders view in the mobile app',
|
|
||||||
description: 'Browse your photos and videos in their folder structure inside the mobile app',
|
|
||||||
release: 'v1.130.0',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '60,000 Stars',
|
|
||||||
description: 'Reached 60K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2025, 2, 4)),
|
|
||||||
},
|
|
||||||
withRelease({
|
|
||||||
icon: mdiTagFaces,
|
|
||||||
iconColor: 'teal',
|
|
||||||
title: 'Manual face tagging',
|
|
||||||
description:
|
|
||||||
'Manually tag or remove faces in photos and videos, even when automatic detection misses or misidentifies them.',
|
|
||||||
release: 'v1.127.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiLinkEdit,
|
|
||||||
iconColor: 'crimson',
|
|
||||||
title: 'Automatic URL switching',
|
|
||||||
description: 'The mobile app now supports automatic switching between different server URLs',
|
|
||||||
release: 'v1.122.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMovieOpenPlayOutline,
|
|
||||||
iconColor: 'darksalmon',
|
|
||||||
title: 'Native video player',
|
|
||||||
description: 'HDR videos are now fully supported using the Immich native video player',
|
|
||||||
release: 'v1.122.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiDatabaseOutline,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Automatic database dumps',
|
|
||||||
description: 'Database dumps are now integrated into the Immich server',
|
|
||||||
release: 'v1.120.0',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '50,000 Stars',
|
|
||||||
description: 'Reached 50K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2024, 10, 1)),
|
|
||||||
},
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFaceRecognition,
|
|
||||||
title: 'Metadata Face Import',
|
|
||||||
description: 'Read face metadata in Digikam format during import',
|
|
||||||
release: 'v1.114.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiTagMultiple,
|
|
||||||
iconColor: 'orange',
|
|
||||||
title: 'Tags',
|
|
||||||
description: 'Tag your photos and videos',
|
|
||||||
release: 'v1.113.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFolderSync,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'Album sync (mobile)',
|
|
||||||
description: 'Sync or mirror an album from your phone to the Immich server',
|
|
||||||
release: 'v1.113.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFolderMultiple,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Folders view',
|
|
||||||
description: 'Browse your photos and videos in their folder structure',
|
|
||||||
release: 'v1.113.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiPalette,
|
|
||||||
title: 'Theming (mobile)',
|
|
||||||
description: 'Pick a primary color for the mobile app',
|
|
||||||
release: 'v1.112.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiStarOutline,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'Star rating',
|
|
||||||
description: 'Rate your photos and videos',
|
|
||||||
release: 'v1.112.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCrop,
|
|
||||||
iconColor: 'royalblue',
|
|
||||||
title: 'Editor (mobile)',
|
|
||||||
description: 'Crop and rotate on mobile',
|
|
||||||
release: 'v1.111.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMap,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'Deploy tiles.immich.cloud',
|
|
||||||
description: 'Dedicated tile server for Immich',
|
|
||||||
release: 'v1.111.0',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '40,000 Stars',
|
|
||||||
description: 'Reached 40K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2024, 6, 21)),
|
|
||||||
},
|
|
||||||
withRelease({
|
|
||||||
icon: mdiShare,
|
|
||||||
title: 'Deploy my.immich.app',
|
|
||||||
description: 'Url router for immich links',
|
|
||||||
release: 'v1.109.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiLicense,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'Supporter Badge',
|
|
||||||
description: 'The option to buy Immich to support its development!',
|
|
||||||
release: 'v1.109.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiHistory,
|
|
||||||
title: 'Versioned documentation',
|
|
||||||
description: 'View documentation as it was at the time of past releases',
|
|
||||||
release: 'v1.106.1',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiWeb,
|
|
||||||
iconColor: 'royalblue',
|
|
||||||
title: 'Web translations',
|
|
||||||
description: 'Translate the web application to multiple languages',
|
|
||||||
release: 'v1.106.1',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiContentDuplicate,
|
|
||||||
title: 'Similar image detection',
|
|
||||||
description: "Detect duplicate assets that aren't exactly identical",
|
|
||||||
release: 'v1.106.1',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiVectorCombine,
|
|
||||||
title: 'Container consolidation',
|
|
||||||
description:
|
|
||||||
'The microservices container can be run as a worker within the server image, allowing us to remove it from the default stack.',
|
|
||||||
release: 'v1.106.1',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiPencil,
|
|
||||||
iconColor: 'saddlebrown',
|
|
||||||
title: 'Read-write external libraries',
|
|
||||||
description: 'Edit, update, and delete files in external libraries',
|
|
||||||
release: 'v1.104.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiEmailOutline,
|
|
||||||
iconColor: 'crimson',
|
|
||||||
title: 'Email notifications',
|
|
||||||
description: 'Send emails for important events',
|
|
||||||
release: 'v1.104.0',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
icon: mdiHandshakeOutline,
|
|
||||||
iconColor: 'magenta',
|
|
||||||
title: 'Immich joins FUTO!',
|
|
||||||
description: 'Joined Futo and Immich core team goes full-time',
|
|
||||||
getDateLabel: withLanguage(new Date(2024, 4, 1)),
|
|
||||||
},
|
|
||||||
withRelease({
|
|
||||||
icon: mdiEyeOutline,
|
|
||||||
iconColor: 'darkslategray',
|
|
||||||
title: 'Read-only albums',
|
|
||||||
description: 'Share albums with other users as read-only',
|
|
||||||
release: 'v1.103.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiBookmark,
|
|
||||||
iconColor: 'orangered',
|
|
||||||
title: 'Permanent URLs (Web)',
|
|
||||||
description: 'Assets on the web now have permanent URLs',
|
|
||||||
release: 'v1.103.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '30,000 Stars',
|
|
||||||
description: 'Reached 30K Stars on GitHub!',
|
|
||||||
release: 'v1.102.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiChartBoxMultipleOutline,
|
|
||||||
iconColor: 'mediumvioletred',
|
|
||||||
title: 'OpenTelemetry metrics',
|
|
||||||
description: 'OpenTelemetry metrics for local evaluation and advanced debugging',
|
|
||||||
release: 'v1.99.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: 'immich',
|
|
||||||
title: 'New logo',
|
|
||||||
description: 'Immich got its new logo',
|
|
||||||
release: 'v1.98.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMagnifyScan,
|
|
||||||
title: 'Search enhancement with advanced filters',
|
|
||||||
description: 'Advanced search with filters by date, location and more',
|
|
||||||
release: 'v1.95.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiScaleBalance,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: 'AGPL License',
|
|
||||||
description: 'Immich switches to AGPLv3 license',
|
|
||||||
release: 'v1.95.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiEyeRefreshOutline,
|
|
||||||
title: 'Library watching',
|
|
||||||
description: 'Automatically import files in external libraries when the operating system detects changes.',
|
|
||||||
release: 'v1.94.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiExpansionCard,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'GPU acceleration for machine-learning',
|
|
||||||
description: 'Hardware acceleration support for Nvidia and Intel devices through CUDA and OpenVINO.',
|
|
||||||
release: 'v1.94.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiAccountGroupOutline,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: '250 unique contributors',
|
|
||||||
description: '250 amazing people contributed to Immich',
|
|
||||||
release: 'v1.93.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMatrix,
|
|
||||||
title: 'Search improvement with pgvecto.rs',
|
|
||||||
description: 'Moved the search from typesense to pgvecto.rs',
|
|
||||||
release: 'v1.91.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiPencil,
|
|
||||||
iconColor: 'saddlebrown',
|
|
||||||
title: 'Edit metadata',
|
|
||||||
description: "Edit a photo or video's date, time, hours, timezone, and GPS information",
|
|
||||||
release: 'v1.90.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiVectorCombine,
|
|
||||||
title: 'Container consolidation',
|
|
||||||
description:
|
|
||||||
'The serving of the web app is merged into the server image, allowing us to remove two containers from the stack.',
|
|
||||||
release: 'v1.88.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiBash,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'CLI v2',
|
|
||||||
description: 'Version 2 of the Immich CLI is released, replacing the legacy v1 CLI.',
|
|
||||||
release: 'v1.88.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiForum,
|
|
||||||
iconColor: 'dodgerblue',
|
|
||||||
title: 'Activity',
|
|
||||||
description: 'Comment a photo or a video in a shared album',
|
|
||||||
release: 'v1.84.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '20,000 Stars',
|
|
||||||
description: 'Reached 20K Stars on GitHub!',
|
|
||||||
release: 'v1.83.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCameraBurst,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Stack assets',
|
|
||||||
description: 'Manual asset stacking for grouping and hiding related assets in the main timeline.',
|
|
||||||
release: 'v1.83.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiPalette,
|
|
||||||
iconColor: 'magenta',
|
|
||||||
title: 'Custom theme',
|
|
||||||
description: 'Apply your custom CSS for modifying fonts, colors, and styles in the web application.',
|
|
||||||
release: 'v1.83.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiTrashCanOutline,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Trash feature',
|
|
||||||
description: 'Trash, restore from trash, and automatically empty the recycle bin after 30 days.',
|
|
||||||
release: 'v1.82.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiBookSearchOutline,
|
|
||||||
title: 'External libraries',
|
|
||||||
description: 'Automatically import media into Immich based on imports paths and ignore patterns.',
|
|
||||||
release: 'v1.79.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMap,
|
|
||||||
iconColor: 'darksalmon',
|
|
||||||
title: 'Map view (mobile)',
|
|
||||||
description: 'Heat map implementation in the mobile app.',
|
|
||||||
release: 'v1.76.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFile,
|
|
||||||
iconColor: 'lightblue',
|
|
||||||
title: 'Configuration file',
|
|
||||||
description: 'Auto-configure an Immich installation via a configuration file.',
|
|
||||||
release: 'v1.75.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMonitor,
|
|
||||||
iconColor: 'darkcyan',
|
|
||||||
title: 'Slideshow mode (web)',
|
|
||||||
description: 'Start a full-screen slideshow from an Album on the web.',
|
|
||||||
release: 'v1.75.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiServer,
|
|
||||||
iconColor: 'lightskyblue',
|
|
||||||
title: 'Hardware transcoding',
|
|
||||||
description: 'Support hardware acceleration (QuickSync, VAAPI, and Nvidia) for video transcoding.',
|
|
||||||
release: 'v1.72.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImageAlbum,
|
|
||||||
iconColor: 'olivedrab',
|
|
||||||
title: 'View albums via time buckets',
|
|
||||||
description: 'Upgrade albums to use time buckets, an optimized virtual viewport.',
|
|
||||||
release: 'v1.72.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImageAlbum,
|
|
||||||
iconColor: 'olivedrab',
|
|
||||||
title: 'Album description',
|
|
||||||
description: 'Save an album description.',
|
|
||||||
release: 'v1.72.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiRotate360,
|
|
||||||
title: '360° Photos (web)',
|
|
||||||
description: 'View 360° Photos on the web.',
|
|
||||||
release: 'v1.71.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMotionPlayOutline,
|
|
||||||
title: 'Android motion photos',
|
|
||||||
description: 'Add support for Android Motion Photos.',
|
|
||||||
release: 'v1.69.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFaceManOutline,
|
|
||||||
iconColor: 'mistyrose',
|
|
||||||
title: 'Show/hide faces',
|
|
||||||
description: 'Add the options to show or hide faces.',
|
|
||||||
release: 'v1.68.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMerge,
|
|
||||||
iconColor: 'forestgreen',
|
|
||||||
title: 'Merge faces',
|
|
||||||
description: 'Add the ability to merge multiple faces together.',
|
|
||||||
release: 'v1.67.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImage,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Feature photo',
|
|
||||||
description: 'Add the option to change the feature photo for a person.',
|
|
||||||
release: 'v1.66.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiKeyboardSettingsOutline,
|
|
||||||
iconColor: 'darkslategray',
|
|
||||||
title: 'Multi-select via SHIFT',
|
|
||||||
description: 'Add the option to multi-select while holding SHIFT.',
|
|
||||||
release: 'v1.66.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImageMultipleOutline,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Memories (mobile)',
|
|
||||||
description: 'View "On this day..." memories in the mobile app.',
|
|
||||||
release: 'v1.65.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFaceMan,
|
|
||||||
iconColor: 'mistyrose',
|
|
||||||
title: 'Facial recognition (mobile)',
|
|
||||||
description: 'View detected faces in the mobile app.',
|
|
||||||
release: 'v1.63.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImageMultipleOutline,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'Memories (web)',
|
|
||||||
description: 'View pictures taken in past years on this day on the web.',
|
|
||||||
release: 'v1.61.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCollage,
|
|
||||||
iconColor: 'deeppink',
|
|
||||||
title: 'Justified layout (web)',
|
|
||||||
description: 'Implement justified layout (collage) on the web.',
|
|
||||||
release: 'v1.61.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiRaw,
|
|
||||||
title: 'RAW file formats',
|
|
||||||
description: 'Support for RAW file formats.',
|
|
||||||
release: 'v1.61.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiShareAll,
|
|
||||||
iconColor: 'darkturquoise',
|
|
||||||
title: 'Partner sharing (mobile)',
|
|
||||||
description: 'View shared partner photos in the mobile app.',
|
|
||||||
release: 'v1.58.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFile,
|
|
||||||
iconColor: 'lightblue',
|
|
||||||
title: 'XMP sidecar',
|
|
||||||
description: 'Attach XMP sidecar files to assets.',
|
|
||||||
release: 'v1.58.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFolder,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Custom storage label',
|
|
||||||
description: 'Replace the user UUID in the storage template with a custom label.',
|
|
||||||
release: 'v1.57.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiShareCircle,
|
|
||||||
title: 'Partner sharing',
|
|
||||||
description: 'Share your entire collection with another user.',
|
|
||||||
release: 'v1.56.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFaceMan,
|
|
||||||
iconColor: 'mistyrose',
|
|
||||||
title: 'Facial recognition',
|
|
||||||
description: 'Detect faces in pictures and cluster them together as people, which can be named.',
|
|
||||||
release: 'v1.56.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMap,
|
|
||||||
iconColor: 'darksalmon',
|
|
||||||
title: 'Map view (web)',
|
|
||||||
description: 'View a global map, with clusters of photos based on corresponding GPS data.',
|
|
||||||
release: 'v1.55.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiDevices,
|
|
||||||
iconColor: 'slategray',
|
|
||||||
title: 'Manage auth devices',
|
|
||||||
description: 'Manage logged-in devices and revoke access from User Settings.',
|
|
||||||
release: 'v1.55.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '10,000 Stars',
|
|
||||||
description: 'Reached 10K stars on GitHub!',
|
|
||||||
release: 'v1.54.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiText,
|
|
||||||
title: 'Asset descriptions',
|
|
||||||
description: 'Save an asset description',
|
|
||||||
release: 'v1.54.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiArchiveOutline,
|
|
||||||
title: 'Archiving',
|
|
||||||
description: 'Remove assets from the main timeline by archiving them.',
|
|
||||||
release: 'v1.54.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiDevices,
|
|
||||||
iconColor: 'slategray',
|
|
||||||
title: 'Responsive web app',
|
|
||||||
description: 'Optimize the web app for small screen.',
|
|
||||||
release: 'v1.54.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFileSearch,
|
|
||||||
iconColor: 'brown',
|
|
||||||
title: 'Search by metadata',
|
|
||||||
description: 'Search images by filename, description, tagged people, make, model, and other metadata.',
|
|
||||||
release: 'v1.52.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImageSearch,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'CLIP search',
|
|
||||||
description: 'Search images with free-form text like "Sunset at the beach".',
|
|
||||||
release: 'v1.51.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMagnify,
|
|
||||||
iconColor: 'lightblue',
|
|
||||||
title: 'Explore page',
|
|
||||||
description: 'View tagged places, object, and people.',
|
|
||||||
release: 'v1.51.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiAppleIos,
|
|
||||||
title: 'iOS background uploads',
|
|
||||||
description: 'Automatically backup pictures in the background on iOS.',
|
|
||||||
release: 'v1.48.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMotionPlayOutline,
|
|
||||||
title: 'Auto-Link live photos',
|
|
||||||
description: 'Automatically link live photos, even when uploaded as separate files.',
|
|
||||||
release: 'v1.48.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMaterialDesign,
|
|
||||||
iconColor: 'blue',
|
|
||||||
title: 'Material design 3 (mobile)',
|
|
||||||
description: 'Upgrade the mobile app to Material Design 3.',
|
|
||||||
release: 'v1.47.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiHeart,
|
|
||||||
iconColor: 'red',
|
|
||||||
title: 'Favorites (mobile)',
|
|
||||||
description: 'Show favorites on the mobile app.',
|
|
||||||
release: 'v1.46.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCakeVariant,
|
|
||||||
iconColor: 'deeppink',
|
|
||||||
title: 'Immich turns 1',
|
|
||||||
description: 'Immich is officially one year old.',
|
|
||||||
release: 'v1.43.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiHeart,
|
|
||||||
iconColor: 'red',
|
|
||||||
title: 'Favorites page (web)',
|
|
||||||
description: 'Favorite and view favorites on the web.',
|
|
||||||
release: 'v1.43.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiShareCircle,
|
|
||||||
title: 'Public share links',
|
|
||||||
description: 'Share photos and albums publicly via a shared link.',
|
|
||||||
release: 'v1.41.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiFolder,
|
|
||||||
iconColor: 'lightblue',
|
|
||||||
title: 'User-defined storage structure',
|
|
||||||
description: 'Support custom storage structures.',
|
|
||||||
release: 'v1.39.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiMotionPlayOutline,
|
|
||||||
title: 'iOS live photos',
|
|
||||||
description: 'Backup and display iOS Live Photos.',
|
|
||||||
release: 'v1.36.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiSecurity,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'OAuth integration',
|
|
||||||
description: 'Support OAuth2 and OIDC capable identity providers.',
|
|
||||||
release: 'v1.36.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiWeb,
|
|
||||||
iconColor: 'royalblue',
|
|
||||||
title: 'Documentation site',
|
|
||||||
description: 'Release an official documentation website.',
|
|
||||||
release: 'v1.33.1',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiThemeLightDark,
|
|
||||||
iconColor: 'slategray',
|
|
||||||
title: 'Dark mode (web)',
|
|
||||||
description: 'Dark mode on the web.',
|
|
||||||
release: 'v1.32.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiPanVertical,
|
|
||||||
title: 'Virtual scrollbar (web)',
|
|
||||||
description: 'View the main timeline with a virtual scrollbar, allowing to jump to any point in time, instantly.',
|
|
||||||
release: 'v1.27.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCheckAll,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'Checksum duplication check',
|
|
||||||
description: 'Enforce per user sha1 checksum uniqueness.',
|
|
||||||
release: 'v1.27.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiAndroid,
|
|
||||||
iconColor: 'greenyellow',
|
|
||||||
title: 'Android background backup',
|
|
||||||
description: 'Automatic backup in the background on Android.',
|
|
||||||
release: 'v1.24.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiAccountGroup,
|
|
||||||
iconColor: 'gray',
|
|
||||||
title: 'Admin portal',
|
|
||||||
description: 'Manage users and admin settings from the web.',
|
|
||||||
release: 'v1.10.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiShareCircle,
|
|
||||||
title: 'Album sharing',
|
|
||||||
description: 'Share albums with other users.',
|
|
||||||
release: 'v1.7.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiTag,
|
|
||||||
iconColor: 'coral',
|
|
||||||
title: 'Image tagging',
|
|
||||||
description: 'Tag images with custom values.',
|
|
||||||
release: 'v1.7.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiImage,
|
|
||||||
iconColor: 'rebeccapurple',
|
|
||||||
title: 'View exif',
|
|
||||||
description: 'View metadata about assets.',
|
|
||||||
release: 'v1.3.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiCheckboxMarked,
|
|
||||||
iconColor: 'green',
|
|
||||||
title: 'Multi select',
|
|
||||||
description: 'Select and execute actions on multiple assets at the same time.',
|
|
||||||
release: 'v1.2.0',
|
|
||||||
}),
|
|
||||||
withRelease({
|
|
||||||
icon: mdiVideo,
|
|
||||||
iconColor: 'slategray',
|
|
||||||
title: 'Video player',
|
|
||||||
description: 'Play videos in the web and on mobile.',
|
|
||||||
release: 'v1.2.0',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
icon: mdiPartyPopper,
|
|
||||||
iconColor: 'deeppink',
|
|
||||||
title: 'First commit',
|
|
||||||
description: 'First commit on GitHub, Immich is born.',
|
|
||||||
getDateLabel: withLanguage(new Date(2022, 1, 3)),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function MilestonePage(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<Layout title={title} description={description}>
|
|
||||||
<section className="my-8">
|
|
||||||
<h1 className="md:text-6xl text-center mb-10 text-immich-primary dark:text-immich-dark-primary px-2">
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
<p className="text-center text-xl px-2">{description}</p>
|
|
||||||
<div className="flex justify-around mt-8 w-full max-w-full">
|
|
||||||
<Timeline items={[...roadmap, ...milestones]} />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
5
docs/static/.well-known/security.txt
vendored
5
docs/static/.well-known/security.txt
vendored
@@ -1,5 +0,0 @@
|
|||||||
Policy: https://github.com/immich-app/immich/blob/main/SECURITY.md
|
|
||||||
Contact: mailto:security@immich.app
|
|
||||||
Preferred-Languages: en
|
|
||||||
Expires: 2026-05-01T23:59:00.000Z
|
|
||||||
Canonical: https://immich.app/.well-known/security.txt
|
|
||||||
52
docs/static/archived-versions.json
vendored
52
docs/static/archived-versions.json
vendored
@@ -1,4 +1,56 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"label": "v1.143.1",
|
||||||
|
"url": "https://v1.143.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.143.0",
|
||||||
|
"url": "https://v1.143.0.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.142.1",
|
||||||
|
"url": "https://v1.142.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.142.0",
|
||||||
|
"url": "https://v1.142.0.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.141.1",
|
||||||
|
"url": "https://v1.141.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.141.0",
|
||||||
|
"url": "https://v1.141.0.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.140.1",
|
||||||
|
"url": "https://v1.140.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.140.0",
|
||||||
|
"url": "https://v1.140.0.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.139.4",
|
||||||
|
"url": "https://v1.139.4.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.139.3",
|
||||||
|
"url": "https://v1.139.3.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.139.2",
|
||||||
|
"url": "https://v1.139.2.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.138.1",
|
||||||
|
"url": "https://v1.138.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.138.0",
|
||||||
|
"url": "https://v1.138.0.archive.immich.app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "v1.137.3",
|
"label": "v1.137.3",
|
||||||
"url": "https://v1.137.3.archive.immich.app"
|
"url": "https://v1.137.3.archive.immich.app"
|
||||||
|
|||||||
1
e2e/.gitignore
vendored
1
e2e/.gitignore
vendored
@@ -3,3 +3,4 @@ node_modules/
|
|||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
|
/dist
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ services:
|
|||||||
image: redis:6.2-alpine@sha256:7fe72c486b910f6b1a9769c937dad5d63648ddee82e056f47417542dd40825bb
|
image: redis:6.2-alpine@sha256:7fe72c486b910f6b1a9769c937dad5d63648ddee82e056f47417542dd40825bb
|
||||||
|
|
||||||
database:
|
database:
|
||||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:0e763a2383d56f90364fcd72767ac41400cd30d2627f407f7e7960c9f1923c21
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:11ced39d65a92a54d12890ced6a26cc2003f92697d6f0d4d944b98459dba7138
|
||||||
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
|
command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
|
|||||||
7419
e2e/package-lock.json
generated
7419
e2e/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.137.3",
|
"version": "1.143.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -19,19 +19,17 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@immich/cli": "file:../cli",
|
"@immich/cli": "file:../cli",
|
||||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@socket.io/component-emitter": "^3.1.2",
|
"@socket.io/component-emitter": "^3.1.2",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.17.0",
|
"@types/node": "^22.18.1",
|
||||||
"@types/oidc-provider": "^9.0.0",
|
"@types/oidc-provider": "^9.0.0",
|
||||||
"@types/pg": "^8.15.1",
|
"@types/pg": "^8.15.1",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
@@ -45,7 +43,7 @@
|
|||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-organize-imports": "^4.0.0",
|
"prettier-plugin-organize-imports": "^4.0.0",
|
||||||
"sharp": "^0.34.0",
|
"sharp": "^0.34.3",
|
||||||
"socket.io-client": "^4.7.4",
|
"socket.io-client": "^4.7.4",
|
||||||
"supertest": "^7.0.0",
|
"supertest": "^7.0.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
@@ -54,6 +52,6 @@
|
|||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1466,10 +1466,10 @@ describe('/asset', () => {
|
|||||||
expectedDate: '2023-04-04T04:00:00.000Z',
|
expectedDate: '2023-04-04T04:00:00.000Z',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'CreateDate when DateTimeOriginal missing',
|
name: 'CreationDate when DateTimeOriginal missing',
|
||||||
exifData: {
|
exifData: {
|
||||||
CreateDate: '2023:05:05 05:00:00', // TESTABLE
|
CreationDate: '2023:05:05 05:00:00', // TESTABLE
|
||||||
CreationDate: '2023:07:07 07:00:00', // TESTABLE
|
CreateDate: '2023:07:07 07:00:00', // TESTABLE
|
||||||
GPSDateTime: '2023:10:10 10:00:00', // TESTABLE
|
GPSDateTime: '2023:10:10 10:00:00', // TESTABLE
|
||||||
},
|
},
|
||||||
expectedDate: '2023-05-05T05:00:00.000Z',
|
expectedDate: '2023-05-05T05:00:00.000Z',
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ describe('/partners', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
createPartner({ id: user2.userId }, { headers: asBearerAuth(user1.accessToken) }),
|
createPartner({ partnerCreateDto: { sharedWithId: user2.userId } }, { headers: asBearerAuth(user1.accessToken) }),
|
||||||
createPartner({ id: user1.userId }, { headers: asBearerAuth(user2.accessToken) }),
|
createPartner({ partnerCreateDto: { sharedWithId: user1.userId } }, { headers: asBearerAuth(user2.accessToken) }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const tempDir = tmpdir();
|
|||||||
export const asBearerAuth = (accessToken: string) => ({ Authorization: `Bearer ${accessToken}` });
|
export const asBearerAuth = (accessToken: string) => ({ Authorization: `Bearer ${accessToken}` });
|
||||||
export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
|
export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
|
||||||
export const immichCli = (args: string[]) =>
|
export const immichCli = (args: string[]) =>
|
||||||
executeCommand('node', ['node_modules/.bin/immich', '-d', `/${tempDir}/immich/`, ...args]).promise;
|
executeCommand('pnpm', ['exec', 'immich', '-d', `/${tempDir}/immich/`, ...args], { cwd: '../cli' }).promise;
|
||||||
export const immichAdmin = (args: string[]) =>
|
export const immichAdmin = (args: string[]) =>
|
||||||
executeCommand('docker', ['exec', '-i', 'immich-e2e-server', '/bin/bash', '-c', `immich-admin ${args.join(' ')}`]);
|
executeCommand('docker', ['exec', '-i', 'immich-e2e-server', '/bin/bash', '-c', `immich-admin ${args.join(' ')}`]);
|
||||||
export const specialCharStrings = ["'", '"', ',', '{', '}', '*'];
|
export const specialCharStrings = ["'", '"', ',', '{', '}', '*'];
|
||||||
@@ -462,7 +462,8 @@ export const utils = {
|
|||||||
updateLibrary: (accessToken: string, id: string, dto: UpdateLibraryDto) =>
|
updateLibrary: (accessToken: string, id: string, dto: UpdateLibraryDto) =>
|
||||||
updateLibrary({ id, updateLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
|
updateLibrary({ id, updateLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|
||||||
createPartner: (accessToken: string, id: string) => createPartner({ id }, { headers: asBearerAuth(accessToken) }),
|
createPartner: (accessToken: string, id: string) =>
|
||||||
|
createPartner({ partnerCreateDto: { sharedWithId: id } }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|
||||||
updateMyPreferences: (accessToken: string, userPreferencesUpdateDto: UserPreferencesUpdateDto) =>
|
updateMyPreferences: (accessToken: string, userPreferencesUpdateDto: UserPreferencesUpdateDto) =>
|
||||||
updateMyPreferences({ userPreferencesUpdateDto }, { headers: asBearerAuth(accessToken) }),
|
updateMyPreferences({ userPreferencesUpdateDto }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|||||||
38
i18n/af.json
38
i18n/af.json
@@ -14,6 +14,7 @@
|
|||||||
"add_a_location": "Voeg 'n ligging by",
|
"add_a_location": "Voeg 'n ligging by",
|
||||||
"add_a_name": "Voeg 'n naam by",
|
"add_a_name": "Voeg 'n naam by",
|
||||||
"add_a_title": "Voeg 'n titel by",
|
"add_a_title": "Voeg 'n titel by",
|
||||||
|
"add_birthday": "Voeg 'n verjaarsdag by",
|
||||||
"add_endpoint": "Voeg Koppelvlakpunt by",
|
"add_endpoint": "Voeg Koppelvlakpunt by",
|
||||||
"add_exclusion_pattern": "Voeg uitsgluitingspatrone by",
|
"add_exclusion_pattern": "Voeg uitsgluitingspatrone by",
|
||||||
"add_import_path": "Voeg invoerpad by",
|
"add_import_path": "Voeg invoerpad by",
|
||||||
@@ -27,6 +28,8 @@
|
|||||||
"add_to_album": "Voeg na album",
|
"add_to_album": "Voeg na album",
|
||||||
"add_to_album_bottom_sheet_added": "By {album} bygevoeg",
|
"add_to_album_bottom_sheet_added": "By {album} bygevoeg",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Reeds in {album}",
|
"add_to_album_bottom_sheet_already_exists": "Reeds in {album}",
|
||||||
|
"add_to_albums": "Voeg by albums",
|
||||||
|
"add_to_albums_count": "Voeg by ({count}) albums",
|
||||||
"add_to_shared_album": "Voeg toe aan gedeelde album",
|
"add_to_shared_album": "Voeg toe aan gedeelde album",
|
||||||
"add_url": "Voeg URL by",
|
"add_url": "Voeg URL by",
|
||||||
"added_to_archive": "By argief toegevoegd",
|
"added_to_archive": "By argief toegevoegd",
|
||||||
@@ -44,6 +47,11 @@
|
|||||||
"backup_database": "Skep Datastortlêer",
|
"backup_database": "Skep Datastortlêer",
|
||||||
"backup_database_enable_description": "Aktiveer databasisrugsteun",
|
"backup_database_enable_description": "Aktiveer databasisrugsteun",
|
||||||
"backup_keep_last_amount": "Aantal vorige rugsteune om te hou",
|
"backup_keep_last_amount": "Aantal vorige rugsteune om te hou",
|
||||||
|
"backup_onboarding_3_description": "totale kopieë van jou data, insluitende die oorspronklikke lêers. Dit sluit in 1 kopie op 'n ander perseel en 2 kopieë om die huidige rekenaar.",
|
||||||
|
"backup_onboarding_description": "'N <backblaze-link>3-2-1 rugsteun strategie</backblaze-link> word sterk aanbeveel om jou data veilig te hou. Hou kopieë van jou fotos/videos so wel as die Immich databasis vir 'n volledige rugsteun oplossing.",
|
||||||
|
"backup_onboarding_footer": "Vir meer inligting oor hoe om 'n rugsteun kopie van Immich te maak, gaan lees asseblief hierdie <link>dokument</link>.",
|
||||||
|
"backup_onboarding_parts_title": "'N 3-2-1 rugsteun sluit in:",
|
||||||
|
"backup_onboarding_title": "Rugsteun kopieë",
|
||||||
"backup_settings": "Rugsteun instellings",
|
"backup_settings": "Rugsteun instellings",
|
||||||
"backup_settings_description": "Bestuur databasis rugsteun instellings.",
|
"backup_settings_description": "Bestuur databasis rugsteun instellings.",
|
||||||
"cleared_jobs": "Poste gevee vir: {job}",
|
"cleared_jobs": "Poste gevee vir: {job}",
|
||||||
@@ -62,8 +70,8 @@
|
|||||||
"duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search",
|
"duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search",
|
||||||
"exclusion_pattern_description": "Met uitsluitingspatrone kan jy lêers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lêers bevat wat jy nie wil invoer nie, soos RAW-lêers.",
|
"exclusion_pattern_description": "Met uitsluitingspatrone kan jy lêers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lêers bevat wat jy nie wil invoer nie, soos RAW-lêers.",
|
||||||
"external_library_management": "Eksterne Biblioteekbestuur",
|
"external_library_management": "Eksterne Biblioteekbestuur",
|
||||||
"face_detection": "Gesig deteksie",
|
"face_detection": "Gesig herkenning",
|
||||||
"face_detection_description": "Detecteer die gesigte in media deur middel van masjienleer. Vir videos word slegs die duimnaelskets oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder boonop alle huidige gesigdata. “Onverwerk” plaas bates in die tou wat nog nie verwerk is nie. Gedekte gesigte sal ná voltooiing van Gesigdetectie vir Gesigherkenning in die tou geplaas word, om hulle in bestaande of nuwe persone te groepeer.",
|
"face_detection_description": "Identifiseer die gesigte in media deur middel van masjienleer. Vir videos word slegs die duimnaelskets oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder alle huidige gesigdata. “Onverwerk” plaas bates in die tou wat nog nie verwerk is nie. Geidentifiseerde gesigte sal ná voltooiing van Gesigidentifikasie vir Gesigherkenning in die tou geplaas word, om hulle in bestaande of nuwe persone te groepeer.",
|
||||||
"facial_recognition_job_description": "Groepeer gesigte in mense in. Die stap is vinniger nadat Gesig Deteksie klaar is. \"Herstel\" (her-)groepeer alle gesigte. \"Vermiste\" plaas gesigte in ry wat nie 'n persoon gekoppel het nie.",
|
"facial_recognition_job_description": "Groepeer gesigte in mense in. Die stap is vinniger nadat Gesig Deteksie klaar is. \"Herstel\" (her-)groepeer alle gesigte. \"Vermiste\" plaas gesigte in ry wat nie 'n persoon gekoppel het nie.",
|
||||||
"failed_job_command": "Opdrag {command} het misluk vir werk: {job}",
|
"failed_job_command": "Opdrag {command} het misluk vir werk: {job}",
|
||||||
"force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lêers kan nie herstel word nie.",
|
"force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lêers kan nie herstel word nie.",
|
||||||
@@ -93,15 +101,33 @@
|
|||||||
"job_status": "Werkstatus",
|
"job_status": "Werkstatus",
|
||||||
"library_created": "Biblioteek geskep: {library}",
|
"library_created": "Biblioteek geskep: {library}",
|
||||||
"library_deleted": "Biblioteek verwyder",
|
"library_deleted": "Biblioteek verwyder",
|
||||||
"library_import_path_description": "Spesifiseer 'n leer om in te neem. Hierdie leer, en al die sub leers, gaan geskandeer for vir prente en videos.",
|
"library_import_path_description": "Spesifiseer 'n leer om in te neem. Hierdie leer, en al die sub leers, gaan deursoek word vir prente en videos.",
|
||||||
"library_scanning": "Periodieke Skandering",
|
"library_scanning": "Periodieke Soek",
|
||||||
"library_scanning_description": "Stel periodieke skandering van biblioteek in",
|
"library_scanning_description": "Stel periodieke deursoek van biblioteek in",
|
||||||
"library_scanning_enable_description": "Aktiveer periodieke biblioteekskandering",
|
"library_scanning_enable_description": "Aktiveer periodieke biblioteekskandering",
|
||||||
"library_settings": "Eksterne Biblioteek",
|
"library_settings": "Eksterne Biblioteek",
|
||||||
|
"library_settings_description": "Eksterne biblioteek verstellings",
|
||||||
|
"library_tasks_description": "Deursoek eksterne biblioteke vir nuwe of veranderde bates",
|
||||||
|
"library_watching_enable_description": "Hou eksterne biblioteke dop vir leer veranderinge",
|
||||||
|
"library_watching_settings": "Biblioteek dop hou (EKSPERIMENTEEL)",
|
||||||
|
"library_watching_settings_description": "Hou automaties dop vir veranderinge",
|
||||||
|
"logging_enable_description": "Aktifeer \"logging\"",
|
||||||
|
"logging_level_description": "Wanneer aktief, watter vlak van \"logs\" om te skep.",
|
||||||
|
"logging_settings": "\"Logs\"",
|
||||||
|
"machine_learning_clip_model": "CLIP model",
|
||||||
|
"machine_learning_duplicate_detection": "Duplikaat herkenning",
|
||||||
|
"machine_learning_duplicate_detection_enabled": "Aktifeer duplikaat herkenning",
|
||||||
|
"machine_learning_enabled": "Aktifeer masjienleer",
|
||||||
|
"machine_learning_facial_recognition": "Gesigsherkenning",
|
||||||
|
"machine_learning_facial_recognition_description": "Herken, identifiseer en groepeer gesigte in fotos",
|
||||||
|
"machine_learning_facial_recognition_model": "Gesigsherkennings model",
|
||||||
|
"machine_learning_facial_recognition_setting": "Aktifeer gesigsherkenning",
|
||||||
|
"machine_learning_max_detection_distance": "Maksimum herkennings afstand",
|
||||||
"map_settings": "Kaart",
|
"map_settings": "Kaart",
|
||||||
"migration_job": "Migrasie",
|
"migration_job": "Migrasie",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
"transcoding_acceleration_vaapi": "VAAPI"
|
"transcoding_acceleration_vaapi": "VAAPI",
|
||||||
|
"transcoding_preferred_hardware_device": "Verkiesde hardeware"
|
||||||
},
|
},
|
||||||
"administration": "Administrasie",
|
"administration": "Administrasie",
|
||||||
"advanced": "Gevorderde",
|
"advanced": "Gevorderde",
|
||||||
|
|||||||
113
i18n/ar.json
113
i18n/ar.json
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"about": "عن",
|
"about": "حَوْل",
|
||||||
"account": "حساب",
|
"account": "حساب",
|
||||||
"account_settings": "إعدادات الحساب",
|
"account_settings": "إعدادات الحساب",
|
||||||
"acknowledge": "أُدرك ذلك",
|
"acknowledge": "أُدرك ذلك",
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
"add_a_location": "إضافة موقع",
|
"add_a_location": "إضافة موقع",
|
||||||
"add_a_name": "إضافة إسم",
|
"add_a_name": "إضافة إسم",
|
||||||
"add_a_title": "إضافة عنوان",
|
"add_a_title": "إضافة عنوان",
|
||||||
|
"add_birthday": "أضف تاريخ الميلاد",
|
||||||
"add_endpoint": "اضف نقطة نهاية",
|
"add_endpoint": "اضف نقطة نهاية",
|
||||||
"add_exclusion_pattern": "إضافة نمط إستثناء",
|
"add_exclusion_pattern": "إضافة نمط إستثناء",
|
||||||
"add_import_path": "إضافة مسار الإستيراد",
|
"add_import_path": "إضافة مسار الإستيراد",
|
||||||
@@ -25,8 +26,11 @@
|
|||||||
"add_tag": "اضف علامة",
|
"add_tag": "اضف علامة",
|
||||||
"add_to": "إضافة إلى…",
|
"add_to": "إضافة إلى…",
|
||||||
"add_to_album": "إضافة إلى ألبوم",
|
"add_to_album": "إضافة إلى ألبوم",
|
||||||
"add_to_album_bottom_sheet_added": "تمت الاضافة{album}",
|
"add_to_album_bottom_sheet_added": "تمت الاضافة الى {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "موجودة مسبقا {album}",
|
"add_to_album_bottom_sheet_already_exists": "موجود مسبقا في {album}",
|
||||||
|
"add_to_album_toggle": "تبديل التحديد لـ{album}",
|
||||||
|
"add_to_albums": "إضافة الى البومات",
|
||||||
|
"add_to_albums_count": "إضافه إلى البومات ({count})",
|
||||||
"add_to_shared_album": "إضافة إلى ألبوم مشارك",
|
"add_to_shared_album": "إضافة إلى ألبوم مشارك",
|
||||||
"add_url": "إضافة رابط",
|
"add_url": "إضافة رابط",
|
||||||
"added_to_archive": "أُضيفت للأرشيف",
|
"added_to_archive": "أُضيفت للأرشيف",
|
||||||
@@ -34,16 +38,23 @@
|
|||||||
"added_to_favorites_count": "تم إضافة {count, number} إلى المفضلات",
|
"added_to_favorites_count": "تم إضافة {count, number} إلى المفضلات",
|
||||||
"admin": {
|
"admin": {
|
||||||
"add_exclusion_pattern_description": "إضافة أنماط الاستبعاد. يدعم التمويه باستخدام *، **، و؟. لتجاهل جميع الملفات في أي دليل يسمى \"Raw\"، استخدم \"**/Raw/**\". لتجاهل جميع الملفات التي تنتهي بـ \".tif\"، استخدم \"**/*.tif\". لتجاهل مسار مطلق، استخدم \"/path/to/ignore/**\".",
|
"add_exclusion_pattern_description": "إضافة أنماط الاستبعاد. يدعم التمويه باستخدام *، **، و؟. لتجاهل جميع الملفات في أي دليل يسمى \"Raw\"، استخدم \"**/Raw/**\". لتجاهل جميع الملفات التي تنتهي بـ \".tif\"، استخدم \"**/*.tif\". لتجاهل مسار مطلق، استخدم \"/path/to/ignore/**\".",
|
||||||
"admin_user": "مستخدم مدير",
|
"admin_user": "مستخدم مسؤول",
|
||||||
"asset_offline_description": "لم يعد هذا الأصل الخاص بالمكتبة الخارجية موجودًا على القرص وتم نقله إلى سلة المهملات. إذا تم نقل الملف داخل المكتبة، فتحقق من الجدول الزمني الخاص بك لمعرفة الأصل الجديد المقابل. لاستعادة هذا الأصل، يرجى التأكد من إمكانية الوصول إلى مسار الملف أدناه بواسطة Immich ومن ثم قم بمسح المكتبة.",
|
"asset_offline_description": "لم يعد هذا الأصل الخاص بالمكتبة الخارجية موجودًا على القرص وتم نقله إلى سلة المهملات. إذا تم نقل الملف داخل المكتبة، فتحقق من الجدول الزمني الخاص بك لمعرفة الأصل الجديد المقابل. لاستعادة هذا الأصل، يرجى التأكد من إمكانية الوصول إلى مسار الملف أدناه بواسطة Immich ومن ثم قم بمسح المكتبة.",
|
||||||
"authentication_settings": "إعدادات المصادقة",
|
"authentication_settings": "إعدادات المصادقة",
|
||||||
"authentication_settings_description": "إدارة كلمة المرور وOAuth وإعدادات المصادقة الأُخرى",
|
"authentication_settings_description": "إدارة كلمة المرور وOAuth وإعدادات المصادقة الأُخرى",
|
||||||
"authentication_settings_disable_all": "هل أنت متأكد أنك تريد تعطيل جميع وسائل تسجيل الدخول؟ سيتم تعطيل تسجيل الدخول بالكامل.",
|
"authentication_settings_disable_all": "هل أنت متأكد أنك تريد تعطيل جميع وسائل تسجيل الدخول؟ سيتم تعطيل تسجيل الدخول بالكامل.",
|
||||||
"authentication_settings_reenable": "لإعادة التفعيل، استخدم <link>أمر الخادم</link>.",
|
"authentication_settings_reenable": "لإعادة التفعيل، استخدم <link>أمر الخادم</link>.",
|
||||||
"background_task_job": "المهام الخلفية",
|
"background_task_job": "المهام في الخلفية",
|
||||||
"backup_database": "انشاء تفريغ قاعدة البيانات",
|
"backup_database": "انشاء تفريغ قاعدة البيانات",
|
||||||
"backup_database_enable_description": "تمكين تفريغ قاعدة البيانات",
|
"backup_database_enable_description": "تمكين تفريغ قاعدة البيانات",
|
||||||
"backup_keep_last_amount": "مقدار التفريغات السابقة للاحتفاظ بها",
|
"backup_keep_last_amount": "مقدار التفريغات السابقة للاحتفاظ بها",
|
||||||
|
"backup_onboarding_1_description": "نسخة خارج الموقع في موقع آخر.",
|
||||||
|
"backup_onboarding_2_description": "نسخ محلية على أجهزة مختلفة. يشمل ذلك الملفات الرئيسية ونسخة احتياطية محلية منها.",
|
||||||
|
"backup_onboarding_3_description": "إجمالي نسخ بياناتك، بما في ذلك الملفات الأصلية. يشمل ذلك نسخةً واحدةً خارج الموقع ونسختين محليتين.",
|
||||||
|
"backup_onboarding_description": "يُنصح باتباع <backblaze-link>استراتيجية النسخ الاحتياطي 3-2-1</backblaze-link> لحماية بياناتك. احتفظ بنسخ احتياطية من صورك/فيديوهاتك المحمّلة، بالإضافة إلى قاعدة بيانات Immich، لضمان حل نسخ احتياطي شامل.",
|
||||||
|
"backup_onboarding_footer": "لمزيد من المعلومات حول النسخ الاحتياطي لـ Immich، يرجى الرجوع إلى <link> التعليمات </link>.",
|
||||||
|
"backup_onboarding_parts_title": "يتضمن النسخ الاحتياطي 3-2-1 ما يلي:",
|
||||||
|
"backup_onboarding_title": "النسخ الاحتياطية",
|
||||||
"backup_settings": "إعدادات تفريغ قاعدة البيانات",
|
"backup_settings": "إعدادات تفريغ قاعدة البيانات",
|
||||||
"backup_settings_description": "إدارة إعدادات تفريغ قاعدة البيانات.",
|
"backup_settings_description": "إدارة إعدادات تفريغ قاعدة البيانات.",
|
||||||
"cleared_jobs": "تم إخلاء مهام: {job}",
|
"cleared_jobs": "تم إخلاء مهام: {job}",
|
||||||
@@ -112,6 +123,7 @@
|
|||||||
"logging_enable_description": "تفعيل تسجيل الأحداث",
|
"logging_enable_description": "تفعيل تسجيل الأحداث",
|
||||||
"logging_level_description": "عند التفعيل، أي مستوى تسجيل سيستخدم.",
|
"logging_level_description": "عند التفعيل، أي مستوى تسجيل سيستخدم.",
|
||||||
"logging_settings": "تسجيل الاحداث",
|
"logging_settings": "تسجيل الاحداث",
|
||||||
|
"machine_learning_availability_checks": "تحقق من التوفر",
|
||||||
"machine_learning_clip_model": "نموذج CLIP",
|
"machine_learning_clip_model": "نموذج CLIP",
|
||||||
"machine_learning_clip_model_description": "اسم نموذج CLIP مدرجٌ <link>هنا</link>. يرجى ملاحظة أنه يجب إعادة تشغيل وظيفة \"البحث الذكي\" لجميع الصور بعد تغيير النموذج.",
|
"machine_learning_clip_model_description": "اسم نموذج CLIP مدرجٌ <link>هنا</link>. يرجى ملاحظة أنه يجب إعادة تشغيل وظيفة \"البحث الذكي\" لجميع الصور بعد تغيير النموذج.",
|
||||||
"machine_learning_duplicate_detection": "كشف التكرار",
|
"machine_learning_duplicate_detection": "كشف التكرار",
|
||||||
@@ -210,6 +222,8 @@
|
|||||||
"oauth_mobile_redirect_uri": "عنوان URI لإعادة التوجيه على الهاتف",
|
"oauth_mobile_redirect_uri": "عنوان URI لإعادة التوجيه على الهاتف",
|
||||||
"oauth_mobile_redirect_uri_override": "تجاوز عنوان URI لإعادة التوجيه على الهاتف",
|
"oauth_mobile_redirect_uri_override": "تجاوز عنوان URI لإعادة التوجيه على الهاتف",
|
||||||
"oauth_mobile_redirect_uri_override_description": "قم بتفعيله عندما لا يسمح موفر OAuth بمعرف URI للجوال، مثل ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "قم بتفعيله عندما لا يسمح موفر OAuth بمعرف URI للجوال، مثل ''{callback}''",
|
||||||
|
"oauth_role_claim": "المطالبة بالدور(صلاحيات)",
|
||||||
|
"oauth_role_claim_description": "منح وصول المسؤول تلقائيًا بناءً على وجود هذا الطلب. قد يكون الطلب إما 'مستخدم' أو 'مسؤول'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
"oauth_settings_description": "إدارة إعدادات تسجيل الدخول OAuth",
|
"oauth_settings_description": "إدارة إعدادات تسجيل الدخول OAuth",
|
||||||
"oauth_settings_more_details": "لمزيد من التفاصيل حول هذه الميزة، يرجى الرجوع إلى <link>الوثائق</link>.",
|
"oauth_settings_more_details": "لمزيد من التفاصيل حول هذه الميزة، يرجى الرجوع إلى <link>الوثائق</link>.",
|
||||||
@@ -345,6 +359,9 @@
|
|||||||
"trash_number_of_days_description": "عدد أيام الاحتفاظ بالمحتويات في سلة المهملات قبل حذفها نهائيًا",
|
"trash_number_of_days_description": "عدد أيام الاحتفاظ بالمحتويات في سلة المهملات قبل حذفها نهائيًا",
|
||||||
"trash_settings": "إعدادات سلة المهملات",
|
"trash_settings": "إعدادات سلة المهملات",
|
||||||
"trash_settings_description": "إدارة إعدادات سلة المهملات",
|
"trash_settings_description": "إدارة إعدادات سلة المهملات",
|
||||||
|
"unlink_all_oauth_accounts": "ازالة ربط جميع حسابات OAuth",
|
||||||
|
"unlink_all_oauth_accounts_description": "تذكّر ان تزيل ربط جميع حسابات OAuth قبل ان تنقل الى مزود جديد.",
|
||||||
|
"unlink_all_oauth_accounts_prompt": "هل انت متأكد من ازالة ربط جميع حسابات OAuth؟ هذا سيقوم باعادة ضبط الID الخاص بالOAuth لكل مستخدم ولا يمكن التراجع عن العملية.",
|
||||||
"user_cleanup_job": "تنظيف المستخدم",
|
"user_cleanup_job": "تنظيف المستخدم",
|
||||||
"user_delete_delay": "سيتم جدولة حساب <b>{user}</b> ومحتوياته للحذف النهائي في غضون {delay, plural, one {# يوم} other {# أيام}}.",
|
"user_delete_delay": "سيتم جدولة حساب <b>{user}</b> ومحتوياته للحذف النهائي في غضون {delay, plural, one {# يوم} other {# أيام}}.",
|
||||||
"user_delete_delay_settings": "فترة التأخير قبل الحذف",
|
"user_delete_delay_settings": "فترة التأخير قبل الحذف",
|
||||||
@@ -374,10 +391,11 @@
|
|||||||
"advanced_settings_enable_alternate_media_filter_subtitle": "استخدم هذا الخيار لتصفية الوسائط اثناء المزامنه بناء على معايير بديلة. جرب هذا الخيار فقط كان لديك مشاكل مع التطبيق بالكشف عن جميع الالبومات.",
|
"advanced_settings_enable_alternate_media_filter_subtitle": "استخدم هذا الخيار لتصفية الوسائط اثناء المزامنه بناء على معايير بديلة. جرب هذا الخيار فقط كان لديك مشاكل مع التطبيق بالكشف عن جميع الالبومات.",
|
||||||
"advanced_settings_enable_alternate_media_filter_title": "[تجريبي] استخدم جهاز تصفية مزامنه البومات بديل",
|
"advanced_settings_enable_alternate_media_filter_title": "[تجريبي] استخدم جهاز تصفية مزامنه البومات بديل",
|
||||||
"advanced_settings_log_level_title": "مستوى السجل: {level}",
|
"advanced_settings_log_level_title": "مستوى السجل: {level}",
|
||||||
"advanced_settings_prefer_remote_subtitle": "تكون بعض الأجهزة بطيئة للغاية في تحميل الصور المصغرة من الأصول الموجودة على الجهاز. قم بتنشيط هذا الإعداد لتحميل الصور البعيدة بدلاً من ذلك.",
|
"advanced_settings_prefer_remote_subtitle": "تكون بعض الأجهزة بطيئة للغاية في تحميل الصور المصغرة من الأصول المحلية. قم بتفعيل هذا الخيار لتحميل الصور البعيدة بدلاً من ذلك.",
|
||||||
"advanced_settings_prefer_remote_title": "تفضل الصور البعيدة",
|
"advanced_settings_prefer_remote_title": "تفضل الصور البعيدة",
|
||||||
"advanced_settings_proxy_headers_subtitle": "عرف عناوين الوكيل التي يستخدمها Immich لارسال كل طلب شبكي",
|
"advanced_settings_proxy_headers_subtitle": "عرف عناوين الوكيل التي يستخدمها Immich لارسال كل طلب شبكي",
|
||||||
"advanced_settings_proxy_headers_title": "عناوين الوكيل",
|
"advanced_settings_proxy_headers_title": "عناوين الوكيل",
|
||||||
|
"advanced_settings_readonly_mode_title": "وضع القراءة فقط",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "تخطي التحقق من شهادة SSL لخادم النقطة النهائي. مكلوب للشهادات الموقعة ذاتيا.",
|
"advanced_settings_self_signed_ssl_subtitle": "تخطي التحقق من شهادة SSL لخادم النقطة النهائي. مكلوب للشهادات الموقعة ذاتيا.",
|
||||||
"advanced_settings_self_signed_ssl_title": "السماح بشهادات SSL الموقعة ذاتيًا",
|
"advanced_settings_self_signed_ssl_title": "السماح بشهادات SSL الموقعة ذاتيًا",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "حذف او استعادة تلقائي للاصول على هذا الجهاز عند تنفيذ العملية على الويب",
|
"advanced_settings_sync_remote_deletions_subtitle": "حذف او استعادة تلقائي للاصول على هذا الجهاز عند تنفيذ العملية على الويب",
|
||||||
@@ -507,7 +525,7 @@
|
|||||||
"back_close_deselect": "الرجوع أو الإغلاق أو إلغاء التحديد",
|
"back_close_deselect": "الرجوع أو الإغلاق أو إلغاء التحديد",
|
||||||
"background_location_permission": "اذن الوصول للموقع في الخلفية",
|
"background_location_permission": "اذن الوصول للموقع في الخلفية",
|
||||||
"background_location_permission_content": "للتمكن من تبديل الشبكه بالخلفية، Immich يحتاج*دائما* للحصول على موقع دقيق ليتمكن التطبيق من قرائة اسم شبكة الWi-Fi",
|
"background_location_permission_content": "للتمكن من تبديل الشبكه بالخلفية، Immich يحتاج*دائما* للحصول على موقع دقيق ليتمكن التطبيق من قرائة اسم شبكة الWi-Fi",
|
||||||
"backup": "دعم",
|
"backup": "نسخ احتياطي",
|
||||||
"backup_album_selection_page_albums_device": "الالبومات على الجهاز ({count})",
|
"backup_album_selection_page_albums_device": "الالبومات على الجهاز ({count})",
|
||||||
"backup_album_selection_page_albums_tap": "انقر للتضمين، وانقر نقرًا مزدوجًا للاستثناء",
|
"backup_album_selection_page_albums_tap": "انقر للتضمين، وانقر نقرًا مزدوجًا للاستثناء",
|
||||||
"backup_album_selection_page_assets_scatter": "يمكن أن تنتشر الأصول عبر ألبومات متعددة. وبالتالي، يمكن تضمين الألبومات أو استبعادها أثناء عملية النسخ الاحتياطي.",
|
"backup_album_selection_page_assets_scatter": "يمكن أن تنتشر الأصول عبر ألبومات متعددة. وبالتالي، يمكن تضمين الألبومات أو استبعادها أثناء عملية النسخ الاحتياطي.",
|
||||||
@@ -568,11 +586,11 @@
|
|||||||
"backup_manual_in_progress": "قيد التحميل حاول مره اخرى",
|
"backup_manual_in_progress": "قيد التحميل حاول مره اخرى",
|
||||||
"backup_manual_success": "نجاح",
|
"backup_manual_success": "نجاح",
|
||||||
"backup_manual_title": "حالة التحميل",
|
"backup_manual_title": "حالة التحميل",
|
||||||
|
"backup_options": "خيارات النسخ الاحتياطي",
|
||||||
"backup_options_page_title": "خيارات النسخ الاحتياطي",
|
"backup_options_page_title": "خيارات النسخ الاحتياطي",
|
||||||
"backup_setting_subtitle": "ادارة اعدادات التحميل في الخلفية والمقدمة",
|
"backup_setting_subtitle": "ادارة اعدادات التحميل في الخلفية والمقدمة",
|
||||||
|
"backup_settings_subtitle": "إدارة إعدادات التحميل",
|
||||||
"backward": "الى الوراء",
|
"backward": "الى الوراء",
|
||||||
"beta_sync": "حالة المزامنة التجريبية",
|
|
||||||
"beta_sync_subtitle": "ادارة نظام المزامنة الجديد",
|
|
||||||
"biometric_auth_enabled": "المصادقة البايومترية مفعله",
|
"biometric_auth_enabled": "المصادقة البايومترية مفعله",
|
||||||
"biometric_locked_out": "لقد قفلت عنك المصادقة البيومترية",
|
"biometric_locked_out": "لقد قفلت عنك المصادقة البيومترية",
|
||||||
"biometric_no_options": "لا توجد خيارات بايومترية متوفرة",
|
"biometric_no_options": "لا توجد خيارات بايومترية متوفرة",
|
||||||
@@ -639,6 +657,7 @@
|
|||||||
"clear": "إخلاء",
|
"clear": "إخلاء",
|
||||||
"clear_all": "إخلاء الكل",
|
"clear_all": "إخلاء الكل",
|
||||||
"clear_all_recent_searches": "مسح جميع عمليات البحث الأخيرة",
|
"clear_all_recent_searches": "مسح جميع عمليات البحث الأخيرة",
|
||||||
|
"clear_file_cache": "مسح ذاكرة التخزين المؤقت للملفات",
|
||||||
"clear_message": "إخلاء الرسالة",
|
"clear_message": "إخلاء الرسالة",
|
||||||
"clear_value": "إخلاء القيمة",
|
"clear_value": "إخلاء القيمة",
|
||||||
"client_cert_dialog_msg_confirm": "حسنا",
|
"client_cert_dialog_msg_confirm": "حسنا",
|
||||||
@@ -709,6 +728,7 @@
|
|||||||
"create_new_user": "إنشاء مستخدم جديد",
|
"create_new_user": "إنشاء مستخدم جديد",
|
||||||
"create_shared_album_page_share_add_assets": "إضافة الأصول",
|
"create_shared_album_page_share_add_assets": "إضافة الأصول",
|
||||||
"create_shared_album_page_share_select_photos": "حدد الصور",
|
"create_shared_album_page_share_select_photos": "حدد الصور",
|
||||||
|
"create_shared_link": "انشاء رابط مشترك",
|
||||||
"create_tag": "إنشاء علامة",
|
"create_tag": "إنشاء علامة",
|
||||||
"create_tag_description": "أنشئ علامة جديدة. بالنسبة للعلامات المتداخلة، يرجى إدخال المسار الكامل للعلامة بما في ذلك الخطوط المائلة للأمام.",
|
"create_tag_description": "أنشئ علامة جديدة. بالنسبة للعلامات المتداخلة، يرجى إدخال المسار الكامل للعلامة بما في ذلك الخطوط المائلة للأمام.",
|
||||||
"create_user": "إنشاء مستخدم",
|
"create_user": "إنشاء مستخدم",
|
||||||
@@ -721,6 +741,7 @@
|
|||||||
"current_server_address": "عنوان الخادم الحالي",
|
"current_server_address": "عنوان الخادم الحالي",
|
||||||
"custom_locale": "لغة مخصصة",
|
"custom_locale": "لغة مخصصة",
|
||||||
"custom_locale_description": "تنسيق التواريخ والأرقام بناءً على اللغة والمنطقة",
|
"custom_locale_description": "تنسيق التواريخ والأرقام بناءً على اللغة والمنطقة",
|
||||||
|
"custom_url": "رابط مخصص",
|
||||||
"daily_title_text_date": "E ، MMM DD",
|
"daily_title_text_date": "E ، MMM DD",
|
||||||
"daily_title_text_date_year": "E ، MMM DD ، yyyy",
|
"daily_title_text_date_year": "E ، MMM DD ، yyyy",
|
||||||
"dark": "معتم",
|
"dark": "معتم",
|
||||||
@@ -732,6 +753,7 @@
|
|||||||
"date_of_birth_saved": "تم حفظ تاريخ الميلاد بنجاح",
|
"date_of_birth_saved": "تم حفظ تاريخ الميلاد بنجاح",
|
||||||
"date_range": "نطاق الموعد",
|
"date_range": "نطاق الموعد",
|
||||||
"day": "يوم",
|
"day": "يوم",
|
||||||
|
"days": "ايام",
|
||||||
"deduplicate_all": "إلغاء تكرار الكل",
|
"deduplicate_all": "إلغاء تكرار الكل",
|
||||||
"deduplication_criteria_1": "حجم الصورة بوحدات البايت",
|
"deduplication_criteria_1": "حجم الصورة بوحدات البايت",
|
||||||
"deduplication_criteria_2": "عدد بيانات EXIF",
|
"deduplication_criteria_2": "عدد بيانات EXIF",
|
||||||
@@ -816,8 +838,12 @@
|
|||||||
"edit": "تعديل",
|
"edit": "تعديل",
|
||||||
"edit_album": "تعديل الألبوم",
|
"edit_album": "تعديل الألبوم",
|
||||||
"edit_avatar": "تعديل الصورة الشخصية",
|
"edit_avatar": "تعديل الصورة الشخصية",
|
||||||
|
"edit_birthday": "تعديل تاريخ الميلاد",
|
||||||
"edit_date": "تعديل التاريخ",
|
"edit_date": "تعديل التاريخ",
|
||||||
"edit_date_and_time": "تعديل التاريخ والوقت",
|
"edit_date_and_time": "تعديل التاريخ والوقت",
|
||||||
|
"edit_date_and_time_action_prompt": "تم تعديل التاريخ والوقت ل{count} ملف(ات)",
|
||||||
|
"edit_date_and_time_by_offset": "تعديل التاريخ حسب قيمة ازاحة معينة",
|
||||||
|
"edit_date_and_time_by_offset_interval": "نطاق التاريخ الجديد: {from} - {to}",
|
||||||
"edit_description": "تعديل الوصف",
|
"edit_description": "تعديل الوصف",
|
||||||
"edit_description_prompt": "الرجاء اختيار وصف جديد:",
|
"edit_description_prompt": "الرجاء اختيار وصف جديد:",
|
||||||
"edit_exclusion_pattern": "تعديل نمط الاستبعاد",
|
"edit_exclusion_pattern": "تعديل نمط الاستبعاد",
|
||||||
@@ -890,6 +916,7 @@
|
|||||||
"failed_to_load_notifications": "فشل تحميل الإشعارات",
|
"failed_to_load_notifications": "فشل تحميل الإشعارات",
|
||||||
"failed_to_load_people": "فشل تحميل الأشخاص",
|
"failed_to_load_people": "فشل تحميل الأشخاص",
|
||||||
"failed_to_remove_product_key": "تعذر إزالة مفتاح المنتج",
|
"failed_to_remove_product_key": "تعذر إزالة مفتاح المنتج",
|
||||||
|
"failed_to_reset_pin_code": "فشل اعادة تعيين رمز الPIN",
|
||||||
"failed_to_stack_assets": "فشل في تكديس المحتويات",
|
"failed_to_stack_assets": "فشل في تكديس المحتويات",
|
||||||
"failed_to_unstack_assets": "فشل في فصل المحتويات",
|
"failed_to_unstack_assets": "فشل في فصل المحتويات",
|
||||||
"failed_to_update_notification_status": "فشل في تحديث حالة الإشعار",
|
"failed_to_update_notification_status": "فشل في تحديث حالة الإشعار",
|
||||||
@@ -898,6 +925,7 @@
|
|||||||
"paths_validation_failed": "فشل في التحقق من {paths, plural, one {# مسار} other {# مسارات}}",
|
"paths_validation_failed": "فشل في التحقق من {paths, plural, one {# مسار} other {# مسارات}}",
|
||||||
"profile_picture_transparent_pixels": "لا يمكن أن تحتوي صور الملف الشخصي على أجزاء/بكسلات شفافة. يرجى التكبير و/أو تحريك الصورة.",
|
"profile_picture_transparent_pixels": "لا يمكن أن تحتوي صور الملف الشخصي على أجزاء/بكسلات شفافة. يرجى التكبير و/أو تحريك الصورة.",
|
||||||
"quota_higher_than_disk_size": "لقد قمت بتعيين حصة نسبية أعلى من حجم القرص",
|
"quota_higher_than_disk_size": "لقد قمت بتعيين حصة نسبية أعلى من حجم القرص",
|
||||||
|
"something_went_wrong": "حدث خطأ ما",
|
||||||
"unable_to_add_album_users": "تعذر إضافة مستخدمين إلى الألبوم",
|
"unable_to_add_album_users": "تعذر إضافة مستخدمين إلى الألبوم",
|
||||||
"unable_to_add_assets_to_shared_link": "تعذر إضافة المحتويات إلى الرابط المشترك",
|
"unable_to_add_assets_to_shared_link": "تعذر إضافة المحتويات إلى الرابط المشترك",
|
||||||
"unable_to_add_comment": "تعذر إضافة التعليق",
|
"unable_to_add_comment": "تعذر إضافة التعليق",
|
||||||
@@ -983,13 +1011,11 @@
|
|||||||
},
|
},
|
||||||
"exif": "Exif (صيغة ملف صوري قابل للتبادل)",
|
"exif": "Exif (صيغة ملف صوري قابل للتبادل)",
|
||||||
"exif_bottom_sheet_description": "اضف وصفا...",
|
"exif_bottom_sheet_description": "اضف وصفا...",
|
||||||
|
"exif_bottom_sheet_description_error": "خطأ في تحديث الوصف",
|
||||||
"exif_bottom_sheet_details": "تفاصيل",
|
"exif_bottom_sheet_details": "تفاصيل",
|
||||||
"exif_bottom_sheet_location": "موقع",
|
"exif_bottom_sheet_location": "موقع",
|
||||||
"exif_bottom_sheet_people": "الناس",
|
"exif_bottom_sheet_people": "الناس",
|
||||||
"exif_bottom_sheet_person_add_person": "اضف اسما",
|
"exif_bottom_sheet_person_add_person": "اضف اسما",
|
||||||
"exif_bottom_sheet_person_age_months": "العمر {months} اشهر",
|
|
||||||
"exif_bottom_sheet_person_age_year_months": "العمر ١ سنة،{months} اشهر",
|
|
||||||
"exif_bottom_sheet_person_age_years": "العمر {years}",
|
|
||||||
"exit_slideshow": "خروج من العرض التقديمي",
|
"exit_slideshow": "خروج من العرض التقديمي",
|
||||||
"expand_all": "توسيع الكل",
|
"expand_all": "توسيع الكل",
|
||||||
"experimental_settings_new_asset_list_subtitle": "أعمال جارية",
|
"experimental_settings_new_asset_list_subtitle": "أعمال جارية",
|
||||||
@@ -1031,11 +1057,13 @@
|
|||||||
"filter_people": "تصفية الاشخاص",
|
"filter_people": "تصفية الاشخاص",
|
||||||
"filter_places": "تصفية الاماكن",
|
"filter_places": "تصفية الاماكن",
|
||||||
"find_them_fast": "يمكنك العثور عليها بسرعة بالاسم من خلال البحث",
|
"find_them_fast": "يمكنك العثور عليها بسرعة بالاسم من خلال البحث",
|
||||||
|
"first": "الاول",
|
||||||
"fix_incorrect_match": "إصلاح المطابقة غير الصحيحة",
|
"fix_incorrect_match": "إصلاح المطابقة غير الصحيحة",
|
||||||
"folder": "مجلد",
|
"folder": "مجلد",
|
||||||
"folder_not_found": "لم يتم العثور على المجلد",
|
"folder_not_found": "لم يتم العثور على المجلد",
|
||||||
"folders": "المجلدات",
|
"folders": "المجلدات",
|
||||||
"folders_feature_description": "تصفح عرض المجلد للصور ومقاطع الفيديو الموجودة على نظام الملفات",
|
"folders_feature_description": "تصفح عرض المجلد للصور ومقاطع الفيديو الموجودة على نظام الملفات",
|
||||||
|
"forgot_pin_code_question": "هل نسيت رمز الPIN الخاص بك؟",
|
||||||
"forward": "إلى الأمام",
|
"forward": "إلى الأمام",
|
||||||
"gcast_enabled": "كوكل كاست",
|
"gcast_enabled": "كوكل كاست",
|
||||||
"gcast_enabled_description": "تقوم هذه الميزة بتحميل الموارد الخارجية من Google حتى تعمل.",
|
"gcast_enabled_description": "تقوم هذه الميزة بتحميل الموارد الخارجية من Google حتى تعمل.",
|
||||||
@@ -1056,6 +1084,9 @@
|
|||||||
"haptic_feedback_switch": "تمكين ردود الفعل اللمسية",
|
"haptic_feedback_switch": "تمكين ردود الفعل اللمسية",
|
||||||
"haptic_feedback_title": "ردود فعل لمسية",
|
"haptic_feedback_title": "ردود فعل لمسية",
|
||||||
"has_quota": "محدد بحصة",
|
"has_quota": "محدد بحصة",
|
||||||
|
"hash_asset": "عمل Hash للأصل (للملف)",
|
||||||
|
"hashed_assets": "أصول (ملفات) تم عمل Hash لها",
|
||||||
|
"hashing": "يتم عمل Hash",
|
||||||
"header_settings_add_header_tip": "اضاف راس",
|
"header_settings_add_header_tip": "اضاف راس",
|
||||||
"header_settings_field_validator_msg": "القيمة لا يمكن ان تكون فارغة",
|
"header_settings_field_validator_msg": "القيمة لا يمكن ان تكون فارغة",
|
||||||
"header_settings_header_name_input": "اسم الرأس",
|
"header_settings_header_name_input": "اسم الرأس",
|
||||||
@@ -1069,9 +1100,9 @@
|
|||||||
"hide_password": "اخفاء كلمة المرور",
|
"hide_password": "اخفاء كلمة المرور",
|
||||||
"hide_person": "اخفاء الشخص",
|
"hide_person": "اخفاء الشخص",
|
||||||
"hide_unnamed_people": "إخفاء الأشخاص بدون إسم",
|
"hide_unnamed_people": "إخفاء الأشخاص بدون إسم",
|
||||||
"home_page_add_to_album_conflicts": "تمت إضافة {تمت إضافة} الأصول إلى الألبوم {الألبوم}.{فشل} الأصول موجودة بالفعل في الألبوم.",
|
"home_page_add_to_album_conflicts": "تمت إضافة {added} أصول إلى الألبوم {album}. {failed} أصول موجودة بالفعل في الألبوم.",
|
||||||
"home_page_add_to_album_err_local": "لا يمكن إضافة الأصول المحلية إلى الألبومات حتى الآن ، سوف يتخطى",
|
"home_page_add_to_album_err_local": "لا يمكن إضافة الأصول المحلية إلى الألبومات حتى الآن ، سوف يتخطى",
|
||||||
"home_page_add_to_album_success": "تمت إضافة {تمت إضافة} الأصول إلى الألبوم {الألبوم}.",
|
"home_page_add_to_album_success": "تمت إضافة {added} أصول إلى الألبوم {album}.",
|
||||||
"home_page_album_err_partner": "لا يمكن إضافة أصول شريكة إلى ألبوم حتى الآن ، سوف يتخطى",
|
"home_page_album_err_partner": "لا يمكن إضافة أصول شريكة إلى ألبوم حتى الآن ، سوف يتخطى",
|
||||||
"home_page_archive_err_local": "لا يمكن أرشفة الأصول المحلية حتى الآن ، سوف يتخطى",
|
"home_page_archive_err_local": "لا يمكن أرشفة الأصول المحلية حتى الآن ، سوف يتخطى",
|
||||||
"home_page_archive_err_partner": "لا يمكن أرشفة الأصول الشريكة ، سوف يتخطى",
|
"home_page_archive_err_partner": "لا يمكن أرشفة الأصول الشريكة ، سوف يتخطى",
|
||||||
@@ -1087,7 +1118,9 @@
|
|||||||
"home_page_upload_err_limit": "لا يمكن إلا تحميل 30 أحد الأصول في وقت واحد ، سوف يتخطى",
|
"home_page_upload_err_limit": "لا يمكن إلا تحميل 30 أحد الأصول في وقت واحد ، سوف يتخطى",
|
||||||
"host": "المضيف",
|
"host": "المضيف",
|
||||||
"hour": "ساعة",
|
"hour": "ساعة",
|
||||||
|
"hours": "ساعات",
|
||||||
"id": "المعرف",
|
"id": "المعرف",
|
||||||
|
"idle": "خامل",
|
||||||
"ignore_icloud_photos": "تجاهل صور iCloud",
|
"ignore_icloud_photos": "تجاهل صور iCloud",
|
||||||
"ignore_icloud_photos_description": "الصور المخزنة في Cloud لن يتم تحميلها إلى خادم Immich",
|
"ignore_icloud_photos_description": "الصور المخزنة في Cloud لن يتم تحميلها إلى خادم Immich",
|
||||||
"image": "صورة",
|
"image": "صورة",
|
||||||
@@ -1145,10 +1178,13 @@
|
|||||||
"language_no_results_title": "لم يتم العثور على لغات",
|
"language_no_results_title": "لم يتم العثور على لغات",
|
||||||
"language_search_hint": "البحث عن لغات...",
|
"language_search_hint": "البحث عن لغات...",
|
||||||
"language_setting_description": "اختر لغتك المفضلة",
|
"language_setting_description": "اختر لغتك المفضلة",
|
||||||
|
"large_files": "ملفات كبيرة",
|
||||||
|
"last": "الاخير",
|
||||||
"last_seen": "اخر ظهور",
|
"last_seen": "اخر ظهور",
|
||||||
"latest_version": "احدث اصدار",
|
"latest_version": "احدث اصدار",
|
||||||
"latitude": "خط العرض",
|
"latitude": "خط العرض",
|
||||||
"leave": "مغادرة",
|
"leave": "مغادرة",
|
||||||
|
"leave_album": "اترك الالبوم",
|
||||||
"lens_model": "نموذج العدسات",
|
"lens_model": "نموذج العدسات",
|
||||||
"let_others_respond": "دع الآخرين يستجيبون",
|
"let_others_respond": "دع الآخرين يستجيبون",
|
||||||
"level": "المستوى",
|
"level": "المستوى",
|
||||||
@@ -1160,7 +1196,9 @@
|
|||||||
"library_page_sort_created": "تاريخ الإنشاء",
|
"library_page_sort_created": "تاريخ الإنشاء",
|
||||||
"library_page_sort_last_modified": "آخر تعديل",
|
"library_page_sort_last_modified": "آخر تعديل",
|
||||||
"library_page_sort_title": "عنوان الألبوم",
|
"library_page_sort_title": "عنوان الألبوم",
|
||||||
|
"licenses": "رُخَص",
|
||||||
"light": "المضيئ",
|
"light": "المضيئ",
|
||||||
|
"like": "اعجاب",
|
||||||
"like_deleted": "تم حذف الإعجاب",
|
"like_deleted": "تم حذف الإعجاب",
|
||||||
"link_motion_video": "رابط فيديو الحركة",
|
"link_motion_video": "رابط فيديو الحركة",
|
||||||
"link_to_oauth": "الربط مع OAuth",
|
"link_to_oauth": "الربط مع OAuth",
|
||||||
@@ -1168,7 +1206,9 @@
|
|||||||
"list": "قائمة",
|
"list": "قائمة",
|
||||||
"loading": "تحميل",
|
"loading": "تحميل",
|
||||||
"loading_search_results_failed": "فشل تحميل نتائج البحث",
|
"loading_search_results_failed": "فشل تحميل نتائج البحث",
|
||||||
|
"local": "محلّي",
|
||||||
"local_asset_cast_failed": "غير قادر على بث أصل لم يتم تحميله إلى الخادم",
|
"local_asset_cast_failed": "غير قادر على بث أصل لم يتم تحميله إلى الخادم",
|
||||||
|
"local_assets": "أُصول (ملفات) محلية",
|
||||||
"local_network": "شبكة محلية",
|
"local_network": "شبكة محلية",
|
||||||
"local_network_sheet_info": "سيتصل التطبيق بالخادم من خلال عنوان URL هذا عند استخدام شبكة Wi-Fi المحددة",
|
"local_network_sheet_info": "سيتصل التطبيق بالخادم من خلال عنوان URL هذا عند استخدام شبكة Wi-Fi المحددة",
|
||||||
"location_permission": "اذن الموقع",
|
"location_permission": "اذن الموقع",
|
||||||
@@ -1225,7 +1265,7 @@
|
|||||||
"manage_your_devices": "إدارة الأجهزة التي تم تسجيل الدخول إليها",
|
"manage_your_devices": "إدارة الأجهزة التي تم تسجيل الدخول إليها",
|
||||||
"manage_your_oauth_connection": "إدارة اتصال OAuth الخاص بك",
|
"manage_your_oauth_connection": "إدارة اتصال OAuth الخاص بك",
|
||||||
"map": "الخريطة",
|
"map": "الخريطة",
|
||||||
"map_assets_in_bounds": "{count} صور",
|
"map_assets_in_bounds": "{count, plural, =0 {لايوجد صور في هذه المنطقة} one {# صورة} other {# صور}}",
|
||||||
"map_cannot_get_user_location": "لا يمكن الحصول على موقع المستخدم",
|
"map_cannot_get_user_location": "لا يمكن الحصول على موقع المستخدم",
|
||||||
"map_location_dialog_yes": "نعم",
|
"map_location_dialog_yes": "نعم",
|
||||||
"map_location_picker_page_use_location": "استخدم هذا الموقع",
|
"map_location_picker_page_use_location": "استخدم هذا الموقع",
|
||||||
@@ -1233,7 +1273,6 @@
|
|||||||
"map_location_service_disabled_title": "خدمة الموقع معطل",
|
"map_location_service_disabled_title": "خدمة الموقع معطل",
|
||||||
"map_marker_for_images": "علامة الخريطة للصور الملتقطة في {city}، {country}",
|
"map_marker_for_images": "علامة الخريطة للصور الملتقطة في {city}، {country}",
|
||||||
"map_marker_with_image": "علامة الخريطة مع الصورة",
|
"map_marker_with_image": "علامة الخريطة مع الصورة",
|
||||||
"map_no_assets_in_bounds": "لا توجد صور في هذا المجال",
|
|
||||||
"map_no_location_permission_content": "هناك حاجة إلى إذن الموقع لعرض الأصول من موقعك الحالي.هل تريد السماح به الآن؟",
|
"map_no_location_permission_content": "هناك حاجة إلى إذن الموقع لعرض الأصول من موقعك الحالي.هل تريد السماح به الآن؟",
|
||||||
"map_no_location_permission_title": "تم رفض إذن الموقع",
|
"map_no_location_permission_title": "تم رفض إذن الموقع",
|
||||||
"map_settings": "إعدادات الخريطة",
|
"map_settings": "إعدادات الخريطة",
|
||||||
@@ -1270,6 +1309,7 @@
|
|||||||
"merged_people_count": "دمج {count, plural, one {شخص واحد} other {# أشخاص}}",
|
"merged_people_count": "دمج {count, plural, one {شخص واحد} other {# أشخاص}}",
|
||||||
"minimize": "تصغير",
|
"minimize": "تصغير",
|
||||||
"minute": "دقيقة",
|
"minute": "دقيقة",
|
||||||
|
"minutes": "دقائق",
|
||||||
"missing": "المفقودة",
|
"missing": "المفقودة",
|
||||||
"model": "نموذج",
|
"model": "نموذج",
|
||||||
"month": "شهر",
|
"month": "شهر",
|
||||||
@@ -1289,6 +1329,9 @@
|
|||||||
"my_albums": "ألبوماتي",
|
"my_albums": "ألبوماتي",
|
||||||
"name": "الاسم",
|
"name": "الاسم",
|
||||||
"name_or_nickname": "الاسم أو اللقب",
|
"name_or_nickname": "الاسم أو اللقب",
|
||||||
|
"network_requirement_photos_upload": "استخدام بيانات الهاتف المحمول لعمل نسخة احتياطية للصور",
|
||||||
|
"network_requirement_videos_upload": "استخدام بيانات الهاتف المحمول لعمل نسخة احتياطية لمقاطع الفيديو",
|
||||||
|
"network_requirements_updated": "تم تغيير متطلبات الشبكة، يتم إعادة تعيين قائمة انتظار النسخ الاحتياطي",
|
||||||
"networking_settings": "الشبكات",
|
"networking_settings": "الشبكات",
|
||||||
"networking_subtitle": "إدارة إعدادات نقطة الخادم النهائية",
|
"networking_subtitle": "إدارة إعدادات نقطة الخادم النهائية",
|
||||||
"never": "أبداً",
|
"never": "أبداً",
|
||||||
@@ -1324,6 +1367,7 @@
|
|||||||
"no_results": "لا يوجد نتائج",
|
"no_results": "لا يوجد نتائج",
|
||||||
"no_results_description": "جرب كلمة رئيسية مرادفة أو أكثر عمومية",
|
"no_results_description": "جرب كلمة رئيسية مرادفة أو أكثر عمومية",
|
||||||
"no_shared_albums_message": "قم بإنشاء ألبوم لمشاركة الصور ومقاطع الفيديو مع الأشخاص في شبكتك",
|
"no_shared_albums_message": "قم بإنشاء ألبوم لمشاركة الصور ومقاطع الفيديو مع الأشخاص في شبكتك",
|
||||||
|
"no_uploads_in_progress": "لا يوجد اي ملفات قيد الرفع",
|
||||||
"not_in_any_album": "ليست في أي ألبوم",
|
"not_in_any_album": "ليست في أي ألبوم",
|
||||||
"not_selected": "لم يختار",
|
"not_selected": "لم يختار",
|
||||||
"note_apply_storage_label_to_previously_uploaded assets": "ملاحظة: لتطبيق سمة التخزين على المحتويات التي تم رفعها مسبقًا، قم بتشغيل",
|
"note_apply_storage_label_to_previously_uploaded assets": "ملاحظة: لتطبيق سمة التخزين على المحتويات التي تم رفعها مسبقًا، قم بتشغيل",
|
||||||
@@ -1339,6 +1383,7 @@
|
|||||||
"oauth": "OAuth",
|
"oauth": "OAuth",
|
||||||
"official_immich_resources": "الموارد الرسمية لشركة Immich",
|
"official_immich_resources": "الموارد الرسمية لشركة Immich",
|
||||||
"offline": "غير متصل",
|
"offline": "غير متصل",
|
||||||
|
"offset": "ازاحة",
|
||||||
"ok": "نعم",
|
"ok": "نعم",
|
||||||
"oldest_first": "الأقدم أولا",
|
"oldest_first": "الأقدم أولا",
|
||||||
"on_this_device": "على هذا الجهاز",
|
"on_this_device": "على هذا الجهاز",
|
||||||
@@ -1361,6 +1406,7 @@
|
|||||||
"original": "أصلي",
|
"original": "أصلي",
|
||||||
"other": "أخرى",
|
"other": "أخرى",
|
||||||
"other_devices": "أجهزة أخرى",
|
"other_devices": "أجهزة أخرى",
|
||||||
|
"other_entities": "كيانات أخرى",
|
||||||
"other_variables": "متغيرات أخرى",
|
"other_variables": "متغيرات أخرى",
|
||||||
"owned": "مملوكة",
|
"owned": "مملوكة",
|
||||||
"owner": "المالك",
|
"owner": "المالك",
|
||||||
@@ -1415,7 +1461,10 @@
|
|||||||
"permission_onboarding_permission_limited": "إذن محدود. للسماح بالنسخ الاحتياطي للتطبيق وإدارة مجموعة المعرض بالكامل، امنح أذونات الصور والفيديو في الإعدادات.",
|
"permission_onboarding_permission_limited": "إذن محدود. للسماح بالنسخ الاحتياطي للتطبيق وإدارة مجموعة المعرض بالكامل، امنح أذونات الصور والفيديو في الإعدادات.",
|
||||||
"permission_onboarding_request": "يتطلب التطبيق إذنًا لعرض الصور ومقاطع الفيديو الخاصة بك.",
|
"permission_onboarding_request": "يتطلب التطبيق إذنًا لعرض الصور ومقاطع الفيديو الخاصة بك.",
|
||||||
"person": "شخص",
|
"person": "شخص",
|
||||||
"person_birthdate": "تاريخ الميلاد {التاريخ}",
|
"person_age_months": "{months, plural, one {# شهر} other {# اشهر}} من العمر",
|
||||||
|
"person_age_year_months": "1 عام, {months, plural, one {# شهر} other {# اشهر}} من العمر",
|
||||||
|
"person_age_years": "{years, plural, other {# اعوام}} من العمر",
|
||||||
|
"person_birthdate": "ولد في {date}",
|
||||||
"person_hidden": "{name}{hidden, select, true { (مخفي)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (مخفي)} other {}}",
|
||||||
"photo_shared_all_users": "يبدو أنك شاركت صورك مع جميع المستخدمين أو ليس لديك أي مستخدم للمشاركة معه.",
|
"photo_shared_all_users": "يبدو أنك شاركت صورك مع جميع المستخدمين أو ليس لديك أي مستخدم للمشاركة معه.",
|
||||||
"photos": "الصور",
|
"photos": "الصور",
|
||||||
@@ -1492,6 +1541,7 @@
|
|||||||
"purchase_server_description_2": "حالة الداعم",
|
"purchase_server_description_2": "حالة الداعم",
|
||||||
"purchase_server_title": "الخادم",
|
"purchase_server_title": "الخادم",
|
||||||
"purchase_settings_server_activated": "يتم إدارة مفتاح منتج الخادم من قبل مدير النظام",
|
"purchase_settings_server_activated": "يتم إدارة مفتاح منتج الخادم من قبل مدير النظام",
|
||||||
|
"queue_status": "يتم الاضافة الى قائمة انتظار النسخ الاحتياطي {count}/{total}",
|
||||||
"rating": "تقييم نجمي",
|
"rating": "تقييم نجمي",
|
||||||
"rating_clear": "مسح التقييم",
|
"rating_clear": "مسح التقييم",
|
||||||
"rating_count": "{count, plural, one {# نجمة} other {# نجوم}}",
|
"rating_count": "{count, plural, one {# نجمة} other {# نجوم}}",
|
||||||
@@ -1520,6 +1570,8 @@
|
|||||||
"refreshing_faces": "جاري تحديث الوجوه",
|
"refreshing_faces": "جاري تحديث الوجوه",
|
||||||
"refreshing_metadata": "جارٍ تحديث البيانات الوصفية",
|
"refreshing_metadata": "جارٍ تحديث البيانات الوصفية",
|
||||||
"regenerating_thumbnails": "جارٍ تجديد الصور المصغرة",
|
"regenerating_thumbnails": "جارٍ تجديد الصور المصغرة",
|
||||||
|
"remote": "بعيد",
|
||||||
|
"remote_assets": "الأُصول البعيدة",
|
||||||
"remove": "إزالة",
|
"remove": "إزالة",
|
||||||
"remove_assets_album_confirmation": "هل أنت متأكد أنك تريد إزالة {count, plural, one {# المحتوى} other {# المحتويات}} من الألبوم ؟",
|
"remove_assets_album_confirmation": "هل أنت متأكد أنك تريد إزالة {count, plural, one {# المحتوى} other {# المحتويات}} من الألبوم ؟",
|
||||||
"remove_assets_shared_link_confirmation": "هل أنت متأكد أنك تريد إزالة {count, plural, one {# المحتوى} other {# المحتويات}} من رابط المشاركة هذا؟",
|
"remove_assets_shared_link_confirmation": "هل أنت متأكد أنك تريد إزالة {count, plural, one {# المحتوى} other {# المحتويات}} من رابط المشاركة هذا؟",
|
||||||
@@ -1527,6 +1579,7 @@
|
|||||||
"remove_custom_date_range": "إزالة النطاق الزمني المخصص",
|
"remove_custom_date_range": "إزالة النطاق الزمني المخصص",
|
||||||
"remove_deleted_assets": "إزالة الملفات الغير متصلة",
|
"remove_deleted_assets": "إزالة الملفات الغير متصلة",
|
||||||
"remove_from_album": "إزالة من الألبوم",
|
"remove_from_album": "إزالة من الألبوم",
|
||||||
|
"remove_from_album_action_prompt": "تم ازالة {count} من الالبوم",
|
||||||
"remove_from_favorites": "إزالة من المفضلة",
|
"remove_from_favorites": "إزالة من المفضلة",
|
||||||
"remove_from_lock_folder_action_prompt": "{count} أويل من المجلد المقفل",
|
"remove_from_lock_folder_action_prompt": "{count} أويل من المجلد المقفل",
|
||||||
"remove_from_locked_folder": "ازالة من المجلد المقفل",
|
"remove_from_locked_folder": "ازالة من المجلد المقفل",
|
||||||
@@ -1556,19 +1609,28 @@
|
|||||||
"reset_password": "إعادة تعيين كلمة المرور",
|
"reset_password": "إعادة تعيين كلمة المرور",
|
||||||
"reset_people_visibility": "إعادة ضبط ظهور الأشخاص",
|
"reset_people_visibility": "إعادة ضبط ظهور الأشخاص",
|
||||||
"reset_pin_code": "اعادة تعيين رمز PIN",
|
"reset_pin_code": "اعادة تعيين رمز PIN",
|
||||||
|
"reset_pin_code_description": "اذا نسيت رمز الPIN الخاص بك، بامكانك التواصل مع مدير الخادم لديك لاعادة تعيينه",
|
||||||
|
"reset_pin_code_success": "تم اعادة تعيين رمز الPIN بنجاح",
|
||||||
|
"reset_pin_code_with_password": "يمكنك دائما اعادة تعيين رمز الPIN الخاص بك عن طريق كلمة المرور الخاصة بك",
|
||||||
|
"reset_sqlite": "إعادة تعيين قاعدة بيانات SQLite",
|
||||||
|
"reset_sqlite_confirmation": "هل أنت متأكد من رغبتك في إعادة ضبط قاعدة بيانات SQLite؟ ستحتاج إلى تسجيل الخروج ثم تسجيل الدخول مرة أخرى لإعادة مزامنة البيانات",
|
||||||
|
"reset_sqlite_success": "تم إعادة تعيين قاعدة بيانات SQLite بنجاح",
|
||||||
"reset_to_default": "إعادة التعيين إلى الافتراضي",
|
"reset_to_default": "إعادة التعيين إلى الافتراضي",
|
||||||
"resolve_duplicates": "معالجة النسخ المكررة",
|
"resolve_duplicates": "معالجة النسخ المكررة",
|
||||||
"resolved_all_duplicates": "تم حل جميع التكرارات",
|
"resolved_all_duplicates": "تم حل جميع التكرارات",
|
||||||
"restore": "الاستعاده من سلة المهملات",
|
"restore": "الاستعاده من سلة المهملات",
|
||||||
"restore_all": "استعادة الكل",
|
"restore_all": "استعادة الكل",
|
||||||
|
"restore_trash_action_prompt": "تم استعادة {count} من المهملات",
|
||||||
"restore_user": "استعادة المستخدم",
|
"restore_user": "استعادة المستخدم",
|
||||||
"restored_asset": "المحتويات المستعادة",
|
"restored_asset": "المحتويات المستعادة",
|
||||||
"resume": "استئناف",
|
"resume": "استئناف",
|
||||||
"retry_upload": "أعد محاولة الرفع",
|
"retry_upload": "أعد محاولة الرفع",
|
||||||
"review_duplicates": "مراجعة التكرارات",
|
"review_duplicates": "مراجعة التكرارات",
|
||||||
|
"review_large_files": "مراجعة الملفات الكبيرة",
|
||||||
"role": "الدور",
|
"role": "الدور",
|
||||||
"role_editor": "المحرر",
|
"role_editor": "المحرر",
|
||||||
"role_viewer": "العارض",
|
"role_viewer": "العارض",
|
||||||
|
"running": "قيد التشغيل",
|
||||||
"save": "حفظ",
|
"save": "حفظ",
|
||||||
"save_to_gallery": "حفظ الى المعرض",
|
"save_to_gallery": "حفظ الى المعرض",
|
||||||
"saved_api_key": "تم حفظ مفتاح الـ API",
|
"saved_api_key": "تم حفظ مفتاح الـ API",
|
||||||
@@ -1700,6 +1762,7 @@
|
|||||||
"settings_saved": "تم حفظ الإعدادات",
|
"settings_saved": "تم حفظ الإعدادات",
|
||||||
"setup_pin_code": "تحديد رمز PIN",
|
"setup_pin_code": "تحديد رمز PIN",
|
||||||
"share": "مشاركة",
|
"share": "مشاركة",
|
||||||
|
"share_action_prompt": "تم مشاركة {count} أصل (ملف)",
|
||||||
"share_add_photos": "إضافة الصور",
|
"share_add_photos": "إضافة الصور",
|
||||||
"share_assets_selected": "اختيار {count}",
|
"share_assets_selected": "اختيار {count}",
|
||||||
"share_dialog_preparing": "تحضير...",
|
"share_dialog_preparing": "تحضير...",
|
||||||
@@ -1721,6 +1784,7 @@
|
|||||||
"shared_link_clipboard_copied_massage": "نسخ إلى الحافظة",
|
"shared_link_clipboard_copied_massage": "نسخ إلى الحافظة",
|
||||||
"shared_link_clipboard_text": "رابط: {link}\nكلمة المرور: {password}",
|
"shared_link_clipboard_text": "رابط: {link}\nكلمة المرور: {password}",
|
||||||
"shared_link_create_error": "خطأ أثناء إنشاء رابط مشترك",
|
"shared_link_create_error": "خطأ أثناء إنشاء رابط مشترك",
|
||||||
|
"shared_link_custom_url_description": "الوصول إلى هذا الرابط المشترك باستخدام عنوان URL مخصص",
|
||||||
"shared_link_edit_description_hint": "أدخل وصف المشاركة",
|
"shared_link_edit_description_hint": "أدخل وصف المشاركة",
|
||||||
"shared_link_edit_expire_after_option_day": "يوم 1",
|
"shared_link_edit_expire_after_option_day": "يوم 1",
|
||||||
"shared_link_edit_expire_after_option_days": "{count} ايام",
|
"shared_link_edit_expire_after_option_days": "{count} ايام",
|
||||||
@@ -1746,6 +1810,7 @@
|
|||||||
"shared_link_info_chip_metadata": "EXIF",
|
"shared_link_info_chip_metadata": "EXIF",
|
||||||
"shared_link_manage_links": "إدارة الروابط المشتركة",
|
"shared_link_manage_links": "إدارة الروابط المشتركة",
|
||||||
"shared_link_options": "خيارات الرابط المشترك",
|
"shared_link_options": "خيارات الرابط المشترك",
|
||||||
|
"shared_link_password_description": "طلب كلمة مرور للوصول إلى هذا الرابط المشترك",
|
||||||
"shared_links": "روابط مشتركة",
|
"shared_links": "روابط مشتركة",
|
||||||
"shared_links_description": "وصف الروابط المشتركة",
|
"shared_links_description": "وصف الروابط المشتركة",
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# الصور ومقاطع الفيديو المُشارَكة.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# الصور ومقاطع الفيديو المُشارَكة.}}",
|
||||||
@@ -1795,12 +1860,14 @@
|
|||||||
"sort_created": "تاريخ الإنشاء",
|
"sort_created": "تاريخ الإنشاء",
|
||||||
"sort_items": "عدد العناصر",
|
"sort_items": "عدد العناصر",
|
||||||
"sort_modified": "تم تعديل التاريخ",
|
"sort_modified": "تم تعديل التاريخ",
|
||||||
|
"sort_newest": "احدث صورة",
|
||||||
"sort_oldest": "أقدم صورة",
|
"sort_oldest": "أقدم صورة",
|
||||||
"sort_people_by_similarity": "رتب الأشخاص حسب التشابه",
|
"sort_people_by_similarity": "رتب الأشخاص حسب التشابه",
|
||||||
"sort_recent": "أحدث صورة",
|
"sort_recent": "أحدث صورة",
|
||||||
"sort_title": "العنوان",
|
"sort_title": "العنوان",
|
||||||
"source": "المصدر",
|
"source": "المصدر",
|
||||||
"stack": "تجميع",
|
"stack": "تجميع",
|
||||||
|
"stack_action_prompt": "{count} مكدسة",
|
||||||
"stack_duplicates": "تجميع النسخ المكررة",
|
"stack_duplicates": "تجميع النسخ المكررة",
|
||||||
"stack_select_one_photo": "حدد صورة رئيسية واحدة للمجموعة",
|
"stack_select_one_photo": "حدد صورة رئيسية واحدة للمجموعة",
|
||||||
"stack_selected_photos": "كدس الصور المحددة",
|
"stack_selected_photos": "كدس الصور المحددة",
|
||||||
@@ -1820,6 +1887,7 @@
|
|||||||
"storage_quota": "حصة الخزن",
|
"storage_quota": "حصة الخزن",
|
||||||
"storage_usage": "{used} من {available} مُستخْدم",
|
"storage_usage": "{used} من {available} مُستخْدم",
|
||||||
"submit": "إرسال",
|
"submit": "إرسال",
|
||||||
|
"success": "تم بنجاح",
|
||||||
"suggestions": "اقتراحات",
|
"suggestions": "اقتراحات",
|
||||||
"sunrise_on_the_beach": "شروق الشمس على الشاطئ",
|
"sunrise_on_the_beach": "شروق الشمس على الشاطئ",
|
||||||
"support": "الدعم",
|
"support": "الدعم",
|
||||||
@@ -1829,6 +1897,8 @@
|
|||||||
"sync": "مزامنة",
|
"sync": "مزامنة",
|
||||||
"sync_albums": "مزامنة الالبومات",
|
"sync_albums": "مزامنة الالبومات",
|
||||||
"sync_albums_manual_subtitle": "مزامنة جميع الفديوهات والصور المرفوعة الى البومات الخزن الاحتياطي المختارة",
|
"sync_albums_manual_subtitle": "مزامنة جميع الفديوهات والصور المرفوعة الى البومات الخزن الاحتياطي المختارة",
|
||||||
|
"sync_local": "مزامنة الملفات المحلية",
|
||||||
|
"sync_remote": "مزامنة الملفات البعيدة",
|
||||||
"sync_upload_album_setting_subtitle": "انشئ و ارفع صورك و فديوهاتك الالبومات المختارة في Immich",
|
"sync_upload_album_setting_subtitle": "انشئ و ارفع صورك و فديوهاتك الالبومات المختارة في Immich",
|
||||||
"tag": "العلامة",
|
"tag": "العلامة",
|
||||||
"tag_assets": "أصول العلامة",
|
"tag_assets": "أصول العلامة",
|
||||||
@@ -1839,6 +1909,7 @@
|
|||||||
"tag_updated": "تم تحديث العلامة: {tag}",
|
"tag_updated": "تم تحديث العلامة: {tag}",
|
||||||
"tagged_assets": "تم وضع علامة {count, plural, one {# asset} other {# assets}}",
|
"tagged_assets": "تم وضع علامة {count, plural, one {# asset} other {# assets}}",
|
||||||
"tags": "العلامات",
|
"tags": "العلامات",
|
||||||
|
"tap_to_run_job": "انقر لتشغيل المهمة",
|
||||||
"template": "النموذج",
|
"template": "النموذج",
|
||||||
"theme": "مظهر",
|
"theme": "مظهر",
|
||||||
"theme_selection": "اختيار السمة",
|
"theme_selection": "اختيار السمة",
|
||||||
@@ -1911,15 +1982,20 @@
|
|||||||
"unselect_all_duplicates": "إلغاء تحديد كافة النسخ المكررة",
|
"unselect_all_duplicates": "إلغاء تحديد كافة النسخ المكررة",
|
||||||
"unselect_all_in": "إلغاء تحديد الكل في {group}",
|
"unselect_all_in": "إلغاء تحديد الكل في {group}",
|
||||||
"unstack": "فك الكومه",
|
"unstack": "فك الكومه",
|
||||||
|
"unstack_action_prompt": "تم ازالة تكديس {count}",
|
||||||
"unstacked_assets_count": "تم إخراج {count, plural, one {# الأصل} other {# الأصول}} من التكديس",
|
"unstacked_assets_count": "تم إخراج {count, plural, one {# الأصل} other {# الأصول}} من التكديس",
|
||||||
|
"untagged": "غير مُعَلَّم",
|
||||||
"up_next": "التالي",
|
"up_next": "التالي",
|
||||||
"updated_at": "تم التحديث",
|
"updated_at": "تم التحديث",
|
||||||
"updated_password": "تم تحديث كلمة المرور",
|
"updated_password": "تم تحديث كلمة المرور",
|
||||||
"upload": "رفع",
|
"upload": "رفع",
|
||||||
|
"upload_action_prompt": "{count} ملف في قائمة الانتظار للرفع",
|
||||||
"upload_concurrency": "الرفع المتزامن",
|
"upload_concurrency": "الرفع المتزامن",
|
||||||
|
"upload_details": "تفاصيل الرفع",
|
||||||
"upload_dialog_info": "هل تريد النسخ الاحتياطي للأصول (الأصول) المحددة إلى الخادم؟",
|
"upload_dialog_info": "هل تريد النسخ الاحتياطي للأصول (الأصول) المحددة إلى الخادم؟",
|
||||||
"upload_dialog_title": "تحميل الأصول",
|
"upload_dialog_title": "تحميل الأصول",
|
||||||
"upload_errors": "إكتمل الرفع مع {count, plural, one {# خطأ} other {# أخطاء}}, قم بتحديث الصفحة لرؤية المحتويات الجديدة التي تم رفعها.",
|
"upload_errors": "إكتمل الرفع مع {count, plural, one {# خطأ} other {# أخطاء}}, قم بتحديث الصفحة لرؤية المحتويات الجديدة التي تم رفعها.",
|
||||||
|
"upload_finished": "تم الانتهاء من الرفع",
|
||||||
"upload_progress": "متبقية {remaining, number} - معالجة {processed, number}/{total, number}",
|
"upload_progress": "متبقية {remaining, number} - معالجة {processed, number}/{total, number}",
|
||||||
"upload_skipped_duplicates": "تم تخطي {count, plural, one {# محتوى مكرر} other {# محتويات مكررة }}",
|
"upload_skipped_duplicates": "تم تخطي {count, plural, one {# محتوى مكرر} other {# محتويات مكررة }}",
|
||||||
"upload_status_duplicates": "التكرارات",
|
"upload_status_duplicates": "التكرارات",
|
||||||
@@ -1928,6 +2004,7 @@
|
|||||||
"upload_success": "تم الرفع بنجاح، قم بتحديث الصفحة لرؤية المحتويات المرفوعة الجديدة.",
|
"upload_success": "تم الرفع بنجاح، قم بتحديث الصفحة لرؤية المحتويات المرفوعة الجديدة.",
|
||||||
"upload_to_immich": "الرفع الىImmich ({count})",
|
"upload_to_immich": "الرفع الىImmich ({count})",
|
||||||
"uploading": "جاري الرفع",
|
"uploading": "جاري الرفع",
|
||||||
|
"uploading_media": "رفع الوسائط",
|
||||||
"url": "عنوان URL",
|
"url": "عنوان URL",
|
||||||
"usage": "الاستخدام",
|
"usage": "الاستخدام",
|
||||||
"use_biometric": "استخدم البايومتري",
|
"use_biometric": "استخدم البايومتري",
|
||||||
@@ -1948,6 +2025,7 @@
|
|||||||
"user_usage_stats_description": "عرض إحصائيات استخدام الحساب",
|
"user_usage_stats_description": "عرض إحصائيات استخدام الحساب",
|
||||||
"username": "اسم المستخدم",
|
"username": "اسم المستخدم",
|
||||||
"users": "المستخدمين",
|
"users": "المستخدمين",
|
||||||
|
"users_added_to_album_count": "تم اضافة{count, plural, one {# مستخدم} other {# مستخدمين}} الى الالبوم",
|
||||||
"utilities": "أدوات",
|
"utilities": "أدوات",
|
||||||
"validate": "تحقْق",
|
"validate": "تحقْق",
|
||||||
"validate_endpoint_error": "الرجاء ادخال عنوان URL صالح",
|
"validate_endpoint_error": "الرجاء ادخال عنوان URL صالح",
|
||||||
@@ -1966,6 +2044,7 @@
|
|||||||
"view_album": "عرض الألبوم",
|
"view_album": "عرض الألبوم",
|
||||||
"view_all": "عرض الكل",
|
"view_all": "عرض الكل",
|
||||||
"view_all_users": "عرض كافة المستخدمين",
|
"view_all_users": "عرض كافة المستخدمين",
|
||||||
|
"view_details": "رؤية التفاصيل",
|
||||||
"view_in_timeline": "عرض في الجدول الزمني",
|
"view_in_timeline": "عرض في الجدول الزمني",
|
||||||
"view_link": "عرض الرابط",
|
"view_link": "عرض الرابط",
|
||||||
"view_links": "عرض الروابط",
|
"view_links": "عرض الروابط",
|
||||||
|
|||||||
29
i18n/az.json
29
i18n/az.json
@@ -1,37 +1,53 @@
|
|||||||
{
|
{
|
||||||
"about": "Haqqinda",
|
"about": "Haqqında",
|
||||||
"account": "Hesab",
|
"account": "Hesab",
|
||||||
"account_settings": "Hesab parametrləri",
|
"account_settings": "Hesab parametrləri",
|
||||||
"acknowledge": "Təsdiq et",
|
"acknowledge": "Təsdiq et",
|
||||||
"action": "Əməliyyat",
|
"action": "Əməliyyat",
|
||||||
|
"action_common_update": "Yenilə",
|
||||||
"actions": "Əməliyyatlar",
|
"actions": "Əməliyyatlar",
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"activity": "Fəaliyyət",
|
"activity": "Fəaliyyət",
|
||||||
|
"activity_changed": "Fəaliyyət {enabled, select, true {aktivdir} other {aktiv deyil}}",
|
||||||
"add": "Əlavə et",
|
"add": "Əlavə et",
|
||||||
"add_a_description": "Təsviri əlavə et",
|
"add_a_description": "Təsviri əlavə et",
|
||||||
"add_a_location": "Məkan əlavə et",
|
"add_a_location": "Məkan əlavə et",
|
||||||
"add_a_name": "Ad əlavə et",
|
"add_a_name": "Ad əlavə et",
|
||||||
"add_a_title": "Başlıq əlavə et",
|
"add_a_title": "Başlıq əlavə et",
|
||||||
|
"add_birthday": "Doğum günü əlavə et",
|
||||||
|
"add_endpoint": "Son nöqtə əlavə et",
|
||||||
"add_exclusion_pattern": "İstisna nümunəsi əlavə et",
|
"add_exclusion_pattern": "İstisna nümunəsi əlavə et",
|
||||||
"add_import_path": "Import yolunu əlavə et",
|
"add_import_path": "Import yolunu əlavə et",
|
||||||
"add_location": "Məkanı əlavə et",
|
"add_location": "Məkan əlavə et",
|
||||||
"add_more_users": "Daha çox istifadəçi əlavə et",
|
"add_more_users": "Daha çox istifadəçi əlavə et",
|
||||||
"add_partner": "Partnyor əlavə et",
|
"add_partner": "Partnyor əlavə et",
|
||||||
"add_path": "Yol əlavə et",
|
"add_path": "Yol əlavə et",
|
||||||
"add_photos": "Şəkilləri əlavə et",
|
"add_photos": "Şəkillər əlavə et",
|
||||||
"add_to": "... əlavə et",
|
"add_tag": "Etiket əlavə et",
|
||||||
|
"add_to": "Bura əlavə et…",
|
||||||
"add_to_album": "Albom əlavə et",
|
"add_to_album": "Albom əlavə et",
|
||||||
|
"add_to_album_bottom_sheet_added": "{album} albomuna əlavə edildi",
|
||||||
|
"add_to_album_bottom_sheet_already_exists": "Artıq {album} albomunda var",
|
||||||
|
"add_to_album_toggle": "{album} üçün seçimi dəyişin",
|
||||||
|
"add_to_albums": "Albomlara əlavə et",
|
||||||
|
"add_to_albums_count": "Albomlara əlavə et ({count})",
|
||||||
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
||||||
|
"add_url": "URL əlavə et",
|
||||||
"added_to_archive": "Arxivə əlavə edildi",
|
"added_to_archive": "Arxivə əlavə edildi",
|
||||||
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
||||||
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
||||||
"admin": {
|
"admin": {
|
||||||
|
"add_exclusion_pattern_description": "İstisna şablonlarını əlavə edin. *, ** və ? ilə Globbing dəstəklənir. Məs.: \"Raw\" adlanan hər hansısa bir qovluqda bütün faylları saymamaq üçün \"**/Raw/**\"-dan istifadə edin. \".tif\" ilə bitən bütün faylları saymamaq üçün \"**/*.tif\"-dən istifadə edin. Faylı mütləq yoldan istifadə etməklə saymamaq istəyirsinizsə \"/path/to/ignore/**\"-dan istifadə edin.",
|
||||||
|
"admin_user": "Admin İstifadəçi",
|
||||||
|
"asset_offline_description": "Bu xarici kitabxana varlığı diskdə artıq tapılmadı və zibil qutusuna köçürüldü. Əgər fayl kitabxana içərisində köçürülübsə, zaman şkalanızı yeni uyğun gələn varlıq üçün yoxlayın. Varlığı yenidən qaytarmaq üçün aşağıda verilmiş fayl yolunun Immich tərəfindən əlçatan olduğundan əmin olduqdan sonra kitabxananı skan edin.",
|
||||||
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
||||||
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
||||||
"background_task_job": "Arxa plan tapşırıqları",
|
"background_task_job": "Arxa plan tapşırıqları",
|
||||||
"backup_database_enable_description": "Verilənlər bazasının ehtiyat nüsxələrini aktiv et",
|
"backup_database": "Verilənlər bazasının dump-ını yaradın",
|
||||||
|
"backup_database_enable_description": "Verilənlər bazasının artıq nüsxələrini aktiv et",
|
||||||
|
"backup_keep_last_amount": "Tutulması gərəkən nüsxələrin sayı",
|
||||||
"backup_settings": "Ehtiyat Nüsxə Parametrləri",
|
"backup_settings": "Ehtiyat Nüsxə Parametrləri",
|
||||||
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
||||||
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
||||||
@@ -84,5 +100,6 @@
|
|||||||
"machine_learning_facial_recognition": "Üz Tanıma",
|
"machine_learning_facial_recognition": "Üz Tanıma",
|
||||||
"machine_learning_facial_recognition_description": "Şəkillərdəki üzləri aşkarla, tanı və qruplaşdır",
|
"machine_learning_facial_recognition_description": "Şəkillərdəki üzləri aşkarla, tanı və qruplaşdır",
|
||||||
"machine_learning_facial_recognition_model": "Üz tanıma modeli"
|
"machine_learning_facial_recognition_model": "Üz tanıma modeli"
|
||||||
}
|
},
|
||||||
|
"timeline": "Zaman şkalası"
|
||||||
}
|
}
|
||||||
|
|||||||
53
i18n/be.json
53
i18n/be.json
@@ -14,6 +14,7 @@
|
|||||||
"add_a_location": "Дадаць месца",
|
"add_a_location": "Дадаць месца",
|
||||||
"add_a_name": "Дадаць імя",
|
"add_a_name": "Дадаць імя",
|
||||||
"add_a_title": "Дадаць загаловак",
|
"add_a_title": "Дадаць загаловак",
|
||||||
|
"add_birthday": "Дадаць дзень нараджэння",
|
||||||
"add_endpoint": "Дадаць кропку доступу",
|
"add_endpoint": "Дадаць кропку доступу",
|
||||||
"add_exclusion_pattern": "Дадаць шаблон выключэння",
|
"add_exclusion_pattern": "Дадаць шаблон выключэння",
|
||||||
"add_import_path": "Дадаць шлях імпарту",
|
"add_import_path": "Дадаць шлях імпарту",
|
||||||
@@ -27,6 +28,8 @@
|
|||||||
"add_to_album": "Дадаць у альбом",
|
"add_to_album": "Дадаць у альбом",
|
||||||
"add_to_album_bottom_sheet_added": "Дададзена да {album}",
|
"add_to_album_bottom_sheet_added": "Дададзена да {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Ужо знаходзіцца ў {album}",
|
"add_to_album_bottom_sheet_already_exists": "Ужо знаходзіцца ў {album}",
|
||||||
|
"add_to_albums": "Дадаць у альбомы",
|
||||||
|
"add_to_albums_count": "Дадаць у альбомы ({count})",
|
||||||
"add_to_shared_album": "Дадаць у агульны альбом",
|
"add_to_shared_album": "Дадаць у агульны альбом",
|
||||||
"add_url": "Дадаць URL",
|
"add_url": "Дадаць URL",
|
||||||
"added_to_archive": "Дададзена ў архіў",
|
"added_to_archive": "Дададзена ў архіў",
|
||||||
@@ -44,6 +47,10 @@
|
|||||||
"backup_database": "Стварыць рэзервовую копію базы даных",
|
"backup_database": "Стварыць рэзервовую копію базы даных",
|
||||||
"backup_database_enable_description": "Уключыць рэзерваванне базы даных",
|
"backup_database_enable_description": "Уключыць рэзерваванне базы даных",
|
||||||
"backup_keep_last_amount": "Колькасць папярэдніх рэзервовых копій для захавання",
|
"backup_keep_last_amount": "Колькасць папярэдніх рэзервовых копій для захавання",
|
||||||
|
"backup_onboarding_1_description": "зняшняя копія ў воблаку або ў іншым фізічным месцы.",
|
||||||
|
"backup_onboarding_2_description": "лакальныя копіі на іншых прыладах. Гэта ўключае ў сябе асноўныя файлы і лакальную рэзервовую копію гэтых файлаў.",
|
||||||
|
"backup_onboarding_parts_title": "Рэзервовая копія «3-2-1» уключае ў сябе:",
|
||||||
|
"backup_onboarding_title": "Рэзервовыя копіі",
|
||||||
"backup_settings": "Налады рэзервовага капіявання",
|
"backup_settings": "Налады рэзервовага капіявання",
|
||||||
"backup_settings_description": "Кіраванне наладамі рэзервавання базы даных.",
|
"backup_settings_description": "Кіраванне наладамі рэзервавання базы даных.",
|
||||||
"cleared_jobs": "Ачышчаны заданні для: {job}",
|
"cleared_jobs": "Ачышчаны заданні для: {job}",
|
||||||
@@ -56,14 +63,14 @@
|
|||||||
"confirm_user_pin_code_reset": "Вы ўпэўнены ў тым, што жадаеце скінуць PIN-код {user}?",
|
"confirm_user_pin_code_reset": "Вы ўпэўнены ў тым, што жадаеце скінуць PIN-код {user}?",
|
||||||
"create_job": "Стварыць заданне",
|
"create_job": "Стварыць заданне",
|
||||||
"cron_expression": "Выраз Cron",
|
"cron_expression": "Выраз Cron",
|
||||||
"cron_expression_description": "Усталюйце інтэрвал сканавання, выкарыстоўваючы фармат cron. Для атрымання дадатковай інфармацыі, калі ласка, звярніцеся, напрыклад, да <link>Crontab Guru</link>",
|
"cron_expression_description": "Задайце інтэрвал сканавання, выкарыстоўваючы фармат cron. Для атрымання дадатковай інфармацыі, звярніцеся, напрыклад, да <link>Crontab Guru</link>",
|
||||||
"cron_expression_presets": "Прадустаноўкі выразаў Cron",
|
"cron_expression_presets": "Прадустаноўкі выразаў Cron",
|
||||||
"disable_login": "Адключыць уваход",
|
"disable_login": "Адключыць уваход",
|
||||||
"duplicate_detection_job_description": "Запусціць машыннае навучанне на актывах для выяўлення падобных выяў. Залежыць ад Smart Search",
|
"duplicate_detection_job_description": "Запусціць машыннае навучанне на актывах для выяўлення падобных выяў. Залежыць ад Smart Search",
|
||||||
"exclusion_pattern_description": "Шаблоны выключэння дазваляюць ігнараваць файлы і папкі пры сканаванні вашай бібліятэкі. Гэта карысна, калі ў вас ёсць папкі, якія змяшчаюць файлы, якія вы не хочаце імпартаваць, напрыклад, файлы RAW.",
|
"exclusion_pattern_description": "Шаблоны выключэння дазваляюць ігнараваць файлы і папкі пры сканаванні вашай бібліятэкі. Гэта карысна, калі ў вас ёсць папкі, якія змяшчаюць файлы, якія вы не хочаце імпартаваць, напрыклад, файлы RAW.",
|
||||||
"external_library_management": "Кіраванне знешняй бібліятэкай",
|
"external_library_management": "Кіраванне знешняй бібліятэкай",
|
||||||
"face_detection": "Выяўленне твараў",
|
"face_detection": "Выяўленне твараў",
|
||||||
"face_detection_description": "Выяўляць твары на фотаздымках і відэа з дапамогай машыннага навучання. Для відэа ўлічваецца толькі мініяцюра. \"Абнавіць\" (пера)апрацоўвае ўсе медыя. \"Скінуць\" дадаткова ачышчае ўсе бягучыя дадзеныя пра твары. \"Адсутнічае\" ставіць у чаргу медыя, якія яшчэ не былі апрацаваныя. Выяўленыя твары будуць пастаўлены ў чаргу для распазнавання асоб пасля завяршэння выяўлення твараў, з групаваннем іх па існуючых або новых людзях.",
|
"face_detection_description": "Выяўляць твары на фотаздымках і відэа з дапамогай машыннага навучання. Для відэа ўлічваецца толькі мініяцюра. \"Абнавіць\" (пера)апрацоўвае ўсе медыя. \"Скінуць\" дадаткова ачышчае ўсе бягучыя даныя пра твары. \"Адсутнічае\" ставіць у чаргу медыя, якія яшчэ не былі апрацаваныя. Выяўленыя твары будуць пастаўлены ў чаргу для распазнавання асоб пасля завяршэння выяўлення твараў, з групаваннем іх па існуючых або новых людзях.",
|
||||||
"facial_recognition_job_description": "Групаваць выяўленыя твары па асобах. Гэты этап выконваецца пасля завяршэння выяўлення твараў. \"Скінуць\" (паўторна) перагрупоўвае ўсе твары. \"Адсутнічае\" ставіць у чаргу твары, якія яшчэ не прыпісаныя да якой-небудзь асобы.",
|
"facial_recognition_job_description": "Групаваць выяўленыя твары па асобах. Гэты этап выконваецца пасля завяршэння выяўлення твараў. \"Скінуць\" (паўторна) перагрупоўвае ўсе твары. \"Адсутнічае\" ставіць у чаргу твары, якія яшчэ не прыпісаныя да якой-небудзь асобы.",
|
||||||
"failed_job_command": "Каманда {command} не выканалася для задання: {job}",
|
"failed_job_command": "Каманда {command} не выканалася для задання: {job}",
|
||||||
"force_delete_user_warning": "ПАПЯРЭДЖАННЕ: Гэта дзеянне неадкладна выдаліць карыстальніка і ўсе аб'екты. Гэта дзеянне не можа быць адроблена і файлы немагчыма будзе аднавіць.",
|
"force_delete_user_warning": "ПАПЯРЭДЖАННЕ: Гэта дзеянне неадкладна выдаліць карыстальніка і ўсе аб'екты. Гэта дзеянне не можа быць адроблена і файлы немагчыма будзе аднавіць.",
|
||||||
@@ -75,17 +82,39 @@
|
|||||||
"image_fullsize_quality_description": "Якасць выявы ў поўным памеры ад 1 да 100. Больш высокае значэнне лепшае, але прыводзіць да павелічэння памеру файла.",
|
"image_fullsize_quality_description": "Якасць выявы ў поўным памеры ад 1 да 100. Больш высокае значэнне лепшае, але прыводзіць да павелічэння памеру файла.",
|
||||||
"image_fullsize_title": "Налады выявы ў поўным памеры",
|
"image_fullsize_title": "Налады выявы ў поўным памеры",
|
||||||
"image_prefer_embedded_preview": "Аддаваць перавагу ўбудаванай праяве",
|
"image_prefer_embedded_preview": "Аддаваць перавагу ўбудаванай праяве",
|
||||||
"image_prefer_embedded_preview_setting_description": "Выкарыстоўваць убудаваныя праявы ў RAW-фотаздымках ў якасці ўваходных дадзеных для апрацоўкі малюнкаў, калі магчыма. Гэта дазваляе атрымаць больш дакладныя колеры для некаторых відарысаў, але ж якасць праяў залежыць ад камеры, і на відарысе можа быць больш артэфактаў сціску.",
|
"image_prefer_embedded_preview_setting_description": "Выкарыстоўваць убудаваныя праявы ў RAW-фотаздымках ў якасці ўваходных даных для апрацоўкі малюнкаў, калі магчыма. Гэта дазваляе атрымаць больш дакладныя колеры для некаторых відарысаў, але ж якасць праяў залежыць ад камеры, і на відарысе можа быць больш артэфактаў сціску.",
|
||||||
"image_prefer_wide_gamut": "Аддаць перавагу шырокай гаме",
|
"image_prefer_wide_gamut": "Аддаць перавагу шырокай гаме",
|
||||||
"image_preview_description": "Відарыс сярэдняга памеру з выдаленымі метададзенымі, выкарыстоўваецца пры праглядзе асобнага рэсурсу і для машыннага навучання",
|
"image_preview_description": "Відарыс сярэдняга памеру з выдаленымі метаданымі, выкарыстоўваецца пры праглядзе асобнага рэсурсу і для машыннага навучання",
|
||||||
"image_preview_quality_description": "Якасць праявы ад 1 да 100. Чым вышэй, тым лепш, але пры гэтым ствараюцца файлы большага памеру і можа знізіцца хуткасць водгуку прыкладання. Ўстаноўка нізкага значэння можа паўплываць на якасць машыннага навучання.",
|
"image_preview_quality_description": "Якасць праявы ад 1 да 100. Чым вышэй, тым лепш, але пры гэтым ствараюцца файлы большага памеру і можа знізіцца хуткасць водгуку прыкладання. Ўстаноўка нізкага значэння можа паўплываць на якасць машыннага навучання.",
|
||||||
"image_preview_title": "Налады папярэдняга прагляду",
|
"image_preview_title": "Налады папярэдняга прагляду",
|
||||||
"image_quality": "Якасць",
|
"image_quality": "Якасць",
|
||||||
"image_resolution": "Раздзяляльнасць",
|
"image_resolution": "Раздзяляльнасць",
|
||||||
"image_settings": "Налады відарыса",
|
"image_settings": "Налады відарыса",
|
||||||
"image_settings_description": "Кіруйце якасцю і раздзяляльнасцю сгенерыраваных відарысаў",
|
"image_settings_description": "Кіруйце якасцю і раздзяляльнасцю сгенерыраваных відарысаў",
|
||||||
|
"image_thumbnail_title": "Налады мініяцюр",
|
||||||
|
"job_concurrency": "{job} канкурэнтнасць",
|
||||||
|
"job_created": "Заданне створана",
|
||||||
|
"job_not_concurrency_safe": "Гэта заданне небяспечнае для канкурэнтнага(адначасовага, паралельнага) выканання.",
|
||||||
|
"job_settings": "Налады заданняў",
|
||||||
|
"job_settings_description": "Кіраваць наладамі адначасовага (паралельнага) выканання задання",
|
||||||
|
"job_status": "Становішча задання",
|
||||||
"library_created": "Створана бібліятэка: {library}",
|
"library_created": "Створана бібліятэка: {library}",
|
||||||
"library_deleted": "Бібліятэка выдалена",
|
"library_deleted": "Бібліятэка выдалена",
|
||||||
|
"library_scanning": "Сканаванне па раскладзе",
|
||||||
|
"library_scanning_description": "Наладзьце параметры сканавання вашай бібліятэкі",
|
||||||
|
"library_scanning_enable_description": "Уключыць сканаванне бібліятэкі па раскладзе",
|
||||||
|
"library_settings": "Знешняя бібліятэка",
|
||||||
|
"library_settings_description": "Наладзьце параметры знешняй бібліятэкі",
|
||||||
|
"library_tasks_description": "Сканаваць знешнія бібліятэкі на наяўнасць новых і/або змененых рэсурсаў",
|
||||||
|
"library_watching_enable_description": "Назіраць за зменамі файлаў у знешніх бібліятэках",
|
||||||
|
"library_watching_settings": "Сачыць за бібліятэкай (эксперыментальны)",
|
||||||
|
"library_watching_settings_description": "Аўтаматычна сачыць за зменамі ў файлах",
|
||||||
|
"logging_enable_description": "Уключыць вядзенне журнала",
|
||||||
|
"logging_level_description": "Калі уключана, які ўзровень журналявання выкарыстоўваць.",
|
||||||
|
"logging_settings": "Вядзенне журнала",
|
||||||
|
"machine_learning_clip_model": "CLIP мадэль",
|
||||||
|
"machine_learning_clip_model_description": "Назва CLIP мадэлі паказана <link>тут</link>. Звярніце ўвагу, што пры змене мадэлі неабходна паўторна запусціць заданне \"Smart Search\" для ўсіх відарысаў.",
|
||||||
|
"machine_learning_duplicate_detection": "Выяўленне падобных",
|
||||||
"map_dark_style": "Цёмны стыль",
|
"map_dark_style": "Цёмны стыль",
|
||||||
"map_enable_description": "Уключыць функцыі карты",
|
"map_enable_description": "Уключыць функцыі карты",
|
||||||
"map_gps_settings": "Налады карты і GPS",
|
"map_gps_settings": "Налады карты і GPS",
|
||||||
@@ -133,7 +162,7 @@
|
|||||||
"user_settings_description": "Кіраванне наладамі карыстальніка",
|
"user_settings_description": "Кіраванне наладамі карыстальніка",
|
||||||
"user_successfully_removed": "Карыстальнік {email} быў паспяхова выдалены.",
|
"user_successfully_removed": "Карыстальнік {email} быў паспяхова выдалены.",
|
||||||
"version_check_enabled_description": "Уключыць праверку версіі",
|
"version_check_enabled_description": "Уключыць праверку версіі",
|
||||||
"version_check_implications": "Функцыі праверкі версіі перыядычна звяртаецца да github.com",
|
"version_check_implications": "Функцыя праверкі версіі перыядычна звяртаецца да github.com",
|
||||||
"version_check_settings": "Праверка версіі",
|
"version_check_settings": "Праверка версіі",
|
||||||
"version_check_settings_description": "Уключыць/адключыць апавяшчэнні аб новай версіі"
|
"version_check_settings_description": "Уключыць/адключыць апавяшчэнні аб новай версіі"
|
||||||
},
|
},
|
||||||
@@ -206,7 +235,10 @@
|
|||||||
"asset_skipped_in_trash": "У сметніцы",
|
"asset_skipped_in_trash": "У сметніцы",
|
||||||
"asset_uploaded": "Запампавана",
|
"asset_uploaded": "Запампавана",
|
||||||
"asset_uploading": "Запампоўванне…",
|
"asset_uploading": "Запампоўванне…",
|
||||||
|
"assets_were_part_of_albums_count": "{count, plural, one {Актыў ужо быў} other {Актывы ужо былі}} часткай альбому",
|
||||||
"authorized_devices": "Аўтарызаваныя прылады",
|
"authorized_devices": "Аўтарызаваныя прылады",
|
||||||
|
"automatic_endpoint_switching_subtitle": "Падключацца лакальна па вылучаным Wi-Fi, калі гэта магчыма, і выкарыстоўваць альтэрнатыўныя падключэння ў іншых месцах",
|
||||||
|
"automatic_endpoint_switching_title": "Аўтаматычнае пераключэнне URL",
|
||||||
"back": "Назад",
|
"back": "Назад",
|
||||||
"backup_album_selection_page_albums_device": "Альбомы на прыладзе ({count})",
|
"backup_album_selection_page_albums_device": "Альбомы на прыладзе ({count})",
|
||||||
"backup_all": "Усе",
|
"backup_all": "Усе",
|
||||||
@@ -369,6 +401,15 @@
|
|||||||
"purchase_button_buy": "Купіць",
|
"purchase_button_buy": "Купіць",
|
||||||
"purchase_button_buy_immich": "Купіць Immich",
|
"purchase_button_buy_immich": "Купіць Immich",
|
||||||
"purchase_button_select": "Выбраць",
|
"purchase_button_select": "Выбраць",
|
||||||
|
"readonly_mode_disabled": "Выключаны рэжым толькі для чытання",
|
||||||
|
"readonly_mode_enabled": "Уключаны рэжым толькі для чытання",
|
||||||
|
"reassign": "Перапрызначыць",
|
||||||
|
"reassing_hint": "Прыпісаць выбраныя актывы існуючай асобе",
|
||||||
|
"recent": "Нядаўні",
|
||||||
|
"recent-albums": "Нядаўнія альбомы",
|
||||||
|
"recent_searches": "Нядаўнія пошукі",
|
||||||
|
"recently_added": "Нядаўна дададзена",
|
||||||
|
"refresh_faces": "Абнавіць твары",
|
||||||
"remove": "Выдаліць",
|
"remove": "Выдаліць",
|
||||||
"remove_from_album": "Выдаліць з альбома",
|
"remove_from_album": "Выдаліць з альбома",
|
||||||
"remove_from_favorites": "Выдаліць з абраных",
|
"remove_from_favorites": "Выдаліць з абраных",
|
||||||
@@ -457,7 +498,7 @@
|
|||||||
"view_all_users": "Праглядзець усех карыстальнікаў",
|
"view_all_users": "Праглядзець усех карыстальнікаў",
|
||||||
"view_in_timeline": "Паглядзець хроніку",
|
"view_in_timeline": "Паглядзець хроніку",
|
||||||
"view_links": "Праглядзець спасылкі",
|
"view_links": "Праглядзець спасылкі",
|
||||||
"view_name": "Прагледзець",
|
"view_name": "Прагляд",
|
||||||
"view_next_asset": "Паказаць наступны аб'ект",
|
"view_next_asset": "Паказаць наступны аб'ект",
|
||||||
"view_previous_asset": "Праглядзець папярэдні аб'ект",
|
"view_previous_asset": "Праглядзець папярэдні аб'ект",
|
||||||
"view_stack": "Прагляд стэка",
|
"view_stack": "Прагляд стэка",
|
||||||
|
|||||||
167
i18n/bg.json
167
i18n/bg.json
@@ -13,20 +13,24 @@
|
|||||||
"add_a_description": "Добави описание",
|
"add_a_description": "Добави описание",
|
||||||
"add_a_location": "Добави местоположение",
|
"add_a_location": "Добави местоположение",
|
||||||
"add_a_name": "Добави име",
|
"add_a_name": "Добави име",
|
||||||
"add_a_title": "Добавете заглавие",
|
"add_a_title": "Добaви заглавие",
|
||||||
|
"add_birthday": "Добави дата на раждане",
|
||||||
"add_endpoint": "Добави крайна точка",
|
"add_endpoint": "Добави крайна точка",
|
||||||
"add_exclusion_pattern": "Добави модел за изключване",
|
"add_exclusion_pattern": "Добави модел за изключване",
|
||||||
"add_import_path": "Добави път за импортиране",
|
"add_import_path": "Добави път за импортиране",
|
||||||
"add_location": "Добавете местоположение",
|
"add_location": "Дoбави местоположение",
|
||||||
"add_more_users": "Добавете още потребители",
|
"add_more_users": "Добави още потребители",
|
||||||
"add_partner": "Добавете партньор",
|
"add_partner": "Добави партньор",
|
||||||
"add_path": "Добави път",
|
"add_path": "Добави път",
|
||||||
"add_photos": "Добавете снимки",
|
"add_photos": "Добави снимки",
|
||||||
"add_tag": "Добави маркер",
|
"add_tag": "Добави маркер",
|
||||||
"add_to": "Добави към…",
|
"add_to": "Добави към…",
|
||||||
"add_to_album": "Добави към албум",
|
"add_to_album": "Добави към албум",
|
||||||
"add_to_album_bottom_sheet_added": "Добавено в {album}",
|
"add_to_album_bottom_sheet_added": "Добавено в {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Вече е в {album}",
|
"add_to_album_bottom_sheet_already_exists": "Вече е в {album}",
|
||||||
|
"add_to_album_toggle": "Сменете избора за {album}",
|
||||||
|
"add_to_albums": "Добавяне в албуми",
|
||||||
|
"add_to_albums_count": "Добавяне в албуми ({count})",
|
||||||
"add_to_shared_album": "Добави към споделен албум",
|
"add_to_shared_album": "Добави към споделен албум",
|
||||||
"add_url": "Добави URL",
|
"add_url": "Добави URL",
|
||||||
"added_to_archive": "Добавено към архива",
|
"added_to_archive": "Добавено към архива",
|
||||||
@@ -44,6 +48,13 @@
|
|||||||
"backup_database": "Създай резервна база данни",
|
"backup_database": "Създай резервна база данни",
|
||||||
"backup_database_enable_description": "Разреши резервни копия на базата данни",
|
"backup_database_enable_description": "Разреши резервни копия на базата данни",
|
||||||
"backup_keep_last_amount": "Брой запазени резервни копия",
|
"backup_keep_last_amount": "Брой запазени резервни копия",
|
||||||
|
"backup_onboarding_1_description": "копие на облака или друго физическо място.",
|
||||||
|
"backup_onboarding_2_description": "локални копия на различни устройства. Това включва основните файлове и локални архиви на тези файлове.",
|
||||||
|
"backup_onboarding_3_description": "общо копия на вашите данни, включитено оригиналните файлове. Това включва 1 копие извън системата и 2 локални копия.",
|
||||||
|
"backup_onboarding_description": "За надеждна защита препоръчваме стратегията <backblaze-link>3-2-1</backblaze-link>. Правете архивни копия както на качените снимки/видеа, така и на базата данни на Immich.",
|
||||||
|
"backup_onboarding_footer": "За подробна информация относно архивирането в Immich, моля вижте в <link>документацията</link>.",
|
||||||
|
"backup_onboarding_parts_title": "Стратегията 3-2-1 включва:",
|
||||||
|
"backup_onboarding_title": "Резервни копия",
|
||||||
"backup_settings": "Настройка на резервни копия на базата данни",
|
"backup_settings": "Настройка на резервни копия на базата данни",
|
||||||
"backup_settings_description": "Управление на настройките за резервно копие на базата данни.",
|
"backup_settings_description": "Управление на настройките за резервно копие на базата данни.",
|
||||||
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
"cleared_jobs": "Изчистени задачи от тип: {job}",
|
||||||
@@ -347,6 +358,9 @@
|
|||||||
"trash_number_of_days_description": "Брой дни, в които файловете да се съхраняват на боклука, преди да бъдат окончателно премахнати",
|
"trash_number_of_days_description": "Брой дни, в които файловете да се съхраняват на боклука, преди да бъдат окончателно премахнати",
|
||||||
"trash_settings": "Настройки на кошчето",
|
"trash_settings": "Настройки на кошчето",
|
||||||
"trash_settings_description": "Управление на настройките на кошчето",
|
"trash_settings_description": "Управление на настройките на кошчето",
|
||||||
|
"unlink_all_oauth_accounts": "Прекрати вписването на всички OAuth профили",
|
||||||
|
"unlink_all_oauth_accounts_description": "Не забравяйте да прекратите вписването на всички OAuth профили преди да мигрирате към нов доставчик.",
|
||||||
|
"unlink_all_oauth_accounts_prompt": "Сигурни ли сте, че искате да отпишете всички OAuth профили? Това ще нулира OAuth ID за всеки потребител и не може да бъде отменено.",
|
||||||
"user_cleanup_job": "Почистване на потребители",
|
"user_cleanup_job": "Почистване на потребители",
|
||||||
"user_delete_delay": "<b>{user}</b> aкаунтът и файловете на потребителя ще бъдат планирани за постоянно изтриване след {delay, plural, one {# ден} other {# дни}}.",
|
"user_delete_delay": "<b>{user}</b> aкаунтът и файловете на потребителя ще бъдат планирани за постоянно изтриване след {delay, plural, one {# ден} other {# дни}}.",
|
||||||
"user_delete_delay_settings": "Забавяне на изтриване",
|
"user_delete_delay_settings": "Забавяне на изтриване",
|
||||||
@@ -373,8 +387,6 @@
|
|||||||
"admin_password": "Администраторска парола",
|
"admin_password": "Администраторска парола",
|
||||||
"administration": "Администрация",
|
"administration": "Администрация",
|
||||||
"advanced": "Разширено",
|
"advanced": "Разширено",
|
||||||
"advanced_settings_beta_timeline_subtitle": "Опитайте новите функции на приложението",
|
|
||||||
"advanced_settings_beta_timeline_title": "Бета версия на времевата линия",
|
|
||||||
"advanced_settings_enable_alternate_media_filter_subtitle": "При синхронизация, използвайте тази опция като филтър, основан на промяна на даден критерии. Опитайте само в случай, че приложението има проблем с откриване на всички албуми.",
|
"advanced_settings_enable_alternate_media_filter_subtitle": "При синхронизация, използвайте тази опция като филтър, основан на промяна на даден критерии. Опитайте само в случай, че приложението има проблем с откриване на всички албуми.",
|
||||||
"advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНТАЛНО] Използвай филтъра на алтернативното устройство за синхронизация на албуми",
|
"advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНТАЛНО] Използвай филтъра на алтернативното устройство за синхронизация на албуми",
|
||||||
"advanced_settings_log_level_title": "Ниво на запис в дневника: {level}",
|
"advanced_settings_log_level_title": "Ниво на запис в дневника: {level}",
|
||||||
@@ -382,13 +394,15 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Предпочитай изображенията на сървъра",
|
"advanced_settings_prefer_remote_title": "Предпочитай изображенията на сървъра",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Дефиниране на прокси хедъри, които Immich трябва да изпраща с всяка мрежова заявка",
|
"advanced_settings_proxy_headers_subtitle": "Дефиниране на прокси хедъри, които Immich трябва да изпраща с всяка мрежова заявка",
|
||||||
"advanced_settings_proxy_headers_title": "Прокси хедъри",
|
"advanced_settings_proxy_headers_title": "Прокси хедъри",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Активира режима \"само за четене\", при който снимките могат да бъдат разглеждани, но неща като избор на няколко изображения, споделяне, изтриване са забранени. Активиране/деактивиране на режима само за четене става от картинката-аватар на потребителя от основния екран",
|
||||||
|
"advanced_settings_readonly_mode_title": "Режим само за четене",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Пропуска проверката на SSL-сертификата на сървъра. Изисква се при самоподписани сертификати.",
|
"advanced_settings_self_signed_ssl_subtitle": "Пропуска проверката на SSL-сертификата на сървъра. Изисква се при самоподписани сертификати.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Разреши самоподписани SSL сертификати",
|
"advanced_settings_self_signed_ssl_title": "Разреши самоподписани SSL сертификати",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Автоматично изтрии или възстанови обект на това устройство, когато действието е извършено през уеб-интерфейса",
|
"advanced_settings_sync_remote_deletions_subtitle": "Автоматично изтрии или възстанови обект на това устройство, когато действието е извършено през уеб-интерфейса",
|
||||||
"advanced_settings_sync_remote_deletions_title": "Синхронизация на дистанционни изтривания [ЕКСПЕРИМЕНТАЛНО]",
|
"advanced_settings_sync_remote_deletions_title": "Синхронизация на дистанционни изтривания [ЕКСПЕРИМЕНТАЛНО]",
|
||||||
"advanced_settings_tile_subtitle": "Разширени потребителски настройки",
|
"advanced_settings_tile_subtitle": "Разширени потребителски настройки",
|
||||||
"advanced_settings_troubleshooting_subtitle": "Разреши допълнителни възможности за отстраняване на проблеми",
|
"advanced_settings_troubleshooting_subtitle": "Разреши допълнителни възможности за отстраняване на проблеми",
|
||||||
"advanced_settings_troubleshooting_title": "Отстраняване на проблеми",
|
"advanced_settings_troubleshooting_title": "Отстраняванe на проблеми",
|
||||||
"age_months": "Възраст {months, plural, one {# месец} other {# месеци}}",
|
"age_months": "Възраст {months, plural, one {# месец} other {# месеци}}",
|
||||||
"age_year_months": "Възраст 1 година, {months, plural, one {# месец} other {# месеци}}",
|
"age_year_months": "Възраст 1 година, {months, plural, one {# месец} other {# месеци}}",
|
||||||
"age_years": "{years, plural, other {Година #}}",
|
"age_years": "{years, plural, other {Година #}}",
|
||||||
@@ -397,6 +411,7 @@
|
|||||||
"album_cover_updated": "Обложката на албума е актуализирана",
|
"album_cover_updated": "Обложката на албума е актуализирана",
|
||||||
"album_delete_confirmation": "Сигурни ли сте, че искате да изтриете албума {album}?",
|
"album_delete_confirmation": "Сигурни ли сте, че искате да изтриете албума {album}?",
|
||||||
"album_delete_confirmation_description": "Ако този албум е споделен, други потребители вече няма да имат достъп до него.",
|
"album_delete_confirmation_description": "Ако този албум е споделен, други потребители вече няма да имат достъп до него.",
|
||||||
|
"album_deleted": "Албума е изтрит",
|
||||||
"album_info_card_backup_album_excluded": "ИЗКЛЮЧЕН",
|
"album_info_card_backup_album_excluded": "ИЗКЛЮЧЕН",
|
||||||
"album_info_card_backup_album_included": "ВКЛЮЧЕН",
|
"album_info_card_backup_album_included": "ВКЛЮЧЕН",
|
||||||
"album_info_updated": "Информацията за албума е актуализирана",
|
"album_info_updated": "Информацията за албума е актуализирана",
|
||||||
@@ -406,7 +421,9 @@
|
|||||||
"album_options": "Настройки на албума",
|
"album_options": "Настройки на албума",
|
||||||
"album_remove_user": "Премахване на потребител?",
|
"album_remove_user": "Премахване на потребител?",
|
||||||
"album_remove_user_confirmation": "Сигурни ли сте, че искате да премахнете {user}?",
|
"album_remove_user_confirmation": "Сигурни ли сте, че искате да премахнете {user}?",
|
||||||
|
"album_search_not_found": "Няма намерени албуми, отговарящи на търсенето ви",
|
||||||
"album_share_no_users": "Изглежда, че сте споделили този албум с всички потребители или нямате друг потребител, с когото да го споделите.",
|
"album_share_no_users": "Изглежда, че сте споделили този албум с всички потребители или нямате друг потребител, с когото да го споделите.",
|
||||||
|
"album_summary": "Обобщение на албума",
|
||||||
"album_updated": "Албумът е актуализиран",
|
"album_updated": "Албумът е актуализиран",
|
||||||
"album_updated_setting_description": "Получавайте известие по имейл, когато споделен албум има нови файлове",
|
"album_updated_setting_description": "Получавайте известие по имейл, когато споделен албум има нови файлове",
|
||||||
"album_user_left": "Напусна {album}",
|
"album_user_left": "Напусна {album}",
|
||||||
@@ -425,6 +442,7 @@
|
|||||||
"albums_default_sort_order": "Ред по подразбиране за сортиране на албуми",
|
"albums_default_sort_order": "Ред по подразбиране за сортиране на албуми",
|
||||||
"albums_default_sort_order_description": "Първоначален ред на сортиране при създаване на нов албум.",
|
"albums_default_sort_order_description": "Първоначален ред на сортиране при създаване на нов албум.",
|
||||||
"albums_feature_description": "Колекции от обекти, които могат да бъдат споделяни с други поребители.",
|
"albums_feature_description": "Колекции от обекти, които могат да бъдат споделяни с други поребители.",
|
||||||
|
"albums_on_device_count": "Албуми на устройството ({count})",
|
||||||
"all": "Всички",
|
"all": "Всички",
|
||||||
"all_albums": "Всички албуми",
|
"all_albums": "Всички албуми",
|
||||||
"all_people": "Всички хора",
|
"all_people": "Всички хора",
|
||||||
@@ -444,6 +462,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Излез от профила",
|
"app_bar_signout_dialog_title": "Излез от профила",
|
||||||
"app_settings": "Настройки ма приложението",
|
"app_settings": "Настройки ма приложението",
|
||||||
"appears_in": "Излиза в",
|
"appears_in": "Излиза в",
|
||||||
|
"apply_count": "Приложи ({count, number})",
|
||||||
"archive": "Архив",
|
"archive": "Архив",
|
||||||
"archive_action_prompt": "{count} са добавени в Архива",
|
"archive_action_prompt": "{count} са добавени в Архива",
|
||||||
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
||||||
@@ -476,6 +495,8 @@
|
|||||||
"asset_restored_successfully": "Успешно възстановен обект",
|
"asset_restored_successfully": "Успешно възстановен обект",
|
||||||
"asset_skipped": "Пропуснато",
|
"asset_skipped": "Пропуснато",
|
||||||
"asset_skipped_in_trash": "В кошчето",
|
"asset_skipped_in_trash": "В кошчето",
|
||||||
|
"asset_trashed": "Обектът е изхвърлен",
|
||||||
|
"asset_troubleshoot": "Поправка на грешки с обекта",
|
||||||
"asset_uploaded": "Качено",
|
"asset_uploaded": "Качено",
|
||||||
"asset_uploading": "Качване…",
|
"asset_uploading": "Качване…",
|
||||||
"asset_viewer_settings_subtitle": "Управление на настройките за изглед",
|
"asset_viewer_settings_subtitle": "Управление на настройките за изглед",
|
||||||
@@ -483,7 +504,9 @@
|
|||||||
"assets": "Елементи",
|
"assets": "Елементи",
|
||||||
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
||||||
|
"assets_added_to_albums_count": "{assetTotal, plural, one {# обект е добавен} other {# обекта са добавени}} в {albumTotal, plural, one {# албум} other {# албума}}",
|
||||||
"assets_cannot_be_added_to_album_count": "{count, plural, one {Обекта не може да се добави} other {Обектите не може да се добавят}} в албума",
|
"assets_cannot_be_added_to_album_count": "{count, plural, one {Обекта не може да се добави} other {Обектите не може да се добавят}} в албума",
|
||||||
|
"assets_cannot_be_added_to_albums": "{count, plural, one {обект не може да бъде добавен} other {обекта не могат да бъдат добавени}} в никой от албумите",
|
||||||
"assets_count": "{count, plural, one {# актив} other {# актива}}",
|
"assets_count": "{count, plural, one {# актив} other {# актива}}",
|
||||||
"assets_deleted_permanently": "{count} обекта са изтрити завинаги",
|
"assets_deleted_permanently": "{count} обекта са изтрити завинаги",
|
||||||
"assets_deleted_permanently_from_server": "{count} обекта са изтити от Immich сървъра завинаги",
|
"assets_deleted_permanently_from_server": "{count} обекта са изтити от Immich сървъра завинаги",
|
||||||
@@ -500,14 +523,17 @@
|
|||||||
"assets_trashed_count": "Възстановен(и) са {count, plural, one {# файл} other {# файла}}",
|
"assets_trashed_count": "Възстановен(и) са {count, plural, one {# файл} other {# файла}}",
|
||||||
"assets_trashed_from_server": "{count} обекта са преместени в коша на Immich сървъра",
|
"assets_trashed_from_server": "{count} обекта са преместени в коша на Immich сървъра",
|
||||||
"assets_were_part_of_album_count": "{count, plural, one {Файлът е} other {Файловете са}} вече част от албума",
|
"assets_were_part_of_album_count": "{count, plural, one {Файлът е} other {Файловете са}} вече част от албума",
|
||||||
|
"assets_were_part_of_albums_count": "{count, plural, one {обект вече е} other {обекта вече са}} част от албумите",
|
||||||
"authorized_devices": "Удостоверени устройства",
|
"authorized_devices": "Удостоверени устройства",
|
||||||
"automatic_endpoint_switching_subtitle": "Когато е достъпна, използвай посочената Wi-Fi мрежа, иначе използвай алтернативни връзки",
|
"automatic_endpoint_switching_subtitle": "Когато е достъпна, използвай посочената Wi-Fi мрежа, иначе използвай алтернативни връзки",
|
||||||
"automatic_endpoint_switching_title": "Автоматично превключване на URL",
|
"automatic_endpoint_switching_title": "Автоматично превключване на URL",
|
||||||
"autoplay_slideshow": "Автоматична смяна на слайдовете",
|
"autoplay_slideshow": "Автоматична смяна на слайдовете",
|
||||||
"back": "Назад",
|
"back": "Назад",
|
||||||
"back_close_deselect": "Назад, затваряне или премахване на избора",
|
"back_close_deselect": "Назад, затваряне или премахване на избора",
|
||||||
|
"background_backup_running_error": "Стартирано е фоново архивиране, не може да се пусне ръчно архивиране",
|
||||||
"background_location_permission": "Разрешение за достъп до местоположението във фонов режим",
|
"background_location_permission": "Разрешение за достъп до местоположението във фонов режим",
|
||||||
"background_location_permission_content": "За да може да чете имената на Wi-Fi мрежите и да ги превключва при работа във фонов режим, Immich трябва *винаги* да има достъп до точното местоположение",
|
"background_location_permission_content": "За да може да чете имената на Wi-Fi мрежите и да ги превключва при работа във фонов режим, Immich трябва *винаги* да има достъп до точното местоположение",
|
||||||
|
"background_options": "Опции за фоновите задачи",
|
||||||
"backup": "Архивиране",
|
"backup": "Архивиране",
|
||||||
"backup_album_selection_page_albums_device": "Албуми на устройството ({count})",
|
"backup_album_selection_page_albums_device": "Албуми на устройството ({count})",
|
||||||
"backup_album_selection_page_albums_tap": "Натисни за да включиш, двойно за да изключиш",
|
"backup_album_selection_page_albums_tap": "Натисни за да включиш, двойно за да изключиш",
|
||||||
@@ -515,6 +541,7 @@
|
|||||||
"backup_album_selection_page_select_albums": "Избор на албуми",
|
"backup_album_selection_page_select_albums": "Избор на албуми",
|
||||||
"backup_album_selection_page_selection_info": "Информация за избраното",
|
"backup_album_selection_page_selection_info": "Информация за избраното",
|
||||||
"backup_album_selection_page_total_assets": "Уникални обекти общо",
|
"backup_album_selection_page_total_assets": "Уникални обекти общо",
|
||||||
|
"backup_albums_sync": "Синхронизиране на архивите",
|
||||||
"backup_all": "Всичко",
|
"backup_all": "Всичко",
|
||||||
"backup_background_service_backup_failed_message": "Неуспешно архивиране. Нов опит…",
|
"backup_background_service_backup_failed_message": "Неуспешно архивиране. Нов опит…",
|
||||||
"backup_background_service_connection_failed_message": "Неуспешно свързване към сървъра. Нов опит…",
|
"backup_background_service_connection_failed_message": "Неуспешно свързване към сървъра. Нов опит…",
|
||||||
@@ -564,13 +591,15 @@
|
|||||||
"backup_controller_page_turn_on": "Включи архивиране в активен режим",
|
"backup_controller_page_turn_on": "Включи архивиране в активен режим",
|
||||||
"backup_controller_page_uploading_file_info": "Инфо за архивирания файл",
|
"backup_controller_page_uploading_file_info": "Инфо за архивирания файл",
|
||||||
"backup_err_only_album": "Не може да се премахне единствения албум",
|
"backup_err_only_album": "Не може да се премахне единствения албум",
|
||||||
"backup_info_card_assets": "обекти",
|
"backup_info_card_assets": "обекта",
|
||||||
"backup_manual_cancelled": "Отменено",
|
"backup_manual_cancelled": "Отменено",
|
||||||
"backup_manual_in_progress": "Върви архивиране. Опитай след малко",
|
"backup_manual_in_progress": "Върви архивиране. Опитай след малко",
|
||||||
"backup_manual_success": "Успешно",
|
"backup_manual_success": "Успешно",
|
||||||
"backup_manual_title": "Състояние на архивирането",
|
"backup_manual_title": "Състояние на архивирането",
|
||||||
|
"backup_options": "Опции за архивиране",
|
||||||
"backup_options_page_title": "Настройки за архивиране",
|
"backup_options_page_title": "Настройки за архивиране",
|
||||||
"backup_setting_subtitle": "Управлявай настройките за архивиране в активен и фонов режим",
|
"backup_setting_subtitle": "Управлявай настройките за архивиране в активен и фонов режим",
|
||||||
|
"backup_settings_subtitle": "Управление на настройките за качване",
|
||||||
"backward": "Назад",
|
"backward": "Назад",
|
||||||
"biometric_auth_enabled": "Включена биометрично удостоверяване",
|
"biometric_auth_enabled": "Включена биометрично удостоверяване",
|
||||||
"biometric_locked_out": "Няма достъп до биометрично удостоверяване",
|
"biometric_locked_out": "Няма достъп до биометрично удостоверяване",
|
||||||
@@ -589,7 +618,7 @@
|
|||||||
"cache_settings_clear_cache_button": "Изчисти кеша",
|
"cache_settings_clear_cache_button": "Изчисти кеша",
|
||||||
"cache_settings_clear_cache_button_title": "Изчиства кеша на приложението. Това ще повлияе производителността на приложението докато кеша не бъде създаден отново.",
|
"cache_settings_clear_cache_button_title": "Изчиства кеша на приложението. Това ще повлияе производителността на приложението докато кеша не бъде създаден отново.",
|
||||||
"cache_settings_duplicated_assets_clear_button": "ИЗЧИСТИ",
|
"cache_settings_duplicated_assets_clear_button": "ИЗЧИСТИ",
|
||||||
"cache_settings_duplicated_assets_subtitle": "Снимки и видеа, които са в Черния списък на приложението",
|
"cache_settings_duplicated_assets_subtitle": "Снимки и видеа, които са в Списъка за игнориране от приложението",
|
||||||
"cache_settings_duplicated_assets_title": "Дублирани обекти ({count})",
|
"cache_settings_duplicated_assets_title": "Дублирани обекти ({count})",
|
||||||
"cache_settings_statistics_album": "Библиотека с миниатюри",
|
"cache_settings_statistics_album": "Библиотека с миниатюри",
|
||||||
"cache_settings_statistics_full": "Пълни изображения",
|
"cache_settings_statistics_full": "Пълни изображения",
|
||||||
@@ -606,6 +635,7 @@
|
|||||||
"cancel": "Откажи",
|
"cancel": "Откажи",
|
||||||
"cancel_search": "Отмени търсенето",
|
"cancel_search": "Отмени търсенето",
|
||||||
"canceled": "Отменено",
|
"canceled": "Отменено",
|
||||||
|
"canceling": "Анулиране",
|
||||||
"cannot_merge_people": "Не може да обединява хора",
|
"cannot_merge_people": "Не може да обединява хора",
|
||||||
"cannot_undo_this_action": "Не можете да отмените това действие!",
|
"cannot_undo_this_action": "Не можете да отмените това действие!",
|
||||||
"cannot_update_the_description": "Описанието не може да бъде актуализирано",
|
"cannot_update_the_description": "Описанието не може да бъде актуализирано",
|
||||||
@@ -628,6 +658,8 @@
|
|||||||
"change_pin_code": "Смени PIN кода",
|
"change_pin_code": "Смени PIN кода",
|
||||||
"change_your_password": "Променете паролата си",
|
"change_your_password": "Променете паролата си",
|
||||||
"changed_visibility_successfully": "Видимостта е променена успешно",
|
"changed_visibility_successfully": "Видимостта е променена успешно",
|
||||||
|
"charging": "При зареждане",
|
||||||
|
"charging_requirement_mobile_backup": "Фоново архивиране само при зареждане на устройството",
|
||||||
"check_corrupt_asset_backup": "Провери за повредени архивни копия",
|
"check_corrupt_asset_backup": "Провери за повредени архивни копия",
|
||||||
"check_corrupt_asset_backup_button": "Провери",
|
"check_corrupt_asset_backup_button": "Провери",
|
||||||
"check_corrupt_asset_backup_description": "Изпълни тази проверка само при Wi-Fi и след архивиране на всички обекти. Процедурата може да продължи няколко минути.",
|
"check_corrupt_asset_backup_description": "Изпълни тази проверка само при Wi-Fi и след архивиране на всички обекти. Процедурата може да продължи няколко минути.",
|
||||||
@@ -637,6 +669,7 @@
|
|||||||
"clear": "Изчисти",
|
"clear": "Изчисти",
|
||||||
"clear_all": "Изчисти всичко",
|
"clear_all": "Изчисти всичко",
|
||||||
"clear_all_recent_searches": "Изчистете всички скорошни търсения",
|
"clear_all_recent_searches": "Изчистете всички скорошни търсения",
|
||||||
|
"clear_file_cache": "Изчистване на кеша на файловете",
|
||||||
"clear_message": "Изчисти съобщението",
|
"clear_message": "Изчисти съобщението",
|
||||||
"clear_value": "Изчисти стойността",
|
"clear_value": "Изчисти стойността",
|
||||||
"client_cert_dialog_msg_confirm": "ОК",
|
"client_cert_dialog_msg_confirm": "ОК",
|
||||||
@@ -707,11 +740,13 @@
|
|||||||
"create_new_user": "Създаване на нов потребител",
|
"create_new_user": "Създаване на нов потребител",
|
||||||
"create_shared_album_page_share_add_assets": "ДОБАВИ ОБЕКТИ",
|
"create_shared_album_page_share_add_assets": "ДОБАВИ ОБЕКТИ",
|
||||||
"create_shared_album_page_share_select_photos": "Избери снимки",
|
"create_shared_album_page_share_select_photos": "Избери снимки",
|
||||||
|
"create_shared_link": "Създай линк за споделяне",
|
||||||
"create_tag": "Създай таг",
|
"create_tag": "Създай таг",
|
||||||
"create_tag_description": "Създайте нов таг. За вложени тагове, моля, въведете пълния път на тага, включително наклонените черти.",
|
"create_tag_description": "Създайте нов таг. За вложени тагове, моля, въведете пълния път на тага, включително наклонените черти.",
|
||||||
"create_user": "Създай потребител",
|
"create_user": "Създай потребител",
|
||||||
"created": "Създадено",
|
"created": "Създадено",
|
||||||
"created_at": "Създаден",
|
"created_at": "Създаден",
|
||||||
|
"creating_linked_albums": "Създаване на свързани албуми...",
|
||||||
"crop": "Изрежи",
|
"crop": "Изрежи",
|
||||||
"curated_object_page_title": "Неща",
|
"curated_object_page_title": "Неща",
|
||||||
"current_device": "Текущо устройство",
|
"current_device": "Текущо устройство",
|
||||||
@@ -719,6 +754,7 @@
|
|||||||
"current_server_address": "Настоящ адрес на сървъра",
|
"current_server_address": "Настоящ адрес на сървъра",
|
||||||
"custom_locale": "Персонализиран локал",
|
"custom_locale": "Персонализиран локал",
|
||||||
"custom_locale_description": "Форматиране на дати и числа в зависимост от езика и региона",
|
"custom_locale_description": "Форматиране на дати и числа в зависимост от езика и региона",
|
||||||
|
"custom_url": "Персонализиран URL адрес",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
"daily_title_text_date": "E, dd MMM",
|
||||||
"daily_title_text_date_year": "E, dd MMM yyyy",
|
"daily_title_text_date_year": "E, dd MMM yyyy",
|
||||||
"dark": "Тъмен",
|
"dark": "Тъмен",
|
||||||
@@ -730,6 +766,7 @@
|
|||||||
"date_of_birth_saved": "Дата на раждане е записана успешно",
|
"date_of_birth_saved": "Дата на раждане е записана успешно",
|
||||||
"date_range": "Период от време",
|
"date_range": "Период от време",
|
||||||
"day": "Ден",
|
"day": "Ден",
|
||||||
|
"days": "Дни",
|
||||||
"deduplicate_all": "Дедупликиране на всички",
|
"deduplicate_all": "Дедупликиране на всички",
|
||||||
"deduplication_criteria_1": "Размер на снимката в байтове",
|
"deduplication_criteria_1": "Размер на снимката в байтове",
|
||||||
"deduplication_criteria_2": "Брой EXIF данни",
|
"deduplication_criteria_2": "Брой EXIF данни",
|
||||||
@@ -738,7 +775,8 @@
|
|||||||
"default_locale": "Локализация по подразбиране",
|
"default_locale": "Локализация по подразбиране",
|
||||||
"default_locale_description": "Форматиране на дати и числа в зависимост от езиковата настройка на браузъра",
|
"default_locale_description": "Форматиране на дати и числа в зависимост от езиковата настройка на браузъра",
|
||||||
"delete": "Изтрий",
|
"delete": "Изтрий",
|
||||||
"delete_action_prompt": "{count} са изтрити завинаги",
|
"delete_action_confirmation_message": "Сигурни ли сте, че искате да изтриете този обект? Следва преместване на обекта в коша за отпадъци на сървъра и ще получите предложение обекта да бъде изтрит локално",
|
||||||
|
"delete_action_prompt": "{count} са изтрити",
|
||||||
"delete_album": "Изтрий албум",
|
"delete_album": "Изтрий албум",
|
||||||
"delete_api_key_prompt": "Сигурни ли сте, че искате да изтриете този API ключ?",
|
"delete_api_key_prompt": "Сигурни ли сте, че искате да изтриете този API ключ?",
|
||||||
"delete_dialog_alert": "Тези обекти ще бъдат изтрити завинаги и от Immich сървъра и от устройството",
|
"delete_dialog_alert": "Тези обекти ще бъдат изтрити завинаги и от Immich сървъра и от устройството",
|
||||||
@@ -756,6 +794,8 @@
|
|||||||
"delete_local_dialog_ok_backed_up_only": "Изтрий локално само архивираните",
|
"delete_local_dialog_ok_backed_up_only": "Изтрий локално само архивираните",
|
||||||
"delete_local_dialog_ok_force": "Въпреки това изтрий",
|
"delete_local_dialog_ok_force": "Въпреки това изтрий",
|
||||||
"delete_others": "Изтрий останалите",
|
"delete_others": "Изтрий останалите",
|
||||||
|
"delete_permanently": "Изтрий за постоянно",
|
||||||
|
"delete_permanently_action_prompt": "{count} изтрити за постоянно",
|
||||||
"delete_shared_link": "Изтриване на споделен линк",
|
"delete_shared_link": "Изтриване на споделен линк",
|
||||||
"delete_shared_link_dialog_title": "Изтрий споделената връзка",
|
"delete_shared_link_dialog_title": "Изтрий споделената връзка",
|
||||||
"delete_tag": "Изтрий таг",
|
"delete_tag": "Изтрий таг",
|
||||||
@@ -766,6 +806,7 @@
|
|||||||
"description": "Описание",
|
"description": "Описание",
|
||||||
"description_input_hint_text": "Добави описание...",
|
"description_input_hint_text": "Добави описание...",
|
||||||
"description_input_submit_error": "Неуспешно обновяване на описанието. За подробности вижте в дневника",
|
"description_input_submit_error": "Неуспешно обновяване на описанието. За подробности вижте в дневника",
|
||||||
|
"deselect_all": "Премахни избора от всички",
|
||||||
"details": "Детайли",
|
"details": "Детайли",
|
||||||
"direction": "Посока",
|
"direction": "Посока",
|
||||||
"disabled": "Изключено",
|
"disabled": "Изключено",
|
||||||
@@ -810,8 +851,12 @@
|
|||||||
"edit": "Редактиране",
|
"edit": "Редактиране",
|
||||||
"edit_album": "Редактиране на албум",
|
"edit_album": "Редактиране на албум",
|
||||||
"edit_avatar": "Редактиране на аватар",
|
"edit_avatar": "Редактиране на аватар",
|
||||||
|
"edit_birthday": "Редактиране на рожден ден",
|
||||||
"edit_date": "Редактиране на дата",
|
"edit_date": "Редактиране на дата",
|
||||||
"edit_date_and_time": "Редактиране на дата и час",
|
"edit_date_and_time": "Редактиране на дата и час",
|
||||||
|
"edit_date_and_time_action_prompt": "{count} дата и време са редактирани",
|
||||||
|
"edit_date_and_time_by_offset": "Промяна на датата чрез отместване",
|
||||||
|
"edit_date_and_time_by_offset_interval": "Нов период от време: {from} - {to}",
|
||||||
"edit_description": "Редактирай описание",
|
"edit_description": "Редактирай описание",
|
||||||
"edit_description_prompt": "Моля, избери ново описание:",
|
"edit_description_prompt": "Моля, избери ново описание:",
|
||||||
"edit_exclusion_pattern": "Редактиране на шаблон за изключване",
|
"edit_exclusion_pattern": "Редактиране на шаблон за изключване",
|
||||||
@@ -840,6 +885,7 @@
|
|||||||
"empty_trash": "Изпразване на кош",
|
"empty_trash": "Изпразване на кош",
|
||||||
"empty_trash_confirmation": "Сигурни ли сте, че искате да изпразните кошчето? Това ще премахне всичко в кошчето за постоянно от Immich.\nНе можете да отмените това действие!",
|
"empty_trash_confirmation": "Сигурни ли сте, че искате да изпразните кошчето? Това ще премахне всичко в кошчето за постоянно от Immich.\nНе можете да отмените това действие!",
|
||||||
"enable": "Включване",
|
"enable": "Включване",
|
||||||
|
"enable_backup": "Включи резервното копиране",
|
||||||
"enable_biometric_auth_description": "Въведете вашия PIN код, за да разрешите биометрично удостоверяване",
|
"enable_biometric_auth_description": "Въведете вашия PIN код, за да разрешите биометрично удостоверяване",
|
||||||
"enabled": "Включено",
|
"enabled": "Включено",
|
||||||
"end_date": "Крайна дата",
|
"end_date": "Крайна дата",
|
||||||
@@ -850,7 +896,9 @@
|
|||||||
"error": "Грешка",
|
"error": "Грешка",
|
||||||
"error_change_sort_album": "Неуспешна промяна на реда на сортиране на албум",
|
"error_change_sort_album": "Неуспешна промяна на реда на сортиране на албум",
|
||||||
"error_delete_face": "Грешка при изтриване на лице от актива",
|
"error_delete_face": "Грешка при изтриване на лице от актива",
|
||||||
|
"error_getting_places": "Грешка при събиране на местата",
|
||||||
"error_loading_image": "Грешка при зареждане на изображението",
|
"error_loading_image": "Грешка при зареждане на изображението",
|
||||||
|
"error_loading_partners": "Грешка при зареждане на партньори: {error}",
|
||||||
"error_saving_image": "Грешка: {error}",
|
"error_saving_image": "Грешка: {error}",
|
||||||
"error_tag_face_bounding_box": "Грешка при отбелязване на лице - неуспешно получаване на координати на рамката",
|
"error_tag_face_bounding_box": "Грешка при отбелязване на лице - неуспешно получаване на координати на рамката",
|
||||||
"error_title": "Грешка - нещо се обърка",
|
"error_title": "Грешка - нещо се обърка",
|
||||||
@@ -874,7 +922,7 @@
|
|||||||
"error_selecting_all_assets": "Грешка при избора на всички файлове",
|
"error_selecting_all_assets": "Грешка при избора на всички файлове",
|
||||||
"exclusion_pattern_already_exists": "Този модел за изключване вече съществува.",
|
"exclusion_pattern_already_exists": "Този модел за изключване вече съществува.",
|
||||||
"failed_to_create_album": "Неуспешно създаване на албум",
|
"failed_to_create_album": "Неуспешно създаване на албум",
|
||||||
"failed_to_create_shared_link": "Неуспешно създаване на споделена връзка",
|
"failed_to_create_shared_link": "Неуспешно създаване на спoделена връзка",
|
||||||
"failed_to_edit_shared_link": "Неуспешно редактиране на споделена връзка",
|
"failed_to_edit_shared_link": "Неуспешно редактиране на споделена връзка",
|
||||||
"failed_to_get_people": "Неуспешно зареждане на хора",
|
"failed_to_get_people": "Неуспешно зареждане на хора",
|
||||||
"failed_to_keep_this_delete_others": "Неуспешно запазване на този обект и изтриване на останалите обекти",
|
"failed_to_keep_this_delete_others": "Неуспешно запазване на този обект и изтриване на останалите обекти",
|
||||||
@@ -883,6 +931,7 @@
|
|||||||
"failed_to_load_notifications": "Неуспешно зареждане на известия",
|
"failed_to_load_notifications": "Неуспешно зареждане на известия",
|
||||||
"failed_to_load_people": "Неуспешно зареждане на хора",
|
"failed_to_load_people": "Неуспешно зареждане на хора",
|
||||||
"failed_to_remove_product_key": "Неуспешно премахване на продуктовия ключ",
|
"failed_to_remove_product_key": "Неуспешно премахване на продуктовия ключ",
|
||||||
|
"failed_to_reset_pin_code": "Неуспешно нулиране на ПИН кода",
|
||||||
"failed_to_stack_assets": "Неуспешно подреждане на обекти",
|
"failed_to_stack_assets": "Неуспешно подреждане на обекти",
|
||||||
"failed_to_unstack_assets": "Неуспешно премахване на подредбата на обекти",
|
"failed_to_unstack_assets": "Неуспешно премахване на подредбата на обекти",
|
||||||
"failed_to_update_notification_status": "Неуспешно обновяване на състоянието на известията",
|
"failed_to_update_notification_status": "Неуспешно обновяване на състоянието на известията",
|
||||||
@@ -891,6 +940,7 @@
|
|||||||
"paths_validation_failed": "{paths, plural, one {# път} other {# пътища}} не преминаха валидация",
|
"paths_validation_failed": "{paths, plural, one {# път} other {# пътища}} не преминаха валидация",
|
||||||
"profile_picture_transparent_pixels": "Профилните снимки не могат да имат прозрачни пиксели. Моля, увеличете и/или преместете изображението.",
|
"profile_picture_transparent_pixels": "Профилните снимки не могат да имат прозрачни пиксели. Моля, увеличете и/или преместете изображението.",
|
||||||
"quota_higher_than_disk_size": "Зададена е квота, по-голяма от размера на диска",
|
"quota_higher_than_disk_size": "Зададена е квота, по-голяма от размера на диска",
|
||||||
|
"something_went_wrong": "Нещо се обърка",
|
||||||
"unable_to_add_album_users": "Неуспешно добавяне на потребители в албум",
|
"unable_to_add_album_users": "Неуспешно добавяне на потребители в албум",
|
||||||
"unable_to_add_assets_to_shared_link": "Неуспешно добавяне на обекти в споделен линк",
|
"unable_to_add_assets_to_shared_link": "Неуспешно добавяне на обекти в споделен линк",
|
||||||
"unable_to_add_comment": "Неуспешно добавяне на коментар",
|
"unable_to_add_comment": "Неуспешно добавяне на коментар",
|
||||||
@@ -976,13 +1026,11 @@
|
|||||||
},
|
},
|
||||||
"exif": "Exif",
|
"exif": "Exif",
|
||||||
"exif_bottom_sheet_description": "Добави Описание...",
|
"exif_bottom_sheet_description": "Добави Описание...",
|
||||||
|
"exif_bottom_sheet_description_error": "Неуспешно обновяване на описание",
|
||||||
"exif_bottom_sheet_details": "ПОДРОБНОСТИ",
|
"exif_bottom_sheet_details": "ПОДРОБНОСТИ",
|
||||||
"exif_bottom_sheet_location": "МЯСТО",
|
"exif_bottom_sheet_location": "МЯСТО",
|
||||||
"exif_bottom_sheet_people": "ХОРА",
|
"exif_bottom_sheet_people": "ХОРА",
|
||||||
"exif_bottom_sheet_person_add_person": "Добави име",
|
"exif_bottom_sheet_person_add_person": "Добави име",
|
||||||
"exif_bottom_sheet_person_age_months": "Възраст {months} месеца",
|
|
||||||
"exif_bottom_sheet_person_age_year_months": "Възраст 1 година и {months} месеца",
|
|
||||||
"exif_bottom_sheet_person_age_years": "Възраст {years}",
|
|
||||||
"exit_slideshow": "Изход от слайдшоуто",
|
"exit_slideshow": "Изход от слайдшоуто",
|
||||||
"expand_all": "Разшири всички",
|
"expand_all": "Разшири всички",
|
||||||
"experimental_settings_new_asset_list_subtitle": "В развитие",
|
"experimental_settings_new_asset_list_subtitle": "В развитие",
|
||||||
@@ -996,6 +1044,8 @@
|
|||||||
"explorer": "Преглед",
|
"explorer": "Преглед",
|
||||||
"export": "Експорт",
|
"export": "Експорт",
|
||||||
"export_as_json": "Експортиране като JSON",
|
"export_as_json": "Експортиране като JSON",
|
||||||
|
"export_database": "Експорт на базата данни",
|
||||||
|
"export_database_description": "Експорт на базата данни SQLite",
|
||||||
"extension": "Разширение",
|
"extension": "Разширение",
|
||||||
"external": "Външно",
|
"external": "Външно",
|
||||||
"external_libraries": "Външни библиотеки",
|
"external_libraries": "Външни библиотеки",
|
||||||
@@ -1013,6 +1063,7 @@
|
|||||||
"favorites_page_no_favorites": "Не са намерени любими обекти",
|
"favorites_page_no_favorites": "Не са намерени любими обекти",
|
||||||
"feature_photo_updated": "Представителната снимка е променена",
|
"feature_photo_updated": "Представителната снимка е променена",
|
||||||
"features": "Функции",
|
"features": "Функции",
|
||||||
|
"features_in_development": "Функции в процес на разработка",
|
||||||
"features_setting_description": "Управление на функциите на приложението",
|
"features_setting_description": "Управление на функциите на приложението",
|
||||||
"file_name": "Име на файла",
|
"file_name": "Име на файла",
|
||||||
"file_name_or_extension": "Име на файл или разширение",
|
"file_name_or_extension": "Име на файл или разширение",
|
||||||
@@ -1022,21 +1073,26 @@
|
|||||||
"filter_people": "Филтриране на хора",
|
"filter_people": "Филтриране на хора",
|
||||||
"filter_places": "Филтър по място",
|
"filter_places": "Филтър по място",
|
||||||
"find_them_fast": "Намерете ги бързо по име с търсене",
|
"find_them_fast": "Намерете ги бързо по име с търсене",
|
||||||
|
"first": "Първи",
|
||||||
"fix_incorrect_match": "Поправяне на неправилно съвпадение",
|
"fix_incorrect_match": "Поправяне на неправилно съвпадение",
|
||||||
"folder": "Папка",
|
"folder": "Папка",
|
||||||
"folder_not_found": "Папката не е намерена",
|
"folder_not_found": "Папката не е намерена",
|
||||||
"folders": "Папки",
|
"folders": "Папки",
|
||||||
"folders_feature_description": "Преглеждане на папката за снимките и видеоклиповете в файловата система",
|
"folders_feature_description": "Преглеждане на папката за снимките и видеоклиповете в файловата система",
|
||||||
|
"forgot_pin_code_question": "Забравили сте своя ПИН код?",
|
||||||
"forward": "Напред",
|
"forward": "Напред",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
||||||
"general": "Общи",
|
"general": "Общи",
|
||||||
|
"geolocation_instruction_location": "Изберете обект с GPS координати за да използвате тях или изберете място директно от картата",
|
||||||
"get_help": "Помощ",
|
"get_help": "Помощ",
|
||||||
"get_wifiname_error": "Неуспешно получаване името на Wi-Fi мрежата. Моля, убедете се, че са предоставени нужните разрешения на приложението и има връзка с Wi-Fi",
|
"get_wifiname_error": "Неуспешно получаване името на Wi-Fi мрежата. Моля, убедете се, че са предоставени нужните разрешения на приложението и има връзка с Wi-Fi",
|
||||||
"getting_started": "Как да започнем",
|
"getting_started": "Как да започнем",
|
||||||
"go_back": "Връщане назад",
|
"go_back": "Връщане назад",
|
||||||
"go_to_folder": "Отиди в папката",
|
"go_to_folder": "Отиди в папката",
|
||||||
"go_to_search": "Преминаване към търсене",
|
"go_to_search": "Преминаване към търсене",
|
||||||
|
"gps": "GPS координати",
|
||||||
|
"gps_missing": "Няма GPS координати",
|
||||||
"grant_permission": "Дай разрешение",
|
"grant_permission": "Дай разрешение",
|
||||||
"group_albums_by": "Групирай албум по...",
|
"group_albums_by": "Групирай албум по...",
|
||||||
"group_country": "Групирай по държава",
|
"group_country": "Групирай по държава",
|
||||||
@@ -1047,6 +1103,9 @@
|
|||||||
"haptic_feedback_switch": "Включи тактилна обратна връзка",
|
"haptic_feedback_switch": "Включи тактилна обратна връзка",
|
||||||
"haptic_feedback_title": "Тактилна обратна връзка",
|
"haptic_feedback_title": "Тактилна обратна връзка",
|
||||||
"has_quota": "Лимит",
|
"has_quota": "Лимит",
|
||||||
|
"hash_asset": "Обект с хеш",
|
||||||
|
"hashed_assets": "Хеширани обекти",
|
||||||
|
"hashing": "Хеширане",
|
||||||
"header_settings_add_header_tip": "Добави заглавие",
|
"header_settings_add_header_tip": "Добави заглавие",
|
||||||
"header_settings_field_validator_msg": "Недопустимо е да няма стойност",
|
"header_settings_field_validator_msg": "Недопустимо е да няма стойност",
|
||||||
"header_settings_header_name_input": "Име на заглавието",
|
"header_settings_header_name_input": "Име на заглавието",
|
||||||
@@ -1078,7 +1137,9 @@
|
|||||||
"home_page_upload_err_limit": "Може да качвате максимум 30 обекта едновременно, пропускане",
|
"home_page_upload_err_limit": "Може да качвате максимум 30 обекта едновременно, пропускане",
|
||||||
"host": "Хост",
|
"host": "Хост",
|
||||||
"hour": "Час",
|
"hour": "Час",
|
||||||
|
"hours": "Часа",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
"idle": "Бездействие",
|
||||||
"ignore_icloud_photos": "Пропусни снимки от iCloud",
|
"ignore_icloud_photos": "Пропусни снимки от iCloud",
|
||||||
"ignore_icloud_photos_description": "Снимки, които са запазени в iCloud няма да се качват в Immich сървъра",
|
"ignore_icloud_photos_description": "Снимки, които са запазени в iCloud няма да се качват в Immich сървъра",
|
||||||
"image": "Изображение",
|
"image": "Изображение",
|
||||||
@@ -1136,10 +1197,13 @@
|
|||||||
"language_no_results_title": "Не са намерени езици",
|
"language_no_results_title": "Не са намерени езици",
|
||||||
"language_search_hint": "Търсене на езици...",
|
"language_search_hint": "Търсене на езици...",
|
||||||
"language_setting_description": "Изберете предпочитан език",
|
"language_setting_description": "Изберете предпочитан език",
|
||||||
|
"large_files": "Големи файлове",
|
||||||
|
"last": "Последен",
|
||||||
"last_seen": "Последно видяно",
|
"last_seen": "Последно видяно",
|
||||||
"latest_version": "Последна версия",
|
"latest_version": "Последна версия",
|
||||||
"latitude": "Ширина",
|
"latitude": "Ширина",
|
||||||
"leave": "Излез",
|
"leave": "Излез",
|
||||||
|
"leave_album": "Напускане на албума",
|
||||||
"lens_model": "Модел леща",
|
"lens_model": "Модел леща",
|
||||||
"let_others_respond": "Позволете на другите да отговорят",
|
"let_others_respond": "Позволете на другите да отговорят",
|
||||||
"level": "Ниво",
|
"level": "Ниво",
|
||||||
@@ -1153,6 +1217,7 @@
|
|||||||
"library_page_sort_title": "Заглавие на албума",
|
"library_page_sort_title": "Заглавие на албума",
|
||||||
"licenses": "Лицензи",
|
"licenses": "Лицензи",
|
||||||
"light": "Светло",
|
"light": "Светло",
|
||||||
|
"like": "Харесайте",
|
||||||
"like_deleted": "Като изтрит",
|
"like_deleted": "Като изтрит",
|
||||||
"link_motion_video": "Линк към видео",
|
"link_motion_video": "Линк към видео",
|
||||||
"link_to_oauth": "Линк към OAuth",
|
"link_to_oauth": "Линк към OAuth",
|
||||||
@@ -1160,7 +1225,10 @@
|
|||||||
"list": "Лист",
|
"list": "Лист",
|
||||||
"loading": "Зареждане",
|
"loading": "Зареждане",
|
||||||
"loading_search_results_failed": "Зареждането на резултатите от търсенето е неуспешно",
|
"loading_search_results_failed": "Зареждането на резултатите от търсенето е неуспешно",
|
||||||
|
"local": "Локално",
|
||||||
"local_asset_cast_failed": "Не може да се предава обект, който още не е качен на сървъра",
|
"local_asset_cast_failed": "Не може да се предава обект, който още не е качен на сървъра",
|
||||||
|
"local_assets": "Локални обекти",
|
||||||
|
"local_media_summary": "Обобщение на локалните медийни файлове",
|
||||||
"local_network": "Локална мрежа",
|
"local_network": "Локална мрежа",
|
||||||
"local_network_sheet_info": "Приложението ще се свърже със сървъра на този URL, когато устройството е свързано към зададената Wi-Fi мрежа",
|
"local_network_sheet_info": "Приложението ще се свърже със сървъра на този URL, когато устройството е свързано към зададената Wi-Fi мрежа",
|
||||||
"location_permission": "Разрешение за местоположение",
|
"location_permission": "Разрешение за местоположение",
|
||||||
@@ -1172,6 +1240,7 @@
|
|||||||
"location_picker_longitude_hint": "Въведете географска дължина тук",
|
"location_picker_longitude_hint": "Въведете географска дължина тук",
|
||||||
"lock": "Заключи",
|
"lock": "Заключи",
|
||||||
"locked_folder": "Заключена папка",
|
"locked_folder": "Заключена папка",
|
||||||
|
"log_detail_title": "Подробности от дневника",
|
||||||
"log_out": "Излизане",
|
"log_out": "Излизане",
|
||||||
"log_out_all_devices": "Излизане с всички устройства",
|
"log_out_all_devices": "Излизане с всички устройства",
|
||||||
"logged_in_as": "Вписан като {user}",
|
"logged_in_as": "Вписан като {user}",
|
||||||
@@ -1202,6 +1271,7 @@
|
|||||||
"login_password_changed_success": "Успешно обновена парола",
|
"login_password_changed_success": "Успешно обновена парола",
|
||||||
"logout_all_device_confirmation": "Сигурни ли сте, че искате да излезете от всички устройства?",
|
"logout_all_device_confirmation": "Сигурни ли сте, че искате да излезете от всички устройства?",
|
||||||
"logout_this_device_confirmation": "Сигурни ли сте, че искате да излезете от това устройство?",
|
"logout_this_device_confirmation": "Сигурни ли сте, че искате да излезете от това устройство?",
|
||||||
|
"logs": "Дневник",
|
||||||
"longitude": "Дължина",
|
"longitude": "Дължина",
|
||||||
"look": "Изглед",
|
"look": "Изглед",
|
||||||
"loop_videos": "Повтаряне на видеата",
|
"loop_videos": "Повтаряне на видеата",
|
||||||
@@ -1209,6 +1279,7 @@
|
|||||||
"main_branch_warning": "Използвате версия за разработчици, силно препоръчваме да използвате официална версия!",
|
"main_branch_warning": "Използвате версия за разработчици, силно препоръчваме да използвате официална версия!",
|
||||||
"main_menu": "Главно меню",
|
"main_menu": "Главно меню",
|
||||||
"make": "Марка",
|
"make": "Марка",
|
||||||
|
"manage_geolocation": "Управление на местоположенията",
|
||||||
"manage_shared_links": "Управление на споделени връзки",
|
"manage_shared_links": "Управление на споделени връзки",
|
||||||
"manage_sharing_with_partners": "Управление на споделянето с партньори",
|
"manage_sharing_with_partners": "Управление на споделянето с партньори",
|
||||||
"manage_the_app_settings": "Управление на настройките на приложението",
|
"manage_the_app_settings": "Управление на настройките на приложението",
|
||||||
@@ -1217,7 +1288,7 @@
|
|||||||
"manage_your_devices": "Управление на влезлите в системата устройства",
|
"manage_your_devices": "Управление на влезлите в системата устройства",
|
||||||
"manage_your_oauth_connection": "Управление на OAuth връзката",
|
"manage_your_oauth_connection": "Управление на OAuth връзката",
|
||||||
"map": "Карта",
|
"map": "Карта",
|
||||||
"map_assets_in_bounds": "{count} снимки",
|
"map_assets_in_bounds": "{count, plural, =0 {Няма снимки} one {# снимка} other {# снимки}}",
|
||||||
"map_cannot_get_user_location": "Не можах да получа местоположението",
|
"map_cannot_get_user_location": "Не можах да получа местоположението",
|
||||||
"map_location_dialog_yes": "Да",
|
"map_location_dialog_yes": "Да",
|
||||||
"map_location_picker_page_use_location": "Използвай това местоположение",
|
"map_location_picker_page_use_location": "Използвай това местоположение",
|
||||||
@@ -1225,7 +1296,6 @@
|
|||||||
"map_location_service_disabled_title": "Услугата за местоположение е изключена",
|
"map_location_service_disabled_title": "Услугата за местоположение е изключена",
|
||||||
"map_marker_for_images": "Маркери на картата за снимки направени в {city}, {country}",
|
"map_marker_for_images": "Маркери на картата за снимки направени в {city}, {country}",
|
||||||
"map_marker_with_image": "Маркер на картата с изображение",
|
"map_marker_with_image": "Маркер на картата с изображение",
|
||||||
"map_no_assets_in_bounds": "Няма снимки от този район",
|
|
||||||
"map_no_location_permission_content": "За да се показват обектите от текущото място, трябва разрешение за определяне на местоположението. Искате ли да предоставите разрешение сега?",
|
"map_no_location_permission_content": "За да се показват обектите от текущото място, трябва разрешение за определяне на местоположението. Искате ли да предоставите разрешение сега?",
|
||||||
"map_no_location_permission_title": "Отказан достъп до местоположение",
|
"map_no_location_permission_title": "Отказан достъп до местоположение",
|
||||||
"map_settings": "Настройки на картата",
|
"map_settings": "Настройки на картата",
|
||||||
@@ -1244,6 +1314,7 @@
|
|||||||
"mark_as_read": "Маркирай като четено",
|
"mark_as_read": "Маркирай като четено",
|
||||||
"marked_all_as_read": "Всички маркирани като прочетени",
|
"marked_all_as_read": "Всички маркирани като прочетени",
|
||||||
"matches": "Съвпадения",
|
"matches": "Съвпадения",
|
||||||
|
"matching_assets": "Съвпадащи обекти",
|
||||||
"media_type": "Вид медия",
|
"media_type": "Вид медия",
|
||||||
"memories": "Спомени",
|
"memories": "Спомени",
|
||||||
"memories_all_caught_up": "Това е всичко за днес",
|
"memories_all_caught_up": "Това е всичко за днес",
|
||||||
@@ -1262,6 +1333,7 @@
|
|||||||
"merged_people_count": "Слят {count, plural, one {# човек} other {# човека}}",
|
"merged_people_count": "Слят {count, plural, one {# човек} other {# човека}}",
|
||||||
"minimize": "Минимизиране",
|
"minimize": "Минимизиране",
|
||||||
"minute": "Минута",
|
"minute": "Минута",
|
||||||
|
"minutes": "Минути",
|
||||||
"missing": "Липсващи",
|
"missing": "Липсващи",
|
||||||
"model": "Модел",
|
"model": "Модел",
|
||||||
"month": "Месец",
|
"month": "Месец",
|
||||||
@@ -1281,6 +1353,10 @@
|
|||||||
"my_albums": "Мои албуми",
|
"my_albums": "Мои албуми",
|
||||||
"name": "Име",
|
"name": "Име",
|
||||||
"name_or_nickname": "Име или прякор",
|
"name_or_nickname": "Име или прякор",
|
||||||
|
"network_requirement_photos_upload": "Използвай мобилни данни за архивиране на снимки",
|
||||||
|
"network_requirement_videos_upload": "Използвай мобилни данни за архивиране на видео",
|
||||||
|
"network_requirements": "Изисквания към мрежата",
|
||||||
|
"network_requirements_updated": "Мрежовите настройки са променени, нулиране на опашката за архивиране",
|
||||||
"networking_settings": "Мрежа",
|
"networking_settings": "Мрежа",
|
||||||
"networking_subtitle": "Управление на настройките за връзка със сървъра",
|
"networking_subtitle": "Управление на настройките за връзка със сървъра",
|
||||||
"never": "Никога",
|
"never": "Никога",
|
||||||
@@ -1290,6 +1366,7 @@
|
|||||||
"new_person": "Нов човек",
|
"new_person": "Нов човек",
|
||||||
"new_pin_code": "Нов PIN код",
|
"new_pin_code": "Нов PIN код",
|
||||||
"new_pin_code_subtitle": "Това е първи достъп до заключена папка. Създайте PIN код за защитен достъп до тази страница",
|
"new_pin_code_subtitle": "Това е първи достъп до заключена папка. Създайте PIN код за защитен достъп до тази страница",
|
||||||
|
"new_timeline": "Нова времева линия",
|
||||||
"new_user_created": "Създаден нов потребител",
|
"new_user_created": "Създаден нов потребител",
|
||||||
"new_version_available": "НАЛИЧНА НОВА ВЕРСИЯ",
|
"new_version_available": "НАЛИЧНА НОВА ВЕРСИЯ",
|
||||||
"newest_first": "Най-новите първи",
|
"newest_first": "Най-новите първи",
|
||||||
@@ -1303,19 +1380,25 @@
|
|||||||
"no_assets_message": "КЛИКНЕТЕ, ЗА ДА КАЧИТЕ ПЪРВАТА СИ СНИМКА",
|
"no_assets_message": "КЛИКНЕТЕ, ЗА ДА КАЧИТЕ ПЪРВАТА СИ СНИМКА",
|
||||||
"no_assets_to_show": "Няма обекти за показване",
|
"no_assets_to_show": "Няма обекти за показване",
|
||||||
"no_cast_devices_found": "Няма намерени устройства за предаване",
|
"no_cast_devices_found": "Няма намерени устройства за предаване",
|
||||||
|
"no_checksum_local": "Липсват контролни суми - не може да се получат локални обекти",
|
||||||
|
"no_checksum_remote": "Липсват контролни суми - не може да се получат обекти от сървъра",
|
||||||
"no_duplicates_found": "Не бяха открити дубликати.",
|
"no_duplicates_found": "Не бяха открити дубликати.",
|
||||||
"no_exif_info_available": "Няма exif информация",
|
"no_exif_info_available": "Няма exif информация",
|
||||||
"no_explore_results_message": "Качете още снимки, за да разгледате колекцията си.",
|
"no_explore_results_message": "Качете още снимки, за да разгледате колекцията си.",
|
||||||
"no_favorites_message": "Добавете в любими, за да намирате бързо най-добрите си снимки и видеоклипове",
|
"no_favorites_message": "Добавете в любими, за да намирате бързо най-добрите си снимки и видеоклипове",
|
||||||
"no_libraries_message": "Създайте външна библиотека за да разглеждате снимки и видеоклипове",
|
"no_libraries_message": "Създайте външна библиотека за да разглеждате снимки и видеоклипове",
|
||||||
|
"no_local_assets_found": "Не е намерен локален обект с такава контролна сума",
|
||||||
"no_locked_photos_message": "Снимките и видеата в заключената папка са скрити и не се показват при разглеждане на библиотеката.",
|
"no_locked_photos_message": "Снимките и видеата в заключената папка са скрити и не се показват при разглеждане на библиотеката.",
|
||||||
"no_name": "Без име",
|
"no_name": "Без име",
|
||||||
"no_notifications": "Няма известия",
|
"no_notifications": "Няма известия",
|
||||||
"no_people_found": "Не са намерени съответстващи хора",
|
"no_people_found": "Не са намерени съответстващи хора",
|
||||||
"no_places": "Няма места",
|
"no_places": "Няма места",
|
||||||
|
"no_remote_assets_found": "Не е намерен обект на сървъра с такава контролна сума",
|
||||||
"no_results": "Няма резултати",
|
"no_results": "Няма резултати",
|
||||||
"no_results_description": "Опитайте със синоним или по-обща ключова дума",
|
"no_results_description": "Опитайте със синоним или по-обща ключова дума",
|
||||||
"no_shared_albums_message": "Създайте албум, за да споделяте снимки и видеоклипове с хората в мрежата си",
|
"no_shared_albums_message": "Създайте албум, за да споделяте снимки и видеоклипове с хората в мрежата си",
|
||||||
|
"no_uploads_in_progress": "Няма качване в момента",
|
||||||
|
"not_available": "Неналично",
|
||||||
"not_in_any_album": "Не е в никой албум",
|
"not_in_any_album": "Не е в никой албум",
|
||||||
"not_selected": "Не е избрано",
|
"not_selected": "Не е избрано",
|
||||||
"note_apply_storage_label_to_previously_uploaded assets": "Забележка: За да приложите етикета за съхранение към предварително качени активи, стартирайте",
|
"note_apply_storage_label_to_previously_uploaded assets": "Забележка: За да приложите етикета за съхранение към предварително качени активи, стартирайте",
|
||||||
@@ -1331,6 +1414,7 @@
|
|||||||
"oauth": "OAuth",
|
"oauth": "OAuth",
|
||||||
"official_immich_resources": "Официална информация за Immich",
|
"official_immich_resources": "Официална информация за Immich",
|
||||||
"offline": "Офлайн",
|
"offline": "Офлайн",
|
||||||
|
"offset": "Отместване",
|
||||||
"ok": "Добре",
|
"ok": "Добре",
|
||||||
"oldest_first": "Най-старите първи",
|
"oldest_first": "Най-старите първи",
|
||||||
"on_this_device": "На това устройство",
|
"on_this_device": "На това устройство",
|
||||||
@@ -1349,10 +1433,13 @@
|
|||||||
"open_the_search_filters": "Отвари филтрите за търсене",
|
"open_the_search_filters": "Отвари филтрите за търсене",
|
||||||
"options": "Настройки",
|
"options": "Настройки",
|
||||||
"or": "или",
|
"or": "или",
|
||||||
|
"organize_into_albums": "Organitzar per àlbums",
|
||||||
|
"organize_into_albums_description": "Posar les fotos existents dins dels àlbums fent servir la configuració de sincronització",
|
||||||
"organize_your_library": "Организиране на вашата библиотека",
|
"organize_your_library": "Организиране на вашата библиотека",
|
||||||
"original": "оригинал",
|
"original": "оригинал",
|
||||||
"other": "Други",
|
"other": "Други",
|
||||||
"other_devices": "Други устройства",
|
"other_devices": "Други устройства",
|
||||||
|
"other_entities": "Други обекти",
|
||||||
"other_variables": "Други променливи",
|
"other_variables": "Други променливи",
|
||||||
"owned": "Моите",
|
"owned": "Моите",
|
||||||
"owner": "Собственик",
|
"owner": "Собственик",
|
||||||
@@ -1407,6 +1494,9 @@
|
|||||||
"permission_onboarding_permission_limited": "Ограничен достъп. За да може Immich да архивира и управлява галерията, предоставете достъп до снимки и видео в настройките.",
|
"permission_onboarding_permission_limited": "Ограничен достъп. За да може Immich да архивира и управлява галерията, предоставете достъп до снимки и видео в настройките.",
|
||||||
"permission_onboarding_request": "Immich се нуждае от разрешение за преглед на снимки и видео.",
|
"permission_onboarding_request": "Immich се нуждае от разрешение за преглед на снимки и видео.",
|
||||||
"person": "Човек",
|
"person": "Човек",
|
||||||
|
"person_age_months": "{months, plural, one {# месец} other {# месеца}}",
|
||||||
|
"person_age_year_months": "1 година и {months, plural, one {# месец} other {# месеца}}",
|
||||||
|
"person_age_years": "{years, plural, other {# години}}",
|
||||||
"person_birthdate": "Дата на раждане {date}",
|
"person_birthdate": "Дата на раждане {date}",
|
||||||
"person_hidden": "{name}{hidden, select, true { (скрит)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (скрит)} other {}}",
|
||||||
"photo_shared_all_users": "Изглежда, че сте споделили снимките си с всички потребители или нямате потребители, с които да споделяте.",
|
"photo_shared_all_users": "Изглежда, че сте споделили снимките си с всички потребители или нямате потребители, с които да споделяте.",
|
||||||
@@ -1446,6 +1536,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "Мобилното приложение е остаряло. Моля, актуализирай до най-новата версия.",
|
"profile_drawer_client_out_of_date_minor": "Мобилното приложение е остаряло. Моля, актуализирай до най-новата версия.",
|
||||||
"profile_drawer_client_server_up_to_date": "Клиента и сървъра са обновени",
|
"profile_drawer_client_server_up_to_date": "Клиента и сървъра са обновени",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Режима само за четене е активиран. С дълго натискане върху картиката-аватар на потребителя ще деактивирате само за четене.",
|
||||||
"profile_drawer_server_out_of_date_major": "Версията на сървъра е остаряла. Моля, актуализирай поне до последната главна версия.",
|
"profile_drawer_server_out_of_date_major": "Версията на сървъра е остаряла. Моля, актуализирай поне до последната главна версия.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Версията на сървъра е остаряла. Моля, актуализирай до последната версия.",
|
"profile_drawer_server_out_of_date_minor": "Версията на сървъра е остаряла. Моля, актуализирай до последната версия.",
|
||||||
"profile_image_of_user": "Профилна снимка на {user}",
|
"profile_image_of_user": "Профилна снимка на {user}",
|
||||||
@@ -1484,12 +1575,16 @@
|
|||||||
"purchase_server_description_2": "Статус на поддръжник",
|
"purchase_server_description_2": "Статус на поддръжник",
|
||||||
"purchase_server_title": "Сървър",
|
"purchase_server_title": "Сървър",
|
||||||
"purchase_settings_server_activated": "Продуктовият ключ на сървъра се управлява от администратора",
|
"purchase_settings_server_activated": "Продуктовият ключ на сървъра се управлява от администратора",
|
||||||
|
"query_asset_id": "Buscar item per ID",
|
||||||
|
"queue_status": "В опашка {count} от {total}",
|
||||||
"rating": "Оценка със звезди",
|
"rating": "Оценка със звезди",
|
||||||
"rating_clear": "Изчисти оценката",
|
"rating_clear": "Изчисти оценката",
|
||||||
"rating_count": "{count, plural, one {# звезда} other {# звезди}}",
|
"rating_count": "{count, plural, one {# звезда} other {# звезди}}",
|
||||||
"rating_description": "Покажи EXIF оценката в панела с информация",
|
"rating_description": "Покажи EXIF оценката в панела с информация",
|
||||||
"reaction_options": "Избор на реакция",
|
"reaction_options": "Избор на реакция",
|
||||||
"read_changelog": "Прочети промените",
|
"read_changelog": "Прочети промените",
|
||||||
|
"readonly_mode_disabled": "Режима само за четене е деактивиран",
|
||||||
|
"readonly_mode_enabled": "Режима само за четене е активиран",
|
||||||
"reassign": "Преназначаване",
|
"reassign": "Преназначаване",
|
||||||
"reassigned_assets_to_existing_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на {name, select, null {съществуващ човек} other {{name}}}",
|
"reassigned_assets_to_existing_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на {name, select, null {съществуващ човек} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на нов човек",
|
"reassigned_assets_to_new_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на нов човек",
|
||||||
@@ -1512,6 +1607,9 @@
|
|||||||
"refreshing_faces": "Опресняване на лицата",
|
"refreshing_faces": "Опресняване на лицата",
|
||||||
"refreshing_metadata": "Опресняване на метаданните",
|
"refreshing_metadata": "Опресняване на метаданните",
|
||||||
"regenerating_thumbnails": "Пресъздаване на миниатюрите",
|
"regenerating_thumbnails": "Пресъздаване на миниатюрите",
|
||||||
|
"remote": "На сървъра",
|
||||||
|
"remote_assets": "Обекти на сървъра",
|
||||||
|
"remote_media_summary": "Обобщение на медийните файлове на сървъра",
|
||||||
"remove": "Премахни",
|
"remove": "Премахни",
|
||||||
"remove_assets_album_confirmation": "Сигурни ли сте, че искате да премахнете {count, plural, one {# елемент} other {# елемента}} от албума?",
|
"remove_assets_album_confirmation": "Сигурни ли сте, че искате да премахнете {count, plural, one {# елемент} other {# елемента}} от албума?",
|
||||||
"remove_assets_shared_link_confirmation": "Сигурни ли сте, че искате да премахнете {count, plural, one {# елемент} other {# елемента}} от този споеделен линк?",
|
"remove_assets_shared_link_confirmation": "Сигурни ли сте, че искате да премахнете {count, plural, one {# елемент} other {# елемента}} от този споеделен линк?",
|
||||||
@@ -1549,19 +1647,29 @@
|
|||||||
"reset_password": "Нулиране на паролата",
|
"reset_password": "Нулиране на паролата",
|
||||||
"reset_people_visibility": "Нулиране на видимостта на хората",
|
"reset_people_visibility": "Нулиране на видимостта на хората",
|
||||||
"reset_pin_code": "Нулирай PIN кода",
|
"reset_pin_code": "Нулирай PIN кода",
|
||||||
|
"reset_pin_code_description": "Ако сте си забравили ПИН кода, може да се обърнете към администратора на сървъра за да го нулира",
|
||||||
|
"reset_pin_code_success": "Успешно нулиран ПИН код",
|
||||||
|
"reset_pin_code_with_password": "С вашата парола можете винаги да нулирате своя ПИН код",
|
||||||
|
"reset_sqlite": "Нулиране на базата данни SQLite",
|
||||||
|
"reset_sqlite_confirmation": "Наистина ли искате да нулирате базата данни SQLite? Ще трябва да излезете от системата и да се впишете отново за нова синхронизация на данните",
|
||||||
|
"reset_sqlite_success": "Успешно нулиране на базата данни SQLite",
|
||||||
"reset_to_default": "Връщане на фабрични настройки",
|
"reset_to_default": "Връщане на фабрични настройки",
|
||||||
"resolve_duplicates": "Реши дубликатите",
|
"resolve_duplicates": "Реши дубликатите",
|
||||||
"resolved_all_duplicates": "Всички дубликати са решени",
|
"resolved_all_duplicates": "Всички дубликати са решени",
|
||||||
"restore": "Възстановяване",
|
"restore": "Възстановяване",
|
||||||
"restore_all": "Възстанови всички",
|
"restore_all": "Възстанови всички",
|
||||||
|
"restore_trash_action_prompt": "{count} възстановени от коша",
|
||||||
"restore_user": "Възстанови потребител",
|
"restore_user": "Възстанови потребител",
|
||||||
"restored_asset": "Възстановен елемент",
|
"restored_asset": "Възстановен елемент",
|
||||||
"resume": "Продължаване",
|
"resume": "Продължаване",
|
||||||
|
"resume_paused_jobs": "Продължи изпълнението на {count, plural, one {# задача} other {# задачи}}",
|
||||||
"retry_upload": "Опитай качването отново",
|
"retry_upload": "Опитай качването отново",
|
||||||
"review_duplicates": "Разгледай дубликатите",
|
"review_duplicates": "Разгледай дубликатите",
|
||||||
|
"review_large_files": "Преглед на големи файлове",
|
||||||
"role": "Роля",
|
"role": "Роля",
|
||||||
"role_editor": "Редактор",
|
"role_editor": "Редактор",
|
||||||
"role_viewer": "Зрител",
|
"role_viewer": "Зрител",
|
||||||
|
"running": "Изпълняване",
|
||||||
"save": "Запази",
|
"save": "Запази",
|
||||||
"save_to_gallery": "Запази в галерията",
|
"save_to_gallery": "Запази в галерията",
|
||||||
"saved_api_key": "Запазен API Key",
|
"saved_api_key": "Запазен API Key",
|
||||||
@@ -1648,6 +1756,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Създаването на албум не бе успешно",
|
"select_user_for_sharing_page_err_album": "Създаването на албум не бе успешно",
|
||||||
"selected": "Избрано",
|
"selected": "Избрано",
|
||||||
"selected_count": "{count, plural, other {# избрани}}",
|
"selected_count": "{count, plural, other {# избрани}}",
|
||||||
|
"selected_gps_coordinates": "Избрани GPS координати",
|
||||||
"send_message": "Изпратете съобщение",
|
"send_message": "Изпратете съобщение",
|
||||||
"send_welcome_email": "Изпратете имейл за добре дошли",
|
"send_welcome_email": "Изпратете имейл за добре дошли",
|
||||||
"server_endpoint": "Адрес на сървъра",
|
"server_endpoint": "Адрес на сървъра",
|
||||||
@@ -1715,6 +1824,7 @@
|
|||||||
"shared_link_clipboard_copied_massage": "Копирано в клипборда",
|
"shared_link_clipboard_copied_massage": "Копирано в клипборда",
|
||||||
"shared_link_clipboard_text": "Връзка: {link}\nПарола: {password}",
|
"shared_link_clipboard_text": "Връзка: {link}\nПарола: {password}",
|
||||||
"shared_link_create_error": "Грешка при създаване на споделена връзка",
|
"shared_link_create_error": "Грешка при създаване на споделена връзка",
|
||||||
|
"shared_link_custom_url_description": "Достъпете споделения линк с персонализиран URL адрес",
|
||||||
"shared_link_edit_description_hint": "Въведи описание на споделеното",
|
"shared_link_edit_description_hint": "Въведи описание на споделеното",
|
||||||
"shared_link_edit_expire_after_option_day": "1 ден",
|
"shared_link_edit_expire_after_option_day": "1 ден",
|
||||||
"shared_link_edit_expire_after_option_days": "{count} дни",
|
"shared_link_edit_expire_after_option_days": "{count} дни",
|
||||||
@@ -1740,6 +1850,7 @@
|
|||||||
"shared_link_info_chip_metadata": "EXIF",
|
"shared_link_info_chip_metadata": "EXIF",
|
||||||
"shared_link_manage_links": "Управление на споделените връзки",
|
"shared_link_manage_links": "Управление на споделените връзки",
|
||||||
"shared_link_options": "Опции за споделена връзка",
|
"shared_link_options": "Опции за споделена връзка",
|
||||||
|
"shared_link_password_description": "Изискване на парола за достъп до споделения линк",
|
||||||
"shared_links": "Споделени връзки",
|
"shared_links": "Споделени връзки",
|
||||||
"shared_links_description": "Сподели снимки и видеа с линк",
|
"shared_links_description": "Сподели снимки и видеа с линк",
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# споделени снимки и видеа.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# споделени снимки и видеа.}}",
|
||||||
@@ -1774,6 +1885,7 @@
|
|||||||
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
"show_slideshow_transition": "Покажи прехода на слайдшоуто",
|
||||||
"show_supporter_badge": "Значка поддръжник",
|
"show_supporter_badge": "Значка поддръжник",
|
||||||
"show_supporter_badge_description": "Покажи значка поддръжник",
|
"show_supporter_badge_description": "Покажи значка поддръжник",
|
||||||
|
"show_text_search_menu": "Покажи менюто за търсене на текст",
|
||||||
"shuffle": "Разбъркване",
|
"shuffle": "Разбъркване",
|
||||||
"sidebar": "Странична лента",
|
"sidebar": "Странична лента",
|
||||||
"sidebar_display_description": "Показване на връзка към изгледа в страничната лента",
|
"sidebar_display_description": "Показване на връзка към изгледа в страничната лента",
|
||||||
@@ -1789,6 +1901,7 @@
|
|||||||
"sort_created": "Дата на създаване",
|
"sort_created": "Дата на създаване",
|
||||||
"sort_items": "Брой елементи",
|
"sort_items": "Брой елементи",
|
||||||
"sort_modified": "Дата на промяна",
|
"sort_modified": "Дата на промяна",
|
||||||
|
"sort_newest": "Най-нови снимки",
|
||||||
"sort_oldest": "Най-старата снимка",
|
"sort_oldest": "Най-старата снимка",
|
||||||
"sort_people_by_similarity": "Сортиране на хора по прилика",
|
"sort_people_by_similarity": "Сортиране на хора по прилика",
|
||||||
"sort_recent": "Най-новата снимка",
|
"sort_recent": "Най-новата снимка",
|
||||||
@@ -1815,6 +1928,7 @@
|
|||||||
"storage_quota": "Квота на хранилището",
|
"storage_quota": "Квота на хранилището",
|
||||||
"storage_usage": "Използвани {used} от {available}",
|
"storage_usage": "Използвани {used} от {available}",
|
||||||
"submit": "Изпращане",
|
"submit": "Изпращане",
|
||||||
|
"success": "Успешно",
|
||||||
"suggestions": "Предложения",
|
"suggestions": "Предложения",
|
||||||
"sunrise_on_the_beach": "Изгрев на плажа",
|
"sunrise_on_the_beach": "Изгрев на плажа",
|
||||||
"support": "Поддръжка",
|
"support": "Поддръжка",
|
||||||
@@ -1824,6 +1938,10 @@
|
|||||||
"sync": "Синхронизиране",
|
"sync": "Синхронизиране",
|
||||||
"sync_albums": "Синхронизиране на албуми",
|
"sync_albums": "Синхронизиране на албуми",
|
||||||
"sync_albums_manual_subtitle": "Синхронизирай всички заредени видеа и снимки в избраните архивни албуми",
|
"sync_albums_manual_subtitle": "Синхронизирай всички заредени видеа и снимки в избраните архивни албуми",
|
||||||
|
"sync_local": "Локална синхронизация",
|
||||||
|
"sync_remote": "Синхронизация със сървъра",
|
||||||
|
"sync_status": "Състояние на синхронизацията",
|
||||||
|
"sync_status_subtitle": "Преглед и управление на системата за синхронизация",
|
||||||
"sync_upload_album_setting_subtitle": "Създавайте и зареждайте снимки и видеа в избрани албуми в Immich",
|
"sync_upload_album_setting_subtitle": "Създавайте и зареждайте снимки и видеа в избрани албуми в Immich",
|
||||||
"tag": "Таг",
|
"tag": "Таг",
|
||||||
"tag_assets": "Тагни елементи",
|
"tag_assets": "Тагни елементи",
|
||||||
@@ -1834,6 +1952,7 @@
|
|||||||
"tag_updated": "Актуализиран етикет: {tag}",
|
"tag_updated": "Актуализиран етикет: {tag}",
|
||||||
"tagged_assets": "Тагнати {count, plural, one {# елемент} other {# елементи}}",
|
"tagged_assets": "Тагнати {count, plural, one {# елемент} other {# елементи}}",
|
||||||
"tags": "Етикет",
|
"tags": "Етикет",
|
||||||
|
"tap_to_run_job": "Докоснете, за да стартирате задачата",
|
||||||
"template": "Шаблон",
|
"template": "Шаблон",
|
||||||
"theme": "Тема",
|
"theme": "Тема",
|
||||||
"theme_selection": "Избор на тема",
|
"theme_selection": "Избор на тема",
|
||||||
@@ -1860,7 +1979,9 @@
|
|||||||
"to_change_password": "Промяна на паролата",
|
"to_change_password": "Промяна на паролата",
|
||||||
"to_favorite": "Любим",
|
"to_favorite": "Любим",
|
||||||
"to_login": "Вписване",
|
"to_login": "Вписване",
|
||||||
|
"to_multi_select": "за избор на няколко",
|
||||||
"to_parent": "Отиди към родителския елемент",
|
"to_parent": "Отиди към родителския елемент",
|
||||||
|
"to_select": "за избор",
|
||||||
"to_trash": "Кошче",
|
"to_trash": "Кошче",
|
||||||
"toggle_settings": "Превключване на настройките",
|
"toggle_settings": "Превключване на настройките",
|
||||||
"total": "Общо",
|
"total": "Общо",
|
||||||
@@ -1880,6 +2001,7 @@
|
|||||||
"trash_page_select_assets_btn": "Избери обекти",
|
"trash_page_select_assets_btn": "Избери обекти",
|
||||||
"trash_page_title": "В коша ({count})",
|
"trash_page_title": "В коша ({count})",
|
||||||
"trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# ден} other {# дни}}.",
|
"trashed_items_will_be_permanently_deleted_after": "Изхвърлените в кошчето елементи ще бъдат изтрити за постоянно след {days, plural, one {# ден} other {# дни}}.",
|
||||||
|
"troubleshoot": "Отстраняване на проблеми",
|
||||||
"type": "Тип",
|
"type": "Тип",
|
||||||
"unable_to_change_pin_code": "Невъзможна промяна на PIN кода",
|
"unable_to_change_pin_code": "Невъзможна промяна на PIN кода",
|
||||||
"unable_to_setup_pin_code": "Неуспешно задаване на PIN кода",
|
"unable_to_setup_pin_code": "Неуспешно задаване на PIN кода",
|
||||||
@@ -1910,13 +2032,17 @@
|
|||||||
"unstacked_assets_count": "Разкачени {count, plural, one {# елемент} other {# елементи}}",
|
"unstacked_assets_count": "Разкачени {count, plural, one {# елемент} other {# елементи}}",
|
||||||
"untagged": "Немаркирани",
|
"untagged": "Немаркирани",
|
||||||
"up_next": "Следващ",
|
"up_next": "Следващ",
|
||||||
|
"update_location_action_prompt": "Обнови координатите на {count} избрани обекта с:",
|
||||||
"updated_at": "Обновено",
|
"updated_at": "Обновено",
|
||||||
"updated_password": "Паролата е актуализирана",
|
"updated_password": "Паролата е актуализирана",
|
||||||
"upload": "Качване",
|
"upload": "Качване",
|
||||||
|
"upload_action_prompt": "{count} на опашка за качване",
|
||||||
"upload_concurrency": "Успоредни качвания",
|
"upload_concurrency": "Успоредни качвания",
|
||||||
|
"upload_details": "Детайли за качването",
|
||||||
"upload_dialog_info": "Искате ли да архивирате на сървъра избраните обекти?",
|
"upload_dialog_info": "Искате ли да архивирате на сървъра избраните обекти?",
|
||||||
"upload_dialog_title": "Качи обект",
|
"upload_dialog_title": "Качи обект",
|
||||||
"upload_errors": "Качването е завъшено с {count, plural, one {# грешка} other {# грешки}}, обновете страницата за да видите новите елементи.",
|
"upload_errors": "Качването е завъшено с {count, plural, one {# грешка} other {# грешки}}, обновете страницата за да видите новите елементи.",
|
||||||
|
"upload_finished": "Качването завърши",
|
||||||
"upload_progress": "Остават {remaining, number} - Обработени {processed, number}/{total, number}",
|
"upload_progress": "Остават {remaining, number} - Обработени {processed, number}/{total, number}",
|
||||||
"upload_skipped_duplicates": "Прескочени {count, plural, one {# дублиран елемент} other {# дублирани елементи}}",
|
"upload_skipped_duplicates": "Прескочени {count, plural, one {# дублиран елемент} other {# дублирани елементи}}",
|
||||||
"upload_status_duplicates": "Дубликати",
|
"upload_status_duplicates": "Дубликати",
|
||||||
@@ -1925,6 +2051,7 @@
|
|||||||
"upload_success": "Качването е успешно, опреснете страницата, за да видите новите файлове.",
|
"upload_success": "Качването е успешно, опреснете страницата, за да видите новите файлове.",
|
||||||
"upload_to_immich": "Казване в Immich ({count})",
|
"upload_to_immich": "Казване в Immich ({count})",
|
||||||
"uploading": "Качваме",
|
"uploading": "Качваме",
|
||||||
|
"uploading_media": "Качване на медийни файлове",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"usage": "Потребление",
|
"usage": "Потребление",
|
||||||
"use_biometric": "Използвай биометрия",
|
"use_biometric": "Използвай биометрия",
|
||||||
@@ -1945,6 +2072,7 @@
|
|||||||
"user_usage_stats_description": "Преглед на статистиката за използването на акаунта",
|
"user_usage_stats_description": "Преглед на статистиката за използването на акаунта",
|
||||||
"username": "Потребителско име",
|
"username": "Потребителско име",
|
||||||
"users": "Потребители",
|
"users": "Потребители",
|
||||||
|
"users_added_to_album_count": "{count, plural, one {Добавен е # потребител} other {Добавени са # потребителя}} на албума",
|
||||||
"utilities": "Инструменти",
|
"utilities": "Инструменти",
|
||||||
"validate": "Валидиране",
|
"validate": "Валидиране",
|
||||||
"validate_endpoint_error": "Моля, въведи правилен URL",
|
"validate_endpoint_error": "Моля, въведи правилен URL",
|
||||||
@@ -1963,6 +2091,7 @@
|
|||||||
"view_album": "Разгледай албума",
|
"view_album": "Разгледай албума",
|
||||||
"view_all": "Преглед на всички",
|
"view_all": "Преглед на всички",
|
||||||
"view_all_users": "Преглед на всички потребители",
|
"view_all_users": "Преглед на всички потребители",
|
||||||
|
"view_details": "Подробности за изгледа",
|
||||||
"view_in_timeline": "Покажи във времева линия",
|
"view_in_timeline": "Покажи във времева линия",
|
||||||
"view_link": "Преглед на връзката",
|
"view_link": "Преглед на връзката",
|
||||||
"view_links": "Преглед на връзките",
|
"view_links": "Преглед на връзките",
|
||||||
@@ -1970,6 +2099,7 @@
|
|||||||
"view_next_asset": "Преглед на следващия файл",
|
"view_next_asset": "Преглед на следващия файл",
|
||||||
"view_previous_asset": "Преглед на предишния файл",
|
"view_previous_asset": "Преглед на предишния файл",
|
||||||
"view_qr_code": "Виж QR кода",
|
"view_qr_code": "Виж QR кода",
|
||||||
|
"view_similar_photos": "Виж подобни снимки",
|
||||||
"view_stack": "Покажи в стек",
|
"view_stack": "Покажи в стек",
|
||||||
"view_user": "Виж потребителя",
|
"view_user": "Виж потребителя",
|
||||||
"viewer_remove_from_stack": "Премахване от опашката",
|
"viewer_remove_from_stack": "Премахване от опашката",
|
||||||
@@ -1988,5 +2118,6 @@
|
|||||||
"yes": "Да",
|
"yes": "Да",
|
||||||
"you_dont_have_any_shared_links": "Нямате споделени връзки",
|
"you_dont_have_any_shared_links": "Нямате споделени връзки",
|
||||||
"your_wifi_name": "Вашата Wi-Fi мрежа",
|
"your_wifi_name": "Вашата Wi-Fi мрежа",
|
||||||
"zoom_image": "Увеличаване на изображението"
|
"zoom_image": "Увеличаване на изображението",
|
||||||
|
"zoom_to_bounds": "Приближи до събиране в границите"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,5 +14,10 @@
|
|||||||
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
|
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
|
||||||
"add_import_path": "Putem wan pat blo import",
|
"add_import_path": "Putem wan pat blo import",
|
||||||
"add_location": "Putem wan place blo hem",
|
"add_location": "Putem wan place blo hem",
|
||||||
"add_more_users": "Putem mor man"
|
"add_more_users": "Putem mor man",
|
||||||
|
"readonly_mode_enabled": "Mod blo yu no save janjem i on",
|
||||||
|
"reassigned_assets_to_new_person": "Janjem{count, plural, one {# asset} other {# assets}} blo nu man",
|
||||||
|
"reassing_hint": "janjem ol sumtin yu bin joos i go blo wan man",
|
||||||
|
"recent-albums": "album i no old tu mas",
|
||||||
|
"recent_searches": "lukabout wea i no old tu mas"
|
||||||
}
|
}
|
||||||
|
|||||||
42
i18n/bn.json
42
i18n/bn.json
@@ -14,6 +14,7 @@
|
|||||||
"add_a_location": "একটি অবস্থান যোগ করুন",
|
"add_a_location": "একটি অবস্থান যোগ করুন",
|
||||||
"add_a_name": "একটি নাম যোগ করুন",
|
"add_a_name": "একটি নাম যোগ করুন",
|
||||||
"add_a_title": "একটি শিরোনাম যোগ করুন",
|
"add_a_title": "একটি শিরোনাম যোগ করুন",
|
||||||
|
"add_birthday": "একটি জন্মদিন যোগ করুন",
|
||||||
"add_endpoint": "এন্ডপয়েন্ট যোগ করুন",
|
"add_endpoint": "এন্ডপয়েন্ট যোগ করুন",
|
||||||
"add_exclusion_pattern": "বহির্ভূতকরণ নমুনা",
|
"add_exclusion_pattern": "বহির্ভূতকরণ নমুনা",
|
||||||
"add_import_path": "ইমপোর্ট করার পাথ যুক্ত করুন",
|
"add_import_path": "ইমপোর্ট করার পাথ যুক্ত করুন",
|
||||||
@@ -27,6 +28,9 @@
|
|||||||
"add_to_album": "এলবাম এ যোগ করুন",
|
"add_to_album": "এলবাম এ যোগ করুন",
|
||||||
"add_to_album_bottom_sheet_added": "{album} এ যোগ করা হয়েছে",
|
"add_to_album_bottom_sheet_added": "{album} এ যোগ করা হয়েছে",
|
||||||
"add_to_album_bottom_sheet_already_exists": "{album} এ আগে থেকেই আছে",
|
"add_to_album_bottom_sheet_already_exists": "{album} এ আগে থেকেই আছে",
|
||||||
|
"add_to_album_toggle": "{album} - এর নির্বাচন পরিবর্তন করুন",
|
||||||
|
"add_to_albums": "অ্যালবামে যোগ করুন",
|
||||||
|
"add_to_albums_count": "অ্যালবামে যোগ করুন ({count})",
|
||||||
"add_to_shared_album": "শেয়ার করা অ্যালবামে যোগ করুন",
|
"add_to_shared_album": "শেয়ার করা অ্যালবামে যোগ করুন",
|
||||||
"add_url": "লিঙ্ক যোগ করুন",
|
"add_url": "লিঙ্ক যোগ করুন",
|
||||||
"added_to_archive": "আর্কাইভ এ যোগ করা হয়েছে",
|
"added_to_archive": "আর্কাইভ এ যোগ করা হয়েছে",
|
||||||
@@ -44,6 +48,13 @@
|
|||||||
"backup_database": "ডাটাবেস ডাম্প তৈরি করুন",
|
"backup_database": "ডাটাবেস ডাম্প তৈরি করুন",
|
||||||
"backup_database_enable_description": "ডাটাবেস ডাম্প সক্রিয় করুন",
|
"backup_database_enable_description": "ডাটাবেস ডাম্প সক্রিয় করুন",
|
||||||
"backup_keep_last_amount": "আগের ডাম্পের পরিমাণ রাখা হবে",
|
"backup_keep_last_amount": "আগের ডাম্পের পরিমাণ রাখা হবে",
|
||||||
|
"backup_onboarding_1_description": "অফসাইট কপি ক্লাউডে অথবা অন্য কোনও ভৌত স্থানে।",
|
||||||
|
"backup_onboarding_2_description": "বিভিন্ন ডিভাইসে স্থানীয় কপি। এর মধ্যে রয়েছে প্রধান ফাইল এবং স্থানীয়ভাবে সেই ফাইলগুলির ব্যাকআপ।",
|
||||||
|
"backup_onboarding_3_description": "মূল ফাইল সহ আপনার ডেটার মোট কপি। এর মধ্যে রয়েছে ১টি অফসাইট কপি এবং ২টি স্থানীয় কপি।",
|
||||||
|
"backup_onboarding_description": "আপনার ডেটা সুরক্ষিত রাখার জন্য একটি <backblaze-link>3-2-1 ব্যাকআপ কৌশল</backblaze-link> সুপারিশ করা হয়। একটি বিস্তৃত ব্যাকআপ সমাধানের জন্য আপনার আপলোড করা ফটো/ভিডিওগুলির কপি এবং Immich ডাটাবেস রাখা উচিত।",
|
||||||
|
"backup_onboarding_footer": "Immich এর ব্যাকআপ নেওয়ার বিষয়ে আরও তথ্যের জন্য, অনুগ্রহ করে <link>ডকুমেন্টেশন</link> দেখুন।",
|
||||||
|
"backup_onboarding_parts_title": "৩-২-১ ব্যাকআপের মধ্যে রয়েছে:",
|
||||||
|
"backup_onboarding_title": "ব্যাকআপ",
|
||||||
"backup_settings": "ডাটাবেস ডাম্প সেটিংস",
|
"backup_settings": "ডাটাবেস ডাম্প সেটিংস",
|
||||||
"backup_settings_description": "ডাটাবেস ডাম্প সেটিংস পরিচালনা করুন।",
|
"backup_settings_description": "ডাটাবেস ডাম্প সেটিংস পরিচালনা করুন।",
|
||||||
"cleared_jobs": "{job} এর জন্য jobs খালি করা হয়েছে",
|
"cleared_jobs": "{job} এর জন্য jobs খালি করা হয়েছে",
|
||||||
@@ -64,7 +75,7 @@
|
|||||||
"external_library_management": "বহিরাগত গ্রন্থাগার ব্যবস্থাপনা",
|
"external_library_management": "বহিরাগত গ্রন্থাগার ব্যবস্থাপনা",
|
||||||
"face_detection": "মুখ সনাক্তকরণ",
|
"face_detection": "মুখ সনাক্তকরণ",
|
||||||
"face_detection_description": "মেশিন লার্নিং ব্যবহার করে অ্যাসেটে থাকা মুখ/চেহারা গুলি সনাক্ত করুন। ভিডিও গুলির জন্য, শুধুমাত্র থাম্বনেইল বিবেচনা করা হয়। \"রিফ্রেশ\" (পুনরায়) সমস্ত অ্যাসেট প্রক্রিয়া করে। \"রিসেট\" করার মাধ্যমে অতিরিক্তভাবে সমস্ত বর্তমান মুখের ডেটা সাফ করে। \"অনুপস্থিত\" অ্যাসেটগুলিকে সারিবদ্ধ করে যা এখনও প্রক্রিয়া করা হয়নি। সনাক্ত করা মুখগুলিকে ফেসিয়াল রিকগনিশনের জন্য সারিবদ্ধ করা হবে, ফেসিয়াল ডিটেকশন সম্পূর্ণ হওয়ার পরে, বিদ্যমান বা নতুন ব্যক্তিদের মধ্যে গোষ্ঠীবদ্ধ করে।",
|
"face_detection_description": "মেশিন লার্নিং ব্যবহার করে অ্যাসেটে থাকা মুখ/চেহারা গুলি সনাক্ত করুন। ভিডিও গুলির জন্য, শুধুমাত্র থাম্বনেইল বিবেচনা করা হয়। \"রিফ্রেশ\" (পুনরায়) সমস্ত অ্যাসেট প্রক্রিয়া করে। \"রিসেট\" করার মাধ্যমে অতিরিক্তভাবে সমস্ত বর্তমান মুখের ডেটা সাফ করে। \"অনুপস্থিত\" অ্যাসেটগুলিকে সারিবদ্ধ করে যা এখনও প্রক্রিয়া করা হয়নি। সনাক্ত করা মুখগুলিকে ফেসিয়াল রিকগনিশনের জন্য সারিবদ্ধ করা হবে, ফেসিয়াল ডিটেকশন সম্পূর্ণ হওয়ার পরে, বিদ্যমান বা নতুন ব্যক্তিদের মধ্যে গোষ্ঠীবদ্ধ করে।",
|
||||||
"facial_recognition_job_description": "শনাক্ত করা মুখগুলিকে মানুষের মধ্যে গোষ্ঠীভুক্ত করুন। মুখ সনাক্তকরণ সম্পূর্ণ হওয়ার পরে এই ধাপটি চলে। \"রিসেট\" (পুনরায়) সমস্ত মুখকে ক্লাস্টার করে। \"অনুপস্থিত\" মুখগুলিকে সারিতে রাখে যেখানে কোনও ব্যক্তিকে বরাদ্দ করা হয়নি।",
|
"facial_recognition_job_description": "শনাক্ত করা মুখগুলিকে মানুষের মধ্যে গোষ্ঠীভুক্ত/গ্রুপ করুন। মুখ সনাক্তকরণ সম্পূর্ণ হওয়ার পরে এই ধাপটি চলে। \"রিসেট\" (পুনরায়) সমস্ত মুখকে ক্লাস্টার করে। \"অনুপস্থিত/মিসিং\" মুখগুলিকে সারিতে রাখে যেগুলো কোনও ব্যক্তিকে এসাইন/বরাদ্দ করা হয়নি।",
|
||||||
"failed_job_command": "কমান্ড {command} কাজের জন্য ব্যর্থ হয়েছে: {job}",
|
"failed_job_command": "কমান্ড {command} কাজের জন্য ব্যর্থ হয়েছে: {job}",
|
||||||
"force_delete_user_warning": "সতর্কতা: এটি ব্যবহারকারী এবং সমস্ত সম্পদ অবিলম্বে সরিয়ে ফেলবে। এটি পূর্বাবস্থায় ফেরানো যাবে না এবং ফাইলগুলি পুনরুদ্ধার করা যাবে না।",
|
"force_delete_user_warning": "সতর্কতা: এটি ব্যবহারকারী এবং সমস্ত সম্পদ অবিলম্বে সরিয়ে ফেলবে। এটি পূর্বাবস্থায় ফেরানো যাবে না এবং ফাইলগুলি পুনরুদ্ধার করা যাবে না।",
|
||||||
"image_format": "ফরম্যাট",
|
"image_format": "ফরম্যাট",
|
||||||
@@ -75,9 +86,9 @@
|
|||||||
"image_fullsize_quality_description": "পূর্ণ-আকারের ছবির মান ১-১০০। উচ্চতর হলে ভালো, কিন্তু আরও বড় ফাইল তৈরি হয়।",
|
"image_fullsize_quality_description": "পূর্ণ-আকারের ছবির মান ১-১০০। উচ্চতর হলে ভালো, কিন্তু আরও বড় ফাইল তৈরি হয়।",
|
||||||
"image_fullsize_title": "পূর্ণ-আকারের চিত্র সেটিংস",
|
"image_fullsize_title": "পূর্ণ-আকারের চিত্র সেটিংস",
|
||||||
"image_prefer_embedded_preview": "এম্বেড করা প্রিভিউ পছন্দ করুন",
|
"image_prefer_embedded_preview": "এম্বেড করা প্রিভিউ পছন্দ করুন",
|
||||||
"image_prefer_embedded_preview_setting_description": "ছবি প্রক্রিয়াকরণের জন্য এবং যখনই উপলব্ধ থাকবে তখন RAW ফটোতে এমবেডেড প্রিভিউ ব্যবহার করুন। এটি কিছু ছবির জন্য আরও সঠিক রঙ তৈরি করতে পারে, তবে প্রিভিউয়ের মান ক্যামেরা-নির্ভর এবং ছবিতে আরও কম্প্রেশন আর্টিফ্যাক্ট থাকতে পারে।",
|
"image_prefer_embedded_preview_setting_description": "যদি পাওয়া যায়, RAW ছবির ভেতরে থাকা প্রিভিউ ব্যবহার করুন। এতে কিছু ছবির রঙ আরও সঠিক দেখা যেতে পারে, তবে মান ক্যামেরার ওপর নির্ভর করে এবং ছবিতে বাড়তি কমপ্রেশন আর্টিফ্যাক্ট দেখা যেতে পারে।",
|
||||||
"image_prefer_wide_gamut": "প্রশস্ত পরিসর পছন্দ করুন",
|
"image_prefer_wide_gamut": "প্রশস্ত পরিসর পছন্দ করুন",
|
||||||
"image_prefer_wide_gamut_setting_description": "থাম্বনেইলের জন্য ডিসপ্লে P3 ব্যবহার করুন। এটি প্রশস্ত রঙের স্থান সহ ছবির প্রাণবন্ততা আরও ভালভাবে সংরক্ষণ করে, তবে পুরানো ব্রাউজার সংস্করণ সহ পুরানো ডিভাইসগুলিতে ছবিগুলি ভিন্নভাবে প্রদর্শিত হতে পারে। রঙের পরিবর্তন এড়াতে sRGB ছবিগুলিকে sRGB হিসাবে রাখা হয়।",
|
"image_prefer_wide_gamut_setting_description": "থাম্বনেইলের জন্য Display P3 ব্যবহার করুন। এটি ওয়াইড কালারস্পেস ছবির উজ্জ্বলতা ও প্রাণবন্ত রঙ ভালোভাবে ধরে রাখে, তবে পুরনো ডিভাইস বা ব্রাউজারে ছবিগুলো ভিন্নভাবে দেখা যেতে পারে। sRGB ছবিগুলো রঙের পরিবর্তন এড়াতে sRGB হিসেবেই রাখা হবে।",
|
||||||
"image_preview_description": "স্ট্রিপড মেটাডেটা সহ মাঝারি আকারের ছবি, একটি একক সম্পদ দেখার সময় এবং মেশিন লার্নিংয়ের জন্য ব্যবহৃত হয়",
|
"image_preview_description": "স্ট্রিপড মেটাডেটা সহ মাঝারি আকারের ছবি, একটি একক সম্পদ দেখার সময় এবং মেশিন লার্নিংয়ের জন্য ব্যবহৃত হয়",
|
||||||
"image_preview_quality_description": "১-১০০ এর মধ্যে প্রিভিউ কোয়ালিটি। বেশি হলে ভালো, কিন্তু বড় ফাইল তৈরি হয় এবং অ্যাপের প্রতিক্রিয়াশীলতা কমাতে পারে। কম মান সেট করলে মেশিন লার্নিং কোয়ালিটির উপর প্রভাব পড়তে পারে।",
|
"image_preview_quality_description": "১-১০০ এর মধ্যে প্রিভিউ কোয়ালিটি। বেশি হলে ভালো, কিন্তু বড় ফাইল তৈরি হয় এবং অ্যাপের প্রতিক্রিয়াশীলতা কমাতে পারে। কম মান সেট করলে মেশিন লার্নিং কোয়ালিটির উপর প্রভাব পড়তে পারে।",
|
||||||
"image_preview_title": "প্রিভিউ সেটিংস",
|
"image_preview_title": "প্রিভিউ সেটিংস",
|
||||||
@@ -91,9 +102,30 @@
|
|||||||
"image_thumbnail_title": "থাম্বনেল সেটিংস",
|
"image_thumbnail_title": "থাম্বনেল সেটিংস",
|
||||||
"job_concurrency": "{job} কনকারেন্সি",
|
"job_concurrency": "{job} কনকারেন্সি",
|
||||||
"job_created": "Job তৈরি হয়েছে",
|
"job_created": "Job তৈরি হয়েছে",
|
||||||
"job_not_concurrency_safe": "এই কাজটি সমকালীন-নিরাপদ নয়।",
|
"job_not_concurrency_safe": "এই কাজটি সমান্তরালভাবে চালানো নিরাপদ নয়",
|
||||||
"job_settings": "কাজের সেটিংস",
|
"job_settings": "কাজের সেটিংস",
|
||||||
"job_settings_description": "কাজের সমান্তরালতা পরিচালনা করুন",
|
"job_settings_description": "কাজের সমান্তরালতা পরিচালনা করুন",
|
||||||
"job_status": "চাকরির অবস্থা"
|
"job_status": "চাকরির অবস্থা",
|
||||||
|
"jobs_delayed": "{jobCount, plural, other {# বিলম্বিত}}",
|
||||||
|
"jobs_failed": "{jobCount, plural, other {# ব্যর্থ}}",
|
||||||
|
"library_created": "লাইব্রেরি তৈরি করা হয়েছেঃ {library}",
|
||||||
|
"library_deleted": "লাইব্রেরি মুছে ফেলা হয়েছে",
|
||||||
|
"library_import_path_description": "ইম্পোর্ট/যোগ করার জন্য একটি ফোল্ডার নির্দিষ্ট করুন। সাবফোল্ডার সহ এই ফোল্ডারটি ছবি এবং ভিডিওর জন্য স্ক্যান করা হবে।",
|
||||||
|
"library_scanning": "পর্যায়ক্রমিক স্ক্যানিং",
|
||||||
|
"library_scanning_description": "পর্যায়ক্রমিক লাইব্রেরি স্ক্যানিং কনফিগার করুন",
|
||||||
|
"library_scanning_enable_description": "পর্যায়ক্রমিক লাইব্রেরি স্ক্যানিং সক্ষম করুন",
|
||||||
|
"library_settings": "বহিরাগত লাইব্রেরি",
|
||||||
|
"library_settings_description": "বহিরাগত লাইব্রেরি সেটিংস পরিচালনা করুন",
|
||||||
|
"library_tasks_description": "নতুন এবং/অথবা পরিবর্তিত সম্পদের জন্য বহিরাগত লাইব্রেরি স্ক্যান করুন",
|
||||||
|
"library_watching_enable_description": "ফাইল পরিবর্তনের জন্য বহিরাগত লাইব্রেরিগুলি দেখুন",
|
||||||
|
"library_watching_settings": "লাইব্রেরি দেখা (পরীক্ষামূলক)",
|
||||||
|
"library_watching_settings_description": "পরিবর্তিত ফাইলগুলির জন্য স্বয়ংক্রিয়ভাবে নজর রাখুন",
|
||||||
|
"logging_enable_description": "লগিং এনাবল/সক্ষম করুন",
|
||||||
|
"logging_level_description": "সক্রিয় থাকাকালীন, কোন লগ স্তর ব্যবহার করতে হবে।",
|
||||||
|
"logging_settings": "লগিং",
|
||||||
|
"machine_learning_clip_model": "CLIP মডেল",
|
||||||
|
"machine_learning_clip_model_description": "<link>এখানে</link> তালিকাভুক্ত একটি CLIP মডেলের নাম। মনে রাখবেন, মডেল পরিবর্তনের পর সব ছবির জন্য অবশ্যই ‘Smart Search’ কাজটি আবার চালাতে হবে।",
|
||||||
|
"machine_learning_duplicate_detection": "পুনরাবৃত্তি সনাক্তকরণ",
|
||||||
|
"machine_learning_duplicate_detection_enabled": "পুনরাবৃত্তি শনাক্তকরণ চালু করুন"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user