Skip to content

Commit

Permalink
feat(web): translations containing html (#10491)
Browse files Browse the repository at this point in the history
* feat(web): translations containing html

* add tests and more translations

* more translations

* rename FormatTags --> FormatMessage

* update version_announcement_message
  • Loading branch information
michelheusschen authored Jun 21, 2024
1 parent 1129020 commit b3252ff
Show file tree
Hide file tree
Showing 16 changed files with 313 additions and 101 deletions.
2 changes: 2 additions & 0 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
},
"type": "module",
"dependencies": {
"@formatjs/icu-messageformat-parser": "^2.7.8",
"@immich/sdk": "file:../open-api/typescript-sdk",
"@mdi/js": "^7.4.47",
"@photo-sphere-viewer/core": "^5.7.1",
Expand All @@ -71,6 +72,7 @@
"copy-image-clipboard": "^2.1.2",
"dom-to-image": "^2.6.0",
"handlebars": "^4.7.8",
"intl-messageformat": "^10.5.14",
"justified-layout": "^4.1.0",
"lodash-es": "^4.17.21",
"luxon": "^3.4.4",
Expand Down
16 changes: 12 additions & 4 deletions web/src/lib/components/admin-page/delete-confirm-dialogue.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import { serverConfig } from '$lib/stores/server-config.store';
import { createEventDispatcher } from 'svelte';
import Checkbox from '$lib/components/elements/checkbox.svelte';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let user: UserResponseDto;
Expand Down Expand Up @@ -54,12 +55,19 @@
<div class="flex flex-col gap-4">
{#if forceDelete}
<p>
<b>{user.name}</b>'s account and assets will be queued for permanent deletion <b>immediately</b>.
<FormatMessage message={$json('admin.user_delete_immediately')} values={{ user: user.name }} let:message>
<b>{message}</b>
</FormatMessage>
</p>
{:else}
<p>
<b>{user.name}</b>'s account and assets will be scheduled for permanent deletion in {$serverConfig.userDeleteDelay}
days.
<FormatMessage
message={$json('admin.user_delete_delay')}
values={{ user: user.name, delay: $serverConfig.userDeleteDelay }}
let:message
>
<b>{message}</b>
</FormatMessage>
</p>
{/if}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<script lang="ts">
import FormatMessage from '$lib/components/i18n/format-message.svelte';
import { AppRoute, OpenSettingQueryParameterValue, QueryParameter } from '$lib/constants';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
</script>

Apply the current
<a
href="{AppRoute.ADMIN_SETTINGS}?{QueryParameter.IS_OPEN}={OpenSettingQueryParameterValue.STORAGE_TEMPLATE}"
class="text-immich-primary dark:text-immich-dark-primary"
<FormatMessage
message={$json('admin.storage_template_migration_description')}
values={{ template: $t('admin.storage_template_settings') }}
let:message
>
{$t('admin.storage_template_settings')}
</a>
to previously uploaded assets
<a
href="{AppRoute.ADMIN_SETTINGS}?{QueryParameter.IS_OPEN}={OpenSettingQueryParameterValue.STORAGE_TEMPLATE}"
class="text-immich-primary dark:text-immich-dark-primary"
>
{message}
</a>
</FormatMessage>
9 changes: 7 additions & 2 deletions web/src/lib/components/admin-page/restore-dialogue.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script lang="ts">
import FormatMessage from '$lib/components/i18n/format-message.svelte';
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
import { handleError } from '$lib/utils/handle-error';
import { restoreUserAdmin, type UserResponseDto } from '@immich/sdk';
import { createEventDispatcher } from 'svelte';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
export let user: UserResponseDto;
Expand Down Expand Up @@ -36,6 +37,10 @@
onCancel={() => dispatch('cancel')}
>
<svelte:fragment slot="prompt">
<p><b>{user.name}</b>'s account will be restored.</p>
<p>
<FormatMessage message={$json('admin.user_restore_description')} values={{ user: user.name }} let:message>
<b>{message}</b>
</FormatMessage>
</p>
</svelte:fragment>
</ConfirmDialog>
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import { createEventDispatcher } from 'svelte';
import { fade } from 'svelte/transition';
import type { SettingsEventType } from '../admin-settings';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let savedConfig: SystemConfigDto;
export let defaultConfig: SystemConfigDto;
Expand Down Expand Up @@ -52,15 +53,16 @@
<div class="flex flex-col gap-4">
<p>Are you sure you want to disable all login methods? Login will be completely disabled.</p>
<p>
To re-enable, use a
<a
href="https://immich.app/docs/administration/server-commands"
rel="noreferrer"
target="_blank"
class="underline"
>
Server Command</a
>.
<FormatMessage message={$json('admin.authentication_settings_reenable')} let:message>
<a
href="https://immich.app/docs/administration/server-commands"
rel="noreferrer"
target="_blank"
class="underline"
>
{message}
</a>
</FormatMessage>
</p>
</div>
</svelte:fragment>
Expand All @@ -78,12 +80,16 @@
>
<div class="ml-4 mt-4 flex flex-col gap-4">
<p class="text-sm dark:text-immich-dark-fg">
For more details about this feature, refer to the <a
href="https://immich.app/docs/administration/oauth"
class="underline"
target="_blank"
rel="noreferrer">docs</a
>.
<FormatMessage message={$json('admin.oauth_settings_more_details')} let:message>
<a
href="https://immich.app/docs/administration/oauth"
class="underline"
target="_blank"
rel="noreferrer"
>
{message}
</a>
</FormatMessage>
</p>

<SettingSwitch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import SettingCheckboxes from '$lib/components/shared-components/settings/setting-checkboxes.svelte';
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let savedConfig: SystemConfigDto;
export let defaultConfig: SystemConfigDto;
Expand All @@ -38,17 +39,21 @@
<div class="ml-4 mt-4 flex flex-col gap-4">
<p class="text-sm dark:text-immich-dark-fg">
<Icon path={mdiHelpCircleOutline} class="inline" size="15" />
To learn more about the terminology used here, refer to FFmpeg documentation for
<a href="https://trac.ffmpeg.org/wiki/Encode/H.264" class="underline" target="_blank" rel="noreferrer"
>H.264 codec</a
>,
<a href="https://trac.ffmpeg.org/wiki/Encode/H.265" class="underline" target="_blank" rel="noreferrer"
>{$t('admin.transcoding_hevc_codec')}</a
>
and
<a href="https://trac.ffmpeg.org/wiki/Encode/VP9" class="underline" target="_blank" rel="noreferrer"
>VP9 codec</a
>.
<FormatMessage message={$json('admin.transcoding_codecs_learn_more')} let:tag let:message>
{#if tag === 'h264-link'}
<a href="https://trac.ffmpeg.org/wiki/Encode/H.264" class="underline" target="_blank" rel="noreferrer">
{message}
</a>
{:else if tag === 'hevc-link'}
<a href="https://trac.ffmpeg.org/wiki/Encode/H.265" class="underline" target="_blank" rel="noreferrer">
{message}
</a>
{:else if tag === 'vp9-link'}
<a href="https://trac.ffmpeg.org/wiki/Encode/VP9" class="underline" target="_blank" rel="noreferrer">
{message}
</a>
{/if}
</FormatMessage>
</p>

<SettingInputField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
} from '$lib/components/shared-components/settings/setting-input-field.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let savedConfig: SystemConfigDto;
export let defaultConfig: SystemConfigDto;
Expand Down Expand Up @@ -99,12 +100,11 @@
>
<svelte:fragment slot="desc">
<p class="text-sm dark:text-immich-dark-fg">
Set the scanning interval using the cron format. For more information please refer to e.g. <a
href="https://crontab.guru"
class="underline"
target="_blank"
rel="noreferrer">{$t('admin.crontab_guru')}</a
>
<FormatMessage message={$json('admin.library_cron_expression_description')} let:message>
<a href="https://crontab.guru" class="underline" target="_blank" rel="noreferrer">
{message}
</a>
</FormatMessage>
</p>
</svelte:fragment>
</SettingInputField>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import { featureFlags } from '$lib/stores/server-config.store';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let savedConfig: SystemConfigDto;
export let defaultConfig: SystemConfigDto;
Expand Down Expand Up @@ -70,8 +71,9 @@
isEdited={config.machineLearning.clip.modelName !== savedConfig.machineLearning.clip.modelName}
>
<p slot="desc" class="immich-form-label pb-2 text-sm">
The name of a CLIP model listed <a href="https://huggingface.co/immich-app"><u>here</u></a>. Note that you
must re-run the 'Smart Search' job for all images upon changing a model.
<FormatMessage message={$json('admin.machine_learning_clip_model_description')} let:message>
<a href="https://huggingface.co/immich-app"><u>{message}</u></a>
</FormatMessage>
</p>
</SettingInputField>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
SettingInputFieldType,
} from '$lib/components/shared-components/settings/setting-input-field.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import { t } from 'svelte-i18n';
import { json, t } from 'svelte-i18n';
import FormatMessage from '$lib/components/i18n/format-message.svelte';
export let savedConfig: SystemConfigDto;
export let defaultConfig: SystemConfigDto;
Expand Down Expand Up @@ -88,21 +89,27 @@
<section class="dark:text-immich-dark-fg mt-2">
<div in:fade={{ duration: 500 }} class="mx-4 flex flex-col gap-4 py-4">
<p class="text-sm dark:text-immich-dark-fg">
For more details about this feature, refer to the <a
href="https://immich.app/docs/administration/storage-template"
class="underline"
target="_blank"
rel="noreferrer"
>Storage Template
</a>
and its
<a
href="https://immich.app/docs/administration/backup-and-restore#asset-types-and-storage-locations"
class="underline"
target="_blank"
rel="noreferrer"
>implications
</a>
<FormatMessage message={$json('admin.storage_template_more_details')} let:tag let:message>
{#if tag === 'template-link'}
<a
href="https://immich.app/docs/administration/storage-template"
class="underline"
target="_blank"
rel="noreferrer"
>
{message}
</a>
{:else if tag === 'implications-link'}
<a
href="https://immich.app/docs/administration/backup-and-restore#asset-types-and-storage-locations"
class="underline"
target="_blank"
rel="noreferrer"
>
{message}
</a>
{/if}
</FormatMessage>
</p>
</div>
{#await getTemplateOptions() then}
Expand Down Expand Up @@ -153,15 +160,23 @@
</div>

<p class="text-sm">
Approximately path length limit : <span
class="font-semibold text-immich-primary dark:text-immich-dark-primary"
>{parsedTemplate().length + $user.id.length + 'UPLOAD_LOCATION'.length}</span
>/260
<FormatMessage
message={$json('admin.storage_template_path_length')}
values={{ length: parsedTemplate().length + $user.id.length + 'UPLOAD_LOCATION'.length, limit: 260 }}
let:message
>
<span class="font-semibold text-immich-primary dark:text-immich-dark-primary">{message}</span>
</FormatMessage>
</p>

<p class="text-sm">
<code class="text-immich-primary dark:text-immich-dark-primary">{$user.storageLabel || $user.id}</code> is the
user's Storage Label
<FormatMessage
message={$json('admin.storage_template_user_label')}
values={{ label: $user.storageLabel || $user.id }}
let:message
>
<code class="text-immich-primary dark:text-immich-dark-primary">{message}</code>
</FormatMessage>
</p>

<p class="p-4 py-2 mt-2 text-xs bg-gray-200 rounded-lg dark:bg-gray-700 dark:text-immich-dark-fg">
Expand Down Expand Up @@ -213,20 +228,15 @@
<h3 class="text-base font-medium text-immich-primary dark:text-immich-dark-primary">{$t('notes')}</h3>
<section class="flex flex-col gap-2">
<p>
Template changes will only apply to new assets. To retroactively apply the template to previously
uploaded assets, run the
<a href={AppRoute.ADMIN_JOBS} class="text-immich-primary dark:text-immich-dark-primary"
>{$t('admin.storage_template_migration_job')}</a
>.
</p>
<p>
The template variable <span class="font-mono">{`{{album}}`}</span> will always be empty for new
assets, so manually running the

<a href={AppRoute.ADMIN_JOBS} class="text-immich-primary dark:text-immich-dark-primary"
>{$t('admin.storage_template_migration_job')}</a
<FormatMessage
message={$json('admin.storage_template_migration_info')}
values={{ job: $t('admin.storage_template_migration_job') }}
let:message
>
is required in order to successfully use the variable.
<a href={AppRoute.ADMIN_JOBS} class="text-immich-primary dark:text-immich-dark-primary">
{message}
</a>
</FormatMessage>
</p>
</section>
</div>
Expand Down
Loading

0 comments on commit b3252ff

Please sign in to comment.