chore(web): another missing translations (#10274)
* chore(web): another missing translations * unused removed * more keys * lint fix * test fixed * dynamic translation fix * fixes * people search translation * params fixed * keep filter setting fix * lint fix * $t fixes * Update web/src/lib/i18n/en.json Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> * another missing * activity translation * link sharing translations * expiration dropdown fix - didn't work localized * notification title * device logout * search results * reset to default * unsaved change * select from computer * selected * select-2 * select-3 * unmerge * pluralize, force icu message * Update web/src/lib/components/asset-viewer/asset-viewer.svelte Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> * review fixes * remove user * plural fixes * ffmpeg settings * fixes * error title * plural fixes * onboarding * change password * more more * console log fix * another * api key desc * map marker * format fix * key fix * asset-utils * utils * misc --------- Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
This commit is contained in:
@@ -37,10 +37,9 @@
|
||||
import { createAssetInteractionStore } from '$lib/stores/asset-interaction.store';
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
import { AssetStore } from '$lib/stores/assets.store';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { handlePromiseError, s } from '$lib/utils';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
import { downloadAlbum } from '$lib/utils/asset-utils';
|
||||
import { openFileUploadDialog } from '$lib/utils/file-uploader';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
@@ -168,10 +167,10 @@
|
||||
});
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: `Activity is ${album.isActivityEnabled ? 'enabled' : 'disabled'}`,
|
||||
message: $t('activity_changed', { values: { enabled: album.isActivityEnabled } }),
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, `Can't ${album.isActivityEnabled ? 'disable' : 'enable'} activity`);
|
||||
handleError(error, $t('errors.cant_change_activity', { values: { enabled: album.isActivityEnabled } }));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -189,7 +188,7 @@
|
||||
reactions = [...reactions, isLiked];
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, "Can't change favorite for asset");
|
||||
handleError(error, $t('errors.cant_change_asset_favorite'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,7 +215,7 @@
|
||||
const { comments } = await getActivityStatistics({ albumId: album.id });
|
||||
setNumberOfComments(comments);
|
||||
} catch (error) {
|
||||
handleError(error, "Can't get number of comments");
|
||||
handleError(error, $t('errors.cant_get_number_of_comments'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -283,7 +282,7 @@
|
||||
const count = results.filter(({ success }) => success).length;
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: `Added ${count} asset${s(count)}`,
|
||||
message: $t('assets_added_count', { values: { count: count } }),
|
||||
});
|
||||
|
||||
await refreshAlbum();
|
||||
@@ -291,7 +290,7 @@
|
||||
timelineInteractionStore.clearMultiselect();
|
||||
viewMode = ViewMode.VIEW;
|
||||
} catch (error) {
|
||||
handleError(error, 'Error adding assets to album');
|
||||
handleError(error, $t('errors.error_adding_assets_to_album'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -317,7 +316,7 @@
|
||||
|
||||
viewMode = ViewMode.VIEW;
|
||||
} catch (error) {
|
||||
handleError(error, 'Error adding users to album');
|
||||
handleError(error, $t('errors.error_adding_users_to_album'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -331,7 +330,7 @@
|
||||
await refreshAlbum();
|
||||
viewMode = album.albumUsers.length > 0 ? ViewMode.VIEW_USERS : ViewMode.VIEW;
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_load_album'));
|
||||
handleError(error, $t('errors.error_deleting_shared_user'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -342,7 +341,7 @@
|
||||
const handleRemoveAlbum = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'remove-album',
|
||||
prompt: `Are you sure you want to delete the album ${album.albumName}?\nIf this album is shared, other users will not be able to access it anymore.`,
|
||||
prompt: $t('album_delete_confirmation', { values: { album: album.albumName } }),
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
@@ -393,7 +392,7 @@
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to update album cover');
|
||||
handleError(error, $t('errors.unable_to_update_album_cover'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -495,9 +494,9 @@
|
||||
<svelte:fragment slot="leading">
|
||||
<p class="text-lg dark:text-immich-dark-fg">
|
||||
{#if $timelineSelected.size === 0}
|
||||
Add to album
|
||||
{$t('add_to_album')}
|
||||
{:else}
|
||||
{$timelineSelected.size.toLocaleString($locale)} selected
|
||||
{$t('selected_count', { values: { count: $timelineSelected.size } })}
|
||||
{/if}
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
@@ -508,7 +507,7 @@
|
||||
on:click={handleSelectFromComputer}
|
||||
class="rounded-lg px-6 py-2 text-sm font-medium text-immich-primary transition-all hover:bg-immich-primary/10 dark:text-immich-dark-primary dark:hover:bg-immich-dark-primary/25"
|
||||
>
|
||||
Select from computer
|
||||
{$t('select_from_computer')}
|
||||
</button>
|
||||
<Button size="sm" rounded="lg" disabled={$timelineSelected.size === 0} on:click={handleAddAssets}
|
||||
>{$t('done')}</Button
|
||||
|
||||
@@ -161,21 +161,16 @@
|
||||
if (results.length - count > 0) {
|
||||
notificationController.show({
|
||||
type: NotificationType.Error,
|
||||
message: `Unable to change the visibility for ${results.length - count} ${
|
||||
results.length - count <= 1 ? 'person' : 'people'
|
||||
}`,
|
||||
message: $t('errors.unable_to_change_visibility', { values: { count: results.length - count } }),
|
||||
});
|
||||
}
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: `Visibility changed for ${count} ${count <= 1 ? 'person' : 'people'}`,
|
||||
message: $t('visibility_changed', { values: { count: count } }),
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(
|
||||
error,
|
||||
`Unable to change the visibility for ${changed.length} ${changed.length <= 1 ? 'person' : 'people'}`,
|
||||
);
|
||||
handleError(error, $t('errors.unable_to_change_visibility', { values: { count: changed.length } }));
|
||||
}
|
||||
// Reset variables used on the "Show & hide people" modal
|
||||
showLoadingSpinner = false;
|
||||
@@ -346,7 +341,7 @@
|
||||
return person;
|
||||
});
|
||||
notificationController.show({
|
||||
message: 'Date of birth saved successfully',
|
||||
message: $t('birthdate_saved'),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -447,7 +442,7 @@
|
||||
<div class="flex flex-col content-center items-center text-center">
|
||||
<Icon path={mdiAccountOff} size="3.5em" />
|
||||
<p class="mt-5 text-3xl font-medium max-w-lg line-clamp-2 overflow-hidden">
|
||||
{`No people${searchName ? ` named "${searchName}"` : ''}`}
|
||||
{$t(searchName ? 'search_no_people_named' : 'search_no_people', { values: { name: searchName } })}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
import { AssetStore } from '$lib/stores/assets.store';
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { getPeopleThumbnailUrl, handlePromiseError, s } from '$lib/utils';
|
||||
import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils';
|
||||
import { clickOutside } from '$lib/actions/click-outside';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { isExternalUrl } from '$lib/utils/navigation';
|
||||
@@ -488,7 +488,7 @@
|
||||
{#if data.person.name}
|
||||
<p class="w-40 sm:w-72 font-medium truncate">{data.person.name}</p>
|
||||
<p class="absolute w-fit text-sm text-gray-500 dark:text-immich-gray bottom-0">
|
||||
{`${numberOfAssets} asset${s(numberOfAssets)}`}
|
||||
{$t('assets_count', { values: { count: numberOfAssets } })}
|
||||
</p>
|
||||
{:else}
|
||||
<p class="font-medium">{$t('add_a_name')}</p>
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
<div class="ml-6 text-4xl font-medium text-black/70 dark:text-white/80">{$t('albums').toUpperCase()}</div>
|
||||
<AlbumCardGroup albums={searchResultAlbums} showDateRange showItemCount />
|
||||
|
||||
<div class="m-6 text-4xl font-medium text-black/70 dark:text-white/80">PHOTOS & VIDEOS</div>
|
||||
<div class="m-6 text-4xl font-medium text-black/70 dark:text-white/80">
|
||||
{$t('photos_and_videos').toUpperCase()}
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
<section id="search-content" class="relative bg-immich-bg dark:bg-immich-dark-bg">
|
||||
@@ -296,7 +298,7 @@
|
||||
<div class="flex flex-col content-center items-center text-center">
|
||||
<Icon path={mdiImageOffOutline} size="3.5em" />
|
||||
<p class="mt-5 text-3xl font-medium">{$t('no_results')}</p>
|
||||
<p class="text-base font-normal">Try a synonym or more general keyword</p>
|
||||
<p class="text-base font-normal">{$t('no_results_description')}</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
const handleEmptyTrash = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'empty-trash',
|
||||
prompt:
|
||||
'Are you sure you want to empty the trash? This will remove all the assets in trash permanently from Immich.\nYou cannot undo this action!',
|
||||
prompt: $t('empty_trash_confirmation'),
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
@@ -53,7 +52,7 @@
|
||||
assetStore.removeAssets(deletedAssetIds);
|
||||
|
||||
notificationController.show({
|
||||
message: `Permanently deleted ${numberOfAssets} ${numberOfAssets == 1 ? 'asset' : 'assets'}`,
|
||||
message: $t('assets_permanently_deleted_count', { values: { count: numberOfAssets } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -64,7 +63,7 @@
|
||||
const handleRestoreTrash = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'restore-trash',
|
||||
prompt: 'Are you sure you want to restore all your trashed assets? You cannot undo this action!',
|
||||
prompt: $t('assets_restore_confirmation'),
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
@@ -78,7 +77,7 @@
|
||||
assetStore.removeAssets(restoredAssetIds);
|
||||
|
||||
notificationController.show({
|
||||
message: `Restored ${numberOfAssets} ${numberOfAssets == 1 ? 'asset' : 'assets'}`,
|
||||
message: $t('assets_restored_count', { values: { count: numberOfAssets } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
notificationController.show({
|
||||
message: $featureFlags.trash
|
||||
? $t('assets_moved_to_trash', { values: { count: trashedCount } })
|
||||
: $t('permanently_deleted_assets', { values: { count: trashedCount } }),
|
||||
? $t('assets_moved_to_trash_count', { values: { count: trashedCount } })
|
||||
: $t('permanently_deleted_assets_count', { values: { count: trashedCount } }),
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<div>
|
||||
<div class="flex items-center justify-between gap-4 px-4 py-4">
|
||||
<h1 class="font-medium text-immich-primary dark:text-immich-dark-primary">
|
||||
🚨 Error - Something went wrong
|
||||
🚨 {$t('error_title')}
|
||||
</h1>
|
||||
<div class="flex justify-end">
|
||||
<CircleIconButton
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { resetSavedUser, user } from '$lib/stores/user.store';
|
||||
import { logout } from '@immich/sdk';
|
||||
import type { PageData } from './$types';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -18,11 +19,10 @@
|
||||
|
||||
<FullscreenContainer title={data.meta.title}>
|
||||
<p slot="message">
|
||||
Hi {$user.name} ({$user.email}),
|
||||
{$t('hi_user', { values: { name: $user.name, email: $user.email } })}
|
||||
<br />
|
||||
<br />
|
||||
This 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.
|
||||
{$t('change_password_description')}
|
||||
</p>
|
||||
|
||||
<ChangePasswordForm on:success={onSuccess} />
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AppRoute } from '$lib/constants';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
@@ -11,9 +12,11 @@ export const load = (async () => {
|
||||
redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const $t = get(t);
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Change Password',
|
||||
title: $t('change_password'),
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { defaults, getServerConfig } from '@immich/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ fetch }) => {
|
||||
@@ -11,9 +13,10 @@ export const load = (async ({ fetch }) => {
|
||||
redirect(302, AppRoute.AUTH_REGISTER);
|
||||
}
|
||||
|
||||
const $t = get(t);
|
||||
return {
|
||||
meta: {
|
||||
title: 'Login',
|
||||
title: $t('login'),
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { loadConfig } from '$lib/stores/server-config.store';
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
await authenticate({ admin: true });
|
||||
await loadConfig();
|
||||
|
||||
const $t = get(t);
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Onboarding',
|
||||
title: $t('onboarding'),
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
import AdminRegistrationForm from '$lib/components/forms/admin-registration-form.svelte';
|
||||
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<FullscreenContainer title={data.meta.title}>
|
||||
<p slot="message">
|
||||
Since you are the first user on the system, you will be assigned as the Admin and are responsible for administrative
|
||||
tasks, and additional users will be created by you.
|
||||
{$t('admin.registration_description')}
|
||||
</p>
|
||||
|
||||
<AdminRegistrationForm />
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { getServerConfig } from '@immich/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
@@ -10,9 +12,11 @@ export const load = (async () => {
|
||||
redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const $t = get(t);
|
||||
|
||||
return {
|
||||
meta: {
|
||||
title: 'Admin Registration',
|
||||
title: $t('admin.registration'),
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
Reference in New Issue
Block a user