diff options
| author | Fuwn <[email protected]> | 2026-05-24 13:22:34 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-05-24 13:22:34 +0000 |
| commit | 56a7a7851b09cb30a5cd543c8cb4f926109b4290 (patch) | |
| tree | a620f908405fa48fd601580c5a48432831ec5c33 /src/lib/Tools | |
| parent | fix(layout): preserve list panel when clicking action buttons in summary (diff) | |
| download | due.moe-56a7a7851b09cb30a5cd543c8cb4f926109b4290.tar.xz due.moe-56a7a7851b09cb30a5cd543c8cb4f926109b4290.zip | |
refactor(locale): move hardcoded UI strings into english locale
Adds optional namespaces (common, errors, commandPalette, headTitle,
notifications, schedule, events, home, reader, routes, badgePreview,
badgeWall) and extends existing ones (settings.*, lists.*, tools.*,
user.*, hololive.*) on the Locale interface. New fields are optional
so japanese.ts can omit them; svelte-i18n's fallbackLocale handles
the runtime miss.
HeadTitle gains an optional routeKey prop for type-safe lookup.
defaultActions becomes a factory so the command palette re-reads
locale on language toggle. The existing JP feedback translation
in routes/settings is preserved via japanese.ts.
Out of scope (kept hardcoded): service-worker.ts, app.html,
Landing*.svelte, tools.ts registry, Easter Event 2025 pages.
Diffstat (limited to 'src/lib/Tools')
| -rw-r--r-- | src/lib/Tools/ActivityHistory/Grid.svelte | 3 | ||||
| -rw-r--r-- | src/lib/Tools/ActivityHistory/Tool.svelte | 5 | ||||
| -rw-r--r-- | src/lib/Tools/EpisodeDiscussionCollector.svelte | 9 | ||||
| -rw-r--r-- | src/lib/Tools/FollowFix.svelte | 3 | ||||
| -rw-r--r-- | src/lib/Tools/InputTemplate.svelte | 3 | ||||
| -rw-r--r-- | src/lib/Tools/Likes.svelte | 3 | ||||
| -rw-r--r-- | src/lib/Tools/Picker.svelte | 5 | ||||
| -rw-r--r-- | src/lib/Tools/SequelCatcher/List.svelte | 9 | ||||
| -rw-r--r-- | src/lib/Tools/SequelCatcher/Tool.svelte | 11 | ||||
| -rw-r--r-- | src/lib/Tools/SequelSpy/Tool.svelte | 12 | ||||
| -rw-r--r-- | src/lib/Tools/Tracker/Tool.svelte | 34 | ||||
| -rw-r--r-- | src/lib/Tools/Wrapped/Tool.svelte | 141 |
12 files changed, 144 insertions, 94 deletions
diff --git a/src/lib/Tools/ActivityHistory/Grid.svelte b/src/lib/Tools/ActivityHistory/Grid.svelte index 6a931ab2..afa9cd8f 100644 --- a/src/lib/Tools/ActivityHistory/Grid.svelte +++ b/src/lib/Tools/ActivityHistory/Grid.svelte @@ -11,6 +11,7 @@ import { clearAllParameters } from "../../Utility/parameters"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import tooltip from "$lib/Tooltip/tooltip"; import LogInRestricted from "$lib/Error/LogInRestricted.svelte"; +import locale from "$stores/locale"; export let user: AniListAuthorisation; export let activityData: ActivityHistoryEntry[] | null = null; @@ -52,7 +53,7 @@ const gradientColour = (amount: number, maxAmount: number, baseHue: number) => { role="button" tabindex="0" use:tooltip - title={`Date: ${new Date(activity.date * 1000).toLocaleDateString()}\nAmount: ${ + title={`${$locale().tools.activityHistory?.dateLabel ?? 'Date:'} ${new Date(activity.date * 1000).toLocaleDateString()}\n${$locale().tools.activityHistory?.amountLabel ?? 'Amount:'} ${ activity.amount }`} ></div> diff --git a/src/lib/Tools/ActivityHistory/Tool.svelte b/src/lib/Tools/ActivityHistory/Tool.svelte index 3cf7b09e..5e84db9e 100644 --- a/src/lib/Tools/ActivityHistory/Tool.svelte +++ b/src/lib/Tools/ActivityHistory/Tool.svelte @@ -14,6 +14,7 @@ import ActivityHistoryGrid from "./Grid.svelte"; import SettingHint from "$lib/Settings/SettingHint.svelte"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import LogInRestricted from "$lib/Error/LogInRestricted.svelte"; +import locale from "$stores/locale"; export let user: AniListAuthorisation; @@ -99,10 +100,10 @@ const screenshot = async () => { <Spacer /> <details open> - <summary>Days in risk of developing an activity history hole</summary> + <summary>{$locale().tools.activityHistory?.daysAtRisk}</summary> <SettingHint> - Days in which you did not log any activity or only have one activity logged. + {$locale().tools.activityHistory?.daysAtRiskHint} </SettingHint> <ul> diff --git a/src/lib/Tools/EpisodeDiscussionCollector.svelte b/src/lib/Tools/EpisodeDiscussionCollector.svelte index 68addbdf..2bbefc0a 100644 --- a/src/lib/Tools/EpisodeDiscussionCollector.svelte +++ b/src/lib/Tools/EpisodeDiscussionCollector.svelte @@ -6,6 +6,7 @@ import { clearAllParameters } from "../Utility/parameters"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import InputTemplate from "./InputTemplate.svelte"; import tooltip from "$lib/Tooltip/tooltip"; +import locale from "$stores/locale"; let submission = ""; @@ -46,17 +47,17 @@ onMount(clearAllParameters); {/each} </ol> {:catch} - <p>Threads could not be loaded. You might have been rate-limited.</p> + <p>{$locale().tools.episodeDiscussion?.rateLimit}</p> <p> - Try again in a few minutes. If the problem persists, please contact <a + {$locale().tools.episodeDiscussion?.contactSupport?.split('@fuwn')[0]}<a href="https://anilist.co/user/fuwn" target="_blank">@fuwn</a - > on AniList. + >{$locale().tools.episodeDiscussion?.contactSupport?.split('@fuwn')[1]} </p> {/await} {:else} <Spacer /> - Enter a username to search for to continue. + {$locale().tools.episodeDiscussion?.enterUsername} {/if} </InputTemplate> diff --git a/src/lib/Tools/FollowFix.svelte b/src/lib/Tools/FollowFix.svelte index 6c599569..93d07739 100644 --- a/src/lib/Tools/FollowFix.svelte +++ b/src/lib/Tools/FollowFix.svelte @@ -2,6 +2,7 @@ import { toggleFollow } from "$lib/Data/AniList/follow"; import type { AniListAuthorisation } from "$lib/Data/AniList/identity"; import LogInRestricted from "$lib/Error/LogInRestricted.svelte"; +import locale from "$stores/locale"; export let user: AniListAuthorisation; @@ -28,7 +29,7 @@ let submit = ""; /> {#if input.length > 0} <a href={'#'} onclick={() => (submit = input)}> - Toggle follow for {input} + {$locale({ values: { input } }).tools.followFix?.toggleFor} </a> {/if} </p> diff --git a/src/lib/Tools/InputTemplate.svelte b/src/lib/Tools/InputTemplate.svelte index c90d9b1c..c9d96dfb 100644 --- a/src/lib/Tools/InputTemplate.svelte +++ b/src/lib/Tools/InputTemplate.svelte @@ -3,6 +3,7 @@ import Spacer from "$lib/Layout/Spacer.svelte"; import { clearAllParameters } from "$lib/Utility/parameters"; import { onMount } from "svelte"; import SettingHint from "$lib/Settings/SettingHint.svelte"; +import locale from "$stores/locale"; export let field: string; export let submission: string; @@ -46,7 +47,7 @@ onMount(() => clearAllParameters(saveParameters)); onSubmit(); }} - title="Or click your Enter key" + title={$locale().tools.input?.pressEnter} data-umami-event={event} > {submitText} diff --git a/src/lib/Tools/Likes.svelte b/src/lib/Tools/Likes.svelte index dde5c755..70739ee6 100644 --- a/src/lib/Tools/Likes.svelte +++ b/src/lib/Tools/Likes.svelte @@ -5,6 +5,7 @@ import RateLimited from "$lib/Error/RateLimited.svelte"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import tooltip from "$lib/Tooltip/tooltip"; import settings from "$stores/settings"; +import locale from "$stores/locale"; import InputTemplate from "./InputTemplate.svelte"; let submission = ""; @@ -56,6 +57,6 @@ $: likesPromise = <RateLimited type="Likes" list={false} /> {/await} {:else} - Please enter a valid Activity or Thread URL. + {$locale().tools.likes?.invalidUrl} {/if} </InputTemplate> diff --git a/src/lib/Tools/Picker.svelte b/src/lib/Tools/Picker.svelte index ffece7b6..ad8d3444 100644 --- a/src/lib/Tools/Picker.svelte +++ b/src/lib/Tools/Picker.svelte @@ -2,6 +2,7 @@ import { browser } from "$app/environment"; import { goto } from "$app/navigation"; import root from "$lib/Utility/root"; +import locale from "$stores/locale"; import { tools } from "./tools"; export let tool: string; @@ -14,7 +15,9 @@ export let tool: string; if (browser) goto(root(`/tools/${tool}`)); }} > - <option value="default" selected disabled hidden>Select a tool to continue</option> + <option value="default" selected disabled hidden + >{$locale().tools.picker?.placeholder}</option + > {#each Object.keys(tools).filter((t) => t !== 'default' && !tools[t].hidden) as t} <option value={t}>{tools[t].short || tools[t].name()}</option> diff --git a/src/lib/Tools/SequelCatcher/List.svelte b/src/lib/Tools/SequelCatcher/List.svelte index b1512e22..4b1b8107 100644 --- a/src/lib/Tools/SequelCatcher/List.svelte +++ b/src/lib/Tools/SequelCatcher/List.svelte @@ -4,6 +4,7 @@ import { filterRelations, type Media } from "$lib/Data/AniList/media"; import MediaTitleDisplay from "$lib/List/MediaTitleDisplay.svelte"; import { outboundLink } from "$lib/Media/links"; import settings from "$stores/settings"; +import locale from "$stores/locale"; export let mediaListUnchecked: Media[]; @@ -25,11 +26,11 @@ const matchCheck = (media: Media | undefined, swap = false) => : undefined; </script> -<input type="checkbox" bind:checked={includeCurrent} /> Include current (watching, rewatching, -paused) +<input type="checkbox" bind:checked={includeCurrent} /> +{$locale().tools.sequelCatcher?.includeCurrent} <br /> -<input type="checkbox" bind:checked={includeSideStories} /> Include side stories (e.g., OVAs, -specials, etc.) +<input type="checkbox" bind:checked={includeSideStories} /> +{$locale().tools.sequelCatcher?.includeSideStories} <Spacer /> diff --git a/src/lib/Tools/SequelCatcher/Tool.svelte b/src/lib/Tools/SequelCatcher/Tool.svelte index 727a3a6c..f75b1f78 100644 --- a/src/lib/Tools/SequelCatcher/Tool.svelte +++ b/src/lib/Tools/SequelCatcher/Tool.svelte @@ -12,6 +12,7 @@ import lastPruneTimes from "$stores/lastPruneTimes"; import Message from "$lib/Loading/Message.svelte"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import Username from "$lib/Layout/Username.svelte"; +import locale from "$stores/locale"; export let user: AniListAuthorisation; @@ -69,13 +70,19 @@ onMount(async () => { /> {/if} {:catch} - <Message message="" loader="ripple" slot withReload fullscreen>Error fetching media.</Message> + <Message message="" loader="ripple" slot withReload fullscreen + >{$locale().tools.wrapped?.errorFetchingMedia ?? 'Error fetching media.'}</Message + > {/await} <Spacer /> <blockquote style="margin: 0 0 0 1.5rem;"> - Thanks to <Username username="sevengirl" /> and <Username username="esthereae" /> for the idea! + {$locale().tools.sequelCatcher?.credit?.split('@sevengirl')[0]}<Username + username="sevengirl" + />{$locale().tools.sequelCatcher?.credit?.split('@sevengirl')[1]?.split('@esthereae')[0]}<Username + username="esthereae" + />{$locale().tools.sequelCatcher?.credit?.split('@esthereae')[1]} </blockquote> </div> {/if} diff --git a/src/lib/Tools/SequelSpy/Tool.svelte b/src/lib/Tools/SequelSpy/Tool.svelte index 71056694..87931176 100644 --- a/src/lib/Tools/SequelSpy/Tool.svelte +++ b/src/lib/Tools/SequelSpy/Tool.svelte @@ -10,6 +10,7 @@ import { season as getSeason } from "$lib/Media/Anime/season"; import Skeleton from "$lib/Loading/Skeleton.svelte"; import identity from "$stores/identity"; import LogInRestricted from "$lib/Error/LogInRestricted.svelte"; +import locale from "$stores/locale"; import Prequels from "./Prequels.svelte"; export let user: AniListAuthorisation; @@ -45,10 +46,10 @@ onMount(() => clearAllParameters(["year", "season"])); <div class="card"> <p> <select bind:value={season}> - <option value="WINTER">Winter</option> - <option value="SPRING">Spring</option> - <option value="SUMMER">Summer</option> - <option value="FALL">Fall</option> + <option value="WINTER">{$locale().tools.sequelSpy?.winter}</option> + <option value="SPRING">{$locale().tools.sequelSpy?.spring}</option> + <option value="SUMMER">{$locale().tools.sequelSpy?.summer}</option> + <option value="FALL">{$locale().tools.sequelSpy?.fall}</option> </select> <input type="number" bind:value={year} /> </p> @@ -61,7 +62,6 @@ onMount(() => clearAllParameters(["year", "season"])); <Spacer /> - The count ratio is the number of episodes you've seen of any direct prequels, and the total - number of episodes of all direct prequels. + {$locale().tools.sequelSpy?.countRatio} </div> {/if} diff --git a/src/lib/Tools/Tracker/Tool.svelte b/src/lib/Tools/Tracker/Tool.svelte index 8f7a3197..b495522a 100644 --- a/src/lib/Tools/Tracker/Tool.svelte +++ b/src/lib/Tools/Tracker/Tool.svelte @@ -4,6 +4,8 @@ import { v6 as uuidv6 } from "uuid"; import { database, type TrackerEntry } from "$lib/Database/IDB/tracker"; import { onMount } from "svelte"; import Message from "$lib/Loading/Message.svelte"; +import locale from "$stores/locale"; +import { get } from "svelte/store"; let url = ""; let title = ""; @@ -34,15 +36,19 @@ const adjustEntry = (id: string, to: number) => { const addEntry = async (url: string, title: string, progress: number) => { if (!url || !title) { - error = "URL and title are required fields"; + error = + get(locale)().tools.tracker?.urlTitleRequired ?? + "URL and title are required fields"; return; } if (listAccess.some((entry) => entry.url === url)) { - error = - "Entry with URL already exists: " + - listAccess.find((entry) => entry.url === url)?.title; + const existing = listAccess.find((entry) => entry.url === url)?.title; + + error = ( + get(locale)().tools.tracker?.entryExists ?? "Entry with URL already exists: {url}" + ).replace("{url}", existing ?? ""); return; } @@ -55,7 +61,9 @@ const addEntry = async (url: string, title: string, progress: number) => { const deleteEntry = async (id: string) => { if (confirmDelete !== 1) { confirmDelete = 1; - error = "Click again to confirm deletion"; + error = + get(locale)().tools.tracker?.confirmDelete ?? + "Click again to confirm deletion"; return; } @@ -73,10 +81,16 @@ const deleteEntry = async (id: string) => { <p><b>Error</b>: {error}</p> {/if} - <input type="url" placeholder="URL" bind:value={url} /> - <input type="text" placeholder="Title" bind:value={title} /> - <input type="number" placeholder="Progress (defaults to 0)" bind:value={progress} /> - <button class="button-lined" onclick={() => addEntry(url, title, progress)}> Add </button> + <input type="url" placeholder={$locale().tools.tracker?.urlPlaceholder} bind:value={url} /> + <input type="text" placeholder={$locale().tools.tracker?.titlePlaceholder} bind:value={title} /> + <input + type="number" + placeholder={$locale().tools.tracker?.progressPlaceholder} + bind:value={progress} + /> + <button class="button-lined" onclick={() => addEntry(url, title, progress)} + >{$locale().common?.add}</button + > <Spacer /> @@ -120,7 +134,7 @@ const deleteEntry = async (id: string) => { + </button> <span class="opaque">|</span> - <button onclick={() => deleteEntry(entry.id)}>Remove</button> + <button onclick={() => deleteEntry(entry.id)}>{$locale().common?.remove}</button> </span> </div> </li> diff --git a/src/lib/Tools/Wrapped/Tool.svelte b/src/lib/Tools/Wrapped/Tool.svelte index b04bc5f6..b7d67cb0 100644 --- a/src/lib/Tools/Wrapped/Tool.svelte +++ b/src/lib/Tools/Wrapped/Tool.svelte @@ -2,6 +2,7 @@ import Spacer from "$lib/Layout/Spacer.svelte"; import "./wrapped.css"; import userIdentity from "$stores/identity"; +import locale from "$stores/locale"; import type { AniListAuthorisation } from "$lib/Data/AniList/identity"; import { onMount } from "svelte"; import { @@ -214,33 +215,36 @@ $: { updateWidth(); } $: genreTagTitle = (() => { + const w = $locale().tools.wrapped; switch (genreTagsSort) { case SortOptions.SCORE: - return "Highest Rated"; + return w?.highestRated ?? "Highest Rated"; case SortOptions.MINUTES_WATCHED: - return "Most Watched"; + return w?.mostWatched ?? "Most Watched"; case SortOptions.COUNT: - return "Most Common"; + return w?.mostCommon ?? "Most Common"; } })(); $: animeMostTitle = (() => { + const w = $locale().tools.wrapped; switch (mediaSort) { case SortOptions.SCORE: - return "Highest Rated"; + return w?.highestRated ?? "Highest Rated"; case SortOptions.MINUTES_WATCHED: - return "Most Watched"; + return w?.mostWatched ?? "Most Watched"; case SortOptions.COUNT: - return "Most Common"; + return w?.mostCommon ?? "Most Common"; } })(); $: mangaMostTitle = (() => { + const w = $locale().tools.wrapped; switch (mediaSort) { case SortOptions.SCORE: - return "Highest Rated"; + return w?.highestRated ?? "Highest Rated"; case SortOptions.MINUTES_WATCHED: - return "Most Read"; + return w?.mostRead ?? "Most Read"; case SortOptions.COUNT: - return "Most Common"; + return w?.mostCommon ?? "Most Common"; } })(); @@ -829,12 +833,12 @@ const pruneFullYear = async () => { {#if shouldFetchData} {#key fetchKey} {#await selectedYear !== currentYear || useFullActivityHistory || new Date().getMonth() <= 6 ? fullActivityHistory(user, $userIdentity, selectedYear, disableLoopingActivityCounter) : getActivityHistory($userIdentity)} - <Message message="Loading activity history ..." /> + <Message message={$locale().tools.wrapped?.loadingActivityHistory} /> <Skeleton count={2} /> {:then activities} {#await wrapped(user, $userIdentity, selectedYear, false, disableLoopingActivityCounter)} - <Message message="Loading user data ..." /> + <Message message={$locale().tools.wrapped?.loadingUserData} /> <Skeleton count={2} /> {:then wrapped} @@ -920,9 +924,8 @@ const pruneFullYear = async () => { > {#if useFullActivityHistory} <p> - With <b>many</b> activities, it may take multiple attempts to obtain all of your activity - history from AniList. If this occurs, wait one minute and try again to continue populating - your local activity history database. + {$locale().tools.wrapped?.multiAttemptPrefix}<b>many</b>{$locale().tools.wrapped + ?.multiAttemptSuffix} </p> {/if} </RateLimitedError> @@ -970,7 +973,7 @@ const pruneFullYear = async () => { id="watermark" data-umami-event="Load Wrapped Data" > - Click load data! + {$locale().tools.wrapped?.clickLoadData} </a> </div> </div> @@ -985,7 +988,7 @@ const pruneFullYear = async () => { <Spacer /> <blockquote style="margin: 0 0 0 1.5rem;"> - Click on the image to download, or right click and select "Save Image As...". + {$locale().tools.wrapped?.saveImageInstruction} </blockquote> {/if} </div> @@ -995,66 +998,73 @@ const pruneFullYear = async () => { {/if} <div id="options" class="card"> - <button onclick={screenshot} data-umami-event="Generate Wrapped"> Generate image </button> + <button onclick={screenshot} data-umami-event="Generate Wrapped" + >{$locale().tools.wrapped?.generateImage}</button + > {#if !shouldFetchData} - <button onclick={triggerFetch} data-umami-event="Load Wrapped Data"> Load data </button> + <button onclick={triggerFetch} data-umami-event="Load Wrapped Data" + >{$locale().tools.wrapped?.loadData}</button + > {:else if needsRefetch} <button onclick={triggerFetch} data-umami-event="Refetch Wrapped Data"> - Reload data + {$locale().tools.wrapped?.reloadData} </button> {/if} <details class="no-shadow" open> - <summary>Display</summary> + <summary>{$locale().tools.wrapped?.display}</summary> - <input type="checkbox" bind:checked={watermark} /> Show watermark<br /> - <input type="checkbox" bind:checked={transparency} /> Enable background transparency<br /> + <input type="checkbox" bind:checked={watermark} /> + {$locale().tools.wrapped?.showWatermark}<br /> + <input type="checkbox" bind:checked={transparency} /> + {$locale().tools.wrapped?.bgTransparency}<br /> <input type="checkbox" bind:checked={lightMode} /> - Enable light mode<br /> + {$locale().tools.wrapped?.lightMode}<br /> <input type="checkbox" bind:checked={topGenresTags} /> - Show top genres and tags<br /> + {$locale().tools.wrapped?.showGenresTags}<br /> <input type="checkbox" bind:checked={disableActivityHistory} disabled={selectedYear !== currentYear} /> - Hide activity history<br /> - <input type="checkbox" bind:checked={highestRatedMediaPercentage} /> Show highest rated - media percentages<br /> - <input type="checkbox" bind:checked={highestRatedGenreTagPercentage} /> Show highest rated - genre and tag percentages<br /> - <input type="checkbox" bind:checked={includeOngoingMediaFromPreviousYears} /> Show ongoing - media from previous years<br /> + {$locale().tools.wrapped?.hideActivityHistory}<br /> + <input type="checkbox" bind:checked={highestRatedMediaPercentage} /> + {$locale().tools.wrapped?.showRatedPercentages}<br /> + <input type="checkbox" bind:checked={highestRatedGenreTagPercentage} /> + {$locale().tools.wrapped?.showGenreTagPercentages}<br /> + <input type="checkbox" bind:checked={includeOngoingMediaFromPreviousYears} /> + {$locale().tools.wrapped?.showOngoingPrevious}<br /> <select bind:value={activityHistoryPosition}> - <option value="TOP">Above Top Row</option> - <option value="BELOW_TOP">Below Top Row</option> - <option value="ORIGINAL">Bottom</option> + <option value="TOP">{$locale().tools.wrapped?.aboveTopRow}</option> + <option value="BELOW_TOP">{$locale().tools.wrapped?.belowTopRow}</option> + <option value="ORIGINAL">{$locale().tools.wrapped?.bottom}</option> </select> - Activity history position<br /> + {$locale().tools.wrapped?.activityHistoryPosition}<br /> <select bind:value={highestRatedCount}> {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} <option value={count}>{count}</option> {/each} </select> - Highest rated media count<br /> + {$locale().tools.wrapped?.highestRatedCount}<br /> <select bind:value={genreTagCount}> {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} <option value={count}>{count}</option> {/each} </select> - Highest genre and tag count<br /> - <button onclick={updateWidth}>Find best fit</button> + {$locale().tools.wrapped?.highestGenreTagCount}<br /> + <button onclick={updateWidth}>{$locale().tools.wrapped?.findBestFit}</button> <button onclick={() => (width -= 25)}>-25px</button> <button onclick={() => (width += 25)}>+25px</button> - Width adjustment<br /> + {$locale().tools.wrapped?.widthAdjustment}<br /> </details> <details class="no-shadow" open> - <summary>Calculation</summary> + <summary>{$locale().tools.wrapped?.calculation}</summary> <input type="checkbox" bind:checked={useFullActivityHistory} disabled={needsRefetch} /> - Enable full-year activity<button class="smaller-button" onclick={pruneFullYear} - >Refresh data</button + {$locale().tools.wrapped?.enableFullYear}<button + class="smaller-button" + onclick={pruneFullYear}>{$locale().tools.wrapped?.refreshData}</button > <br /> <select bind:value={selectedYear} disabled={needsRefetch}> @@ -1064,7 +1074,7 @@ const pruneFullYear = async () => { </option> {/each} </select> - Calculate for year<br /> + {$locale().tools.wrapped?.calculateForYear}<br /> <input type="date" bind:value={startDateFilter} @@ -1076,7 +1086,7 @@ const pruneFullYear = async () => { update(); }} /> - Start date filter<br /> + {$locale().tools.wrapped?.startDateFilter}<br /> <input type="date" bind:value={endDateFilter} @@ -1088,25 +1098,30 @@ const pruneFullYear = async () => { update(); }} /> - End date filter<br /> + {$locale().tools.wrapped?.endDateFilter}<br /> <select bind:value={mediaSort}> <option value={SortOptions.SCORE}>Score</option> <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> </select> - Anime and manga sort<br /> + {$locale().tools.wrapped?.animeMangaSort}<br /> <select bind:value={genreTagsSort}> <option value={SortOptions.SCORE}>Score</option> <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> <option value={SortOptions.COUNT}>Count</option> </select> - Genre and tag sort<br /> - <input type="checkbox" bind:checked={includeMusic} /> Include music<br /> - <input type="checkbox" bind:checked={includeRepeats} /> Include rewatches & rereads<br /> - <input type="checkbox" bind:checked={includeSpecials} /> Include specials<br /> - <input type="checkbox" bind:checked={includeOVAs} /> Include OVAs<br /> - <input type="checkbox" bind:checked={includeMovies} /> Include movies<br /> - <input type="checkbox" bind:checked={excludeUnratedUnwatched} /> Excluded unrated & - unwatched<br /> + {$locale().tools.wrapped?.genreTagSort}<br /> + <input type="checkbox" bind:checked={includeMusic} /> + {$locale().tools.wrapped?.includeMusic}<br /> + <input type="checkbox" bind:checked={includeRepeats} /> + {$locale().tools.wrapped?.includeRewatches}<br /> + <input type="checkbox" bind:checked={includeSpecials} /> + {$locale().tools.wrapped?.includeSpecials}<br /> + <input type="checkbox" bind:checked={includeOVAs} /> + {$locale().tools.wrapped?.includeOvas}<br /> + <input type="checkbox" bind:checked={includeMovies} /> + {$locale().tools.wrapped?.includeMovies}<br /> + <input type="checkbox" bind:checked={excludeUnratedUnwatched} /> + {$locale().tools.wrapped?.excludeUnrated}<br /> <input type="text" bind:value={excludedKeywordsInput} @@ -1114,29 +1129,33 @@ const pruneFullYear = async () => { e.key === 'Enter' && submitExcludedKeywords(); }} /> - Excluded keywords - <button onclick={submitExcludedKeywords} title="Or click your Enter key" use:tooltip> - Submit + {$locale().tools.wrapped?.excludedKeywords} + <button + onclick={submitExcludedKeywords} + title={$locale().tools.input?.pressEnter} + use:tooltip + > + {$locale().tools.wrapped?.submit} </button> <br /> - <SettingHint>Comma separated list (e.g., "My Hero, Kaguya")</SettingHint> + <SettingHint>{$locale().tools.wrapped?.excludedHint}</SettingHint> </details> <details class="no-shadow" open> - <summary>Advanced</summary> + <summary>{$locale().tools.wrapped?.advanced}</summary> <input type="checkbox" bind:checked={disableLoopingActivityCounter} disabled={needsRefetch} /> - Disable detailed activity information + {$locale().tools.wrapped?.disableDetailedActivity} </details> </div> </div> </div> {:else} - <Message message="Loading user ..." /> + <Message message={$locale().tools.wrapped?.loadingUser} /> <Skeleton count={2} /> {/if} |