mirror of
https://github.com/immich-app/immich.git
synced 2025-04-01 02:51:27 -05:00
fix(web): translations (#10021)
This commit is contained in:
parent
f2148ddf03
commit
c8f2d994c6
16 changed files with 73 additions and 36 deletions
|
@ -61,12 +61,12 @@
|
|||
[JobName.ThumbnailGeneration]: {
|
||||
icon: mdiFileJpgBox,
|
||||
title: getJobName(JobName.ThumbnailGeneration),
|
||||
subtitle: $t('thumbnail_generation_job_description'),
|
||||
subtitle: $t('admin.thumbnail_generation_job_description'),
|
||||
},
|
||||
[JobName.MetadataExtraction]: {
|
||||
icon: mdiTable,
|
||||
title: getJobName(JobName.MetadataExtraction),
|
||||
subtitle: $t('metadata_extraction_job_description'),
|
||||
subtitle: $t('admin.metadata_extraction_job_description'),
|
||||
},
|
||||
[JobName.Library]: {
|
||||
icon: mdiLibraryShelves,
|
||||
|
@ -78,7 +78,7 @@
|
|||
[JobName.Sidecar]: {
|
||||
title: getJobName(JobName.Sidecar),
|
||||
icon: mdiFileXmlBox,
|
||||
subtitle: $t('sidecar_job_description'),
|
||||
subtitle: $t('admin.sidecar_job_description'),
|
||||
allText: $t('sync').toUpperCase(),
|
||||
missingText: $t('discover').toUpperCase(),
|
||||
disabled: !$featureFlags.sidecar,
|
||||
|
@ -86,13 +86,13 @@
|
|||
[JobName.SmartSearch]: {
|
||||
icon: mdiImageSearch,
|
||||
title: getJobName(JobName.SmartSearch),
|
||||
subtitle: $t('smart_search_job_description'),
|
||||
subtitle: $t('admin.smart_search_job_description'),
|
||||
disabled: !$featureFlags.smartSearch,
|
||||
},
|
||||
[JobName.DuplicateDetection]: {
|
||||
icon: mdiContentDuplicate,
|
||||
title: getJobName(JobName.DuplicateDetection),
|
||||
subtitle: $t('duplicate_detection_job_description'),
|
||||
subtitle: $t('admin.duplicate_detection_job_description'),
|
||||
disabled: !$featureFlags.duplicateDetection,
|
||||
},
|
||||
[JobName.FaceDetection]: {
|
||||
|
@ -114,7 +114,7 @@
|
|||
[JobName.VideoConversion]: {
|
||||
icon: mdiVideo,
|
||||
title: getJobName(JobName.VideoConversion),
|
||||
subtitle: $t('video_conversion_job_description'),
|
||||
subtitle: $t('admin.video_conversion_job_description'),
|
||||
},
|
||||
[JobName.StorageTemplateMigration]: {
|
||||
icon: mdiFolderMove,
|
||||
|
@ -125,7 +125,7 @@
|
|||
[JobName.Migration]: {
|
||||
icon: mdiFolderMove,
|
||||
title: getJobName(JobName.Migration),
|
||||
subtitle: $t('migration_job_description'),
|
||||
subtitle: $t('admin.migration_job_description'),
|
||||
allowForceCommand: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
Apply the current
|
||||
<a href="{AppRoute.ADMIN_SETTINGS}?open=storageTemplate" class="text-immich-primary dark:text-immich-dark-primary"
|
||||
>{$t('storage_template_settings')}</a
|
||||
>{$t('admin.storage_template_settings')}</a
|
||||
>
|
||||
to previously uploaded assets
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
},
|
||||
{
|
||||
value: TranscodeHWAccel.Disabled,
|
||||
text: $t('disabled'),
|
||||
text: $t('admin.disabled'),
|
||||
},
|
||||
]}
|
||||
isEdited={config.ffmpeg.accel !== savedConfig.ffmpeg.accel}
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
href="https://crontab.guru"
|
||||
class="underline"
|
||||
target="_blank"
|
||||
rel="noreferrer">{$t('crontab_guru')}</a
|
||||
rel="noreferrer">{$t('admin.crontab_guru')}</a
|
||||
>
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
|
|
|
@ -315,7 +315,7 @@
|
|||
await handleDeleteAlbum(albumToDelete);
|
||||
} catch {
|
||||
notificationController.show({
|
||||
message: $t('errors.errors.unable_to_delete_album'),
|
||||
message: $t('errors.unable_to_delete_album'),
|
||||
type: NotificationType.Error,
|
||||
});
|
||||
} finally {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
<OnboardingCard>
|
||||
<p class="text-xl text-immich-primary dark:text-immich-dark-primary">
|
||||
{$t('storage_template_settings').toUpperCase()}
|
||||
{$t('admin.storage_template_settings').toUpperCase()}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</script>
|
||||
|
||||
{#if unstack}
|
||||
<MenuOption text={$t('un-stack')} icon={mdiImageMinusOutline} on:click={handleUnstack} />
|
||||
<MenuOption text={$t('unstack')} icon={mdiImageMinusOutline} on:click={handleUnstack} />
|
||||
{:else}
|
||||
<MenuOption text={$t('stack')} icon={mdiImageMultipleOutline} on:click={handleStack} />
|
||||
{/if}
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label={$t('duration')}
|
||||
desc={$t('slideshow_duration_description')}
|
||||
desc={$t('admin.slideshow_duration_description')}
|
||||
min={1}
|
||||
bind:value={$slideshowDelay}
|
||||
/>
|
||||
|
|
36
web/src/lib/i18n.spec.ts
Normal file
36
web/src/lib/i18n.spec.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import messages from '$lib/i18n/en.json';
|
||||
import { exec as execCallback } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import { init } from 'svelte-i18n';
|
||||
|
||||
type Messages = { [key: string]: string | Messages };
|
||||
|
||||
const exec = promisify(execCallback);
|
||||
|
||||
function setEmptyMessages(messages: Messages) {
|
||||
const copy = { ...messages };
|
||||
|
||||
for (const key in copy) {
|
||||
const message = copy[key];
|
||||
if (typeof message === 'string') {
|
||||
copy[key] = '';
|
||||
} else if (typeof message === 'object') {
|
||||
setEmptyMessages(message);
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
describe('i18n', () => {
|
||||
beforeEach(() => init({ fallbackLocale: 'dev' }));
|
||||
|
||||
test('no missing messages', async () => {
|
||||
const { stdout } = await exec('npx svelte-i18n extract -c svelte.config.js "src/**/*"');
|
||||
const extractedMessages: Messages = JSON.parse(stdout);
|
||||
const existingMessages = setEmptyMessages(messages);
|
||||
|
||||
// Only translations directly using the store seem to get extracted
|
||||
expect({ ...extractedMessages, ...existingMessages }).toEqual(existingMessages);
|
||||
});
|
||||
});
|
|
@ -473,7 +473,7 @@
|
|||
"info": "Info",
|
||||
"interval": {
|
||||
"day_at_onepm": "Every day at 1pm",
|
||||
"hours": "Every {hours, plural, one {hour} other {{hours, number} hours}",
|
||||
"hours": "Every {hours, plural, one {hour} other {{hours, number} hours}}",
|
||||
"night_at_midnight": "Every night at midnight",
|
||||
"night_at_twoam": "Every night at 2am"
|
||||
},
|
||||
|
@ -552,6 +552,7 @@
|
|||
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
||||
"not_in_any_album": "Not in any album",
|
||||
"notes": "Notes",
|
||||
"oauth": "OAuth",
|
||||
"offline": "Offline",
|
||||
"ok": "Ok",
|
||||
"oldest_first": "Oldest first",
|
||||
|
|
|
@ -364,7 +364,7 @@
|
|||
await deleteAlbum({ id: album.id });
|
||||
await goto(backUrl);
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_delete_album'));
|
||||
handleError(error, $t('errors.unable_to_delete_album'));
|
||||
} finally {
|
||||
viewMode = ViewMode.VIEW;
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
if (personToBeMergedIn.name !== personName && edittingPerson.id === personToBeMergedIn.id) {
|
||||
/*
|
||||
|
@ -235,7 +235,7 @@
|
|||
// trigger reactivity
|
||||
people = people;
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -279,7 +279,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_hide_person'));
|
||||
handleError(error, $t('errors.unable_to_hide_person'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -350,7 +350,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -377,7 +377,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
|
||||
await goto(previousRoute, { replaceState: true });
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_hide_person'));
|
||||
handleError(error, $t('errors.unable_to_hide_person'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -236,7 +236,7 @@
|
|||
}
|
||||
await goto(`${AppRoute.PEOPLE}/${personToBeMergedIn.id}`, { replaceState: true });
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -262,7 +262,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_save_name'));
|
||||
handleError(error, $t('errors.unable_to_save_name'));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_resolve_duplicate'));
|
||||
handleError(error, $t('errors.unable_to_resolve_duplicate'));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_create_library'));
|
||||
handleError(error, $t('errors.unable_to_create_library'));
|
||||
} finally {
|
||||
toCreateLibrary = false;
|
||||
await readLibraryList();
|
||||
|
@ -143,7 +143,7 @@
|
|||
closeAll();
|
||||
await readLibraryList();
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_update_library'));
|
||||
handleError(error, $t('errors.unable_to_update_library'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -163,7 +163,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_remove_library'));
|
||||
handleError(error, $t('errors.unable_to_remove_library'));
|
||||
} finally {
|
||||
confirmDeleteLibrary = null;
|
||||
deletedLibrary = null;
|
||||
|
@ -181,7 +181,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_scan_libraries'));
|
||||
handleError(error, $t('errors.unable_to_scan_libraries'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -193,7 +193,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_scan_library'));
|
||||
handleError(error, $t('errors.unable_to_scan_library'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,7 +205,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_scan_library'));
|
||||
handleError(error, $t('errors.unable_to_scan_library'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -217,7 +217,7 @@
|
|||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_scan_library'));
|
||||
handleError(error, $t('errors.unable_to_scan_library'));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
|
||||
matches = [];
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_repair_items'));
|
||||
handleError(error, $t('errors.unable_to_repair_items'));
|
||||
} finally {
|
||||
repairing = false;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@
|
|||
|
||||
notificationController.show({ message: $t('refreshed'), type: NotificationType.Info });
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_load_items'));
|
||||
handleError(error, $t('errors.unable_to_load_items'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -121,7 +121,7 @@
|
|||
notificationController.show({ message: `Matched 1 item`, type: NotificationType.Info });
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_check_item'));
|
||||
handleError(error, $t('errors.unable_to_check_item'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,7 +137,7 @@
|
|||
count += await loadAndMatch(filenames.slice(index, index + chunkSize));
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, $t('unable_to_check_items'));
|
||||
handleError(error, $t('errors.unable_to_check_items'));
|
||||
} finally {
|
||||
checking = false;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue