Compare commits

...

53 Commits

Author SHA1 Message Date
Alex Tran
7277ea3d7a feat(server): asset_user table 2025-01-28 22:04:21 -06:00
Carsten Otto
da580d4685 fix: show local dates for range in album summary (#15654)
* fix(web): show local dates for range in album summary

* fix(server): show local dates for range in album summary
2025-01-28 14:33:38 -06:00
Simon
cb6d94c7a7 chore: update of the Ukrainian translation (#15751)
Update uk-UA.json

Update of the Ukrainian translation for the Immich app
2025-01-28 20:32:57 +00:00
André Ventura
060300de8a fix(web): cancel people merge selection: do not show "Change name successfully" notification (#15744)
fix(web): cancel people merge selection: do not show "Change name successfully" notification.

Co-authored-by: André Ventura <afv@users.noreply.github.com>
2025-01-28 11:43:52 -06:00
Miguel Angel Nubla
c2ba1cc202 docs: add immich-upload-optimizer to Community Projects list (#15738) 2025-01-28 09:40:00 -06:00
PastLeo
08db77db23 feat: resolution selection and default preview playback for 360° panorama videos (#15747)
* original/preview switching in photo-sphere-viewer

1. default to preview in photo-sphere-viewer video mode
2. install and integrate @photo-sphere-viewer/settings-plugin & @photo-sphere-viewer/resolution-plugin

* fix lint errors
2025-01-28 09:09:40 -06:00
RiggiG
92dff839d0 fix(web): do not throw error when hash fails (#15740)
change: do not throw error when hash fails
2025-01-28 03:54:56 +00:00
Christian Kündig
fe1e09e51f fix(server): Allow negative rating (for rejected images) (#15699)
Allow negative rating (for rejected images)
2025-01-27 21:54:29 -06:00
github-actions
f44669447f chore: version v1.125.6 2025-01-28 02:58:27 +00:00
Mert
92412ca2f7 fix(server): person thumbnail generation always being queued (#15734)
* fix person thumbnail generation always being queued

* fix thumbhash comparison

* fix mock
2025-01-27 16:20:18 -06:00
github-actions
64d926581f chore: version v1.125.5 2025-01-27 20:04:50 +00:00
Alex
c139e05170 fix(mobile): locale option causes the datetime filter error out (#15704) 2025-01-27 14:02:23 -06:00
Alex
0fe62298e1 fix(server): duplicate detection (#15727) 2025-01-27 13:53:59 -06:00
github-actions
e5794e6cfc chore: version v1.125.4 2025-01-27 18:44:12 +00:00
Alex
f6cbc9db06 fix(server): cannot render album page when all assets of an album are in trash (#15690)
* fix(server): cannot render album page when all assets of an album are in trash

* inner join

* add e2e test

* check empty albums too

* render add to album button on empty album

* lint

* count 0 if undefined

* fix album card test

---------

Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
2025-01-26 21:18:34 -06:00
Alex
8dab5d3798 chore(mobile): post release task (#15662) 2025-01-26 15:09:15 -06:00
Carsten Otto
e864811a85 fix(web): sort folders (#15691)
fixes #13145
2025-01-26 15:07:22 -06:00
github-actions
72a55c13b6 chore: version v1.125.3 2025-01-26 14:14:48 +00:00
sudbrack
206412267a fix(server): /search/random API returns same assets every call (#15682)
* Fix for server searchRandom function not returning random results

* Fix lint
2025-01-26 14:06:18 +00:00
Damiano Ferrari
f780a56e24 fix(mobile): Misaligned text icon in circle avatar (#15683)
style(mobile): Use `DefaultTextStyle` for the text icon in `CircleAvatar`
2025-01-26 07:51:46 -06:00
Alex
7bbffccf76 fix(web): neon overflow on mobile screen (#15676) 2025-01-26 08:06:26 -05:00
Mert
05a446c259 fix(server): avoid duplicate rows in album queries (#15670)
* avoid duplicate rows

* left join, handle null vs. undefined

* update sql
2025-01-25 22:37:19 -06:00
Carsten Otto
4f725b95e1 fix(server): do not count deleted assets for album summary (#15668)
fixes #15645
fixes #15646
2025-01-25 16:45:13 -06:00
Carsten Otto
64b92cb24c fix(server): do not reset fileCreatedDate (#15650)
When marking an offline asset as online again, do not reset the
fileCreatedAt value. This value contains the "true" date, copied
from exif.dateTimeOriginal. If we overwrite this value, we'd need
to run the metadata extraction job again. Instead, we just leave
the old (and correct) value in place.

fixes #15640
2025-01-25 13:50:37 -06:00
Gagan Yadav
19f2f888ee fix(mobile): improve timezone picker (#15615)
- Fix missing timezones

- Remove the UTC prefix from timezone display text to align with web app

- Remove unnecessary layout builder

- Created a custom `DropdownSearchMenu` widget

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-01-25 13:36:49 -06:00
Alex
d12b1c907d fix(server): bulk update location (#15642) 2025-01-25 11:58:07 -06:00
Robert Schütz
947c053c15 chore(server): add DB_URL supports Unix sockets unit test (#15629)
* test(server): DB_URL supports Unix sockets

* chore: format

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2025-01-25 10:38:00 +00:00
Regenxyz
79592701dd chore: fix typos in Thai Language Readme (#15637)
Update README_th_TH.md

Fixing weird Thai Translate
2025-01-25 10:30:53 +00:00
jdicioccio
39697cd973 fix: increase upload timeout (#15588)
Fix upload timeout issue

Fix an issue where when uploading a large file, the upload would consistently abort after 30 minutes. I changed this timeout from 30 minutes to 1 day. Maybe that's excessive, or maybe the timeout isn't even needed, but the current 30 minute timeout definitely seems way too short.
2025-01-25 04:26:52 -06:00
Jonathan Jogenfors
10e518db42 chore(server): print stack in case of worker error (#15632)
feat: show error stack
2025-01-24 22:45:55 -05:00
Mert
72fa31f9e9 fix(server): changing vector dim size (#15630) 2025-01-24 20:01:24 -05:00
github-actions
9871a04d54 chore: version v1.125.2 2025-01-24 19:09:06 +00:00
Mert
ba01b40e7c fix(server): sslmode not working (#15587)
* parse db url before passing it to the driver

* don't be lazy

* simplify

* simplify

* add tests

* update sql sync script

* update mock

* remove unused import

* remove unused imports
2025-01-24 13:01:55 -06:00
Alex
f5a3d7ba23 fix(mobile): failed to load ga/gl locale (#15623) 2025-01-24 12:47:29 -06:00
Alex
d4a9eed4a1 fix(server): migration mentions public schema (#15622) 2025-01-24 18:11:22 +00:00
Alex
9d8072b994 fix(server): failed to get albums with archived assets (#15611)
* fix(mobile): failed to get albums with archived assets

* sql
2025-01-24 17:54:53 +00:00
Saschl
3c1fa22109 fix(mobile): deletion of single assets (#15597)
fix: set asset in currentassetprovider on image load

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-01-24 17:47:54 +00:00
Matthew Momjian
c0210bd6c0 fix(mobile): translation (no /api, experimental features) (#15600)
* initial /api removal

* translations /api

* experimental features

* japanese url update

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-01-24 11:47:01 -06:00
Mert
a6ace5151c fix(server): no exif metadata in the deduplication utility (#15585)
add exif to `getDuplicates`
2025-01-24 11:42:39 -06:00
Jason Rasmussen
ede9c99adb fix: demo login page (#15616) 2025-01-24 11:39:06 -06:00
Alex
ec7ab209f3 fix(server): link live photos (#15612)
* fix(server): link live photos

* chore: sql

* formatting
2025-01-24 11:38:59 -06:00
Alex
61bc24d7ea chore(mobile): post release task (#15581) 2025-01-24 17:28:00 +00:00
Alex
6c95eb22b7 fix(mobile): full refresh doesn't get albums (#15560) 2025-01-24 17:27:33 +00:00
Jason Rasmussen
aaea5cf1ad fix: login page (#15613) 2025-01-24 17:17:04 +00:00
Alex
96d2e9b4c5 fix(mobile): unit test (#15604)
* fix(mobile): unit test

* fix(mobile): unit test
2025-01-24 12:11:38 -05:00
Alex
19740a3560 fix(web): neon artifacts (#15582) 2025-01-24 09:18:26 -06:00
bo0tzz
8a481e2ea1 docs: add FAQ about app update approval (#15599) 2025-01-24 09:08:01 -06:00
Mert
ba105d9f19 fix(server): searchRandom response (#15580)
* fix searchRandom

* add e2e

* set outer limit
2025-01-24 00:41:54 -05:00
Lukas
065d885ca0 fix(server): Fix for sorting faces during merging (#15571)
* Fix for sorting faces

* Put uneccessary orderBy in if statement
2025-01-23 21:33:24 -05:00
Mert
a07ae9b5b2 fix(server): set updatedAt on updates (#15573)
* `updatedAt` triggers

* drop function at the end
2025-01-23 19:24:29 -05:00
Jason Rasmussen
1869b1b41a refactor: repositories (#15561)
* refactor: version history repository

* refactor: oauth repository

* refactor: trash repository

* refactor: telemetry repository

* refactor: metadata repository

* refactor: cron repository

* refactor: map repository

* refactor: server-info repository

* refactor: album user repository

* refactor: notification repository
2025-01-23 18:10:17 -05:00
Alex
995314446b feat(web): neon light behinds login form (#15570) 2025-01-23 17:23:23 -05:00
Jason Rasmussen
a1691ddc0f fix(web): auth page padding (#15569) 2025-01-23 21:38:34 +00:00
193 changed files with 3135 additions and 1187 deletions

6
cli/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.42", "version": "2.2.47",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.42", "version": "2.2.47",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
@@ -52,7 +52,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.125.1", "version": "1.125.6",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.42", "version": "2.2.47",
"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",

View File

@@ -62,6 +62,10 @@ Instead of these experimental features, we recommend using the URL switching fea
We are not actively developing these features and will not be able to provide support, but welcome contributions to improve them. We are not actively developing these features and will not be able to provide support, but welcome contributions to improve them.
Please discuss any large PRs with our dev team to ensure your time is not wasted. Please discuss any large PRs with our dev team to ensure your time is not wasted.
### Why isn't the mobile app updated yet?
The app stores can take a few days to approve new builds of the app. If you're impatient, android APKs can be downloaded from the GitHub releases.
--- ---
## Assets ## Assets

View File

@@ -27,7 +27,7 @@ The script will perform the following actions:
1. Download [docker-compose.yml](https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml), and the [.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file from the main branch of the [repository](https://github.com/immich-app/immich). 1. Download [docker-compose.yml](https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml), and the [.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file from the main branch of the [repository](https://github.com/immich-app/immich).
2. Start the containers. 2. Start the containers.
The web application will be available at `http://<machine-ip-address>:2283`, and the server URL for the mobile app will be `http://<machine-ip-address>:2283/api` The web application and mobile app will be available at `http://<machine-ip-address>:2283`
The directory which is used to store the library files is `./immich-app` relative to the current directory. The directory which is used to store the library files is `./immich-app` relative to the current directory.

View File

@@ -1,3 +1,3 @@
Login to the mobile app with the server endpoint URL at `http://<machine-ip-address>:2283/api` Login to the mobile app with the server endpoint URL at `http://<machine-ip-address>:2283`
<img src={require('./img/sign-in-phone.webp').default} width='50%' title='Mobile App Sign In' /> <img src={require('./img/sign-in-phone.webp').default} width='50%' title='Mobile App Sign In' />

View File

@@ -99,6 +99,11 @@ const projects: CommunityProjectProps[] = [
description: 'Downloads a configurable number of random photos based on people or album ID.', description: 'Downloads a configurable number of random photos based on people or album ID.',
url: 'https://github.com/jon6fingrs/immich-dl', url: 'https://github.com/jon6fingrs/immich-dl',
}, },
{
title: 'Immich Upload Optimizer',
description: 'Automatically optimize files uploaded to Immich in order to save storage space',
url: 'https://github.com/miguelangel-nubla/immich-upload-optimizer',
},
]; ];
function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element { function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element {

View File

@@ -1,4 +1,24 @@
[ [
{
"label": "v1.125.6",
"url": "https://v1.125.6.archive.immich.app"
},
{
"label": "v1.125.5",
"url": "https://v1.125.5.archive.immich.app"
},
{
"label": "v1.125.4",
"url": "https://v1.125.4.archive.immich.app"
},
{
"label": "v1.125.3",
"url": "https://v1.125.3.archive.immich.app"
},
{
"label": "v1.125.2",
"url": "https://v1.125.2.archive.immich.app"
},
{ {
"label": "v1.125.1", "label": "v1.125.1",
"url": "https://v1.125.1.archive.immich.app" "url": "https://v1.125.1.archive.immich.app"

8
e2e/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.125.1", "version": "1.125.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.125.1", "version": "1.125.6",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.1.0", "@eslint/eslintrc": "^3.1.0",
@@ -45,7 +45,7 @@
}, },
"../cli": { "../cli": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.42", "version": "2.2.47",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
@@ -92,7 +92,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.125.1", "version": "1.125.6",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.125.1", "version": "1.125.6",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@@ -22,79 +22,92 @@ const user1NotShared = 'user1NotShared';
const user2SharedUser = 'user2SharedUser'; const user2SharedUser = 'user2SharedUser';
const user2SharedLink = 'user2SharedLink'; const user2SharedLink = 'user2SharedLink';
const user2NotShared = 'user2NotShared'; const user2NotShared = 'user2NotShared';
const user4DeletedAsset = 'user4DeletedAsset';
const user4Empty = 'user4Empty';
describe('/albums', () => { describe('/albums', () => {
let admin: LoginResponseDto; let admin: LoginResponseDto;
let user1: LoginResponseDto; let user1: LoginResponseDto;
let user1Asset1: AssetMediaResponseDto; let user1Asset1: AssetMediaResponseDto;
let user1Asset2: AssetMediaResponseDto; let user1Asset2: AssetMediaResponseDto;
let user4Asset1: AssetMediaResponseDto;
let user1Albums: AlbumResponseDto[]; let user1Albums: AlbumResponseDto[];
let user2: LoginResponseDto; let user2: LoginResponseDto;
let user2Albums: AlbumResponseDto[]; let user2Albums: AlbumResponseDto[];
let deletedAssetAlbum: AlbumResponseDto;
let user3: LoginResponseDto; // deleted let user3: LoginResponseDto; // deleted
let user4: LoginResponseDto;
beforeAll(async () => { beforeAll(async () => {
await utils.resetDatabase(); await utils.resetDatabase();
admin = await utils.adminSetup(); admin = await utils.adminSetup();
[user1, user2, user3] = await Promise.all([ [user1, user2, user3, user4] = await Promise.all([
utils.userSetup(admin.accessToken, createUserDto.user1), utils.userSetup(admin.accessToken, createUserDto.user1),
utils.userSetup(admin.accessToken, createUserDto.user2), utils.userSetup(admin.accessToken, createUserDto.user2),
utils.userSetup(admin.accessToken, createUserDto.user3), utils.userSetup(admin.accessToken, createUserDto.user3),
utils.userSetup(admin.accessToken, createUserDto.user4),
]); ]);
[user1Asset1, user1Asset2] = await Promise.all([ [user1Asset1, user1Asset2, user4Asset1] = await Promise.all([
utils.createAsset(user1.accessToken, { isFavorite: true }), utils.createAsset(user1.accessToken, { isFavorite: true }),
utils.createAsset(user1.accessToken), utils.createAsset(user1.accessToken),
utils.createAsset(user1.accessToken),
]); ]);
user1Albums = await Promise.all([ [user1Albums, user2Albums, deletedAssetAlbum] = await Promise.all([
utils.createAlbum(user1.accessToken, { Promise.all([
albumName: user1SharedEditorUser, utils.createAlbum(user1.accessToken, {
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Editor }], albumName: user1SharedEditorUser,
assetIds: [user1Asset1.id], albumUsers: [
}), { userId: admin.userId, role: AlbumUserRole.Editor },
utils.createAlbum(user1.accessToken, { { userId: user2.userId, role: AlbumUserRole.Editor },
albumName: user1SharedLink, ],
assetIds: [user1Asset1.id], assetIds: [user1Asset1.id],
}), }),
utils.createAlbum(user1.accessToken, { utils.createAlbum(user1.accessToken, {
albumName: user1NotShared, albumName: user1SharedLink,
assetIds: [user1Asset1.id, user1Asset2.id], assetIds: [user1Asset1.id],
}), }),
utils.createAlbum(user1.accessToken, { utils.createAlbum(user1.accessToken, {
albumName: user1SharedViewerUser, albumName: user1NotShared,
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }], assetIds: [user1Asset1.id, user1Asset2.id],
assetIds: [user1Asset1.id], }),
utils.createAlbum(user1.accessToken, {
albumName: user1SharedViewerUser,
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
assetIds: [user1Asset1.id],
}),
]),
Promise.all([
utils.createAlbum(user2.accessToken, {
albumName: user2SharedUser,
albumUsers: [
{ userId: user1.userId, role: AlbumUserRole.Editor },
{ userId: user3.userId, role: AlbumUserRole.Editor },
],
}),
utils.createAlbum(user2.accessToken, { albumName: user2SharedLink }),
utils.createAlbum(user2.accessToken, { albumName: user2NotShared }),
]),
utils.createAlbum(user4.accessToken, { albumName: user4DeletedAsset }),
utils.createAlbum(user4.accessToken, { albumName: user4Empty }),
utils.createAlbum(user3.accessToken, {
albumName: 'Deleted',
albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }],
}), }),
]); ]);
user2Albums = await Promise.all([
utils.createAlbum(user2.accessToken, {
albumName: user2SharedUser,
albumUsers: [
{ userId: user1.userId, role: AlbumUserRole.Editor },
{ userId: user3.userId, role: AlbumUserRole.Editor },
],
}),
utils.createAlbum(user2.accessToken, { albumName: user2SharedLink }),
utils.createAlbum(user2.accessToken, { albumName: user2NotShared }),
]);
await utils.createAlbum(user3.accessToken, {
albumName: 'Deleted',
albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }],
});
await addAssetsToAlbum(
{ id: user2Albums[0].id, bulkIdsDto: { ids: [user1Asset1.id, user1Asset2.id] } },
{ headers: asBearerAuth(user1.accessToken) },
);
user2Albums[0] = await getAlbumInfo({ id: user2Albums[0].id }, { headers: asBearerAuth(user2.accessToken) });
await Promise.all([ await Promise.all([
addAssetsToAlbum(
{ id: user2Albums[0].id, bulkIdsDto: { ids: [user1Asset1.id, user1Asset2.id] } },
{ headers: asBearerAuth(user1.accessToken) },
),
addAssetsToAlbum(
{ id: deletedAssetAlbum.id, bulkIdsDto: { ids: [user4Asset1.id] } },
{ headers: asBearerAuth(user4.accessToken) },
),
// add shared link to user1SharedLink album // add shared link to user1SharedLink album
utils.createSharedLink(user1.accessToken, { utils.createSharedLink(user1.accessToken, {
type: SharedLinkType.Album, type: SharedLinkType.Album,
@@ -107,7 +120,11 @@ describe('/albums', () => {
}), }),
]); ]);
await deleteUserAdmin({ id: user3.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) }); [user2Albums[0]] = await Promise.all([
getAlbumInfo({ id: user2Albums[0].id }, { headers: asBearerAuth(user2.accessToken) }),
deleteUserAdmin({ id: user3.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) }),
utils.deleteAssets(user1.accessToken, [user4Asset1.id]),
]);
}); });
describe('GET /albums', () => { describe('GET /albums', () => {
@@ -284,6 +301,25 @@ describe('/albums', () => {
expect(status).toBe(200); expect(status).toBe(200);
expect(body).toHaveLength(5); expect(body).toHaveLength(5);
}); });
it('should return empty albums and albums where all assets are deleted', async () => {
const { status, body } = await request(app).get('/albums').set('Authorization', `Bearer ${user4.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user4.userId,
albumName: user4DeletedAsset,
shared: false,
}),
expect.objectContaining({
ownerId: user4.userId,
albumName: user4Empty,
shared: false,
}),
]),
);
});
}); });
describe('GET /albums/:id', () => { describe('GET /albums/:id', () => {
@@ -362,6 +398,26 @@ describe('/albums', () => {
shared: true, shared: true,
}); });
}); });
it('should not count trashed assets', async () => {
await utils.deleteAssets(user1.accessToken, [user1Asset2.id]);
const { status, body } = await request(app)
.get(`/albums/${user2Albums[0].id}?withoutAssets=true`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual({
...user2Albums[0],
assets: [],
assetCount: 1,
lastModifiedAssetTimestamp: expect.any(String),
endDate: expect.any(String),
startDate: expect.any(String),
albumUsers: expect.any(Array),
shared: true,
});
});
}); });
describe('GET /albums/statistics', () => { describe('GET /albums/statistics', () => {

View File

@@ -3,11 +3,11 @@ import {
AssetMediaStatus, AssetMediaStatus,
AssetResponseDto, AssetResponseDto,
AssetTypeEnum, AssetTypeEnum,
LoginResponseDto,
SharedLinkType,
getAssetInfo, getAssetInfo,
getConfig, getConfig,
getMyUser, getMyUser,
LoginResponseDto,
SharedLinkType,
updateConfig, updateConfig,
} from '@immich/sdk'; } from '@immich/sdk';
import { exiftool } from 'exiftool-vendored'; import { exiftool } from 'exiftool-vendored';
@@ -19,7 +19,7 @@ import { Socket } from 'socket.io-client';
import { createUserDto, uuidDto } from 'src/fixtures'; import { createUserDto, uuidDto } from 'src/fixtures';
import { makeRandomImage } from 'src/generators'; import { makeRandomImage } from 'src/generators';
import { errorDto } from 'src/responses'; import { errorDto } from 'src/responses';
import { app, asBearerAuth, tempDir, testAssetDir, utils } from 'src/utils'; import { app, asBearerAuth, tempDir, TEN_TIMES, testAssetDir, utils } from 'src/utils';
import request from 'supertest'; import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { afterAll, beforeAll, describe, expect, it } from 'vitest';
@@ -41,8 +41,6 @@ const makeUploadDto = (options?: { omit: string }): Record<string, any> => {
return dto; return dto;
}; };
const TEN_TIMES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const locationAssetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`; const locationAssetFilepath = `${testAssetDir}/metadata/gps-position/thompson-springs.jpg`;
const ratingAssetFilepath = `${testAssetDir}/metadata/rating/mongolels.jpg`; const ratingAssetFilepath = `${testAssetDir}/metadata/rating/mongolels.jpg`;
const facesAssetFilepath = `${testAssetDir}/metadata/faces/portrait.jpg`; const facesAssetFilepath = `${testAssetDir}/metadata/faces/portrait.jpg`;
@@ -703,6 +701,20 @@ describe('/asset', () => {
expect(status).toEqual(200); expect(status).toEqual(200);
}); });
it('should set the negative rating', async () => {
const { status, body } = await request(app)
.put(`/assets/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ rating: -1 });
expect(body).toMatchObject({
id: user1Assets[0].id,
exifInfo: expect.objectContaining({
rating: -1,
}),
});
expect(status).toEqual(200);
});
it('should reject invalid rating', async () => { it('should reject invalid rating', async () => {
for (const test of [{ rating: 7 }, { rating: 3.5 }, { rating: null }]) { for (const test of [{ rating: 7 }, { rating: 3.5 }, { rating: null }]) {
const { status, body } = await request(app) const { status, body } = await request(app)

View File

@@ -1,10 +1,10 @@
import { AssetMediaResponseDto, LoginResponseDto, deleteAssets, updateAsset } from '@immich/sdk'; import { AssetMediaResponseDto, AssetResponseDto, deleteAssets, LoginResponseDto, updateAsset } from '@immich/sdk';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { join } from 'node:path'; import { join } from 'node:path';
import { Socket } from 'socket.io-client'; import { Socket } from 'socket.io-client';
import { errorDto } from 'src/responses'; import { errorDto } from 'src/responses';
import { app, asBearerAuth, testAssetDir, utils } from 'src/utils'; import { app, asBearerAuth, TEN_TIMES, testAssetDir, utils } from 'src/utils';
import request from 'supertest'; import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { afterAll, beforeAll, describe, expect, it } from 'vitest';
const today = DateTime.now(); const today = DateTime.now();
@@ -462,6 +462,55 @@ describe('/search', () => {
}); });
}); });
describe('POST /search/random', () => {
beforeAll(async () => {
await Promise.all([
utils.createAsset(admin.accessToken),
utils.createAsset(admin.accessToken),
utils.createAsset(admin.accessToken),
utils.createAsset(admin.accessToken),
utils.createAsset(admin.accessToken),
utils.createAsset(admin.accessToken),
]);
await utils.waitForQueueFinish(admin.accessToken, 'thumbnailGeneration');
});
it('should require authentication', async () => {
const { status, body } = await request(app).post('/search/random').send({ size: 1 });
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it.each(TEN_TIMES)('should return 1 random assets', async () => {
const { status, body } = await request(app)
.post('/search/random')
.send({ size: 1 })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
const assets: AssetResponseDto[] = body;
expect(assets.length).toBe(1);
expect(assets[0].ownerId).toBe(admin.userId);
});
it.each(TEN_TIMES)('should return 2 random assets', async () => {
const { status, body } = await request(app)
.post('/search/random')
.send({ size: 2 })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
const assets: AssetResponseDto[] = body;
expect(assets.length).toBe(2);
expect(assets[0].ownerId).toBe(admin.userId);
expect(assets[1].ownerId).toBe(admin.userId);
});
});
describe('GET /search/explore', () => { describe('GET /search/explore', () => {
it('should require authentication', async () => { it('should require authentication', async () => {
const { status, body } = await request(app).get('/search/explore'); const { status, body } = await request(app).get('/search/explore');

View File

@@ -76,6 +76,7 @@ export const immichCli = (args: string[]) =>
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 = ["'", '"', ',', '{', '}', '*'];
export const TEN_TIMES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const executeCommand = (command: string, args: string[]) => { const executeCommand = (command: string, args: string[]) => {
let _resolve: (value: CommandResponse) => void; let _resolve: (value: CommandResponse) => void;

View File

@@ -53,7 +53,7 @@ show_friendly_message() {
ip_address=$(hostname -I | awk '{print $1}') ip_address=$(hostname -I | awk '{print $1}')
cat <<EOF cat <<EOF
Successfully deployed Immich! Successfully deployed Immich!
You can access the website at http://$ip_address:2283 and the server URL for the mobile app is http://$ip_address:2283/api You can access the website or the mobile app at http://$ip_address:2283
--------------------------------------------------- ---------------------------------------------------
If you want to configure custom information of the server, including the database, Redis information, or the backup (or upload) location, etc. If you want to configure custom information of the server, including the database, Redis information, or the backup (or upload) location, etc.

View File

@@ -97,8 +97,8 @@ download:
- file: mobile/assets/i18n/id-ID.json - file: mobile/assets/i18n/id-ID.json
locale_code: id-ID locale_code: id-ID
- file: mobile/assets/i18n/gl.json - file: mobile/assets/i18n/gl.json
locale_code: gl-ES locale_code: gl
- file: mobile/assets/i18n/ga.json - file: mobile/assets/i18n/ga.json
locale_code: ga-IE locale_code: ga
- file: mobile/assets/i18n/tr-TR.json - file: mobile/assets/i18n/tr-TR.json
locale_code: tr-TR locale_code: tr-TR

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "machine-learning" name = "machine-learning"
version = "1.125.1" version = "1.125.6"
description = "" description = ""
authors = ["Hau Tran <alex.tran1502@gmail.com>"] authors = ["Hau Tran <alex.tran1502@gmail.com>"]
readme = "README.md" readme = "README.md"

View File

@@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 177, "android.injected.version.code" => 182,
"android.injected.version.name" => "1.125.1", "android.injected.version.name" => "1.125.6",
} }
) )
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')

View File

@@ -336,9 +336,9 @@
"login_form_back_button_text": "الرجوع للخلف", "login_form_back_button_text": "الرجوع للخلف",
"login_form_button_text": "تسجيل الدخول", "login_form_button_text": "تسجيل الدخول",
"login_form_email_hint": "yoursemail@email.com", "login_form_email_hint": "yoursemail@email.com",
"login_form_endpoint_hint": "http: // your-server-ip: port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "url نقطة نهاية الخادم", "login_form_endpoint_url": "url نقطة نهاية الخادم",
"login_form_err_http": "يرجى تحديد http: // أو https: //", "login_form_err_http": "يرجى تحديد http:// أو https://",
"login_form_err_invalid_email": "بريد إلكتروني خاطئ", "login_form_err_invalid_email": "بريد إلكتروني خاطئ",
"login_form_err_invalid_url": "URL غير صالح", "login_form_err_invalid_url": "URL غير صالح",
"login_form_err_leading_whitespace": "قيادة المساحة البيضاء", "login_form_err_leading_whitespace": "قيادة المساحة البيضاء",
@@ -670,4 +670,4 @@
"viewer_unstack": "فك الكومه", "viewer_unstack": "فك الكومه",
"wifi_name": "WiFi Name", "wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name" "your_wifi_name": "Your WiFi name"
} }

View File

@@ -238,7 +238,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Entra", "login_form_button_text": "Entra",
"login_form_email_hint": "elteu@correu.cat", "login_form_email_hint": "elteu@correu.cat",
"login_form_endpoint_hint": "http://ip-del-servidor:port/api", "login_form_endpoint_hint": "http://ip-del-servidor:port",
"login_form_endpoint_url": "URL del servidor", "login_form_endpoint_url": "URL del servidor",
"login_form_err_http": "Especifica http:// o https://", "login_form_err_http": "Especifica http:// o https://",
"login_form_err_invalid_email": "Adreça de correu electrònic no vàlida", "login_form_err_invalid_email": "Adreça de correu electrònic no vàlida",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Zpět", "login_form_back_button_text": "Zpět",
"login_form_button_text": "Přihlásit se", "login_form_button_text": "Přihlásit se",
"login_form_email_hint": "tvůje-mail@email.com", "login_form_email_hint": "tvůje-mail@email.com",
"login_form_endpoint_hint": "http://ip-tvého-serveru:port/api", "login_form_endpoint_hint": "http://ip-tvého-serveru:port",
"login_form_endpoint_url": "URL adresa serveru", "login_form_endpoint_url": "URL adresa serveru",
"login_form_err_http": "Prosím, uveďte http:// nebo https://", "login_form_err_http": "Prosím, uveďte http:// nebo https://",
"login_form_err_invalid_email": "Neplatný e-mail", "login_form_err_invalid_email": "Neplatný e-mail",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Tilbage", "login_form_back_button_text": "Tilbage",
"login_form_button_text": "Log ind", "login_form_button_text": "Log ind",
"login_form_email_hint": "din-e-mail@e-mail.com", "login_form_email_hint": "din-e-mail@e-mail.com",
"login_form_endpoint_hint": "http://din-server-ip:port/api", "login_form_endpoint_hint": "http://din-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Angiv venligst http:// eller https://", "login_form_err_http": "Angiv venligst http:// eller https://",
"login_form_err_invalid_email": "Ugyldig e-mail", "login_form_err_invalid_email": "Ugyldig e-mail",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Zurück", "login_form_back_button_text": "Zurück",
"login_form_button_text": "Anmelden", "login_form_button_text": "Anmelden",
"login_form_email_hint": "deine@email.de", "login_form_email_hint": "deine@email.de",
"login_form_endpoint_hint": "http://deine-server-ip:port/api", "login_form_endpoint_hint": "http://deine-server-ip:port",
"login_form_endpoint_url": "Server-URL", "login_form_endpoint_url": "Server-URL",
"login_form_err_http": "Bitte gebe http:// oder https:// an", "login_form_err_http": "Bitte gebe http:// oder https:// an",
"login_form_err_invalid_email": "Ungültige E-Mail", "login_form_err_invalid_email": "Ungültige E-Mail",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Πίσω", "login_form_back_button_text": "Πίσω",
"login_form_button_text": "Σύνδεση", "login_form_button_text": "Σύνδεση",
"login_form_email_hint": "to-email-sou@email.com", "login_form_email_hint": "to-email-sou@email.com",
"login_form_endpoint_hint": "http://ip-tou-server-sou:porta/api", "login_form_endpoint_hint": "http://ip-tou-server-sou:porta",
"login_form_endpoint_url": "URL τελικού σημείου διακομιστή", "login_form_endpoint_url": "URL τελικού σημείου διακομιστή",
"login_form_err_http": "Προσδιορίστε http:// ή https://", "login_form_err_http": "Προσδιορίστε http:// ή https://",
"login_form_err_invalid_email": "Μη έγκυρο email", "login_form_err_invalid_email": "Μη έγκυρο email",

View File

@@ -16,7 +16,7 @@
"advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request",
"advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_proxy_headers_title": "Proxy Headers",
"advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.",
"advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates", "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates (EXPERIMENTAL)",
"advanced_settings_tile_subtitle": "Advanced user's settings", "advanced_settings_tile_subtitle": "Advanced user's settings",
"advanced_settings_tile_title": "Advanced", "advanced_settings_tile_title": "Advanced",
"advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting",
@@ -175,7 +175,7 @@
"client_cert_remove": "Remove", "client_cert_remove": "Remove",
"client_cert_remove_msg": "Client certificate is removed", "client_cert_remove_msg": "Client certificate is removed",
"client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login",
"client_cert_title": "SSL Client Certificate", "client_cert_title": "SSL Client Certificate (EXPERIMENTAL)",
"common_add_to_album": "Add to album", "common_add_to_album": "Add to album",
"common_change_password": "Change Password", "common_change_password": "Change Password",
"common_create_new_album": "Create new album", "common_create_new_album": "Create new album",
@@ -248,6 +248,7 @@
"download_waiting_to_retry": "Waiting to retry", "download_waiting_to_retry": "Waiting to retry",
"edit_date_time_dialog_date_time": "Date and Time", "edit_date_time_dialog_date_time": "Date and Time",
"edit_date_time_dialog_timezone": "Timezone", "edit_date_time_dialog_timezone": "Timezone",
"edit_date_time_dialog_search_timezone": "Search timezone...",
"edit_image_title": "Edit", "edit_image_title": "Edit",
"edit_location_dialog_title": "Location", "edit_location_dialog_title": "Location",
"end_date": "End date", "end_date": "End date",
@@ -281,7 +282,7 @@
"header_settings_field_validator_msg": "Value cannot be empty", "header_settings_field_validator_msg": "Value cannot be empty",
"header_settings_header_name_input": "Header name", "header_settings_header_name_input": "Header name",
"header_settings_header_value_input": "Header value", "header_settings_header_value_input": "Header value",
"header_settings_page_title": "Proxy Headers", "header_settings_page_title": "Proxy Headers (EXPERIMENTAL)",
"headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request",
"headers_settings_tile_title": "Custom proxy headers", "headers_settings_tile_title": "Custom proxy headers",
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.", "home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
@@ -336,7 +337,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",
@@ -670,4 +671,4 @@
"viewer_unstack": "Un-Stack", "viewer_unstack": "Un-Stack",
"wifi_name": "WiFi Name", "wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name" "your_wifi_name": "Your WiFi name"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Atrás", "login_form_back_button_text": "Atrás",
"login_form_button_text": "Iniciar Sesión", "login_form_button_text": "Iniciar Sesión",
"login_form_email_hint": "tucorreo@correo.com", "login_form_email_hint": "tucorreo@correo.com",
"login_form_endpoint_hint": "http://tu-ip-de-servidor:puerto/api", "login_form_endpoint_hint": "http://tu-ip-de-servidor:puerto",
"login_form_endpoint_url": "URL del servidor", "login_form_endpoint_url": "URL del servidor",
"login_form_err_http": "Por favor, especifique http:// o https://", "login_form_err_http": "Por favor, especifique http:// o https://",
"login_form_err_invalid_email": "Correo electrónico no válido", "login_form_err_invalid_email": "Correo electrónico no válido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Iniciar sesión", "login_form_button_text": "Iniciar sesión",
"login_form_email_hint": "tucorreo@correo.com", "login_form_email_hint": "tucorreo@correo.com",
"login_form_endpoint_hint": "http://la-ip-de-tu-servidor:puerto/api", "login_form_endpoint_hint": "http://la-ip-de-tu-servidor:puerto",
"login_form_endpoint_url": "URL del servidor", "login_form_endpoint_url": "URL del servidor",
"login_form_err_http": "Por favor, especifique http:// o https://", "login_form_err_http": "Por favor, especifique http:// o https://",
"login_form_err_invalid_email": "Correo electrónico inválido", "login_form_err_invalid_email": "Correo electrónico inválido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Iniciar sesión", "login_form_button_text": "Iniciar sesión",
"login_form_email_hint": "tucorreo@correo.com", "login_form_email_hint": "tucorreo@correo.com",
"login_form_endpoint_hint": "http://la-ip-de-tu-servidor:puerto/api", "login_form_endpoint_hint": "http://la-ip-de-tu-servidor:puerto",
"login_form_endpoint_url": "URL del servidor", "login_form_endpoint_url": "URL del servidor",
"login_form_err_http": "Por favor, especifique http:// o https://", "login_form_err_http": "Por favor, especifique http:// o https://",
"login_form_err_invalid_email": "Correo electrónico inválido", "login_form_err_invalid_email": "Correo electrónico inválido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Iniciar sesión", "login_form_button_text": "Iniciar sesión",
"login_form_email_hint": "tucorreo@correo.com", "login_form_email_hint": "tucorreo@correo.com",
"login_form_endpoint_hint": "http://ip-de-tu-servidor:puerto/api", "login_form_endpoint_hint": "http://ip-de-tu-servidor:puerto",
"login_form_endpoint_url": "URL del servidor", "login_form_endpoint_url": "URL del servidor",
"login_form_err_http": "Por favor, especifique http:// o https://", "login_form_err_http": "Por favor, especifique http:// o https://",
"login_form_err_invalid_email": "Correo electrónico inválido", "login_form_err_invalid_email": "Correo electrónico inválido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Takaisin", "login_form_back_button_text": "Takaisin",
"login_form_button_text": "Kirjaudu", "login_form_button_text": "Kirjaudu",
"login_form_email_hint": "sahkopostisi@esimerkki.fi", "login_form_email_hint": "sahkopostisi@esimerkki.fi",
"login_form_endpoint_hint": "http://palvelimesi-osoite:portti/api", "login_form_endpoint_hint": "http://palvelimesi-osoite:portti",
"login_form_endpoint_url": "Palvelimen URL", "login_form_endpoint_url": "Palvelimen URL",
"login_form_err_http": "Lisää http:// tai https://", "login_form_err_http": "Lisää http:// tai https://",
"login_form_err_invalid_email": "Virheellinen sähköpostiosoite", "login_form_err_invalid_email": "Virheellinen sähköpostiosoite",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Connexion", "login_form_button_text": "Connexion",
"login_form_email_hint": "votrecourriel@email.com", "login_form_email_hint": "votrecourriel@email.com",
"login_form_endpoint_hint": "http://adresse-ip-serveur:port/api", "login_form_endpoint_hint": "http://adresse-ip-serveur:port",
"login_form_endpoint_url": "URL du point d'accès au serveur", "login_form_endpoint_url": "URL du point d'accès au serveur",
"login_form_err_http": "Veuillez préciser http:// ou https://", "login_form_err_http": "Veuillez préciser http:// ou https://",
"login_form_err_invalid_email": "Courriel invalide", "login_form_err_invalid_email": "Courriel invalide",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Retour", "login_form_back_button_text": "Retour",
"login_form_button_text": "Connexion", "login_form_button_text": "Connexion",
"login_form_email_hint": "votreemail@email.com", "login_form_email_hint": "votreemail@email.com",
"login_form_endpoint_hint": "http://adresse-ip-serveur:port/api", "login_form_endpoint_hint": "http://adresse-ip-serveur:port",
"login_form_endpoint_url": "URL du point d'accès au serveur", "login_form_endpoint_url": "URL du point d'accès au serveur",
"login_form_err_http": "Veuillez préciser http:// ou https://", "login_form_err_http": "Veuillez préciser http:// ou https://",
"login_form_err_invalid_email": "E-mail invalide", "login_form_err_invalid_email": "E-mail invalide",

673
mobile/assets/i18n/ga.json Normal file
View File

@@ -0,0 +1,673 @@
{
"action_common_back": "Back",
"action_common_cancel": "Cancel",
"action_common_clear": "Clear",
"action_common_confirm": "Confirm",
"action_common_save": "Save",
"action_common_select": "Select",
"action_common_update": "Update",
"add_a_name": "Add a name",
"add_endpoint": "Add endpoint",
"add_to_album_bottom_sheet_added": "Added to {album}",
"add_to_album_bottom_sheet_already_exists": "Already in {album}",
"advanced_settings_log_level_title": "Log level: {}",
"advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.",
"advanced_settings_prefer_remote_title": "Prefer remote images",
"advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request",
"advanced_settings_proxy_headers_title": "Proxy Headers",
"advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.",
"advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates (EXPERIMENTAL)",
"advanced_settings_tile_subtitle": "Advanced user's settings",
"advanced_settings_tile_title": "Advanced",
"advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting",
"advanced_settings_troubleshooting_title": "Troubleshooting",
"album_info_card_backup_album_excluded": "EXCLUDED",
"album_info_card_backup_album_included": "INCLUDED",
"albums": "Albums",
"album_thumbnail_card_item": "1 item",
"album_thumbnail_card_items": "{} items",
"album_thumbnail_card_shared": " · Shared",
"album_thumbnail_owned": "Owned",
"album_thumbnail_shared_by": "Shared by {}",
"album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?",
"album_viewer_appbar_share_delete": "Delete album",
"album_viewer_appbar_share_err_delete": "Failed to delete album",
"album_viewer_appbar_share_err_leave": "Failed to leave album",
"album_viewer_appbar_share_err_remove": "There are problems in removing assets from album",
"album_viewer_appbar_share_err_title": "Failed to change album title",
"album_viewer_appbar_share_leave": "Leave album",
"album_viewer_appbar_share_remove": "Remove from album",
"album_viewer_appbar_share_to": "Share To",
"album_viewer_page_share_add_users": "Add users",
"all": "All",
"all_people_page_title": "People",
"all_videos_page_title": "Videos",
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
"app_bar_signout_dialog_ok": "Yes",
"app_bar_signout_dialog_title": "Sign out",
"archived": "Archived",
"archive_page_no_archived_assets": "No archived assets found",
"archive_page_title": "Archive ({})",
"asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping",
"asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping",
"asset_list_group_by_sub_title": "Group by",
"asset_list_layout_settings_dynamic_layout_title": "Dynamic layout",
"asset_list_layout_settings_group_automatically": "Automatic",
"asset_list_layout_settings_group_by": "Group assets by",
"asset_list_layout_settings_group_by_month": "Month",
"asset_list_layout_settings_group_by_month_day": "Month + day",
"asset_list_layout_sub_title": "Layout",
"asset_list_settings_subtitle": "Photo grid layout settings",
"asset_list_settings_title": "Photo Grid",
"asset_restored_successfully": "Asset restored successfully",
"assets_deleted_permanently": "{} asset(s) deleted permanently",
"assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server",
"assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device",
"assets_restored_successfully": "{} asset(s) restored successfully",
"assets_trashed": "{} asset(s) trashed",
"assets_trashed_from_server": "{} asset(s) trashed from the Immich server",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings",
"asset_viewer_settings_title": "Asset Viewer",
"automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere",
"automatic_endpoint_switching_title": "Automatic URL switching",
"background_location_permission": "Background location permission",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name",
"backup_album_selection_page_albums_device": "Albums on device ({})",
"backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude",
"backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.",
"backup_album_selection_page_select_albums": "Select albums",
"backup_album_selection_page_selection_info": "Selection Info",
"backup_album_selection_page_total_assets": "Total unique assets",
"backup_all": "All",
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
"backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…",
"backup_background_service_current_upload_notification": "Uploading {}",
"backup_background_service_default_notification": "Checking for new assets…",
"backup_background_service_error_title": "Backup error",
"backup_background_service_in_progress_notification": "Backing up your assets…",
"backup_background_service_upload_failure_notification": "Failed to upload {}",
"backup_controller_page_albums": "Backup Albums",
"backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.",
"backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled",
"backup_controller_page_background_app_refresh_enable_button_text": "Go to settings",
"backup_controller_page_background_battery_info_link": "Show me how",
"backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.",
"backup_controller_page_background_battery_info_ok": "OK",
"backup_controller_page_background_battery_info_title": "Battery optimizations",
"backup_controller_page_background_charging": "Only while charging",
"backup_controller_page_background_configure_error": "Failed to configure the background service",
"backup_controller_page_background_delay": "Delay new assets backup: {}",
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
"backup_controller_page_background_is_off": "Automatic background backup is off",
"backup_controller_page_background_is_on": "Automatic background backup is on",
"backup_controller_page_background_turn_off": "Turn off background service",
"backup_controller_page_background_turn_on": "Turn on background service",
"backup_controller_page_background_wifi": "Only on WiFi",
"backup_controller_page_backup": "Backup",
"backup_controller_page_backup_selected": "Selected: ",
"backup_controller_page_backup_sub": "Backed up photos and videos",
"backup_controller_page_cancel": "Cancel",
"backup_controller_page_created": "Created on: {}",
"backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.",
"backup_controller_page_excluded": "Excluded: ",
"backup_controller_page_failed": "Failed ({})",
"backup_controller_page_filename": "File name: {} [{}]",
"backup_controller_page_id": "ID: {}",
"backup_controller_page_info": "Backup Information",
"backup_controller_page_none_selected": "None selected",
"backup_controller_page_remainder": "Remainder",
"backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection",
"backup_controller_page_select": "Select",
"backup_controller_page_server_storage": "Server Storage",
"backup_controller_page_start_backup": "Start Backup",
"backup_controller_page_status_off": "Automatic foreground backup is off",
"backup_controller_page_status_on": "Automatic foreground backup is on",
"backup_controller_page_storage_format": "{} of {} used",
"backup_controller_page_to_backup": "Albums to be backed up",
"backup_controller_page_total": "Total",
"backup_controller_page_total_sub": "All unique photos and videos from selected albums",
"backup_controller_page_turn_off": "Turn off foreground backup",
"backup_controller_page_turn_on": "Turn on foreground backup",
"backup_controller_page_uploading_file_info": "Uploading file info",
"backup_err_only_album": "Cannot remove the only album",
"backup_info_card_assets": "assets",
"backup_manual_cancelled": "Cancelled",
"backup_manual_failed": "Failed",
"backup_manual_in_progress": "Upload already in progress. Try after sometime",
"backup_manual_success": "Success",
"backup_manual_title": "Upload status",
"backup_options_page_title": "Backup options",
"backup_setting_subtitle": "Manage background and foreground upload settings",
"cache_settings_album_thumbnails": "Library page thumbnails ({} assets)",
"cache_settings_clear_cache_button": "Clear cache",
"cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.",
"cache_settings_duplicated_assets_clear_button": "CLEAR",
"cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app",
"cache_settings_duplicated_assets_title": "Duplicated Assets ({})",
"cache_settings_image_cache_size": "Image cache size ({} assets)",
"cache_settings_statistics_album": "Library thumbnails",
"cache_settings_statistics_assets": "{} assets ({})",
"cache_settings_statistics_full": "Full images",
"cache_settings_statistics_shared": "Shared album thumbnails",
"cache_settings_statistics_thumbnail": "Thumbnails",
"cache_settings_statistics_title": "Cache usage",
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
"cache_settings_tile_subtitle": "Control the local storage behaviour",
"cache_settings_tile_title": "Local Storage",
"cache_settings_title": "Caching Settings",
"cancel": "Cancel",
"canceled": "Canceled",
"change_display_order": "Change display order",
"change_password_form_confirm_password": "Confirm Password",
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
"change_password_form_new_password": "New Password",
"change_password_form_password_mismatch": "Passwords do not match",
"change_password_form_reenter_new_password": "Re-enter New Password",
"check_corrupt_asset_backup": "Check for corrupt asset backups",
"check_corrupt_asset_backup_button": "Perform check",
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.",
"client_cert_dialog_msg_confirm": "OK",
"client_cert_enter_password": "Enter Password",
"client_cert_import": "Import",
"client_cert_import_success_msg": "Client certificate is imported",
"client_cert_invalid_msg": "Invalid certificate file or wrong password",
"client_cert_remove": "Remove",
"client_cert_remove_msg": "Client certificate is removed",
"client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login",
"client_cert_title": "SSL Client Certificate (EXPERIMENTAL)",
"common_add_to_album": "Add to album",
"common_change_password": "Change Password",
"common_create_new_album": "Create new album",
"common_server_error": "Please check your network connection, make sure the server is reachable and app/server versions are compatible.",
"common_shared": "Shared",
"completed": "Completed",
"contextual_search": "Sunrise on the beach",
"control_bottom_app_bar_add_to_album": "Add to album",
"control_bottom_app_bar_album_info": "{} items",
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
"control_bottom_app_bar_archive": "Archive",
"control_bottom_app_bar_create_new_album": "Create new album",
"control_bottom_app_bar_delete": "Delete",
"control_bottom_app_bar_delete_from_immich": "Delete from Immich",
"control_bottom_app_bar_delete_from_local": "Delete from device",
"control_bottom_app_bar_download": "Download",
"control_bottom_app_bar_edit": "Edit",
"control_bottom_app_bar_edit_location": "Edit Location",
"control_bottom_app_bar_edit_time": "Edit Date & Time",
"control_bottom_app_bar_favorite": "Favorite",
"control_bottom_app_bar_share": "Share",
"control_bottom_app_bar_share_to": "Share To",
"control_bottom_app_bar_stack": "Stack",
"control_bottom_app_bar_trash_from_immich": "Move to Trash",
"control_bottom_app_bar_unarchive": "Unarchive",
"control_bottom_app_bar_unfavorite": "Unfavorite",
"control_bottom_app_bar_upload": "Upload",
"create_album": "Create album",
"create_album_page_untitled": "Untitled",
"create_new": "CREATE NEW",
"create_shared_album_page_create": "Create",
"create_shared_album_page_share": "Share",
"create_shared_album_page_share_add_assets": "ADD ASSETS",
"create_shared_album_page_share_select_photos": "Select Photos",
"crop": "Crop",
"curated_location_page_title": "Places",
"curated_object_page_title": "Things",
"current_server_address": "Current server address",
"daily_title_text_date": "E, MMM dd",
"daily_title_text_date_year": "E, MMM dd, yyyy",
"date_format": "E, LLL d, y • h:mm a",
"delete_dialog_alert": "These items will be permanently deleted from Immich and from your device",
"delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server",
"delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device",
"delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server",
"delete_dialog_cancel": "Cancel",
"delete_dialog_ok": "Delete",
"delete_dialog_ok_force": "Delete Anyway",
"delete_dialog_title": "Delete Permanently",
"delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only",
"delete_local_dialog_ok_force": "Delete Anyway",
"delete_shared_link_dialog_content": "Are you sure you want to delete this shared link?",
"delete_shared_link_dialog_title": "Delete Shared Link",
"description_input_hint_text": "Add description...",
"description_input_submit_error": "Error updating description, check the log for more details",
"download_canceled": "Download canceled",
"download_complete": "Download complete",
"download_enqueue": "Download enqueued",
"download_error": "Download Error",
"download_failed": "Download failed",
"download_filename": "file: {}",
"download_finished": "Download finished",
"downloading": "Downloading...",
"downloading_media": "Downloading media",
"download_notfound": "Download not found",
"download_paused": "Download paused",
"download_started": "Download started",
"download_sucess": "Download success",
"download_sucess_android": "The media has been downloaded to DCIM/Immich",
"download_waiting_to_retry": "Waiting to retry",
"edit_date_time_dialog_date_time": "Date and Time",
"edit_date_time_dialog_timezone": "Timezone",
"edit_image_title": "Edit",
"edit_location_dialog_title": "Location",
"end_date": "End date",
"enqueued": "Enqueued",
"enter_wifi_name": "Enter WiFi name",
"error_change_sort_album": "Failed to change album sort order",
"error_saving_image": "Error: {}",
"exif_bottom_sheet_description": "Add Description...",
"exif_bottom_sheet_details": "DETAILS",
"exif_bottom_sheet_location": "LOCATION",
"exif_bottom_sheet_location_add": "Add a location",
"exif_bottom_sheet_people": "PEOPLE",
"exif_bottom_sheet_person_add_person": "Add name",
"experimental_settings_new_asset_list_subtitle": "Work in progress",
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
"experimental_settings_subtitle": "Use at your own risk!",
"experimental_settings_title": "Experimental",
"external_network": "External network",
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
"failed": "Failed",
"favorites": "Favorites",
"favorites_page_no_favorites": "No favorite assets found",
"favorites_page_title": "Favorites",
"filename_search": "File name or extension",
"filter": "Filter",
"get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network",
"grant_permission": "Grant permission",
"haptic_feedback_switch": "Enable haptic feedback",
"haptic_feedback_title": "Haptic Feedback",
"header_settings_add_header_tip": "Add Header",
"header_settings_field_validator_msg": "Value cannot be empty",
"header_settings_header_name_input": "Header name",
"header_settings_header_value_input": "Header value",
"header_settings_page_title": "Proxy Headers (EXPERIMENTAL)",
"headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request",
"headers_settings_tile_title": "Custom proxy headers",
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
"home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping",
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
"home_page_album_err_partner": "Can not add partner assets to an album yet, skipping",
"home_page_archive_err_local": "Can not archive local assets yet, skipping",
"home_page_archive_err_partner": "Can not archive partner assets, skipping",
"home_page_building_timeline": "Building the timeline",
"home_page_delete_err_partner": "Can not delete partner assets, skipping",
"home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping",
"home_page_favorite_err_local": "Can not favorite local assets yet, skipping",
"home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping",
"home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).",
"home_page_share_err_local": "Can not share local assets via link, skipping",
"home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping",
"ignore_icloud_photos": "Ignore iCloud photos",
"ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server",
"image_saved_successfully": "Image saved",
"image_viewer_page_state_provider_download_error": "Download Error",
"image_viewer_page_state_provider_download_started": "Download Started",
"image_viewer_page_state_provider_download_success": "Download Success",
"image_viewer_page_state_provider_share_error": "Share Error",
"invalid_date": "Invalid date",
"invalid_date_format": "Invalid date format",
"library": "Library",
"library_page_albums": "Albums",
"library_page_archive": "Archive",
"library_page_device_albums": "Albums on Device",
"library_page_favorites": "Favorites",
"library_page_new_album": "New album",
"library_page_sharing": "Sharing",
"library_page_sort_asset_count": "Number of assets",
"library_page_sort_created": "Created date",
"library_page_sort_last_modified": "Last modified",
"library_page_sort_most_oldest_photo": "Oldest photo",
"library_page_sort_most_recent_photo": "Most recent photo",
"library_page_sort_title": "Album title",
"local_network": "Local network",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network",
"location_permission": "Location permission",
"location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name",
"location_picker_choose_on_map": "Choose on map",
"location_picker_latitude": "Latitude",
"location_picker_latitude_error": "Enter a valid latitude",
"location_picker_latitude_hint": "Enter your latitude here",
"location_picker_longitude": "Longitude",
"location_picker_longitude_error": "Enter a valid longitude",
"location_picker_longitude_hint": "Enter your longitude here",
"login_disabled": "Login has been disabled",
"login_form_api_exception": "API exception. Please check the server URL and try again.",
"login_form_back_button_text": "Back",
"login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email",
"login_form_err_invalid_url": "Invalid URL",
"login_form_err_leading_whitespace": "Leading whitespace",
"login_form_err_trailing_whitespace": "Trailing whitespace",
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
"login_form_failed_login": "Error logging you in, check server URL, email and password",
"login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.",
"login_form_label_email": "Email",
"login_form_label_password": "Password",
"login_form_next_button": "Next",
"login_form_password_hint": "password",
"login_form_save_login": "Stay logged in",
"login_form_server_empty": "Enter a server URL.",
"login_form_server_error": "Could not connect to server.",
"login_password_changed_error": "There was an error updating your password",
"login_password_changed_success": "Password updated successfully",
"map_assets_in_bound": "{} photo",
"map_assets_in_bounds": "{} photos",
"map_cannot_get_user_location": "Cannot get user's location",
"map_location_dialog_cancel": "Cancel",
"map_location_dialog_yes": "Yes",
"map_location_picker_page_use_location": "Use this location",
"map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?",
"map_location_service_disabled_title": "Location Service disabled",
"map_no_assets_in_bounds": "No photos in this area",
"map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?",
"map_no_location_permission_title": "Location Permission denied",
"map_settings_dark_mode": "Dark mode",
"map_settings_date_range_option_all": "All",
"map_settings_date_range_option_day": "Past 24 hours",
"map_settings_date_range_option_days": "Past {} days",
"map_settings_date_range_option_year": "Past year",
"map_settings_date_range_option_years": "Past {} years",
"map_settings_dialog_cancel": "Cancel",
"map_settings_dialog_save": "Save",
"map_settings_dialog_title": "Map Settings",
"map_settings_include_show_archived": "Include Archived",
"map_settings_include_show_partners": "Include Partners",
"map_settings_only_relative_range": "Date range",
"map_settings_only_show_favorites": "Show Favorite Only",
"map_settings_theme_settings": "Map Theme",
"map_zoom_to_see_photos": "Zoom out to see photos",
"memories_all_caught_up": "All caught up",
"memories_check_back_tomorrow": "Check back tomorrow for more memories",
"memories_start_over": "Start Over",
"memories_swipe_to_close": "Swipe up to close",
"memories_year_ago": "A year ago",
"memories_years_ago": "{} years ago",
"monthly_title_text_date_format": "MMMM y",
"motion_photos_page_title": "Motion Photos",
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
"my_albums": "My albums",
"networking_settings": "Networking",
"networking_subtitle": "Manage the server endpoint settings",
"no_assets_to_show": "No assets to show",
"no_name": "No name",
"notification_permission_dialog_cancel": "Cancel",
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
"notification_permission_dialog_settings": "Settings",
"notification_permission_list_tile_content": "Grant permission to enable notifications.",
"notification_permission_list_tile_enable_button": "Enable Notifications",
"notification_permission_list_tile_title": "Notification Permission",
"not_selected": "Not selected",
"on_this_device": "On this device",
"partner_list_user_photos": "{user}'s photos",
"partner_list_view_all": "View all",
"partner_page_add_partner": "Add partner",
"partner_page_empty_message": "Your photos are not yet shared with any partner.",
"partner_page_no_more_users": "No more users to add",
"partner_page_partner_add_failed": "Failed to add partner",
"partner_page_select_partner": "Select partner",
"partner_page_shared_to_title": "Shared to",
"partner_page_stop_sharing_content": "{} will no longer be able to access your photos.",
"partner_page_stop_sharing_title": "Stop sharing your photos?",
"partner_page_title": "Partner",
"partners": "Partners",
"paused": "Paused",
"people": "People",
"permission_onboarding_back": "Back",
"permission_onboarding_continue_anyway": "Continue anyway",
"permission_onboarding_get_started": "Get started",
"permission_onboarding_go_to_settings": "Go to settings",
"permission_onboarding_grant_permission": "Grant permission",
"permission_onboarding_log_out": "Log out",
"permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.",
"permission_onboarding_permission_granted": "Permission granted! You are all set.",
"permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.",
"permission_onboarding_request": "Immich requires permission to view your photos and videos.",
"places": "Places",
"preferences_settings_subtitle": "Manage the app's preferences",
"preferences_settings_title": "Preferences",
"profile_drawer_app_logs": "Logs",
"profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.",
"profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.",
"profile_drawer_client_server_up_to_date": "Client and Server are up-to-date",
"profile_drawer_documentation": "Documentation",
"profile_drawer_github": "GitHub",
"profile_drawer_server_out_of_date_major": "Server is out of date. Please update to the latest major version.",
"profile_drawer_server_out_of_date_minor": "Server is out of date. Please update to the latest minor version.",
"profile_drawer_settings": "Settings",
"profile_drawer_sign_out": "Sign Out",
"profile_drawer_trash": "Trash",
"recently_added": "Recently added",
"recently_added_page_title": "Recently Added",
"save": "Save",
"save_to_gallery": "Save to gallery",
"scaffold_body_error_occurred": "Error occurred",
"search_albums": "Search albums",
"search_bar_hint": "Search your photos",
"search_filter_apply": "Apply filter",
"search_filter_camera": "Camera",
"search_filter_camera_make": "Make",
"search_filter_camera_model": "Model",
"search_filter_camera_title": "Select camera type",
"search_filter_date": "Date",
"search_filter_date_interval": "{start} to {end}",
"search_filter_date_title": "Select a date range",
"search_filter_display_option_archive": "Archive",
"search_filter_display_option_favorite": "Favorite",
"search_filter_display_option_not_in_album": "Not in album",
"search_filter_display_options": "Display Options",
"search_filter_display_options_title": "Display options",
"search_filter_location": "Location",
"search_filter_location_city": "City",
"search_filter_location_country": "Country",
"search_filter_location_state": "State",
"search_filter_location_title": "Select location",
"search_filter_media_type": "Media Type",
"search_filter_media_type_all": "All",
"search_filter_media_type_image": "Image",
"search_filter_media_type_title": "Select media type",
"search_filter_media_type_video": "Video",
"search_filter_people": "People",
"search_filter_people_title": "Select people",
"search_page_categories": "Categories",
"search_page_favorites": "Favorites",
"search_page_motion_photos": "Motion Photos",
"search_page_no_objects": "No Objects Info Available",
"search_page_no_places": "No Places Info Available",
"search_page_people": "People",
"search_page_person_add_name_dialog_cancel": "Cancel",
"search_page_person_add_name_dialog_hint": "Name",
"search_page_person_add_name_dialog_save": "Save",
"search_page_person_add_name_dialog_title": "Add a name",
"search_page_person_add_name_subtitle": "Find them fast by name with search",
"search_page_person_add_name_title": "Add a name",
"search_page_person_edit_name": "Edit name",
"search_page_places": "Places",
"search_page_recently_added": "Recently added",
"search_page_screenshots": "Screenshots",
"search_page_search_photos_videos": "Search for your photos and videos",
"search_page_selfies": "Selfies",
"search_page_things": "Things",
"search_page_videos": "Videos",
"search_page_view_all_button": "View all",
"search_page_your_activity": "Your activity",
"search_page_your_map": "Your Map",
"search_result_page_new_search_hint": "New Search",
"search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ",
"search_suggestion_list_smart_search_hint_2": "m:your-search-term",
"select_additional_user_for_sharing_page_suggestions": "Suggestions",
"select_user_for_sharing_page_err_album": "Failed to create album",
"select_user_for_sharing_page_share_suggestions": "Suggestions",
"server_endpoint": "Server Endpoint",
"server_info_box_app_version": "App Version",
"server_info_box_latest_release": "Latest Version",
"server_info_box_server_url": "Server URL",
"server_info_box_server_version": "Server Version",
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
"setting_image_viewer_original_title": "Load original image",
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
"setting_image_viewer_preview_title": "Load preview image",
"setting_image_viewer_title": "Images",
"setting_languages_apply": "Apply",
"setting_languages_subtitle": "Change the app's language",
"setting_languages_title": "Languages",
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
"setting_notifications_notify_hours": "{} hours",
"setting_notifications_notify_immediately": "immediately",
"setting_notifications_notify_minutes": "{} minutes",
"setting_notifications_notify_never": "never",
"setting_notifications_notify_seconds": "{} seconds",
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
"setting_notifications_single_progress_title": "Show background backup detail progress",
"setting_notifications_subtitle": "Adjust your notification preferences",
"setting_notifications_title": "Notifications",
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
"setting_notifications_total_progress_title": "Show background backup total progress",
"setting_pages_app_bar_settings": "Settings",
"settings_require_restart": "Please restart Immich to apply this setting",
"setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.",
"setting_video_viewer_looping_title": "Looping",
"setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.",
"setting_video_viewer_original_video_title": "Force original video",
"setting_video_viewer_title": "Videos",
"share_add": "Add",
"share_add_photos": "Add photos",
"share_add_title": "Add a title",
"share_assets_selected": "{} selected",
"share_create_album": "Create album",
"shared_album_activities_input_disable": "Comment is disabled",
"shared_album_activities_input_hint": "Say something",
"shared_album_activity_remove_content": "Do you want to delete this activity?",
"shared_album_activity_remove_title": "Delete Activity",
"shared_album_activity_setting_subtitle": "Let others respond",
"shared_album_activity_setting_title": "Comments & likes",
"shared_album_section_people_action_error": "Error leaving/removing from album",
"shared_album_section_people_action_leave": "Remove user from album",
"shared_album_section_people_action_remove_user": "Remove user from album",
"shared_album_section_people_owner_label": "Owner",
"shared_album_section_people_title": "PEOPLE",
"share_dialog_preparing": "Preparing...",
"shared_intent_upload_button_progress_text": "{} / {} Uploaded",
"shared_link_app_bar_title": "Shared Links",
"shared_link_clipboard_copied_massage": "Copied to clipboard",
"shared_link_clipboard_text": "Link: {}\nPassword: {}",
"shared_link_create_app_bar_title": "Create link to share",
"shared_link_create_error": "Error while creating shared link",
"shared_link_create_info": "Let anyone with the link see the selected photo(s)",
"shared_link_create_submit_button": "Create link",
"shared_link_edit_allow_download": "Allow public user to download",
"shared_link_edit_allow_upload": "Allow public user to upload",
"shared_link_edit_app_bar_title": "Edit link",
"shared_link_edit_change_expiry": "Change expiration time",
"shared_link_edit_description": "Description",
"shared_link_edit_description_hint": "Enter the share description",
"shared_link_edit_expire_after": "Expire after",
"shared_link_edit_expire_after_option_day": "1 day",
"shared_link_edit_expire_after_option_days": "{} days",
"shared_link_edit_expire_after_option_hour": "1 hour",
"shared_link_edit_expire_after_option_hours": "{} hours",
"shared_link_edit_expire_after_option_minute": "1 minute",
"shared_link_edit_expire_after_option_minutes": "{} minutes",
"shared_link_edit_expire_after_option_months": "{} months",
"shared_link_edit_expire_after_option_never": "Never",
"shared_link_edit_expire_after_option_year": "{} year",
"shared_link_edit_password": "Password",
"shared_link_edit_password_hint": "Enter the share password",
"shared_link_edit_show_meta": "Show metadata",
"shared_link_edit_submit_button": "Update link",
"shared_link_empty": "You don't have any shared links",
"shared_link_error_server_url_fetch": "Cannot fetch the server url",
"shared_link_expired": "Expired",
"shared_link_expires_day": "Expires in {} day",
"shared_link_expires_days": "Expires in {} days",
"shared_link_expires_hour": "Expires in {} hour",
"shared_link_expires_hours": "Expires in {} hours",
"shared_link_expires_minute": "Expires in {} minute",
"shared_link_expires_minutes": "Expires in {} minutes",
"shared_link_expires_never": "Expires ∞",
"shared_link_expires_second": "Expires in {} second",
"shared_link_expires_seconds": "Expires in {} seconds",
"shared_link_individual_shared": "Individual shared",
"shared_link_info_chip_download": "Download",
"shared_link_info_chip_metadata": "EXIF",
"shared_link_info_chip_upload": "Upload",
"shared_link_manage_links": "Manage Shared links",
"shared_link_public_album": "Public album",
"shared_links": "Shared links",
"share_done": "Done",
"shared_with_me": "Shared with me",
"share_invite": "Invite to album",
"sharing_page_album": "Shared albums",
"sharing_page_description": "Create shared albums to share photos and videos with people in your network.",
"sharing_page_empty_list": "EMPTY LIST",
"sharing_silver_appbar_create_shared_album": "New shared album",
"sharing_silver_appbar_shared_links": "Shared links",
"sharing_silver_appbar_share_partner": "Share with partner",
"start_date": "Start date",
"sync": "Sync",
"sync_albums": "Sync albums",
"sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums",
"sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich",
"tab_controller_nav_library": "Library",
"tab_controller_nav_photos": "Photos",
"tab_controller_nav_search": "Search",
"tab_controller_nav_sharing": "Sharing",
"theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles",
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
"theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.",
"theme_setting_colorful_interface_title": "Colorful interface",
"theme_setting_dark_mode_switch": "Dark mode",
"theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
"theme_setting_image_viewer_quality_title": "Image viewer quality",
"theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.",
"theme_setting_primary_color_title": "Primary color",
"theme_setting_system_primary_color_title": "Use system color",
"theme_setting_system_theme_switch": "Automatic (Follow system setting)",
"theme_setting_theme_subtitle": "Choose the app's theme setting",
"theme_setting_theme_title": "Theme",
"theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load",
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
"translated_text_options": "Options",
"trash": "Trash",
"trash_emptied": "Emptied trash",
"trash_page_delete": "Delete",
"trash_page_delete_all": "Delete All",
"trash_page_empty_trash_btn": "Empty trash",
"trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich",
"trash_page_empty_trash_dialog_ok": "Ok",
"trash_page_info": "Trashed items will be permanently deleted after {} days",
"trash_page_no_assets": "No trashed assets",
"trash_page_restore": "Restore",
"trash_page_restore_all": "Restore All",
"trash_page_select_assets_btn": "Select assets",
"trash_page_select_btn": "Select",
"trash_page_title": "Trash ({})",
"upload": "Upload",
"upload_dialog_cancel": "Cancel",
"upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?",
"upload_dialog_ok": "Upload",
"upload_dialog_title": "Upload Asset",
"uploading": "Uploading",
"upload_to_immich": "Upload to Immich ({})",
"use_current_connection": "use current connection",
"validate_endpoint_error": "Please enter a valid URL",
"version_announcement_overlay_ack": "Acknowledge",
"version_announcement_overlay_release_notes": "release notes",
"version_announcement_overlay_text_1": "Hi friend, there is a new release of",
"version_announcement_overlay_text_2": "please take your time to visit the ",
"version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
"version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89",
"videos": "Videos",
"viewer_remove_from_stack": "Remove from Stack",
"viewer_stack_use_as_main_asset": "Use as Main Asset",
"viewer_unstack": "Un-Stack",
"wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name"
}

673
mobile/assets/i18n/gl.json Normal file
View File

@@ -0,0 +1,673 @@
{
"action_common_back": "Back",
"action_common_cancel": "Cancel",
"action_common_clear": "Clear",
"action_common_confirm": "Confirm",
"action_common_save": "Save",
"action_common_select": "Select",
"action_common_update": "Update",
"add_a_name": "Add a name",
"add_endpoint": "Add endpoint",
"add_to_album_bottom_sheet_added": "Added to {album}",
"add_to_album_bottom_sheet_already_exists": "Already in {album}",
"advanced_settings_log_level_title": "Log level: {}",
"advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.",
"advanced_settings_prefer_remote_title": "Prefer remote images",
"advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request",
"advanced_settings_proxy_headers_title": "Proxy Headers",
"advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.",
"advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates (EXPERIMENTAL)",
"advanced_settings_tile_subtitle": "Advanced user's settings",
"advanced_settings_tile_title": "Advanced",
"advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting",
"advanced_settings_troubleshooting_title": "Troubleshooting",
"album_info_card_backup_album_excluded": "EXCLUDED",
"album_info_card_backup_album_included": "INCLUDED",
"albums": "Albums",
"album_thumbnail_card_item": "1 item",
"album_thumbnail_card_items": "{} items",
"album_thumbnail_card_shared": " · Shared",
"album_thumbnail_owned": "Owned",
"album_thumbnail_shared_by": "Shared by {}",
"album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?",
"album_viewer_appbar_share_delete": "Delete album",
"album_viewer_appbar_share_err_delete": "Failed to delete album",
"album_viewer_appbar_share_err_leave": "Failed to leave album",
"album_viewer_appbar_share_err_remove": "There are problems in removing assets from album",
"album_viewer_appbar_share_err_title": "Failed to change album title",
"album_viewer_appbar_share_leave": "Leave album",
"album_viewer_appbar_share_remove": "Remove from album",
"album_viewer_appbar_share_to": "Share To",
"album_viewer_page_share_add_users": "Add users",
"all": "All",
"all_people_page_title": "People",
"all_videos_page_title": "Videos",
"app_bar_signout_dialog_content": "Are you sure you want to sign out?",
"app_bar_signout_dialog_ok": "Yes",
"app_bar_signout_dialog_title": "Sign out",
"archived": "Archived",
"archive_page_no_archived_assets": "No archived assets found",
"archive_page_title": "Archive ({})",
"asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping",
"asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping",
"asset_list_group_by_sub_title": "Group by",
"asset_list_layout_settings_dynamic_layout_title": "Dynamic layout",
"asset_list_layout_settings_group_automatically": "Automatic",
"asset_list_layout_settings_group_by": "Group assets by",
"asset_list_layout_settings_group_by_month": "Month",
"asset_list_layout_settings_group_by_month_day": "Month + day",
"asset_list_layout_sub_title": "Layout",
"asset_list_settings_subtitle": "Photo grid layout settings",
"asset_list_settings_title": "Photo Grid",
"asset_restored_successfully": "Asset restored successfully",
"assets_deleted_permanently": "{} asset(s) deleted permanently",
"assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server",
"assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device",
"assets_restored_successfully": "{} asset(s) restored successfully",
"assets_trashed": "{} asset(s) trashed",
"assets_trashed_from_server": "{} asset(s) trashed from the Immich server",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings",
"asset_viewer_settings_title": "Asset Viewer",
"automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere",
"automatic_endpoint_switching_title": "Automatic URL switching",
"background_location_permission": "Background location permission",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name",
"backup_album_selection_page_albums_device": "Albums on device ({})",
"backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude",
"backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.",
"backup_album_selection_page_select_albums": "Select albums",
"backup_album_selection_page_selection_info": "Selection Info",
"backup_album_selection_page_total_assets": "Total unique assets",
"backup_all": "All",
"backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…",
"backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…",
"backup_background_service_current_upload_notification": "Uploading {}",
"backup_background_service_default_notification": "Checking for new assets…",
"backup_background_service_error_title": "Backup error",
"backup_background_service_in_progress_notification": "Backing up your assets…",
"backup_background_service_upload_failure_notification": "Failed to upload {}",
"backup_controller_page_albums": "Backup Albums",
"backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.",
"backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled",
"backup_controller_page_background_app_refresh_enable_button_text": "Go to settings",
"backup_controller_page_background_battery_info_link": "Show me how",
"backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.",
"backup_controller_page_background_battery_info_ok": "OK",
"backup_controller_page_background_battery_info_title": "Battery optimizations",
"backup_controller_page_background_charging": "Only while charging",
"backup_controller_page_background_configure_error": "Failed to configure the background service",
"backup_controller_page_background_delay": "Delay new assets backup: {}",
"backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app",
"backup_controller_page_background_is_off": "Automatic background backup is off",
"backup_controller_page_background_is_on": "Automatic background backup is on",
"backup_controller_page_background_turn_off": "Turn off background service",
"backup_controller_page_background_turn_on": "Turn on background service",
"backup_controller_page_background_wifi": "Only on WiFi",
"backup_controller_page_backup": "Backup",
"backup_controller_page_backup_selected": "Selected: ",
"backup_controller_page_backup_sub": "Backed up photos and videos",
"backup_controller_page_cancel": "Cancel",
"backup_controller_page_created": "Created on: {}",
"backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.",
"backup_controller_page_excluded": "Excluded: ",
"backup_controller_page_failed": "Failed ({})",
"backup_controller_page_filename": "File name: {} [{}]",
"backup_controller_page_id": "ID: {}",
"backup_controller_page_info": "Backup Information",
"backup_controller_page_none_selected": "None selected",
"backup_controller_page_remainder": "Remainder",
"backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection",
"backup_controller_page_select": "Select",
"backup_controller_page_server_storage": "Server Storage",
"backup_controller_page_start_backup": "Start Backup",
"backup_controller_page_status_off": "Automatic foreground backup is off",
"backup_controller_page_status_on": "Automatic foreground backup is on",
"backup_controller_page_storage_format": "{} of {} used",
"backup_controller_page_to_backup": "Albums to be backed up",
"backup_controller_page_total": "Total",
"backup_controller_page_total_sub": "All unique photos and videos from selected albums",
"backup_controller_page_turn_off": "Turn off foreground backup",
"backup_controller_page_turn_on": "Turn on foreground backup",
"backup_controller_page_uploading_file_info": "Uploading file info",
"backup_err_only_album": "Cannot remove the only album",
"backup_info_card_assets": "assets",
"backup_manual_cancelled": "Cancelled",
"backup_manual_failed": "Failed",
"backup_manual_in_progress": "Upload already in progress. Try after sometime",
"backup_manual_success": "Success",
"backup_manual_title": "Upload status",
"backup_options_page_title": "Backup options",
"backup_setting_subtitle": "Manage background and foreground upload settings",
"cache_settings_album_thumbnails": "Library page thumbnails ({} assets)",
"cache_settings_clear_cache_button": "Clear cache",
"cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.",
"cache_settings_duplicated_assets_clear_button": "CLEAR",
"cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app",
"cache_settings_duplicated_assets_title": "Duplicated Assets ({})",
"cache_settings_image_cache_size": "Image cache size ({} assets)",
"cache_settings_statistics_album": "Library thumbnails",
"cache_settings_statistics_assets": "{} assets ({})",
"cache_settings_statistics_full": "Full images",
"cache_settings_statistics_shared": "Shared album thumbnails",
"cache_settings_statistics_thumbnail": "Thumbnails",
"cache_settings_statistics_title": "Cache usage",
"cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application",
"cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)",
"cache_settings_tile_subtitle": "Control the local storage behaviour",
"cache_settings_tile_title": "Local Storage",
"cache_settings_title": "Caching Settings",
"cancel": "Cancel",
"canceled": "Canceled",
"change_display_order": "Change display order",
"change_password_form_confirm_password": "Confirm Password",
"change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.",
"change_password_form_new_password": "New Password",
"change_password_form_password_mismatch": "Passwords do not match",
"change_password_form_reenter_new_password": "Re-enter New Password",
"check_corrupt_asset_backup": "Check for corrupt asset backups",
"check_corrupt_asset_backup_button": "Perform check",
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.",
"client_cert_dialog_msg_confirm": "OK",
"client_cert_enter_password": "Enter Password",
"client_cert_import": "Import",
"client_cert_import_success_msg": "Client certificate is imported",
"client_cert_invalid_msg": "Invalid certificate file or wrong password",
"client_cert_remove": "Remove",
"client_cert_remove_msg": "Client certificate is removed",
"client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login",
"client_cert_title": "SSL Client Certificate (EXPERIMENTAL)",
"common_add_to_album": "Add to album",
"common_change_password": "Change Password",
"common_create_new_album": "Create new album",
"common_server_error": "Please check your network connection, make sure the server is reachable and app/server versions are compatible.",
"common_shared": "Shared",
"completed": "Completed",
"contextual_search": "Sunrise on the beach",
"control_bottom_app_bar_add_to_album": "Add to album",
"control_bottom_app_bar_album_info": "{} items",
"control_bottom_app_bar_album_info_shared": "{} items · Shared",
"control_bottom_app_bar_archive": "Archive",
"control_bottom_app_bar_create_new_album": "Create new album",
"control_bottom_app_bar_delete": "Delete",
"control_bottom_app_bar_delete_from_immich": "Delete from Immich",
"control_bottom_app_bar_delete_from_local": "Delete from device",
"control_bottom_app_bar_download": "Download",
"control_bottom_app_bar_edit": "Edit",
"control_bottom_app_bar_edit_location": "Edit Location",
"control_bottom_app_bar_edit_time": "Edit Date & Time",
"control_bottom_app_bar_favorite": "Favorite",
"control_bottom_app_bar_share": "Share",
"control_bottom_app_bar_share_to": "Share To",
"control_bottom_app_bar_stack": "Stack",
"control_bottom_app_bar_trash_from_immich": "Move to Trash",
"control_bottom_app_bar_unarchive": "Unarchive",
"control_bottom_app_bar_unfavorite": "Unfavorite",
"control_bottom_app_bar_upload": "Upload",
"create_album": "Create album",
"create_album_page_untitled": "Untitled",
"create_new": "CREATE NEW",
"create_shared_album_page_create": "Create",
"create_shared_album_page_share": "Share",
"create_shared_album_page_share_add_assets": "ADD ASSETS",
"create_shared_album_page_share_select_photos": "Select Photos",
"crop": "Crop",
"curated_location_page_title": "Places",
"curated_object_page_title": "Things",
"current_server_address": "Current server address",
"daily_title_text_date": "E, MMM dd",
"daily_title_text_date_year": "E, MMM dd, yyyy",
"date_format": "E, LLL d, y • h:mm a",
"delete_dialog_alert": "These items will be permanently deleted from Immich and from your device",
"delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server",
"delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device",
"delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server",
"delete_dialog_cancel": "Cancel",
"delete_dialog_ok": "Delete",
"delete_dialog_ok_force": "Delete Anyway",
"delete_dialog_title": "Delete Permanently",
"delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only",
"delete_local_dialog_ok_force": "Delete Anyway",
"delete_shared_link_dialog_content": "Are you sure you want to delete this shared link?",
"delete_shared_link_dialog_title": "Delete Shared Link",
"description_input_hint_text": "Add description...",
"description_input_submit_error": "Error updating description, check the log for more details",
"download_canceled": "Download canceled",
"download_complete": "Download complete",
"download_enqueue": "Download enqueued",
"download_error": "Download Error",
"download_failed": "Download failed",
"download_filename": "file: {}",
"download_finished": "Download finished",
"downloading": "Downloading...",
"downloading_media": "Downloading media",
"download_notfound": "Download not found",
"download_paused": "Download paused",
"download_started": "Download started",
"download_sucess": "Download success",
"download_sucess_android": "The media has been downloaded to DCIM/Immich",
"download_waiting_to_retry": "Waiting to retry",
"edit_date_time_dialog_date_time": "Date and Time",
"edit_date_time_dialog_timezone": "Timezone",
"edit_image_title": "Edit",
"edit_location_dialog_title": "Location",
"end_date": "End date",
"enqueued": "Enqueued",
"enter_wifi_name": "Enter WiFi name",
"error_change_sort_album": "Failed to change album sort order",
"error_saving_image": "Error: {}",
"exif_bottom_sheet_description": "Add Description...",
"exif_bottom_sheet_details": "DETAILS",
"exif_bottom_sheet_location": "LOCATION",
"exif_bottom_sheet_location_add": "Add a location",
"exif_bottom_sheet_people": "PEOPLE",
"exif_bottom_sheet_person_add_person": "Add name",
"experimental_settings_new_asset_list_subtitle": "Work in progress",
"experimental_settings_new_asset_list_title": "Enable experimental photo grid",
"experimental_settings_subtitle": "Use at your own risk!",
"experimental_settings_title": "Experimental",
"external_network": "External network",
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
"failed": "Failed",
"favorites": "Favorites",
"favorites_page_no_favorites": "No favorite assets found",
"favorites_page_title": "Favorites",
"filename_search": "File name or extension",
"filter": "Filter",
"get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network",
"grant_permission": "Grant permission",
"haptic_feedback_switch": "Enable haptic feedback",
"haptic_feedback_title": "Haptic Feedback",
"header_settings_add_header_tip": "Add Header",
"header_settings_field_validator_msg": "Value cannot be empty",
"header_settings_header_name_input": "Header name",
"header_settings_header_value_input": "Header value",
"header_settings_page_title": "Proxy Headers (EXPERIMENTAL)",
"headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request",
"headers_settings_tile_title": "Custom proxy headers",
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
"home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping",
"home_page_add_to_album_success": "Added {added} assets to album {album}.",
"home_page_album_err_partner": "Can not add partner assets to an album yet, skipping",
"home_page_archive_err_local": "Can not archive local assets yet, skipping",
"home_page_archive_err_partner": "Can not archive partner assets, skipping",
"home_page_building_timeline": "Building the timeline",
"home_page_delete_err_partner": "Can not delete partner assets, skipping",
"home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping",
"home_page_favorite_err_local": "Can not favorite local assets yet, skipping",
"home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping",
"home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).",
"home_page_share_err_local": "Can not share local assets via link, skipping",
"home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping",
"ignore_icloud_photos": "Ignore iCloud photos",
"ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server",
"image_saved_successfully": "Image saved",
"image_viewer_page_state_provider_download_error": "Download Error",
"image_viewer_page_state_provider_download_started": "Download Started",
"image_viewer_page_state_provider_download_success": "Download Success",
"image_viewer_page_state_provider_share_error": "Share Error",
"invalid_date": "Invalid date",
"invalid_date_format": "Invalid date format",
"library": "Library",
"library_page_albums": "Albums",
"library_page_archive": "Archive",
"library_page_device_albums": "Albums on Device",
"library_page_favorites": "Favorites",
"library_page_new_album": "New album",
"library_page_sharing": "Sharing",
"library_page_sort_asset_count": "Number of assets",
"library_page_sort_created": "Created date",
"library_page_sort_last_modified": "Last modified",
"library_page_sort_most_oldest_photo": "Oldest photo",
"library_page_sort_most_recent_photo": "Most recent photo",
"library_page_sort_title": "Album title",
"local_network": "Local network",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network",
"location_permission": "Location permission",
"location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name",
"location_picker_choose_on_map": "Choose on map",
"location_picker_latitude": "Latitude",
"location_picker_latitude_error": "Enter a valid latitude",
"location_picker_latitude_hint": "Enter your latitude here",
"location_picker_longitude": "Longitude",
"location_picker_longitude_error": "Enter a valid longitude",
"location_picker_longitude_hint": "Enter your longitude here",
"login_disabled": "Login has been disabled",
"login_form_api_exception": "API exception. Please check the server URL and try again.",
"login_form_back_button_text": "Back",
"login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email",
"login_form_err_invalid_url": "Invalid URL",
"login_form_err_leading_whitespace": "Leading whitespace",
"login_form_err_trailing_whitespace": "Trailing whitespace",
"login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL",
"login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server",
"login_form_failed_login": "Error logging you in, check server URL, email and password",
"login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.",
"login_form_label_email": "Email",
"login_form_label_password": "Password",
"login_form_next_button": "Next",
"login_form_password_hint": "password",
"login_form_save_login": "Stay logged in",
"login_form_server_empty": "Enter a server URL.",
"login_form_server_error": "Could not connect to server.",
"login_password_changed_error": "There was an error updating your password",
"login_password_changed_success": "Password updated successfully",
"map_assets_in_bound": "{} photo",
"map_assets_in_bounds": "{} photos",
"map_cannot_get_user_location": "Cannot get user's location",
"map_location_dialog_cancel": "Cancel",
"map_location_dialog_yes": "Yes",
"map_location_picker_page_use_location": "Use this location",
"map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?",
"map_location_service_disabled_title": "Location Service disabled",
"map_no_assets_in_bounds": "No photos in this area",
"map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?",
"map_no_location_permission_title": "Location Permission denied",
"map_settings_dark_mode": "Dark mode",
"map_settings_date_range_option_all": "All",
"map_settings_date_range_option_day": "Past 24 hours",
"map_settings_date_range_option_days": "Past {} days",
"map_settings_date_range_option_year": "Past year",
"map_settings_date_range_option_years": "Past {} years",
"map_settings_dialog_cancel": "Cancel",
"map_settings_dialog_save": "Save",
"map_settings_dialog_title": "Map Settings",
"map_settings_include_show_archived": "Include Archived",
"map_settings_include_show_partners": "Include Partners",
"map_settings_only_relative_range": "Date range",
"map_settings_only_show_favorites": "Show Favorite Only",
"map_settings_theme_settings": "Map Theme",
"map_zoom_to_see_photos": "Zoom out to see photos",
"memories_all_caught_up": "All caught up",
"memories_check_back_tomorrow": "Check back tomorrow for more memories",
"memories_start_over": "Start Over",
"memories_swipe_to_close": "Swipe up to close",
"memories_year_ago": "A year ago",
"memories_years_ago": "{} years ago",
"monthly_title_text_date_format": "MMMM y",
"motion_photos_page_title": "Motion Photos",
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
"my_albums": "My albums",
"networking_settings": "Networking",
"networking_subtitle": "Manage the server endpoint settings",
"no_assets_to_show": "No assets to show",
"no_name": "No name",
"notification_permission_dialog_cancel": "Cancel",
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
"notification_permission_dialog_settings": "Settings",
"notification_permission_list_tile_content": "Grant permission to enable notifications.",
"notification_permission_list_tile_enable_button": "Enable Notifications",
"notification_permission_list_tile_title": "Notification Permission",
"not_selected": "Not selected",
"on_this_device": "On this device",
"partner_list_user_photos": "{user}'s photos",
"partner_list_view_all": "View all",
"partner_page_add_partner": "Add partner",
"partner_page_empty_message": "Your photos are not yet shared with any partner.",
"partner_page_no_more_users": "No more users to add",
"partner_page_partner_add_failed": "Failed to add partner",
"partner_page_select_partner": "Select partner",
"partner_page_shared_to_title": "Shared to",
"partner_page_stop_sharing_content": "{} will no longer be able to access your photos.",
"partner_page_stop_sharing_title": "Stop sharing your photos?",
"partner_page_title": "Partner",
"partners": "Partners",
"paused": "Paused",
"people": "People",
"permission_onboarding_back": "Back",
"permission_onboarding_continue_anyway": "Continue anyway",
"permission_onboarding_get_started": "Get started",
"permission_onboarding_go_to_settings": "Go to settings",
"permission_onboarding_grant_permission": "Grant permission",
"permission_onboarding_log_out": "Log out",
"permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.",
"permission_onboarding_permission_granted": "Permission granted! You are all set.",
"permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.",
"permission_onboarding_request": "Immich requires permission to view your photos and videos.",
"places": "Places",
"preferences_settings_subtitle": "Manage the app's preferences",
"preferences_settings_title": "Preferences",
"profile_drawer_app_logs": "Logs",
"profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.",
"profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.",
"profile_drawer_client_server_up_to_date": "Client and Server are up-to-date",
"profile_drawer_documentation": "Documentation",
"profile_drawer_github": "GitHub",
"profile_drawer_server_out_of_date_major": "Server is out of date. Please update to the latest major version.",
"profile_drawer_server_out_of_date_minor": "Server is out of date. Please update to the latest minor version.",
"profile_drawer_settings": "Settings",
"profile_drawer_sign_out": "Sign Out",
"profile_drawer_trash": "Trash",
"recently_added": "Recently added",
"recently_added_page_title": "Recently Added",
"save": "Save",
"save_to_gallery": "Save to gallery",
"scaffold_body_error_occurred": "Error occurred",
"search_albums": "Search albums",
"search_bar_hint": "Search your photos",
"search_filter_apply": "Apply filter",
"search_filter_camera": "Camera",
"search_filter_camera_make": "Make",
"search_filter_camera_model": "Model",
"search_filter_camera_title": "Select camera type",
"search_filter_date": "Date",
"search_filter_date_interval": "{start} to {end}",
"search_filter_date_title": "Select a date range",
"search_filter_display_option_archive": "Archive",
"search_filter_display_option_favorite": "Favorite",
"search_filter_display_option_not_in_album": "Not in album",
"search_filter_display_options": "Display Options",
"search_filter_display_options_title": "Display options",
"search_filter_location": "Location",
"search_filter_location_city": "City",
"search_filter_location_country": "Country",
"search_filter_location_state": "State",
"search_filter_location_title": "Select location",
"search_filter_media_type": "Media Type",
"search_filter_media_type_all": "All",
"search_filter_media_type_image": "Image",
"search_filter_media_type_title": "Select media type",
"search_filter_media_type_video": "Video",
"search_filter_people": "People",
"search_filter_people_title": "Select people",
"search_page_categories": "Categories",
"search_page_favorites": "Favorites",
"search_page_motion_photos": "Motion Photos",
"search_page_no_objects": "No Objects Info Available",
"search_page_no_places": "No Places Info Available",
"search_page_people": "People",
"search_page_person_add_name_dialog_cancel": "Cancel",
"search_page_person_add_name_dialog_hint": "Name",
"search_page_person_add_name_dialog_save": "Save",
"search_page_person_add_name_dialog_title": "Add a name",
"search_page_person_add_name_subtitle": "Find them fast by name with search",
"search_page_person_add_name_title": "Add a name",
"search_page_person_edit_name": "Edit name",
"search_page_places": "Places",
"search_page_recently_added": "Recently added",
"search_page_screenshots": "Screenshots",
"search_page_search_photos_videos": "Search for your photos and videos",
"search_page_selfies": "Selfies",
"search_page_things": "Things",
"search_page_videos": "Videos",
"search_page_view_all_button": "View all",
"search_page_your_activity": "Your activity",
"search_page_your_map": "Your Map",
"search_result_page_new_search_hint": "New Search",
"search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ",
"search_suggestion_list_smart_search_hint_2": "m:your-search-term",
"select_additional_user_for_sharing_page_suggestions": "Suggestions",
"select_user_for_sharing_page_err_album": "Failed to create album",
"select_user_for_sharing_page_share_suggestions": "Suggestions",
"server_endpoint": "Server Endpoint",
"server_info_box_app_version": "App Version",
"server_info_box_latest_release": "Latest Version",
"server_info_box_server_url": "Server URL",
"server_info_box_server_version": "Server Version",
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
"setting_image_viewer_original_title": "Load original image",
"setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.",
"setting_image_viewer_preview_title": "Load preview image",
"setting_image_viewer_title": "Images",
"setting_languages_apply": "Apply",
"setting_languages_subtitle": "Change the app's language",
"setting_languages_title": "Languages",
"setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}",
"setting_notifications_notify_hours": "{} hours",
"setting_notifications_notify_immediately": "immediately",
"setting_notifications_notify_minutes": "{} minutes",
"setting_notifications_notify_never": "never",
"setting_notifications_notify_seconds": "{} seconds",
"setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset",
"setting_notifications_single_progress_title": "Show background backup detail progress",
"setting_notifications_subtitle": "Adjust your notification preferences",
"setting_notifications_title": "Notifications",
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
"setting_notifications_total_progress_title": "Show background backup total progress",
"setting_pages_app_bar_settings": "Settings",
"settings_require_restart": "Please restart Immich to apply this setting",
"setting_video_viewer_looping_subtitle": "Enable to automatically loop a video in the detail viewer.",
"setting_video_viewer_looping_title": "Looping",
"setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.",
"setting_video_viewer_original_video_title": "Force original video",
"setting_video_viewer_title": "Videos",
"share_add": "Add",
"share_add_photos": "Add photos",
"share_add_title": "Add a title",
"share_assets_selected": "{} selected",
"share_create_album": "Create album",
"shared_album_activities_input_disable": "Comment is disabled",
"shared_album_activities_input_hint": "Say something",
"shared_album_activity_remove_content": "Do you want to delete this activity?",
"shared_album_activity_remove_title": "Delete Activity",
"shared_album_activity_setting_subtitle": "Let others respond",
"shared_album_activity_setting_title": "Comments & likes",
"shared_album_section_people_action_error": "Error leaving/removing from album",
"shared_album_section_people_action_leave": "Remove user from album",
"shared_album_section_people_action_remove_user": "Remove user from album",
"shared_album_section_people_owner_label": "Owner",
"shared_album_section_people_title": "PEOPLE",
"share_dialog_preparing": "Preparing...",
"shared_intent_upload_button_progress_text": "{} / {} Uploaded",
"shared_link_app_bar_title": "Shared Links",
"shared_link_clipboard_copied_massage": "Copied to clipboard",
"shared_link_clipboard_text": "Link: {}\nPassword: {}",
"shared_link_create_app_bar_title": "Create link to share",
"shared_link_create_error": "Error while creating shared link",
"shared_link_create_info": "Let anyone with the link see the selected photo(s)",
"shared_link_create_submit_button": "Create link",
"shared_link_edit_allow_download": "Allow public user to download",
"shared_link_edit_allow_upload": "Allow public user to upload",
"shared_link_edit_app_bar_title": "Edit link",
"shared_link_edit_change_expiry": "Change expiration time",
"shared_link_edit_description": "Description",
"shared_link_edit_description_hint": "Enter the share description",
"shared_link_edit_expire_after": "Expire after",
"shared_link_edit_expire_after_option_day": "1 day",
"shared_link_edit_expire_after_option_days": "{} days",
"shared_link_edit_expire_after_option_hour": "1 hour",
"shared_link_edit_expire_after_option_hours": "{} hours",
"shared_link_edit_expire_after_option_minute": "1 minute",
"shared_link_edit_expire_after_option_minutes": "{} minutes",
"shared_link_edit_expire_after_option_months": "{} months",
"shared_link_edit_expire_after_option_never": "Never",
"shared_link_edit_expire_after_option_year": "{} year",
"shared_link_edit_password": "Password",
"shared_link_edit_password_hint": "Enter the share password",
"shared_link_edit_show_meta": "Show metadata",
"shared_link_edit_submit_button": "Update link",
"shared_link_empty": "You don't have any shared links",
"shared_link_error_server_url_fetch": "Cannot fetch the server url",
"shared_link_expired": "Expired",
"shared_link_expires_day": "Expires in {} day",
"shared_link_expires_days": "Expires in {} days",
"shared_link_expires_hour": "Expires in {} hour",
"shared_link_expires_hours": "Expires in {} hours",
"shared_link_expires_minute": "Expires in {} minute",
"shared_link_expires_minutes": "Expires in {} minutes",
"shared_link_expires_never": "Expires ∞",
"shared_link_expires_second": "Expires in {} second",
"shared_link_expires_seconds": "Expires in {} seconds",
"shared_link_individual_shared": "Individual shared",
"shared_link_info_chip_download": "Download",
"shared_link_info_chip_metadata": "EXIF",
"shared_link_info_chip_upload": "Upload",
"shared_link_manage_links": "Manage Shared links",
"shared_link_public_album": "Public album",
"shared_links": "Shared links",
"share_done": "Done",
"shared_with_me": "Shared with me",
"share_invite": "Invite to album",
"sharing_page_album": "Shared albums",
"sharing_page_description": "Create shared albums to share photos and videos with people in your network.",
"sharing_page_empty_list": "EMPTY LIST",
"sharing_silver_appbar_create_shared_album": "New shared album",
"sharing_silver_appbar_shared_links": "Shared links",
"sharing_silver_appbar_share_partner": "Share with partner",
"start_date": "Start date",
"sync": "Sync",
"sync_albums": "Sync albums",
"sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums",
"sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich",
"tab_controller_nav_library": "Library",
"tab_controller_nav_photos": "Photos",
"tab_controller_nav_search": "Search",
"tab_controller_nav_sharing": "Sharing",
"theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles",
"theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})",
"theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.",
"theme_setting_colorful_interface_title": "Colorful interface",
"theme_setting_dark_mode_switch": "Dark mode",
"theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
"theme_setting_image_viewer_quality_title": "Image viewer quality",
"theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.",
"theme_setting_primary_color_title": "Primary color",
"theme_setting_system_primary_color_title": "Use system color",
"theme_setting_system_theme_switch": "Automatic (Follow system setting)",
"theme_setting_theme_subtitle": "Choose the app's theme setting",
"theme_setting_theme_title": "Theme",
"theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load",
"theme_setting_three_stage_loading_title": "Enable three-stage loading",
"translated_text_options": "Options",
"trash": "Trash",
"trash_emptied": "Emptied trash",
"trash_page_delete": "Delete",
"trash_page_delete_all": "Delete All",
"trash_page_empty_trash_btn": "Empty trash",
"trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich",
"trash_page_empty_trash_dialog_ok": "Ok",
"trash_page_info": "Trashed items will be permanently deleted after {} days",
"trash_page_no_assets": "No trashed assets",
"trash_page_restore": "Restore",
"trash_page_restore_all": "Restore All",
"trash_page_select_assets_btn": "Select assets",
"trash_page_select_btn": "Select",
"trash_page_title": "Trash ({})",
"upload": "Upload",
"upload_dialog_cancel": "Cancel",
"upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?",
"upload_dialog_ok": "Upload",
"upload_dialog_title": "Upload Asset",
"uploading": "Uploading",
"upload_to_immich": "Upload to Immich ({})",
"use_current_connection": "use current connection",
"validate_endpoint_error": "Please enter a valid URL",
"version_announcement_overlay_ack": "Acknowledge",
"version_announcement_overlay_release_notes": "release notes",
"version_announcement_overlay_text_1": "Hi friend, there is a new release of",
"version_announcement_overlay_text_2": "please take your time to visit the ",
"version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
"version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89",
"videos": "Videos",
"viewer_remove_from_stack": "Remove from Stack",
"viewer_stack_use_as_main_asset": "Use as Main Asset",
"viewer_unstack": "Un-Stack",
"wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name"
}

View File

@@ -336,9 +336,9 @@
"login_form_back_button_text": "חזרה", "login_form_back_button_text": "חזרה",
"login_form_button_text": "התחברות", "login_form_button_text": "התחברות",
"login_form_email_hint": "yourmail@email.com", "login_form_email_hint": "yourmail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/API", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "כתובת נקודת קצה השרת", "login_form_endpoint_url": "כתובת נקודת קצה השרת",
"login_form_err_http": "נא לציין //:htttp או //:https", "login_form_err_http": "נא לציין //:http או //:https",
"login_form_err_invalid_email": "דוא\"ל שגוי", "login_form_err_invalid_email": "דוא\"ל שגוי",
"login_form_err_invalid_url": "כתובת לא חוקית", "login_form_err_invalid_url": "כתובת לא חוקית",
"login_form_err_leading_whitespace": "רווח לבן מוביל", "login_form_err_leading_whitespace": "רווח לבן מוביל",
@@ -670,4 +670,4 @@
"viewer_unstack": "ביטול ערימה", "viewer_unstack": "ביטול ערימה",
"wifi_name": "שם אינטרנט אלחוטי", "wifi_name": "שם אינטרנט אלחוטי",
"your_wifi_name": "שם אינטרנט אלחוטי שלך" "your_wifi_name": "שם אינטרנט אלחוטי שלך"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Vissza", "login_form_back_button_text": "Vissza",
"login_form_button_text": "Bejelentkezés", "login_form_button_text": "Bejelentkezés",
"login_form_email_hint": "email@cimed.hu", "login_form_email_hint": "email@cimed.hu",
"login_form_endpoint_hint": "http(s)://szerver-címe:port/api", "login_form_endpoint_hint": "http://szerver-címe:port",
"login_form_endpoint_url": "Szerver címe", "login_form_endpoint_url": "Szerver címe",
"login_form_err_http": "Kérjük, hogy egy http:// vagy https:// címet adj meg", "login_form_err_http": "Kérjük, hogy egy http:// vagy https:// címet adj meg",
"login_form_err_invalid_email": "Érvénytelen email cím", "login_form_err_invalid_email": "Érvénytelen email cím",
@@ -670,4 +670,4 @@
"viewer_unstack": "Csoport Megszűntetése", "viewer_unstack": "Csoport Megszűntetése",
"wifi_name": "WiFi Name", "wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name" "your_wifi_name": "Your WiFi name"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Kembali", "login_form_back_button_text": "Kembali",
"login_form_button_text": "Masuk", "login_form_button_text": "Masuk",
"login_form_email_hint": "emailmu@email.com", "login_form_email_hint": "emailmu@email.com",
"login_form_endpoint_hint": "http://ip-server-anda:port/api", "login_form_endpoint_hint": "http://ip-server-anda:port",
"login_form_endpoint_url": "URL Endpoint Server", "login_form_endpoint_url": "URL Endpoint Server",
"login_form_err_http": "Harap tentukan http:// atau https://", "login_form_err_http": "Harap tentukan http:// atau https://",
"login_form_err_invalid_email": "Email Tidak Valid", "login_form_err_invalid_email": "Email Tidak Valid",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Indietro", "login_form_back_button_text": "Indietro",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "tuaemail@email.com", "login_form_email_hint": "tuaemail@email.com",
"login_form_endpoint_hint": "http://ip-del-tuo-server:port/api", "login_form_endpoint_hint": "http://ip-del-tuo-server:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Per favore specificare http:// o https://", "login_form_err_http": "Per favore specificare http:// o https://",
"login_form_err_invalid_email": "Email non valida", "login_form_err_invalid_email": "Email non valida",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "戻る", "login_form_back_button_text": "戻る",
"login_form_button_text": "ログイン", "login_form_button_text": "ログイン",
"login_form_email_hint": "hoge@email.com", "login_form_email_hint": "hoge@email.com",
"login_form_endpoint_hint": "https://example.com:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "サーバーのエンドポイントURL", "login_form_endpoint_url": "サーバーのエンドポイントURL",
"login_form_err_http": "http://かhttps://かを指定してください", "login_form_err_http": "http://かhttps://かを指定してください",
"login_form_err_invalid_email": "メールアドレスが無効です", "login_form_err_invalid_email": "メールアドレスが無効です",
@@ -670,4 +670,4 @@
"viewer_unstack": "スタックを解除", "viewer_unstack": "スタックを解除",
"wifi_name": "Wi-Fiの名前(SSID)", "wifi_name": "Wi-Fiの名前(SSID)",
"your_wifi_name": "Wi-Fiの名前(SSID)" "your_wifi_name": "Wi-Fiの名前(SSID)"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "뒤로", "login_form_back_button_text": "뒤로",
"login_form_button_text": "로그인", "login_form_button_text": "로그인",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "서버 엔드포인트 URL", "login_form_endpoint_url": "서버 엔드포인트 URL",
"login_form_err_http": "http:// 또는 https://로 시작해야 합니다.", "login_form_err_http": "http:// 또는 https://로 시작해야 합니다.",
"login_form_err_invalid_email": "유효하지 않은 이메일", "login_form_err_invalid_email": "유효하지 않은 이메일",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Atpakaļ", "login_form_back_button_text": "Atpakaļ",
"login_form_button_text": "Pieteikties", "login_form_button_text": "Pieteikties",
"login_form_email_hint": "jūsuepasts@email.com", "login_form_email_hint": "jūsuepasts@email.com",
"login_form_endpoint_hint": "http://jūsu-servera-ip:ports/api", "login_form_endpoint_hint": "http://jūsu-servera-ip:ports",
"login_form_endpoint_url": "Servera Galapunkta URL", "login_form_endpoint_url": "Servera Galapunkta URL",
"login_form_err_http": "Lūdzu norādiet http:// vai https://", "login_form_err_http": "Lūdzu norādiet http:// vai https://",
"login_form_err_invalid_email": "Nederīgs e-pasts", "login_form_err_invalid_email": "Nederīgs e-pasts",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Tilbake", "login_form_back_button_text": "Tilbake",
"login_form_button_text": "Logg inn", "login_form_button_text": "Logg inn",
"login_form_email_hint": "dinepost@epost.no", "login_form_email_hint": "dinepost@epost.no",
"login_form_endpoint_hint": "http://din-server-ip:port/api", "login_form_endpoint_hint": "http://din-server-ip:port",
"login_form_endpoint_url": "Serverendepunkt-URL", "login_form_endpoint_url": "Serverendepunkt-URL",
"login_form_err_http": "Vennligst spesifiser http:// eller https://", "login_form_err_http": "Vennligst spesifiser http:// eller https://",
"login_form_err_invalid_email": "Ugyldig e-postadresse", "login_form_err_invalid_email": "Ugyldig e-postadresse",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Terug", "login_form_back_button_text": "Terug",
"login_form_button_text": "Inloggen", "login_form_button_text": "Inloggen",
"login_form_email_hint": "jouwemail@email.nl", "login_form_email_hint": "jouwemail@email.nl",
"login_form_endpoint_hint": "http://jouw-server-ip:poort/api", "login_form_endpoint_hint": "http://jouw-server-ip:poort",
"login_form_endpoint_url": "Server-URL", "login_form_endpoint_url": "Server-URL",
"login_form_err_http": "Voer http:// of https:// in", "login_form_err_http": "Voer http:// of https:// in",
"login_form_err_invalid_email": "Ongeldig e-mailadres", "login_form_err_invalid_email": "Ongeldig e-mailadres",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Cofnij", "login_form_back_button_text": "Cofnij",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "twojmail@email.com", "login_form_email_hint": "twojmail@email.com",
"login_form_endpoint_hint": "http://ip-twojego-serwera:port/api", "login_form_endpoint_hint": "http://ip-twojego-serwera:port",
"login_form_endpoint_url": "URL Serwera", "login_form_endpoint_url": "URL Serwera",
"login_form_err_http": "Proszę określić http:// lub https://", "login_form_err_http": "Proszę określić http:// lub https://",
"login_form_err_invalid_email": "Niepoprawny Email", "login_form_err_invalid_email": "Niepoprawny Email",

View File

@@ -74,7 +74,7 @@
"exif_bottom_sheet_location": "LOCALIZAÇÃO", "exif_bottom_sheet_location": "LOCALIZAÇÃO",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "E-mail inválido", "login_form_err_invalid_email": "E-mail inválido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Voltar", "login_form_back_button_text": "Voltar",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "seuemail@email.com", "login_form_email_hint": "seuemail@email.com",
"login_form_endpoint_hint": "http://ip-do-seu-servidor:porta/api", "login_form_endpoint_hint": "http://ip-do-seu-servidor:porta",
"login_form_endpoint_url": "URL do servidor", "login_form_endpoint_url": "URL do servidor",
"login_form_err_http": "Por favor especifique http:// ou https://", "login_form_err_http": "Por favor especifique http:// ou https://",
"login_form_err_invalid_email": "Email Inválido", "login_form_err_invalid_email": "Email Inválido",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Înapoi", "login_form_back_button_text": "Înapoi",
"login_form_button_text": "Conectare", "login_form_button_text": "Conectare",
"login_form_email_hint": "email-ultau@email.com", "login_form_email_hint": "email-ultau@email.com",
"login_form_endpoint_hint": "http://ip-server:port/api", "login_form_endpoint_hint": "http://ip-server:port",
"login_form_endpoint_url": "URL-ul destinației sever-ului", "login_form_endpoint_url": "URL-ul destinației sever-ului",
"login_form_err_http": "Te rugăm specifică http:// sau https://", "login_form_err_http": "Te rugăm specifică http:// sau https://",
"login_form_err_invalid_email": "Email invalid", "login_form_err_invalid_email": "Email invalid",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Назад", "login_form_back_button_text": "Назад",
"login_form_button_text": "Войти", "login_form_button_text": "Войти",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "URL-aдрес сервера", "login_form_endpoint_url": "URL-aдрес сервера",
"login_form_err_http": "Пожалуйста, укажите протокол http:// или https://", "login_form_err_http": "Пожалуйста, укажите протокол http:// или https://",
"login_form_err_invalid_email": "Некорректный адрес электронной почты", "login_form_err_invalid_email": "Некорректный адрес электронной почты",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Späť", "login_form_back_button_text": "Späť",
"login_form_button_text": "Prihlásiť sa", "login_form_button_text": "Prihlásiť sa",
"login_form_email_hint": "tvojmail@email.com", "login_form_email_hint": "tvojmail@email.com",
"login_form_endpoint_hint": "http://ip-tvojho-servera:port/api", "login_form_endpoint_hint": "http://ip-tvojho-servera:port",
"login_form_endpoint_url": "URL adresa servera", "login_form_endpoint_url": "URL adresa servera",
"login_form_err_http": "Prosím, uveďte http:// alebo https://", "login_form_err_http": "Prosím, uveďte http:// alebo https://",
"login_form_err_invalid_email": "Neplatný e-mail", "login_form_err_invalid_email": "Neplatný e-mail",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Nazaj", "login_form_back_button_text": "Nazaj",
"login_form_button_text": "Prijava", "login_form_button_text": "Prijava",
"login_form_email_hint": "vašemail@email.com", "login_form_email_hint": "vašemail@email.com",
"login_form_endpoint_hint": "http://ip-vašega-strežnika:vrata/api", "login_form_endpoint_hint": "http://ip-vašega-strežnika:vrata",
"login_form_endpoint_url": "URL končne točke strežnika", "login_form_endpoint_url": "URL končne točke strežnika",
"login_form_err_http": "Navedi http:// ali https://", "login_form_err_http": "Navedi http:// ali https://",
"login_form_err_invalid_email": "Neveljaven e-poštni naslov", "login_form_err_invalid_email": "Neveljaven e-poštni naslov",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Prijavi se", "login_form_button_text": "Prijavi se",
"login_form_email_hint": "vašemail@email.com", "login_form_email_hint": "vašemail@email.com",
"login_form_endpoint_hint": "http://ip-vašeg-servera:port/api", "login_form_endpoint_hint": "http://ip-vašeg-servera:port",
"login_form_endpoint_url": "URL Servera", "login_form_endpoint_url": "URL Servera",
"login_form_err_http": "Dopiši http:// ili https://", "login_form_err_http": "Dopiši http:// ili https://",
"login_form_err_invalid_email": "Nevažeći Email", "login_form_err_invalid_email": "Nevažeći Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Back", "login_form_back_button_text": "Back",
"login_form_button_text": "Login", "login_form_button_text": "Login",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Please specify http:// or https://", "login_form_err_http": "Please specify http:// or https://",
"login_form_err_invalid_email": "Invalid Email", "login_form_err_invalid_email": "Invalid Email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Bakåt", "login_form_back_button_text": "Bakåt",
"login_form_button_text": "Logga in", "login_form_button_text": "Logga in",
"login_form_email_hint": "din.email@email.com", "login_form_email_hint": "din.email@email.com",
"login_form_endpoint_hint": "http://din-server-ip:port/api", "login_form_endpoint_hint": "http://din-server-ip:port",
"login_form_endpoint_url": "Server Endpoint URL", "login_form_endpoint_url": "Server Endpoint URL",
"login_form_err_http": "Var god ange http:// eller https://", "login_form_err_http": "Var god ange http:// eller https://",
"login_form_err_invalid_email": "Ogiltig email", "login_form_err_invalid_email": "Ogiltig email",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "กลับ", "login_form_back_button_text": "กลับ",
"login_form_button_text": "เข้าสู่ระบบ", "login_form_button_text": "เข้าสู่ระบบ",
"login_form_email_hint": "อีเมลคุณ@อีเมล.com", "login_form_email_hint": "อีเมลคุณ@อีเมล.com",
"login_form_endpoint_hint": "http://ไอพีเชอร์ฟเวอร์คุณ:พอร์ต/api", "login_form_endpoint_hint": "http://ไอพีเชอร์ฟเวอร์คุณ:พอร์ต",
"login_form_endpoint_url": "URL ปลายทางของเซิร์ฟเวอร์", "login_form_endpoint_url": "URL ปลายทางของเซิร์ฟเวอร์",
"login_form_err_http": "โปรดระบุ http:// หรือ https://", "login_form_err_http": "โปรดระบุ http:// หรือ https://",
"login_form_err_invalid_email": "อีเมลไม่ถูกต้อง", "login_form_err_invalid_email": "อีเมลไม่ถูกต้อง",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Geri", "login_form_back_button_text": "Geri",
"login_form_button_text": "Giriş", "login_form_button_text": "Giriş",
"login_form_email_hint": "mail@adresiniz.com", "login_form_email_hint": "mail@adresiniz.com",
"login_form_endpoint_hint": "http://sunucu-ip:port/api", "login_form_endpoint_hint": "http://sunucu-ip:port",
"login_form_endpoint_url": "Sunucu Uç Nokta URL", "login_form_endpoint_url": "Sunucu Uç Nokta URL",
"login_form_err_http": "Lütfen http:// veya https:// olarak belirtin", "login_form_err_http": "Lütfen http:// veya https:// olarak belirtin",
"login_form_err_invalid_email": "Geçersiz E-posta", "login_form_err_invalid_email": "Geçersiz E-posta",

View File

@@ -7,10 +7,10 @@
"action_common_select": "Вибрати", "action_common_select": "Вибрати",
"action_common_update": "Оновити", "action_common_update": "Оновити",
"add_a_name": "Додати ім'я", "add_a_name": "Додати ім'я",
"add_endpoint": "Add endpoint", "add_endpoint": "Додати кінцеву точку",
"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}",
"advanced_settings_log_level_title": "Log level: {}", "advanced_settings_log_level_title": "Рівень журналу: {}",
"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 має надсилати з кожним мережевим запитом.",
@@ -66,12 +66,12 @@
"assets_restored_successfully": "{} елемент(и) успішно відновлено", "assets_restored_successfully": "{} елемент(и) успішно відновлено",
"assets_trashed": "{} елемент(и) поміщено до кошика", "assets_trashed": "{} елемент(и) поміщено до кошика",
"assets_trashed_from_server": "{} елемент(и) поміщено до кошика на сервері Immich", "assets_trashed_from_server": "{} елемент(и) поміщено до кошика на сервері Immich",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings", "asset_viewer_settings_subtitle": "Керувати налаштуваннями переглядача галереї",
"asset_viewer_settings_title": "Переглядач зображень", "asset_viewer_settings_title": "Переглядач зображень",
"automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", "automatic_endpoint_switching_subtitle": "Підключатися локально через визначену Wi-Fi мережу, коли вона доступна, і використовувати альтернативні з'єднання в інших випадках",
"automatic_endpoint_switching_title": "Automatic URL switching", "automatic_endpoint_switching_title": "Автоперемикання URL-адрес",
"background_location_permission": "Background location permission", "background_location_permission": "Дозвіл на місцезнаходження у фоні",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", "background_location_permission_content": "Щоб перемикатися між мережами під час роботи у фоновому режимі, Immich *завжди* повинен мати доступ до точного місцезнаходження, щоб додаток міг зчитувати назву Wi-Fi мережі",
"backup_album_selection_page_albums_device": "Альбоми на пристрої ({})", "backup_album_selection_page_albums_device": "Альбоми на пристрої ({})",
"backup_album_selection_page_albums_tap": "Торкніться, щоб включити,\nторкніться двічі, щоб виключити", "backup_album_selection_page_albums_tap": "Торкніться, щоб включити,\nторкніться двічі, щоб виключити",
"backup_album_selection_page_assets_scatter": "Елементи можуть належати до кількох альбомів водночас. Таким чином, альбоми можуть бути включені або вилучені під час резервного копіювання.", "backup_album_selection_page_assets_scatter": "Елементи можуть належати до кількох альбомів водночас. Таким чином, альбоми можуть бути включені або вилучені під час резервного копіювання.",
@@ -137,7 +137,7 @@
"backup_manual_success": "Успіх", "backup_manual_success": "Успіх",
"backup_manual_title": "Стан завантаження", "backup_manual_title": "Стан завантаження",
"backup_options_page_title": "Резервне копіювання", "backup_options_page_title": "Резервне копіювання",
"backup_setting_subtitle": "Manage background and foreground upload settings", "backup_setting_subtitle": "Керування завантаженням у фоновому та передньому режимах",
"cache_settings_album_thumbnails": "Мініатюри сторінок бібліотеки ({} елементи)", "cache_settings_album_thumbnails": "Мініатюри сторінок бібліотеки ({} елементи)",
"cache_settings_clear_cache_button": "Очистити кеш", "cache_settings_clear_cache_button": "Очистити кеш",
"cache_settings_clear_cache_button_title": "Очищає кеш програми. Це суттєво знизить продуктивність програми, доки кеш не буде перебудовано.", "cache_settings_clear_cache_button_title": "Очищає кеш програми. Це суттєво знизить продуктивність програми, доки кеш не буде перебудовано.",
@@ -156,17 +156,17 @@
"cache_settings_tile_subtitle": "Керування поведінкою локального сховища", "cache_settings_tile_subtitle": "Керування поведінкою локального сховища",
"cache_settings_tile_title": "Локальне сховище", "cache_settings_tile_title": "Локальне сховище",
"cache_settings_title": "Налаштування кешування", "cache_settings_title": "Налаштування кешування",
"cancel": "Cancel", "cancel": "Скасувати",
"canceled": "Canceled", "canceled": "Скасовано",
"change_display_order": "Change display order", "change_display_order": "Змінити порядок відображення",
"change_password_form_confirm_password": "Підтвердити пароль", "change_password_form_confirm_password": "Підтвердити пароль",
"change_password_form_description": "Привіт {name},\n\nВи або або вперше входите у систему, або було зроблено запит на зміну вашого пароля. \nВведіть ваш новий пароль.", "change_password_form_description": "Привіт {name},\n\nВи або або вперше входите у систему, або було зроблено запит на зміну вашого пароля. \nВведіть ваш новий пароль.",
"change_password_form_new_password": "Новий пароль", "change_password_form_new_password": "Новий пароль",
"change_password_form_password_mismatch": "Паролі не співпадають", "change_password_form_password_mismatch": "Паролі не співпадають",
"change_password_form_reenter_new_password": "Повторіть новий пароль", "change_password_form_reenter_new_password": "Повторіть новий пароль",
"check_corrupt_asset_backup": "Check for corrupt asset backups", "check_corrupt_asset_backup": "Перевірити пошкоджені резервні копії",
"check_corrupt_asset_backup_button": "Perform check", "check_corrupt_asset_backup_button": "Виконати перевірку",
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "check_corrupt_asset_backup_description": "Виконуйте цю перевірку лише через Wi-Fi та після того, як усі активи будуть заархівовані. Процес може зайняти кілька хвилин.",
"client_cert_dialog_msg_confirm": "OK", "client_cert_dialog_msg_confirm": "OK",
"client_cert_enter_password": "Введіть пароль", "client_cert_enter_password": "Введіть пароль",
"client_cert_import": "Імпорт", "client_cert_import": "Імпорт",
@@ -181,7 +181,7 @@
"common_create_new_album": "Створити новий альбом", "common_create_new_album": "Створити новий альбом",
"common_server_error": "Будь ласка, перевірте з'єднання, переконайтеся, що сервер доступний і версія програми/сервера сумісна.", "common_server_error": "Будь ласка, перевірте з'єднання, переконайтеся, що сервер доступний і версія програми/сервера сумісна.",
"common_shared": "Спільні", "common_shared": "Спільні",
"completed": "Completed", "completed": "Завершено",
"contextual_search": "Схід сонця на пляжі", "contextual_search": "Схід сонця на пляжі",
"control_bottom_app_bar_add_to_album": "Додати у альбом", "control_bottom_app_bar_add_to_album": "Додати у альбом",
"control_bottom_app_bar_album_info": "{} елементи", "control_bottom_app_bar_album_info": "{} елементи",
@@ -199,7 +199,7 @@
"control_bottom_app_bar_share": "Поділитися", "control_bottom_app_bar_share": "Поділитися",
"control_bottom_app_bar_share_to": "Поділитися", "control_bottom_app_bar_share_to": "Поділитися",
"control_bottom_app_bar_stack": "Стек", "control_bottom_app_bar_stack": "Стек",
"control_bottom_app_bar_trash_from_immich": "Перемістити до кошика", "control_bottom_app_bar_trash_from_immich": "В кошик",
"control_bottom_app_bar_unarchive": "Розархівувати", "control_bottom_app_bar_unarchive": "Розархівувати",
"control_bottom_app_bar_unfavorite": "Видалити з улюблених", "control_bottom_app_bar_unfavorite": "Видалити з улюблених",
"control_bottom_app_bar_upload": "Завантажити", "control_bottom_app_bar_upload": "Завантажити",
@@ -213,7 +213,7 @@
"crop": "Кадрувати", "crop": "Кадрувати",
"curated_location_page_title": "Місця", "curated_location_page_title": "Місця",
"curated_object_page_title": "Речі", "curated_object_page_title": "Речі",
"current_server_address": "Current server address", "current_server_address": "Поточна адреса сервера",
"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",
"date_format": "E, LLL d, y • h:mm a", "date_format": "E, LLL d, y • h:mm a",
@@ -250,10 +250,10 @@
"edit_date_time_dialog_timezone": "Часовий пояс", "edit_date_time_dialog_timezone": "Часовий пояс",
"edit_image_title": "Редагувати", "edit_image_title": "Редагувати",
"edit_location_dialog_title": "Місцезнаходження", "edit_location_dialog_title": "Місцезнаходження",
"end_date": "End date", "end_date": "Дата завершення",
"enqueued": "Enqueued", "enqueued": "В черзі",
"enter_wifi_name": "Enter WiFi name", "enter_wifi_name": "Введіть назву Wi-Fi",
"error_change_sort_album": "Failed to change album sort order", "error_change_sort_album": "Не вдалося змінити порядок сортування альбому",
"error_saving_image": "Помилка: {}", "error_saving_image": "Помилка: {}",
"exif_bottom_sheet_description": "Додати опис...", "exif_bottom_sheet_description": "Додати опис...",
"exif_bottom_sheet_details": "ПОДРОБИЦІ", "exif_bottom_sheet_details": "ПОДРОБИЦІ",
@@ -265,16 +265,16 @@
"experimental_settings_new_asset_list_title": "Експериментальний макет знімків", "experimental_settings_new_asset_list_title": "Експериментальний макет знімків",
"experimental_settings_subtitle": "На власний ризик!", "experimental_settings_subtitle": "На власний ризик!",
"experimental_settings_title": "Експериментальні", "experimental_settings_title": "Експериментальні",
"external_network": "External network", "external_network": "Зовнішня мережа",
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "external_network_sheet_info": "Якщо ви не підключені до бажаної Wi-Fi мережі, додаток підключиться до сервера через першу доступну URL-адресу зверху вниз",
"failed": "Failed", "failed": "Не вдалося",
"favorites": "Вибране", "favorites": "Вибране",
"favorites_page_no_favorites": "Немає улюблених елементів", "favorites_page_no_favorites": "Немає улюблених елементів",
"favorites_page_title": "Улюблені", "favorites_page_title": "Улюблені",
"filename_search": "Ім'я або розширення файлу", "filename_search": "Ім'я або розширення файлу",
"filter": "Фільтр", "filter": "Фільтр",
"get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", "get_wifiname_error": "Не вдалося отримати назву Wi-Fi мережі. Переконайтеся, що ви надали необхідні дозволи та підключені до Wi-Fi мережі",
"grant_permission": "Grant permission", "grant_permission": "Надати дозвіл",
"haptic_feedback_switch": "Увімкнути тактильну віддачу", "haptic_feedback_switch": "Увімкнути тактильну віддачу",
"haptic_feedback_title": "Тактильна віддача", "haptic_feedback_title": "Тактильна віддача",
"header_settings_add_header_tip": "Додати заголовок", "header_settings_add_header_tip": "Додати заголовок",
@@ -320,10 +320,10 @@
"library_page_sort_most_oldest_photo": "Найдавніші фото", "library_page_sort_most_oldest_photo": "Найдавніші фото",
"library_page_sort_most_recent_photo": "Найновіші фото", "library_page_sort_most_recent_photo": "Найновіші фото",
"library_page_sort_title": "Назва альбому", "library_page_sort_title": "Назва альбому",
"local_network": "Local network", "local_network": "Локальна мережа",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", "local_network_sheet_info": "Додаток підключатиметься до сервера через цю URL-адресу при використанні вказаної Wi-Fi мережі",
"location_permission": "Location permission", "location_permission": "Дозвіл до місцезнаходження",
"location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", "location_permission_content": "Для використання функції автоперемикання Immich потрібен дозвіл на точне місцезнаходження, щоб зчитувати назву поточної Wi-Fi мережі",
"location_picker_choose_on_map": "Обрати на мапі", "location_picker_choose_on_map": "Обрати на мапі",
"location_picker_latitude": "Широта", "location_picker_latitude": "Широта",
"location_picker_latitude_error": "Вкажіть дійсну широту", "location_picker_latitude_error": "Вкажіть дійсну широту",
@@ -336,7 +336,7 @@
"login_form_back_button_text": "Назад", "login_form_back_button_text": "Назад",
"login_form_button_text": "Увійти", "login_form_button_text": "Увійти",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_endpoint_hint": "http://your-server-ip:port",
"login_form_endpoint_url": "Адреса точки досупу на сервері", "login_form_endpoint_url": "Адреса точки досупу на сервері",
"login_form_err_http": "Вкажіть http:// або https://", "login_form_err_http": "Вкажіть http:// або https://",
"login_form_err_invalid_email": "Хибний імейл", "login_form_err_invalid_email": "Хибний імейл",
@@ -393,8 +393,8 @@
"multiselect_grid_edit_date_time_err_read_only": "Неможливо редагувати дату елементів лише для читання, пропущено", "multiselect_grid_edit_date_time_err_read_only": "Неможливо редагувати дату елементів лише для читання, пропущено",
"multiselect_grid_edit_gps_err_read_only": "Неможливо редагувати місцезнаходження елементів лише для читання, пропущено", "multiselect_grid_edit_gps_err_read_only": "Неможливо редагувати місцезнаходження елементів лише для читання, пропущено",
"my_albums": "Мої альбоми", "my_albums": "Мої альбоми",
"networking_settings": "Networking", "networking_settings": "Мережа",
"networking_subtitle": "Manage the server endpoint settings", "networking_subtitle": "Керувати налаштуваннями кінцевої точки сервера",
"no_assets_to_show": "Елементи відсутні", "no_assets_to_show": "Елементи відсутні",
"no_name": "Без імені", "no_name": "Без імені",
"notification_permission_dialog_cancel": "Скасувати", "notification_permission_dialog_cancel": "Скасувати",
@@ -403,7 +403,7 @@
"notification_permission_list_tile_content": "Надати дозвіл для сповіщень.", "notification_permission_list_tile_content": "Надати дозвіл для сповіщень.",
"notification_permission_list_tile_enable_button": "Увімкнути Сповіщення", "notification_permission_list_tile_enable_button": "Увімкнути Сповіщення",
"notification_permission_list_tile_title": "Дозвіл на Сповіщення", "notification_permission_list_tile_title": "Дозвіл на Сповіщення",
"not_selected": "Not selected", "not_selected": "Не вибрано",
"on_this_device": "На цьому пристрої", "on_this_device": "На цьому пристрої",
"partner_list_user_photos": "Фотографії {user}", "partner_list_user_photos": "Фотографії {user}",
"partner_list_view_all": "Переглянути усі", "partner_list_view_all": "Переглянути усі",
@@ -417,7 +417,7 @@
"partner_page_stop_sharing_title": "Припинити надання ваших знімків?", "partner_page_stop_sharing_title": "Припинити надання ваших знімків?",
"partner_page_title": "Партнер", "partner_page_title": "Партнер",
"partners": "\nПартнери", "partners": "\nПартнери",
"paused": "Paused", "paused": "Призупинено",
"people": "Люди", "people": "Люди",
"permission_onboarding_back": "Назад", "permission_onboarding_back": "Назад",
"permission_onboarding_continue_anyway": "Все одно продовжити", "permission_onboarding_continue_anyway": "Все одно продовжити",
@@ -430,7 +430,7 @@
"permission_onboarding_permission_limited": "Обмежений доступ. Аби дозволити Immich резервне копіювання та керування вашою галереєю, надайте доступ до знімків та відео у Налаштуваннях", "permission_onboarding_permission_limited": "Обмежений доступ. Аби дозволити Immich резервне копіювання та керування вашою галереєю, надайте доступ до знімків та відео у Налаштуваннях",
"permission_onboarding_request": "Immich потребує доступу до ваших знімків та відео.", "permission_onboarding_request": "Immich потребує доступу до ваших знімків та відео.",
"places": "Місця", "places": "Місця",
"preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_subtitle": "Керувати налаштуваннями додатка",
"preferences_settings_title": "Параметри", "preferences_settings_title": "Параметри",
"profile_drawer_app_logs": "Журнал", "profile_drawer_app_logs": "Журнал",
"profile_drawer_client_out_of_date_major": "Мобільний додаток застарів. Будь ласка, оновіть до останньої мажорної версії.", "profile_drawer_client_out_of_date_major": "Мобільний додаток застарів. Будь ласка, оновіть до останньої мажорної версії.",
@@ -445,7 +445,7 @@
"profile_drawer_trash": "Кошик", "profile_drawer_trash": "Кошик",
"recently_added": "Нещодавно додані", "recently_added": "Нещодавно додані",
"recently_added_page_title": "Нещодавні", "recently_added_page_title": "Нещодавні",
"save": "Save", "save": "Зберегти",
"save_to_gallery": "Зберегти в галерею", "save_to_gallery": "Зберегти в галерею",
"scaffold_body_error_occurred": "Виникла помилка", "scaffold_body_error_occurred": "Виникла помилка",
"search_albums": "Пошук альбому", "search_albums": "Пошук альбому",
@@ -491,7 +491,7 @@
"search_page_places": "Місця", "search_page_places": "Місця",
"search_page_recently_added": "Нещодавно додані", "search_page_recently_added": "Нещодавно додані",
"search_page_screenshots": "Знімки екрану", "search_page_screenshots": "Знімки екрану",
"search_page_search_photos_videos": "Search for your photos and videos", "search_page_search_photos_videos": "Шукайте ваші фотографії та відео",
"search_page_selfies": "Селфі", "search_page_selfies": "Селфі",
"search_page_things": "Речі", "search_page_things": "Речі",
"search_page_videos": "Відео", "search_page_videos": "Відео",
@@ -504,7 +504,7 @@
"select_additional_user_for_sharing_page_suggestions": "Пропозиції", "select_additional_user_for_sharing_page_suggestions": "Пропозиції",
"select_user_for_sharing_page_err_album": "Не вдалося створити альбом", "select_user_for_sharing_page_err_album": "Не вдалося створити альбом",
"select_user_for_sharing_page_share_suggestions": "Пропозиції", "select_user_for_sharing_page_share_suggestions": "Пропозиції",
"server_endpoint": "Server Endpoint", "server_endpoint": "Кінцева точка сервера",
"server_info_box_app_version": "Версія додатка", "server_info_box_app_version": "Версія додатка",
"server_info_box_latest_release": "Остання версія", "server_info_box_latest_release": "Остання версія",
"server_info_box_server_url": "URL сервера", "server_info_box_server_url": "URL сервера",
@@ -516,7 +516,7 @@
"setting_image_viewer_preview_title": "Завантажувати зображення попереднього перегляду", "setting_image_viewer_preview_title": "Завантажувати зображення попереднього перегляду",
"setting_image_viewer_title": "Зображення", "setting_image_viewer_title": "Зображення",
"setting_languages_apply": "Застосувати", "setting_languages_apply": "Застосувати",
"setting_languages_subtitle": "Change the app's language", "setting_languages_subtitle": "Змінити мову додатка",
"setting_languages_title": "Мова", "setting_languages_title": "Мова",
"setting_notifications_notify_failures_grace_period": "Повідомити про помилки фонового резервного копіювання: {}", "setting_notifications_notify_failures_grace_period": "Повідомити про помилки фонового резервного копіювання: {}",
"setting_notifications_notify_hours": "{} годин", "setting_notifications_notify_hours": "{} годин",
@@ -534,8 +534,8 @@
"settings_require_restart": "Перезавантажте програму для застосування цього налаштування", "settings_require_restart": "Перезавантажте програму для застосування цього налаштування",
"setting_video_viewer_looping_subtitle": "Увімкнути циклічне відтворення відео", "setting_video_viewer_looping_subtitle": "Увімкнути циклічне відтворення відео",
"setting_video_viewer_looping_title": "Циклічне відтворення", "setting_video_viewer_looping_title": "Циклічне відтворення",
"setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.", "setting_video_viewer_original_video_subtitle": "При трансляції відео з сервера відтворювати оригінал, навіть якщо доступне транскодоване відео. Це може призвести до буферизації. Відео, доступні локально, відтворюються в оригінальній якості, незалежно від цього налаштування.",
"setting_video_viewer_original_video_title": "Force original video", "setting_video_viewer_original_video_title": "Примусово відтворювати оригінальне відео",
"setting_video_viewer_title": "Відео", "setting_video_viewer_title": "Відео",
"share_add": "Додати", "share_add": "Додати",
"share_add_photos": "Додати знімки", "share_add_photos": "Додати знімки",
@@ -554,7 +554,7 @@
"shared_album_section_people_owner_label": "Власник", "shared_album_section_people_owner_label": "Власник",
"shared_album_section_people_title": "ЛЮДИ", "shared_album_section_people_title": "ЛЮДИ",
"share_dialog_preparing": "Підготовка...", "share_dialog_preparing": "Підготовка...",
"shared_intent_upload_button_progress_text": "{} / {} Uploaded", "shared_intent_upload_button_progress_text": "{} / {} Завантажено",
"shared_link_app_bar_title": "Спільні посилання", "shared_link_app_bar_title": "Спільні посилання",
"shared_link_clipboard_copied_massage": "Скопійовано в буфер обміну", "shared_link_clipboard_copied_massage": "Скопійовано в буфер обміну",
"shared_link_clipboard_text": "Посилання: {}\nПароль: {}", "shared_link_clipboard_text": "Посилання: {}\nПароль: {}",
@@ -649,15 +649,15 @@
"trash_page_select_assets_btn": "Вибрані елементи", "trash_page_select_assets_btn": "Вибрані елементи",
"trash_page_select_btn": "Вибрати", "trash_page_select_btn": "Вибрати",
"trash_page_title": "Кошик ({})", "trash_page_title": "Кошик ({})",
"upload": "Upload", "upload": "Завантажити",
"upload_dialog_cancel": "Скасувати", "upload_dialog_cancel": "Скасувати",
"upload_dialog_info": "Бажаєте створити резервну копію вибраних елементів на сервері?", "upload_dialog_info": "Бажаєте створити резервну копію вибраних елементів на сервері?",
"upload_dialog_ok": "Завантажити", "upload_dialog_ok": "Завантажити",
"upload_dialog_title": "Завантажити Елементи", "upload_dialog_title": "Завантажити Елементи",
"uploading": "Uploading", "uploading": "Завантажується",
"upload_to_immich": "Upload to Immich ({})", "upload_to_immich": "Завантажити в Immich ({})",
"use_current_connection": "use current connection", "use_current_connection": "використовувати поточне з'єднання",
"validate_endpoint_error": "Please enter a valid URL", "validate_endpoint_error": "Будь ласка, введіть дійсну URL-адресу.",
"version_announcement_overlay_ack": "Прийняти", "version_announcement_overlay_ack": "Прийняти",
"version_announcement_overlay_release_notes": "примітки до випуску", "version_announcement_overlay_release_notes": "примітки до випуску",
"version_announcement_overlay_text_1": "Вітаємо, є новий випуск ", "version_announcement_overlay_text_1": "Вітаємо, є новий випуск ",
@@ -668,6 +668,6 @@
"viewer_remove_from_stack": "Видалити зі стеку", "viewer_remove_from_stack": "Видалити зі стеку",
"viewer_stack_use_as_main_asset": "Використовувати як основний елементи", "viewer_stack_use_as_main_asset": "Використовувати як основний елементи",
"viewer_unstack": "Розібрати стек", "viewer_unstack": "Розібрати стек",
"wifi_name": "WiFi Name", "wifi_name": "Назва Wi-Fi",
"your_wifi_name": "Your WiFi name" "your_wifi_name": "Ваша Wi-Fi мережа"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "Quay lại", "login_form_back_button_text": "Quay lại",
"login_form_button_text": "Đăng nhập", "login_form_button_text": "Đăng nhập",
"login_form_email_hint": "emailcuaban@email.com", "login_form_email_hint": "emailcuaban@email.com",
"login_form_endpoint_hint": "http://địa-chỉ-ip-máy-chủ-bạn:cổng/api", "login_form_endpoint_hint": "http://địa-chỉ-ip-máy-chủ-bạn:cổng",
"login_form_endpoint_url": "Địa chỉ máy chủ", "login_form_endpoint_url": "Địa chỉ máy chủ",
"login_form_err_http": "Vui lòng xác định http:// hoặc https://", "login_form_err_http": "Vui lòng xác định http:// hoặc https://",
"login_form_err_invalid_email": "Email không hợp lệ", "login_form_err_invalid_email": "Email không hợp lệ",

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "后退", "login_form_back_button_text": "后退",
"login_form_button_text": "登录", "login_form_button_text": "登录",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http(s)://您的服务器地址:端口/api", "login_form_endpoint_hint": "http://您的服务器地址:端口",
"login_form_endpoint_url": "服务器链接地址", "login_form_endpoint_url": "服务器链接地址",
"login_form_err_http": "请注明 http:// 或 https://", "login_form_err_http": "请注明 http:// 或 https://",
"login_form_err_invalid_email": "无效的电子邮箱", "login_form_err_invalid_email": "无效的电子邮箱",
@@ -670,4 +670,4 @@
"viewer_unstack": "取消堆叠", "viewer_unstack": "取消堆叠",
"wifi_name": "Wi-Fi 名称", "wifi_name": "Wi-Fi 名称",
"your_wifi_name": "您的 Wi-Fi 名称" "your_wifi_name": "您的 Wi-Fi 名称"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "后退", "login_form_back_button_text": "后退",
"login_form_button_text": "登录", "login_form_button_text": "登录",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http(s)://您的服务器地址:端口/api", "login_form_endpoint_hint": "http://您的服务器地址:端口",
"login_form_endpoint_url": "服务器链接地址", "login_form_endpoint_url": "服务器链接地址",
"login_form_err_http": "请注明 http:// 或 https://", "login_form_err_http": "请注明 http:// 或 https://",
"login_form_err_invalid_email": "无效的电子邮箱", "login_form_err_invalid_email": "无效的电子邮箱",
@@ -670,4 +670,4 @@
"viewer_unstack": "取消堆叠", "viewer_unstack": "取消堆叠",
"wifi_name": "Wi-Fi 名称", "wifi_name": "Wi-Fi 名称",
"your_wifi_name": "您的 Wi-Fi 名称" "your_wifi_name": "您的 Wi-Fi 名称"
} }

View File

@@ -336,7 +336,7 @@
"login_form_back_button_text": "後退", "login_form_back_button_text": "後退",
"login_form_button_text": "登入", "login_form_button_text": "登入",
"login_form_email_hint": "youremail@email.com", "login_form_email_hint": "youremail@email.com",
"login_form_endpoint_hint": "http(s)://您的伺服器地址:端口/api", "login_form_endpoint_hint": "http://您的伺服器地址:端口",
"login_form_endpoint_url": "伺服器鏈接地址", "login_form_endpoint_url": "伺服器鏈接地址",
"login_form_err_http": "請注明 http:// 或 https://", "login_form_err_http": "請注明 http:// 或 https://",
"login_form_err_invalid_email": "電郵無效", "login_form_err_invalid_email": "電郵無效",
@@ -670,4 +670,4 @@
"viewer_unstack": "取消堆疊", "viewer_unstack": "取消堆疊",
"wifi_name": "WiFi Name", "wifi_name": "WiFi Name",
"your_wifi_name": "Your WiFi name" "your_wifi_name": "Your WiFi name"
} }

View File

@@ -541,7 +541,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -685,7 +685,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -715,7 +715,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 187; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@@ -748,7 +748,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -791,7 +791,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -831,7 +831,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 190;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;

View File

@@ -78,7 +78,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.124.0</string> <string>1.125.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@@ -93,7 +93,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>187</string> <string>190</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -19,7 +19,7 @@ platform :ios do
desc "iOS Release" desc "iOS Release"
lane :release do lane :release do
increment_version_number( increment_version_number(
version_number: "1.125.1" version_number: "1.125.6"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@@ -262,6 +262,11 @@ class GalleryViewerPage extends HookConsumerWidget {
PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) { PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
var newAsset = loadAsset(index); var newAsset = loadAsset(index);
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(currentAssetProvider.notifier).set(newAsset);
});
final stackId = newAsset.stackId; final stackId = newAsset.stackId;
if (stackId != null && currentIndex.value == index) { if (stackId != null && currentIndex.value == index) {
final stackElements = final stackElements =

View File

@@ -83,11 +83,18 @@ class PhotosPage extends HookConsumerWidget {
Future<void> refreshAssets() async { Future<void> refreshAssets() async {
final fullRefresh = refreshCount.value > 0; final fullRefresh = refreshCount.value > 0;
await ref.read(assetProvider.notifier).getAllAsset(clear: fullRefresh);
if (fullRefresh) { if (fullRefresh) {
Future.wait([
ref.read(assetProvider.notifier).getAllAsset(clear: true),
ref.read(albumProvider.notifier).refreshRemoteAlbums(),
]);
// refresh was forced: user requested another refresh within 2 seconds // refresh was forced: user requested another refresh within 2 seconds
refreshCount.value = 0; refreshCount.value = 0;
} else { } else {
await ref.read(assetProvider.notifier).getAllAsset(clear: false);
refreshCount.value++; refreshCount.value++;
// set counter back to 0 if user does not request refresh again // set counter back to 0 if user does not request refresh again
Timer(const Duration(seconds: 4), () => refreshCount.value = 0); Timer(const Duration(seconds: 4), () => refreshCount.value = 0);

View File

@@ -277,7 +277,6 @@ class SearchPage extends HookConsumerWidget {
fieldEndHintText: 'end_date'.tr(), fieldEndHintText: 'end_date'.tr(),
initialEntryMode: DatePickerEntryMode.calendar, initialEntryMode: DatePickerEntryMode.calendar,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
locale: context.locale,
); );
if (date == null) { if (date == null) {

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/duration_extensions.dart'; import 'package:immich_mobile/extensions/duration_extensions.dart';
import 'package:immich_mobile/widgets/common/dropdown_search_menu.dart';
import 'package:timezone/timezone.dart' as tz; import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/timezone.dart'; import 'package:timezone/timezone.dart';
@@ -24,7 +25,7 @@ Future<String?> showDateTimePicker({
} }
String _getFormattedOffset(int offsetInMilli, tz.Location location) { String _getFormattedOffset(int offsetInMilli, tz.Location location) {
return "${location.name} (UTC${Duration(milliseconds: offsetInMilli).formatAsOffset()})"; return "${location.name} (${Duration(milliseconds: offsetInMilli).formatAsOffset()})";
} }
class _DateTimePicker extends HookWidget { class _DateTimePicker extends HookWidget {
@@ -73,7 +74,6 @@ class _DateTimePicker extends HookWidget {
// returns a list of location<name> along with it's offset in duration // returns a list of location<name> along with it's offset in duration
List<_TimeZoneOffset> getAllTimeZones() { List<_TimeZoneOffset> getAllTimeZones() {
return tz.timeZoneDatabase.locations.values return tz.timeZoneDatabase.locations.values
.where((l) => !l.currentTimeZone.abbreviation.contains("0"))
.map(_TimeZoneOffset.fromLocation) .map(_TimeZoneOffset.fromLocation)
.sorted() .sorted()
.toList(); .toList();
@@ -133,83 +133,78 @@ class _DateTimePicker extends HookWidget {
context.pop(dtWithOffset); context.pop(dtWithOffset);
} }
return LayoutBuilder( return AlertDialog(
builder: (context, constraint) => AlertDialog( contentPadding: const EdgeInsets.symmetric(vertical: 32, horizontal: 18),
contentPadding: actions: [
const EdgeInsets.symmetric(vertical: 32, horizontal: 18), TextButton(
actions: [ onPressed: () => context.pop(),
TextButton( child: Text(
onPressed: () => context.pop(), "action_common_cancel",
child: Text( style: context.textTheme.bodyMedium?.copyWith(
"action_common_cancel", fontWeight: FontWeight.w600,
style: context.textTheme.bodyMedium?.copyWith( color: context.colorScheme.error,
fontWeight: FontWeight.w600, ),
color: context.colorScheme.error, ).tr(),
),
TextButton(
onPressed: popWithDateTime,
child: Text(
"action_common_update",
style: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
color: context.primaryColor,
),
).tr(),
),
],
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"edit_date_time_dialog_date_time",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
).tr(),
const SizedBox(height: 32),
ListTile(
tileColor: context.colorScheme.surfaceContainerHighest,
shape: ShapeBorder.lerp(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
), ),
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
1,
),
trailing: Icon(
Icons.edit_outlined,
size: 18,
color: context.primaryColor,
),
title: Text(
DateFormat("dd-MM-yyyy hh:mm a").format(date.value),
style: context.textTheme.bodyMedium,
).tr(), ).tr(),
onTap: pickDate,
), ),
TextButton( const SizedBox(height: 24),
onPressed: popWithDateTime, DropdownSearchMenu(
child: Text( trailingIcon: Icon(
"action_common_update", Icons.arrow_drop_down,
style: context.textTheme.bodyMedium?.copyWith( color: context.primaryColor,
fontWeight: FontWeight.w600, ),
color: context.primaryColor, hintText: "edit_date_time_dialog_timezone".tr(),
), label: const Text('edit_date_time_dialog_timezone').tr(),
).tr(), textStyle: context.textTheme.bodyMedium,
onSelected: (value) => tzOffset.value = value,
initialSelection: tzOffset.value,
dropdownMenuEntries: menuEntries,
), ),
], ],
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"edit_date_time_dialog_date_time",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
).tr(),
const SizedBox(height: 32),
ListTile(
tileColor: context.colorScheme.surfaceContainerHighest,
shape: ShapeBorder.lerp(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
1,
),
trailing: Icon(
Icons.edit_outlined,
size: 18,
color: context.primaryColor,
),
title: Text(
DateFormat("dd-MM-yyyy hh:mm a").format(date.value),
style: context.textTheme.bodyMedium,
).tr(),
onTap: pickDate,
),
const SizedBox(height: 24),
DropdownMenu(
width: 275,
menuHeight: 300,
trailingIcon: Icon(
Icons.arrow_drop_down,
color: context.primaryColor,
),
hintText: "edit_date_time_dialog_timezone".tr(),
label: const Text('edit_date_time_dialog_timezone').tr(),
textStyle: context.textTheme.bodyMedium,
onSelected: (value) => tzOffset.value = value!,
initialSelection: tzOffset.value,
dropdownMenuEntries: menuEntries,
),
],
),
), ),
); );
} }

View File

@@ -0,0 +1,169 @@
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
class DropdownSearchMenu<T> extends HookWidget {
const DropdownSearchMenu({
super.key,
required this.dropdownMenuEntries,
this.initialSelection,
this.onSelected,
this.trailingIcon,
this.hintText,
this.label,
this.textStyle,
this.menuConstraints,
});
final List<DropdownMenuEntry<T>> dropdownMenuEntries;
final T? initialSelection;
final ValueChanged<T>? onSelected;
final Widget? trailingIcon;
final String? hintText;
final Widget? label;
final TextStyle? textStyle;
final BoxConstraints? menuConstraints;
@override
Widget build(BuildContext context) {
final selectedItem = useState<DropdownMenuEntry<T>?>(
dropdownMenuEntries
.firstWhereOrNull((item) => item.value == initialSelection),
);
final showTimeZoneDropdown = useState<bool>(false);
final effectiveConstraints = menuConstraints ??
const BoxConstraints(
minWidth: 280,
maxWidth: 280,
minHeight: 0,
maxHeight: 280,
);
final inputDecoration = InputDecoration(
contentPadding: const EdgeInsets.fromLTRB(12, 4, 12, 4),
border: const OutlineInputBorder(),
suffixIcon: trailingIcon,
label: label,
hintText: hintText,
).applyDefaults(context.themeData.inputDecorationTheme);
if (!showTimeZoneDropdown.value) {
return ConstrainedBox(
constraints: effectiveConstraints,
child: GestureDetector(
onTap: () => showTimeZoneDropdown.value = true,
child: InputDecorator(
decoration: inputDecoration,
child: selectedItem.value != null
? Text(
selectedItem.value!.label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: textStyle,
)
: null,
),
),
);
}
return ConstrainedBox(
constraints: effectiveConstraints,
child: Autocomplete<DropdownMenuEntry<T>>(
displayStringForOption: (option) => option.label,
optionsBuilder: (textEditingValue) {
return dropdownMenuEntries.where(
(item) => item.label
.toLowerCase()
.trim()
.contains(textEditingValue.text.toLowerCase().trim()),
);
},
onSelected: (option) {
selectedItem.value = option;
showTimeZoneDropdown.value = false;
onSelected?.call(option.value);
},
fieldViewBuilder: (context, textEditingController, focusNode, _) {
return TextField(
autofocus: true,
focusNode: focusNode,
controller: textEditingController,
decoration: inputDecoration.copyWith(
hintText: "edit_date_time_dialog_search_timezone".tr(),
),
maxLines: 1,
style: context.textTheme.bodyMedium,
expands: false,
onTapOutside: (event) {
showTimeZoneDropdown.value = false;
focusNode.unfocus();
},
onSubmitted: (_) {
showTimeZoneDropdown.value = false;
},
);
},
optionsViewBuilder: (context, onSelected, options) {
// This widget is a copy of the default implementation.
// We have only changed the `constraints` parameter.
return Align(
alignment: Alignment.topLeft,
child: ConstrainedBox(
constraints: effectiveConstraints,
child: Material(
elevation: 4.0,
child: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final option = options.elementAt(index);
return InkWell(
onTap: () => onSelected(option),
child: Builder(
builder: (BuildContext context) {
final bool highlight =
AutocompleteHighlightedOption.of(context) ==
index;
if (highlight) {
SchedulerBinding.instance.addPostFrameCallback(
(Duration timeStamp) {
Scrollable.ensureVisible(
context,
alignment: 0.5,
);
},
debugLabel: 'AutocompleteOptions.ensureVisible',
);
}
return Container(
color: highlight
? Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.12)
: null,
padding: const EdgeInsets.all(16.0),
child: Text(
option.label,
style: textStyle,
),
);
},
),
);
},
),
),
),
);
},
),
);
}
}

View File

@@ -28,8 +28,7 @@ class UserCircleAvatar extends ConsumerWidget {
final profileImageUrl = final profileImageUrl =
'${Store.get(StoreKey.serverEndpoint)}/users/${user.id}/profile-image?d=${Random().nextInt(1024)}'; '${Store.get(StoreKey.serverEndpoint)}/users/${user.id}/profile-image?d=${Random().nextInt(1024)}';
final textIcon = Text( final textIcon = DefaultTextStyle(
user.name[0].toUpperCase(),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 12, fontSize: 12,
@@ -37,6 +36,7 @@ class UserCircleAvatar extends ConsumerWidget {
? Colors.black ? Colors.black
: Colors.white, : Colors.white,
), ),
child: Text(user.name[0].toUpperCase()),
); );
return CircleAvatar( return CircleAvatar(
backgroundColor: user.avatarColor.toColor(), backgroundColor: user.avatarColor.toColor(),

View File

@@ -102,7 +102,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
final localEndpoint = await _showEditDialog( final localEndpoint = await _showEditDialog(
context, context,
"server_endpoint".tr(), "server_endpoint".tr(),
"http://local-ip:2283/api", "http://local-ip:2283",
localEndpointText.value, localEndpointText.value,
); );
@@ -212,7 +212,7 @@ class LocalNetworkPreference extends HookConsumerWidget {
leading: const Icon(Icons.lan_rounded), leading: const Icon(Icons.lan_rounded),
title: Text("server_endpoint".tr()), title: Text("server_endpoint".tr()),
subtitle: localEndpointText.value.isEmpty subtitle: localEndpointText.value.isEmpty
? const Text("http://local-ip:2283/api") ? const Text("http://local-ip:2283")
: Text( : Text(
localEndpointText.value, localEndpointText.value,
style: context.textTheme.labelLarge?.copyWith( style: context.textTheme.labelLarge?.copyWith(

View File

@@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.125.1 - API version: 1.125.6
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen

View File

@@ -67,7 +67,7 @@ class AssetBulkUpdateDto {
/// ///
num? longitude; num? longitude;
/// Minimum value: 0 /// Minimum value: -1
/// Maximum value: 5 /// Maximum value: 5
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// Please note: This property should have been non-nullable! Since the specification file

View File

@@ -73,7 +73,7 @@ class UpdateAssetDto {
/// ///
num? longitude; num? longitude;
/// Minimum value: 0 /// Minimum value: -1
/// Maximum value: 5 /// Maximum value: 5
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// Please note: This property should have been non-nullable! Since the specification file

View File

@@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone description: Immich - selfhosted backup media file on mobile phone
publish_to: 'none' publish_to: 'none'
version: 1.125.1+177 version: 1.125.6+182
environment: environment:
sdk: '>=3.3.0 <4.0.0' sdk: '>=3.3.0 <4.0.0'

View File

@@ -1,3 +1,7 @@
@Skip('currently failing due to mock HTTP client to download ISAR binaries')
@Tags(['pages'])
library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -118,72 +122,4 @@ void main() {
captured = verify(() => mockSearchApi.searchAssets(captureAny())).captured; captured = verify(() => mockSearchApi.searchAssets(captureAny())).captured;
expect(captured.first, emptyTextSearch); expect(captured.first, emptyTextSearch);
}); });
// COME BACK LATER
// testWidgets('contextual search with text combined with media type',
// (tester) async {
// await tester.pumpConsumerWidget(
// const SearchPage(),
// overrides: overrides,
// );
// await tester.pumpAndSettle();
// expect(
// find.byIcon(Icons.abc_rounded),
// findsOneWidget,
// reason: 'Should have contextual search icon',
// );
// final searchField = find.byKey(const Key('search_text_field'));
// expect(searchField, findsOneWidget);
// await tester.enterText(searchField, 'test');
// await tester.testTextInput.receiveAction(TextInputAction.search);
// var captured = verify(
// () => mockSearchApi.searchSmart(captureAny()),
// ).captured;
// expect(
// captured.first,
// isA<SmartSearchDto>().having((s) => s.query, 'query', 'test'),
// );
// await tester.dragUntilVisible(
// find.byKey(const Key('media_type_chip')),
// find.byKey(const Key('search_filter_chip_list')),
// const Offset(-100, 0),
// );
// await tester.pumpAndSettle();
// await tester.tap(find.byKey(const Key('media_type_chip')));
// await tester.pumpAndSettle();
// await tester.tap(find.byKey(const Key('search_filter_media_type_image')));
// await tester.pumpAndSettle();
// await tester.tap(find.byKey(const Key('search_filter_apply')));
// await tester.pumpAndSettle();
// captured = verify(() => mockSearchApi.searchSmart(captureAny())).captured;
// expect(
// captured.first,
// isA<SmartSearchDto>()
// .having((s) => s.query, 'query', 'test')
// .having((s) => s.type, 'type', AssetTypeEnum.IMAGE),
// );
// await tester.enterText(searchField, '');
// await tester.testTextInput.receiveAction(TextInputAction.search);
// captured = verify(() => mockSearchApi.searchAssets(captureAny())).captured;
// expect(
// captured.first,
// isA<MetadataSearchDto>()
// .having((s) => s.originalFileName, 'originalFileName', null)
// .having((s) => s.type, 'type', AssetTypeEnum.IMAGE),
// );
// });
} }

View File

@@ -7454,7 +7454,7 @@
"info": { "info": {
"title": "Immich", "title": "Immich",
"description": "Immich API", "description": "Immich API",
"version": "1.125.1", "version": "1.125.6",
"contact": {} "contact": {}
}, },
"tags": [], "tags": [],
@@ -7951,7 +7951,7 @@
}, },
"rating": { "rating": {
"maximum": 5, "maximum": 5,
"minimum": 0, "minimum": -1,
"type": "number" "type": "number"
} }
}, },
@@ -12780,7 +12780,7 @@
}, },
"rating": { "rating": {
"maximum": 5, "maximum": 5,
"minimum": 0, "minimum": -1,
"type": "number" "type": "number"
} }
}, },

View File

@@ -1,12 +1,12 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.125.1", "version": "1.125.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.125.1", "version": "1.125.6",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.125.1", "version": "1.125.6",
"description": "Auto-generated TypeScript SDK for the Immich API", "description": "Auto-generated TypeScript SDK for the Immich API",
"type": "module", "type": "module",
"main": "./build/index.js", "main": "./build/index.js",

View File

@@ -1,6 +1,6 @@
/** /**
* Immich * Immich
* 1.125.1 * 1.125.6
* DO NOT MODIFY - This file has been generated using oazapfts. * DO NOT MODIFY - This file has been generated using oazapfts.
* See https://www.npmjs.com/package/oazapfts * See https://www.npmjs.com/package/oazapfts
*/ */

View File

@@ -40,12 +40,12 @@
<a href="README_vi_VN.md">Tiếng Việt</a> <a href="README_vi_VN.md">Tiếng Việt</a>
</p> </p>
## ข้อจำกัดความรับผิดชอบ ## ข้อควรระวัง
- ⚠️ โพรเจกต์นี้กำลังอยู่ระหว่างการพัฒนา**ที่มีการเปลี่ยนแปลงบ่อยมาก** - ⚠️ โพรเจกต์นี้กำลังอยู่ระหว่างการพัฒนา**มีการเปลี่ยนแปลงบ่อยมาก**
- ⚠️ คาดว่าจะมีข้อผิดพลาดและการเปลี่ยนแปลงที่ส่งผลเสีย - ⚠️ อาจจะเกิดข้อผิดพลาดและการเปลี่ยนแปลงที่ส่งผลเสีย
- ⚠️ **ห้ามใช้แอปนี้เป็นวิธีการเดียวในการจัดเก็บภาพถ่ายและวิดีโอของคุณ** - ⚠️ **ห้ามใช้ระบบนี้เป็นวิธีการเดียวในการจัดเก็บภาพถ่ายและวิดีโอของคุณ**
- ⚠️ ปฏิบัติตามแผนการสำรองข้อมูลแบบ [3-2-1](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) สำหรับภาพถ่ายและวิดีโอที่สำคัญของคุณอยู่เสมอ! - ⚠️ ปฏิบัติตามแผนการสำรองข้อมูลแบบ [3-2-1](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) สำหรับภาพถ่ายและวิดีโอที่สำคัญของคุณอยู่เสมอ
> [!NOTE] > [!NOTE]
> คุณสามารถหาคู่มือหลัก รวมถึงคู่มือการติดตั้ง ได้ที่ https://immich.app/ > คุณสามารถหาคู่มือหลัก รวมถึงคู่มือการติดตั้ง ได้ที่ https://immich.app/
@@ -79,15 +79,15 @@
| :----------------------------------------- | ------ | ------ | | :----------------------------------------- | ------ | ------ |
| อัปโหลดและดูวิดีโอและภาพถ่าย | ใช่ | ใช่ | | อัปโหลดและดูวิดีโอและภาพถ่าย | ใช่ | ใช่ |
| การสำรองข้อมูลอัตโนมัติเมื่อเปิดแอป | ใช่ | N/A | | การสำรองข้อมูลอัตโนมัติเมื่อเปิดแอป | ใช่ | N/A |
| ป้องกันการซ้ำซ้อนของไฟล์ | ใช่ | ใช่ | | ป้องกันการซ้ำของไฟล์ | ใช่ | ใช่ |
| เลือกอัลบั้มสำหรับสำรองข้อมูล | ใช่ | N/A | | เลือกอัลบั้มสำหรับสำรองข้อมูล | ใช่ | N/A |
| ดาวน์โหลดภาพถ่ายและวิดีโอไปยังอุปกรณ์ | ใช่ | ใช่ | | ดาวน์โหลดภาพถ่ายและวิดีโอไปยังอุปกรณ์ | ใช่ | ใช่ |
| รองรับผู้ใช้หลายคน | ใช่ | ใช่ | | รองรับผู้ใช้หลายคน | ใช่ | ใช่ |
| อัลบั้มและอัลบั้มแชร์ | ใช่ | ใช่ | | อัลบั้มและอัลบั้มแชร์ | ใช่ | ใช่ |
| แถบเลื่อนแบบลากได้ | ใช่ | ใช่ | | แถบเลื่อนแบบลากได้ | ใช่ | ใช่ |
| รองรับรูปแบบไฟล์ RAW | ใช่ | ใช่ | | รองรับรูปแบบไฟล์ RAW | ใช่ | ใช่ |
| ดูข้อมูลเมตา (EXIF, แผนที่) | ใช่ | ใช่ | | ดูข้อมูลเมตาดาต้า (EXIF, แผนที่) | ใช่ | ใช่ |
| ค้นหาจากข้อมูลเมตา วัตถุ ใบหน้า และ CLIP | ใช่ | ใช่ | | ค้นหาจากข้อมูลเมตาดาต้า วัตถุ ใบหน้า และ CLIP | ใช่ | ใช่ |
| ฟังก์ชันการจัดการผู้ดูแลระบบ | ไม่ใช่ | ใช่ | | ฟังก์ชันการจัดการผู้ดูแลระบบ | ไม่ใช่ | ใช่ |
| การสำรองข้อมูลพื้นหลัง | ใช่ | N/A | | การสำรองข้อมูลพื้นหลัง | ใช่ | N/A |
| การเลื่อนแบบเสมือน | ใช่ | ใช่ | | การเลื่อนแบบเสมือน | ใช่ | ใช่ |
@@ -100,7 +100,7 @@
| การจัดเก็บและรายการโปรด | ใช่ | ใช่ | | การจัดเก็บและรายการโปรด | ใช่ | ใช่ |
| แผนที่ทั่วโลก | ใช่ | ใช่ | | แผนที่ทั่วโลก | ใช่ | ใช่ |
| การแชร์กับคู่หู | ใช่ | ใช่ | | การแชร์กับคู่หู | ใช่ | ใช่ |
| การจดจำใบหน้าและการจัดกลุ่ม | ใช่ | ใช่ | | ระบบจดจำใบหน้าและการจัดกลุ่ม | ใช่ | ใช่ |
| ความทรงจำ (x ปีที่แล้ว) | ใช่ | ใช่ | | ความทรงจำ (x ปีที่แล้ว) | ใช่ | ใช่ |
| รองรับแบบออฟไลน์ | ใช่ | ไม่ใช่ | | รองรับแบบออฟไลน์ | ใช่ | ไม่ใช่ |
| แกลเลอรีแบบอ่านอย่างเดียว | ใช่ | ใช่ | | แกลเลอรีแบบอ่านอย่างเดียว | ใช่ | ใช่ |
@@ -108,13 +108,13 @@
## การแปลภาษา ## การแปลภาษา
อ่านเพิ่มเติมเกี่ยวกับการแปลภาษา [ที่นี่](https://immich.app/docs/developer/translations) อ่านเพิ่มเติมเกี่ยวกับการแปล [ที่นี่](https://immich.app/docs/developer/translations)
<a href="https://hosted.weblate.org/engage/immich/"> <a href="https://hosted.weblate.org/engage/immich/">
<img src="https://hosted.weblate.org/widget/immich/immich/multi-auto.svg" alt="สถานะการแปล" /> <img src="https://hosted.weblate.org/widget/immich/immich/multi-auto.svg" alt="สถานะการแปล" />
</a> </a>
## กิจกรรมของคลังเก็บข้อมูล ## กิจกรรมของ Repository
![กิจกรรม](https://repobeats.axiom.co/api/embed/9e86d9dc3ddd137161f2f6d2e758d7863b1789cb.svg "ภาพการวิเคราะห์ของ Repobeats") ![กิจกรรม](https://repobeats.axiom.co/api/embed/9e86d9dc3ddd137161f2f6d2e758d7863b1789cb.svg "ภาพการวิเคราะห์ของ Repobeats")

View File

@@ -1,12 +1,12 @@
{ {
"name": "immich", "name": "immich",
"version": "1.125.1", "version": "1.125.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich", "name": "immich",
"version": "1.125.1", "version": "1.125.6",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@nestjs/bullmq": "^11.0.0", "@nestjs/bullmq": "^11.0.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich", "name": "immich",
"version": "1.125.1", "version": "1.125.6",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,

View File

@@ -3,9 +3,11 @@ import { Inject, Module, OnModuleDestroy, OnModuleInit, ValidationPipe } from '@
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE, ModuleRef } from '@nestjs/core'; import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE, ModuleRef } from '@nestjs/core';
import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { PostgresJSDialect } from 'kysely-postgres-js';
import { ClsModule } from 'nestjs-cls'; import { ClsModule } from 'nestjs-cls';
import { KyselyModule } from 'nestjs-kysely'; import { KyselyModule } from 'nestjs-kysely';
import { OpenTelemetryModule } from 'nestjs-otel'; import { OpenTelemetryModule } from 'nestjs-otel';
import postgres from 'postgres';
import { commands } from 'src/commands'; import { commands } from 'src/commands';
import { IWorker } from 'src/constants'; import { IWorker } from 'src/constants';
import { controllers } from 'src/controllers'; import { controllers } from 'src/controllers';
@@ -13,7 +15,6 @@ import { entities } from 'src/entities';
import { ImmichWorker } from 'src/enum'; import { ImmichWorker } from 'src/enum';
import { IEventRepository } from 'src/interfaces/event.interface'; import { IEventRepository } from 'src/interfaces/event.interface';
import { IJobRepository } from 'src/interfaces/job.interface'; import { IJobRepository } from 'src/interfaces/job.interface';
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
import { AuthGuard } from 'src/middleware/auth.guard'; import { AuthGuard } from 'src/middleware/auth.guard';
import { ErrorInterceptor } from 'src/middleware/error.interceptor'; import { ErrorInterceptor } from 'src/middleware/error.interceptor';
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
@@ -22,7 +23,7 @@ import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
import { providers, repositories } from 'src/repositories'; import { providers, repositories } from 'src/repositories';
import { ConfigRepository } from 'src/repositories/config.repository'; import { ConfigRepository } from 'src/repositories/config.repository';
import { LoggingRepository } from 'src/repositories/logging.repository'; import { LoggingRepository } from 'src/repositories/logging.repository';
import { teardownTelemetry } from 'src/repositories/telemetry.repository'; import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
import { services } from 'src/services'; import { services } from 'src/services';
import { CliService } from 'src/services/cli.service'; import { CliService } from 'src/services/cli.service';
import { DatabaseService } from 'src/services/database.service'; import { DatabaseService } from 'src/services/database.service';
@@ -58,7 +59,19 @@ const imports = [
}, },
}), }),
TypeOrmModule.forFeature(entities), TypeOrmModule.forFeature(entities),
KyselyModule.forRoot(database.config.kysely), KyselyModule.forRoot({
dialect: new PostgresJSDialect({ postgres: postgres(database.config.kysely) }),
log(event) {
if (event.level === 'error') {
console.error('Query failed :', {
durationMs: event.queryDurationMillis,
error: event.error,
sql: event.query.sql,
params: event.query.parameters,
});
}
},
}),
]; ];
class BaseModule implements OnModuleInit, OnModuleDestroy { class BaseModule implements OnModuleInit, OnModuleDestroy {
@@ -67,7 +80,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy {
logger: LoggingRepository, logger: LoggingRepository,
@Inject(IEventRepository) private eventRepository: IEventRepository, @Inject(IEventRepository) private eventRepository: IEventRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(IJobRepository) private jobRepository: IJobRepository,
@Inject(ITelemetryRepository) private telemetryRepository: ITelemetryRepository, private telemetryRepository: TelemetryRepository,
) { ) {
logger.setAppName(this.worker); logger.setAppName(this.worker);
} }

View File

@@ -4,10 +4,12 @@ import { Reflector } from '@nestjs/core';
import { SchedulerRegistry } from '@nestjs/schedule'; import { SchedulerRegistry } from '@nestjs/schedule';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { PostgresJSDialect } from 'kysely-postgres-js';
import { KyselyModule } from 'nestjs-kysely'; import { KyselyModule } from 'nestjs-kysely';
import { OpenTelemetryModule } from 'nestjs-otel'; import { OpenTelemetryModule } from 'nestjs-otel';
import { mkdir, rm, writeFile } from 'node:fs/promises'; import { mkdir, rm, writeFile } from 'node:fs/promises';
import { join } from 'node:path'; import { join } from 'node:path';
import postgres from 'postgres';
import { format } from 'sql-formatter'; import { format } from 'sql-formatter';
import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators';
import { entities } from 'src/entities'; import { entities } from 'src/entities';
@@ -84,7 +86,7 @@ class SqlGenerator {
const moduleFixture = await Test.createTestingModule({ const moduleFixture = await Test.createTestingModule({
imports: [ imports: [
KyselyModule.forRoot({ KyselyModule.forRoot({
...database.config.kysely, dialect: new PostgresJSDialect({ postgres: postgres(database.config.kysely) }),
log: (event) => { log: (event) => {
if (event.level === 'query') { if (event.level === 'query') {
this.sqlLogger.logQuery(event.query.sql); this.sqlLogger.logQuery(event.query.sql);

View File

@@ -3,8 +3,8 @@ import { ApiTags } from '@nestjs/swagger';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto'; import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto';
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
import { EmailTemplate } from 'src/interfaces/notification.interface';
import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { EmailTemplate } from 'src/repositories/notification.repository';
import { NotificationService } from 'src/services/notification.service'; import { NotificationService } from 'src/services/notification.service';
@ApiTags('Notifications') @ApiTags('Notifications')

28
server/src/db.d.ts vendored
View File

@@ -3,21 +3,16 @@
* Please do not edit it manually. * Please do not edit it manually.
*/ */
import type { ColumnType } from "kysely"; import type { ColumnType } from 'kysely';
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
? U[]
: ArrayTypeImpl<T>;
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
? ColumnType<S[], I[], U[]>
: T[];
export type AssetsStatusEnum = "active" | "deleted" | "trashed"; export type AssetsStatusEnum = 'active' | 'deleted' | 'trashed';
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> export type Generated<T> =
? ColumnType<S, I | undefined, U> T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
: ColumnType<T, T | undefined, T>;
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>; export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
@@ -33,7 +28,7 @@ export type JsonPrimitive = boolean | number | string | null;
export type JsonValue = JsonArray | JsonObject | JsonPrimitive; export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
export type Sourcetype = "exif" | "machine-learning"; export type Sourcetype = 'exif' | 'machine-learning';
export type Timestamp = ColumnType<Date, Date | string, Date | string>; export type Timestamp = ColumnType<Date, Date | string, Date | string>;
@@ -154,6 +149,12 @@ export interface AssetStack {
primaryAssetId: string; primaryAssetId: string;
} }
export interface AssetUser {
assetId: string;
createdAt: Timestamp;
userId: string;
}
export interface Audit { export interface Audit {
action: string; action: string;
createdAt: Generated<Timestamp>; createdAt: Generated<Timestamp>;
@@ -413,6 +414,7 @@ export interface DB {
asset_files: AssetFiles; asset_files: AssetFiles;
asset_job_status: AssetJobStatus; asset_job_status: AssetJobStatus;
asset_stack: AssetStack; asset_stack: AssetStack;
asset_user: AssetUser;
assets: Assets; assets: Assets;
audit: Audit; audit: Audit;
exif: Exif; exif: Exif;
@@ -438,6 +440,6 @@ export interface DB {
tags_closure: TagsClosure; tags_closure: TagsClosure;
user_metadata: UserMetadata; user_metadata: UserMetadata;
users: Users; users: Users;
"vectors.pg_vector_index_stat": VectorsPgVectorIndexStat; 'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
version_history: VersionHistory; version_history: VersionHistory;
} }

View File

@@ -4,8 +4,8 @@ import { albumStub } from 'test/fixtures/album.stub';
describe('mapAlbum', () => { describe('mapAlbum', () => {
it('should set start and end dates', () => { it('should set start and end dates', () => {
const dto = mapAlbum(albumStub.twoAssets, false); const dto = mapAlbum(albumStub.twoAssets, false);
expect(dto.startDate).toEqual(new Date('2023-02-22T05:06:29.716Z')); expect(dto.startDate).toEqual(new Date('2020-12-31T23:59:00.000Z'));
expect(dto.endDate).toEqual(new Date('2023-02-23T05:06:29.716Z')); expect(dto.endDate).toEqual(new Date('2025-01-01T01:02:03.456Z'));
}); });
it('should not set start and end dates for empty assets', () => { it('should not set start and end dates for empty assets', () => {

View File

@@ -7,7 +7,6 @@ import { AuthDto } from 'src/dtos/auth.dto';
import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
import { AlbumEntity } from 'src/entities/album.entity'; import { AlbumEntity } from 'src/entities/album.entity';
import { AlbumUserRole, AssetOrder } from 'src/enum'; import { AlbumUserRole, AssetOrder } from 'src/enum';
import { getAssetDateTime } from 'src/utils/date-time';
import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation';
export class AlbumInfoDto { export class AlbumInfoDto {
@@ -165,8 +164,8 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt
const hasSharedLink = entity.sharedLinks?.length > 0; const hasSharedLink = entity.sharedLinks?.length > 0;
const hasSharedUser = sharedUsers.length > 0; const hasSharedUser = sharedUsers.length > 0;
let startDate = getAssetDateTime(assets.at(0)); let startDate = assets.at(0)?.localDateTime;
let endDate = getAssetDateTime(assets.at(-1)); let endDate = assets.at(-1)?.localDateTime;
// Swap dates if start date is greater than end date. // Swap dates if start date is greater than end date.
if (startDate && endDate && startDate > endDate) { if (startDate && endDate && startDate > endDate) {
[startDate, endDate] = [endDate, startDate]; [startDate, endDate] = [endDate, startDate];

View File

@@ -52,7 +52,7 @@ export class UpdateAssetBase {
@Optional() @Optional()
@IsInt() @IsInt()
@Max(5) @Max(5)
@Min(0) @Min(-1)
rating?: number; rating?: number;
} }

View File

@@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components';
import * as React from 'react'; import * as React from 'react';
import { ImmichButton } from 'src/emails/components/button.component'; import { ImmichButton } from 'src/emails/components/button.component';
import ImmichLayout from 'src/emails/components/immich.layout'; import ImmichLayout from 'src/emails/components/immich.layout';
import { AlbumInviteEmailProps } from 'src/interfaces/notification.interface'; import { AlbumInviteEmailProps } from 'src/repositories/notification.repository';
import { replaceTemplateTags } from 'src/utils/replace-template-tags'; import { replaceTemplateTags } from 'src/utils/replace-template-tags';
export const AlbumInviteEmail = ({ export const AlbumInviteEmail = ({

View File

@@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components';
import * as React from 'react'; import * as React from 'react';
import { ImmichButton } from 'src/emails/components/button.component'; import { ImmichButton } from 'src/emails/components/button.component';
import ImmichLayout from 'src/emails/components/immich.layout'; import ImmichLayout from 'src/emails/components/immich.layout';
import { AlbumUpdateEmailProps } from 'src/interfaces/notification.interface'; import { AlbumUpdateEmailProps } from 'src/repositories/notification.repository';
import { replaceTemplateTags } from 'src/utils/replace-template-tags'; import { replaceTemplateTags } from 'src/utils/replace-template-tags';
export const AlbumUpdateEmail = ({ export const AlbumUpdateEmail = ({

View File

@@ -1,7 +1,7 @@
import { Link, Row, Text } from '@react-email/components'; import { Link, Row, Text } from '@react-email/components';
import * as React from 'react'; import * as React from 'react';
import ImmichLayout from 'src/emails/components/immich.layout'; import ImmichLayout from 'src/emails/components/immich.layout';
import { TestEmailProps } from 'src/interfaces/notification.interface'; import { TestEmailProps } from 'src/repositories/notification.repository';
export const TestEmail = ({ baseUrl, displayName }: TestEmailProps) => ( export const TestEmail = ({ baseUrl, displayName }: TestEmailProps) => (
<ImmichLayout preview="This is a test email from Immich."> <ImmichLayout preview="This is a test email from Immich.">

View File

@@ -2,7 +2,7 @@ import { Link, Section, Text } from '@react-email/components';
import * as React from 'react'; import * as React from 'react';
import { ImmichButton } from 'src/emails/components/button.component'; import { ImmichButton } from 'src/emails/components/button.component';
import ImmichLayout from 'src/emails/components/immich.layout'; import ImmichLayout from 'src/emails/components/immich.layout';
import { WelcomeEmailProps } from 'src/interfaces/notification.interface'; import { WelcomeEmailProps } from 'src/repositories/notification.repository';
import { replaceTemplateTags } from 'src/utils/replace-template-tags'; import { replaceTemplateTags } from 'src/utils/replace-template-tags';
export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => { export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => {

View File

@@ -0,0 +1,22 @@
import { AssetEntity } from 'src/entities/asset.entity';
import { UserEntity } from 'src/entities/user.entity';
import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm';
@Entity('asset_user')
@Index('IDX_assetId_userId', ['assetId', 'userId'])
export class AssetUserEntity {
@PrimaryColumn()
assetId!: string;
@ManyToOne(() => AssetEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
asset!: AssetEntity;
@PrimaryColumn()
userId!: string;
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
user!: UserEntity;
@Column()
createdAt!: Date;
}

View File

@@ -193,7 +193,7 @@ export function withExifInner<O>(qb: SelectQueryBuilder<DB, 'assets', O>) {
export function withSmartSearch<O>(qb: SelectQueryBuilder<DB, 'assets', O>) { export function withSmartSearch<O>(qb: SelectQueryBuilder<DB, 'assets', O>) {
return qb return qb
.leftJoin('smart_search', 'assets.id', 'smart_search.assetId') .leftJoin('smart_search', 'assets.id', 'smart_search.assetId')
.select(sql<number[]>`smart_search.embedding`.as('embedding')); .select((eb) => eb.fn.toJson(eb.table('smart_search')).as('smartSearch'));
} }
export function withFaces(eb: ExpressionBuilder<DB, 'assets'>) { export function withFaces(eb: ExpressionBuilder<DB, 'assets'>) {

View File

@@ -5,6 +5,7 @@ import { APIKeyEntity } from 'src/entities/api-key.entity';
import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetFaceEntity } from 'src/entities/asset-face.entity';
import { AssetFileEntity } from 'src/entities/asset-files.entity'; import { AssetFileEntity } from 'src/entities/asset-files.entity';
import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity';
import { AssetUserEntity } from 'src/entities/asset-user.entity';
import { AssetEntity } from 'src/entities/asset.entity'; import { AssetEntity } from 'src/entities/asset.entity';
import { AuditEntity } from 'src/entities/audit.entity'; import { AuditEntity } from 'src/entities/audit.entity';
import { ExifEntity } from 'src/entities/exif.entity'; import { ExifEntity } from 'src/entities/exif.entity';
@@ -34,6 +35,7 @@ export const entities = [
AssetEntity, AssetEntity,
AssetFaceEntity, AssetFaceEntity,
AssetFileEntity, AssetFileEntity,
AssetUserEntity,
AssetJobStatusEntity, AssetJobStatusEntity,
AuditEntity, AuditEntity,
ExifEntity, ExifEntity,

View File

@@ -1,18 +0,0 @@
import { Insertable, Selectable, Updateable } from 'kysely';
import { AlbumsSharedUsersUsers } from 'src/db';
export const IAlbumUserRepository = 'IAlbumUserRepository';
export type AlbumPermissionId = {
albumsId: string;
usersId: string;
};
export interface IAlbumUserRepository {
create(albumUser: Insertable<AlbumsSharedUsersUsers>): Promise<Selectable<AlbumsSharedUsersUsers>>;
update(
id: AlbumPermissionId,
albumPermission: Updateable<AlbumsSharedUsersUsers>,
): Promise<Selectable<AlbumsSharedUsersUsers>>;
delete(id: AlbumPermissionId): Promise<void>;
}

Some files were not shown because too many files have changed in this diff Show More